Feat(authentication): username password provider (#6052)
This commit is contained in:
@@ -6,13 +6,16 @@ export async function createAuthUsers(
|
||||
userData: any[] = [
|
||||
{
|
||||
id: "test-id",
|
||||
entity_id: "test-id",
|
||||
provider: "manual",
|
||||
},
|
||||
{
|
||||
id: "test-id-1",
|
||||
entity_id: "test-id-1",
|
||||
provider: "manual",
|
||||
},
|
||||
{
|
||||
entity_id: "test-id-2",
|
||||
provider: "store",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -229,6 +229,7 @@ describe("AuthUser Service", () => {
|
||||
{
|
||||
id: "test",
|
||||
provider_id: "manual",
|
||||
entity_id: "test"
|
||||
},
|
||||
])
|
||||
|
||||
|
||||
@@ -237,6 +237,7 @@ describe("AuthenticationModuleService - AuthUser", () => {
|
||||
{
|
||||
id: "test",
|
||||
provider_id: "manual",
|
||||
entity_id: "test"
|
||||
},
|
||||
])
|
||||
|
||||
|
||||
+24
-1
@@ -5,6 +5,7 @@ import { initialize } from "../../../../src"
|
||||
import { DB_URL } from "@medusajs/pricing/integration-tests/utils"
|
||||
import { MedusaModule } from "@medusajs/modules-sdk"
|
||||
import { IAuthenticationModuleService } from "@medusajs/types"
|
||||
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
@@ -22,6 +23,10 @@ describe("AuthenticationModuleService - AuthProvider", () => {
|
||||
schema: process.env.MEDUSA_PRICING_DB_SCHEMA,
|
||||
},
|
||||
})
|
||||
|
||||
if(service.__hooks?.onApplicationStart) {
|
||||
await service.__hooks.onApplicationStart()
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -30,7 +35,7 @@ describe("AuthenticationModuleService - AuthProvider", () => {
|
||||
})
|
||||
|
||||
describe("listAuthProviders", () => {
|
||||
it("should list default AuthProviders", async () => {
|
||||
it("should list default AuthProviders registered by loaders", async () => {
|
||||
const authProviders = await service.listAuthProviders()
|
||||
const serialized = JSON.parse(JSON.stringify(authProviders))
|
||||
|
||||
@@ -42,4 +47,22 @@ describe("AuthenticationModuleService - AuthProvider", () => {
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("authenticate", () => {
|
||||
it("authenticate validates that a provider is registered in container", async () => {
|
||||
await createAuthProviders(testManager, [
|
||||
{
|
||||
provider: "notRegistered",
|
||||
name: "test",
|
||||
},
|
||||
])
|
||||
|
||||
const { success, error } = await service.authenticate("notRegistered", {})
|
||||
|
||||
expect(success).toBe(false)
|
||||
expect(error).toEqual(
|
||||
"AuthenticationProvider with for provider: notRegistered wasn't registered in the module. Have you configured your options correctly?"
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
import Scrypt from "scrypt-kdf"
|
||||
|
||||
import { MikroOrmWrapper } from "../../../utils"
|
||||
import { initialize } from "../../../../src"
|
||||
import { DB_URL } from "@medusajs/pricing/integration-tests/utils"
|
||||
import { MedusaModule } from "@medusajs/modules-sdk"
|
||||
import { IAuthenticationModuleService } from "@medusajs/types"
|
||||
import { createAuthUsers } from "../../../__fixtures__/auth-user"
|
||||
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
|
||||
|
||||
jest.setTimeout(30000)
|
||||
const seedDefaultData = async (testManager) => {
|
||||
await createAuthProviders(testManager)
|
||||
await createAuthUsers(testManager)
|
||||
}
|
||||
|
||||
describe("AuthenticationModuleService - AuthProvider", () => {
|
||||
let service: IAuthenticationModuleService
|
||||
let testManager: SqlEntityManager
|
||||
|
||||
beforeEach(async () => {
|
||||
await MikroOrmWrapper.setupDatabase()
|
||||
testManager = MikroOrmWrapper.forkManager()
|
||||
|
||||
service = await initialize({
|
||||
database: {
|
||||
clientUrl: DB_URL,
|
||||
schema: process.env.MEDUSA_PRICING_DB_SCHEMA,
|
||||
},
|
||||
})
|
||||
|
||||
if(service.__hooks?.onApplicationStart) {
|
||||
await service.__hooks.onApplicationStart()
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await MikroOrmWrapper.clearDatabase()
|
||||
MedusaModule.clearInstances()
|
||||
})
|
||||
|
||||
describe("authenticate", () => {
|
||||
it("authenticate validates that a provider is registered in container", async () => {
|
||||
const password = "supersecret"
|
||||
const email = "test@test.com"
|
||||
const passwordHash = (
|
||||
await Scrypt.kdf(password, { logN: 15, r: 8, p: 1 })
|
||||
).toString("base64")
|
||||
|
||||
await seedDefaultData(testManager)
|
||||
await createAuthUsers(testManager, [
|
||||
// Add authenticated user
|
||||
{
|
||||
provider: "usernamePassword",
|
||||
entity_id: email,
|
||||
provider_metadata: {
|
||||
password: passwordHash,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const res = await service.authenticate("usernamePassword", {
|
||||
body: {
|
||||
email: "test@test.com",
|
||||
password: password,
|
||||
},
|
||||
})
|
||||
|
||||
expect(res).toEqual({
|
||||
success: true,
|
||||
authUser: expect.objectContaining({
|
||||
entity_id: email,
|
||||
provider_metadata: {
|
||||
},
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
it("fails when no password is given", async () => {
|
||||
const email = "test@test.com"
|
||||
|
||||
await seedDefaultData(testManager)
|
||||
|
||||
const res = await service.authenticate("usernamePassword", {
|
||||
body: { email: "test@test.com" },
|
||||
})
|
||||
|
||||
expect(res).toEqual({
|
||||
success: false,
|
||||
error: "Password should be a string",
|
||||
})
|
||||
})
|
||||
|
||||
it("fails when no email is given", async () => {
|
||||
await seedDefaultData(testManager)
|
||||
|
||||
const res = await service.authenticate("usernamePassword", {
|
||||
body: { password: "supersecret" },
|
||||
})
|
||||
|
||||
expect(res).toEqual({
|
||||
success: false,
|
||||
error: "Email should be a string",
|
||||
})
|
||||
})
|
||||
|
||||
it("fails with an invalid password", async () => {
|
||||
const password = "supersecret"
|
||||
const email = "test@test.com"
|
||||
const passwordHash = (
|
||||
await Scrypt.kdf(password, { logN: 15, r: 8, p: 1 })
|
||||
).toString("base64")
|
||||
|
||||
await seedDefaultData(testManager)
|
||||
await createAuthUsers(testManager, [
|
||||
// Add authenticated user
|
||||
{
|
||||
provider: "usernamePassword",
|
||||
entity_id: email,
|
||||
provider_metadata: {
|
||||
password_hash: passwordHash,
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const res = await service.authenticate("usernamePassword", {
|
||||
body: {
|
||||
email: "test@test.com",
|
||||
password: "password",
|
||||
},
|
||||
})
|
||||
|
||||
expect(res).toEqual({
|
||||
success: false,
|
||||
error: "Invalid email or password",
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -56,6 +56,7 @@
|
||||
"@mikro-orm/postgresql": "5.9.7",
|
||||
"awilix": "^8.0.0",
|
||||
"dotenv": "^16.1.4",
|
||||
"knex": "2.4.2"
|
||||
"knex": "2.4.2",
|
||||
"scrypt-kdf": "^2.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import {
|
||||
ExternalModuleDeclaration,
|
||||
InternalModuleDeclaration,
|
||||
MedusaModule,
|
||||
MODULE_PACKAGE_NAMES,
|
||||
MedusaModule,
|
||||
Modules,
|
||||
} from "@medusajs/modules-sdk"
|
||||
import { IAuthenticationModuleService, ModulesSdkTypes } from "@medusajs/types"
|
||||
import { moduleDefinition } from "../module-definition"
|
||||
|
||||
import { InitializeModuleInjectableDependencies } from "../types"
|
||||
import { moduleDefinition } from "../module-definition"
|
||||
|
||||
export const initialize = async (
|
||||
options?:
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { LoaderOptions, ModulesSdkTypes } from "@medusajs/types"
|
||||
import { asClass } from "awilix"
|
||||
import * as defaultProviders from "@providers"
|
||||
import { AuthProviderService } from "@services"
|
||||
import { ServiceTypes } from "@types"
|
||||
|
||||
import { LoaderOptions, ModulesSdkTypes } from "@medusajs/types"
|
||||
|
||||
import { AwilixContainer, ClassOrFunctionReturning, Resolver, asClass, asFunction, asValue } from "awilix"
|
||||
|
||||
export default async ({
|
||||
container,
|
||||
options,
|
||||
}: LoaderOptions<
|
||||
| ModulesSdkTypes.ModuleServiceInitializeOptions
|
||||
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
|
||||
@@ -17,33 +16,22 @@ export default async ({
|
||||
|
||||
const providersToLoad = Object.values(defaultProviders)
|
||||
|
||||
const authProviderService: AuthProviderService =
|
||||
container.cradle["authProviderService"]
|
||||
|
||||
const providers = await authProviderService.list({
|
||||
provider: providersToLoad.map((p) => p.PROVIDER),
|
||||
})
|
||||
|
||||
const loadedProviders = new Map(providers.map((p) => [p.provider, p]))
|
||||
|
||||
const providersToCreate: ServiceTypes.CreateAuthProviderDTO[] = []
|
||||
|
||||
for (const provider of providersToLoad) {
|
||||
container.registerAdd("providers", asClass(provider).singleton())
|
||||
|
||||
container.register({
|
||||
[`provider_${provider.PROVIDER}`]: asClass(provider).singleton(),
|
||||
})
|
||||
|
||||
if (loadedProviders.has(provider.PROVIDER)) {
|
||||
continue
|
||||
}
|
||||
|
||||
providersToCreate.push({
|
||||
provider: provider.PROVIDER,
|
||||
name: provider.DISPLAY_NAME,
|
||||
[`auth_provider_${provider.PROVIDER}`]: asClass(provider).singleton(),
|
||||
})
|
||||
}
|
||||
|
||||
await authProviderService.create(providersToCreate)
|
||||
container.register({
|
||||
[`auth_providers`]: asArray(providersToLoad),
|
||||
})
|
||||
}
|
||||
|
||||
function asArray(
|
||||
resolvers: (ClassOrFunctionReturning<unknown> | Resolver<unknown>)[]
|
||||
): { resolve: (container: AwilixContainer) => unknown[] } {
|
||||
return {
|
||||
resolve: (container: AwilixContainer) =>
|
||||
resolvers.map((resolver) => container.build(resolver)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,15 @@
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"entity_id": {
|
||||
"name": "entity_id",
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": false,
|
||||
"mappedType": "text"
|
||||
},
|
||||
"provider_id": {
|
||||
"name": "provider_id",
|
||||
"type": "text",
|
||||
@@ -117,6 +126,16 @@
|
||||
"name": "auth_user",
|
||||
"schema": "public",
|
||||
"indexes": [
|
||||
{
|
||||
"keyName": "IDX_auth_user_provider_entity_id",
|
||||
"columnNames": [
|
||||
"provider_id",
|
||||
"entity_id"
|
||||
],
|
||||
"composite": true,
|
||||
"primary": false,
|
||||
"unique": true
|
||||
},
|
||||
{
|
||||
"keyName": "auth_user_pkey",
|
||||
"columnNames": [
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Migration } from '@mikro-orm/migrations';
|
||||
|
||||
export class Migration20240115092929 extends Migration {
|
||||
|
||||
async up(): Promise<void> {
|
||||
this.addSql('alter table "auth_user" add column "entity_id" text not null;');
|
||||
this.addSql('alter table "auth_user" add constraint "IDX_auth_user_provider_entity_id" unique ("provider_id", "entity_id");');
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
this.addSql('alter table "auth_user" drop constraint "IDX_auth_user_provider_entity_id";');
|
||||
this.addSql('alter table "auth_user" drop column "entity_id";');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +1,32 @@
|
||||
import { generateEntityId } from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Cascade,
|
||||
Entity,
|
||||
Index,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
OptionalProps,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
Unique,
|
||||
} from "@mikro-orm/core"
|
||||
|
||||
import AuthProvider from "./auth-provider"
|
||||
import { generateEntityId } from "@medusajs/utils"
|
||||
|
||||
type OptionalFields = "provider_metadata" | "app_metadata" | "user_metadata"
|
||||
|
||||
@Entity()
|
||||
@Unique({ properties: ["provider","entity_id" ], name: "IDX_auth_user_provider_entity_id" })
|
||||
export default class AuthUser {
|
||||
[OptionalProps]: OptionalFields
|
||||
|
||||
@PrimaryKey({ columnType: "text" })
|
||||
id!: string
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
entity_id: string
|
||||
|
||||
@ManyToOne(() => AuthProvider, {
|
||||
joinColumn: "provider",
|
||||
fieldName: "provider_id",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import {
|
||||
AbstractAuthenticationModuleProvider,
|
||||
AuthenticationResponse,
|
||||
} from "@medusajs/types"
|
||||
|
||||
import { AuthUserService } from "@services"
|
||||
import { AbstractAuthenticationModuleProvider } from "@medusajs/types"
|
||||
import Scrypt from "scrypt-kdf"
|
||||
import { isString } from "@medusajs/utils"
|
||||
|
||||
class UsernamePasswordProvider extends AbstractAuthenticationModuleProvider {
|
||||
public static PROVIDER = "usernamePassword"
|
||||
@@ -13,8 +19,48 @@ class UsernamePasswordProvider extends AbstractAuthenticationModuleProvider {
|
||||
this.authUserSerivce_ = AuthUserService
|
||||
}
|
||||
|
||||
async authenticate(userData: Record<string, unknown>) {
|
||||
return {}
|
||||
async authenticate(
|
||||
userData: Record<string, any>
|
||||
): Promise<AuthenticationResponse> {
|
||||
const { email, password } = userData.body
|
||||
|
||||
if (!password || !isString(password)) {
|
||||
return {
|
||||
success: false,
|
||||
error: "Password should be a string",
|
||||
}
|
||||
}
|
||||
|
||||
if (!email || !isString(email)) {
|
||||
return {
|
||||
success: false,
|
||||
error: "Email should be a string",
|
||||
}
|
||||
}
|
||||
|
||||
const authUser = await this.authUserSerivce_.retrieveByProviderAndEntityId(
|
||||
email,
|
||||
UsernamePasswordProvider.PROVIDER
|
||||
)
|
||||
|
||||
const password_hash = authUser.provider_metadata?.password
|
||||
|
||||
if (isString(password_hash)) {
|
||||
const buf = Buffer.from(password_hash, "base64")
|
||||
|
||||
const success = await Scrypt.verify(buf, password)
|
||||
|
||||
if (success) {
|
||||
delete authUser.provider_metadata!.password
|
||||
|
||||
return { success, authUser: JSON.parse(JSON.stringify(authUser)) }
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: "Invalid email or password",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
import { AuthenticationTypes, Context, DAL, FindConfig } from "@medusajs/types"
|
||||
import {
|
||||
InjectManager,
|
||||
MedusaContext,
|
||||
MedusaError,
|
||||
ModulesSdkUtils,
|
||||
} from "@medusajs/utils"
|
||||
import { AuthUser } from "@models"
|
||||
|
||||
import { ServiceTypes } from "@types"
|
||||
import { ServiceTypes, RepositoryTypes } from "@types"
|
||||
|
||||
type InjectedDependencies = {
|
||||
authUserRepository: DAL.RepositoryService
|
||||
@@ -16,8 +20,38 @@ export default class AuthUserService<
|
||||
create: ServiceTypes.CreateAuthUserDTO
|
||||
}
|
||||
>(AuthUser)<TEntity> {
|
||||
protected readonly authUserRepository_: RepositoryTypes.IAuthUserRepository<TEntity>
|
||||
constructor(container: InjectedDependencies) {
|
||||
// @ts-ignore
|
||||
super(...arguments)
|
||||
this.authUserRepository_ = container.authUserRepository
|
||||
}
|
||||
|
||||
@InjectManager("authUserRepository_")
|
||||
async retrieveByProviderAndEntityId<
|
||||
TEntityMethod = AuthenticationTypes.AuthUserDTO
|
||||
>(
|
||||
entityId: string,
|
||||
provider: string,
|
||||
config: FindConfig<TEntityMethod> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<TEntity> {
|
||||
const queryConfig = ModulesSdkUtils.buildQuery<TEntity>(
|
||||
{ entity_id: entityId, provider },
|
||||
{ ...config, take: 1 }
|
||||
)
|
||||
const [result] = await this.authUserRepository_.find(
|
||||
queryConfig,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
if (!result) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`AuthUser with entity_id: "${entityId}" and provider: "${provider}" not found`
|
||||
)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import {
|
||||
AbstractAuthenticationModuleProvider,
|
||||
AuthenticationResponse,
|
||||
AuthenticationTypes,
|
||||
Context,
|
||||
DAL,
|
||||
FindConfig,
|
||||
InternalModuleDeclaration,
|
||||
MedusaContainer,
|
||||
ModuleJoinerConfig,
|
||||
} from "@medusajs/types"
|
||||
|
||||
@@ -11,10 +14,12 @@ import { AuthProvider, AuthUser } from "@models"
|
||||
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import { AuthProviderService, AuthUserService } from "@services"
|
||||
|
||||
import {
|
||||
InjectManager,
|
||||
InjectTransactionManager,
|
||||
MedusaContext,
|
||||
MedusaError,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
AuthProviderDTO,
|
||||
@@ -25,6 +30,7 @@ import {
|
||||
FilterableAuthUserProps,
|
||||
UpdateAuthUserDTO,
|
||||
} from "@medusajs/types/dist/authentication/common"
|
||||
import { ServiceTypes } from "@types"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -37,6 +43,15 @@ export default class AuthenticationModuleService<
|
||||
TAuthProvider extends AuthProvider = AuthProvider
|
||||
> implements AuthenticationTypes.IAuthenticationModuleService
|
||||
{
|
||||
__joinerConfig(): ModuleJoinerConfig {
|
||||
return joinerConfig
|
||||
}
|
||||
|
||||
__hooks = {
|
||||
onApplicationStart: async () => await this.createProvidersOnLoad(),
|
||||
}
|
||||
|
||||
protected __container__: MedusaContainer
|
||||
protected baseRepository_: DAL.RepositoryService
|
||||
|
||||
protected authUserService_: AuthUserService<TAuthUser>
|
||||
@@ -50,6 +65,7 @@ export default class AuthenticationModuleService<
|
||||
}: InjectedDependencies,
|
||||
protected readonly moduleDeclaration: InternalModuleDeclaration
|
||||
) {
|
||||
this.__container__ = arguments[0]
|
||||
this.baseRepository_ = baseRepository
|
||||
this.authUserService_ = authUserService
|
||||
this.authProviderService_ = authProviderService
|
||||
@@ -336,7 +352,64 @@ export default class AuthenticationModuleService<
|
||||
await this.authUserService_.delete(ids, sharedContext)
|
||||
}
|
||||
|
||||
__joinerConfig(): ModuleJoinerConfig {
|
||||
return joinerConfig
|
||||
protected getRegisteredAuthenticationProvider(
|
||||
provider: string
|
||||
): AbstractAuthenticationModuleProvider {
|
||||
let containerProvider: AbstractAuthenticationModuleProvider
|
||||
try {
|
||||
containerProvider = this.__container__[`auth_provider_${provider}`]
|
||||
} catch (error) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`AuthenticationProvider with for provider: ${provider} wasn't registered in the module. Have you configured your options correctly?`
|
||||
)
|
||||
}
|
||||
|
||||
return containerProvider
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async authenticate(
|
||||
provider: string,
|
||||
authenticationData: Record<string, unknown>,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<AuthenticationResponse> {
|
||||
let registeredProvider
|
||||
|
||||
try {
|
||||
await this.retrieveAuthProvider(provider, {})
|
||||
|
||||
registeredProvider = this.getRegisteredAuthenticationProvider(provider)
|
||||
|
||||
return await registeredProvider.authenticate(authenticationData)
|
||||
} catch (error) {
|
||||
return { success: false, error: error.message }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async createProvidersOnLoad() {
|
||||
const providersToLoad = this.__container__["auth_providers"]
|
||||
|
||||
const providers = await this.authProviderService_.list({
|
||||
provider: providersToLoad.map((p) => p.provider),
|
||||
})
|
||||
|
||||
const loadedProvidersMap = new Map(providers.map((p) => [p.provider, p]))
|
||||
|
||||
const providersToCreate: ServiceTypes.CreateAuthProviderDTO[] = []
|
||||
|
||||
for (const provider of providersToLoad) {
|
||||
if (loadedProvidersMap.has(provider.provider)) {
|
||||
continue
|
||||
}
|
||||
|
||||
providersToCreate.push({
|
||||
provider: provider.provider,
|
||||
name: provider.displayName,
|
||||
})
|
||||
}
|
||||
|
||||
await this.authProviderService_.create(providersToCreate)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { AuthUser } from "@models"
|
||||
|
||||
export type CreateAuthUserDTO = {
|
||||
provider_id: string
|
||||
entity_id: string
|
||||
provider_metadata?: Record<string, unknown>
|
||||
user_metadata?: Record<string, unknown>
|
||||
app_metadata?: Record<string, unknown>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { AuthProviderDTO } from "./auth-provider"
|
||||
export type AuthUserDTO = {
|
||||
id: string
|
||||
provider_id: string
|
||||
entity_id: string
|
||||
provider: AuthProviderDTO
|
||||
provider_metadata?: Record<string, unknown>
|
||||
user_metadata: Record<string, unknown>
|
||||
@@ -10,6 +11,7 @@ export type AuthUserDTO = {
|
||||
}
|
||||
|
||||
export type CreateAuthUserDTO = {
|
||||
entity_id: string
|
||||
provider_id: string
|
||||
provider_metadata?: Record<string, unknown>
|
||||
user_metadata?: Record<string, unknown>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { AuthProviderDTO } from "./auth-provider"
|
||||
export type AuthUserDTO = {
|
||||
id: string
|
||||
provider_id: string
|
||||
entity_id: string
|
||||
provider: AuthProviderDTO
|
||||
provider_metadata?: Record<string, unknown>
|
||||
user_metadata: Record<string, unknown>
|
||||
@@ -12,6 +13,7 @@ export type AuthUserDTO = {
|
||||
|
||||
export type CreateAuthUserDTO = {
|
||||
provider_id: string
|
||||
entity_id: string
|
||||
provider_metadata?: Record<string, unknown>
|
||||
user_metadata?: Record<string, unknown>
|
||||
app_metadata?: Record<string, unknown>
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
import { AuthUserDTO } from "./common"
|
||||
|
||||
export abstract class AbstractAuthenticationModuleProvider {
|
||||
public static PROVIDER: string
|
||||
public static DISPLAY_NAME: string
|
||||
|
||||
public get provider() {
|
||||
return (this.constructor as Function & { PROVIDER: string}).PROVIDER
|
||||
}
|
||||
|
||||
public get displayName() {
|
||||
return (this.constructor as Function & { DISPLAY_NAME: string}).DISPLAY_NAME
|
||||
}
|
||||
|
||||
abstract authenticate(
|
||||
data: Record<string, unknown>
|
||||
): Promise<Record<string, unknown>>
|
||||
): Promise<AuthenticationResponse>
|
||||
}
|
||||
|
||||
export type AuthenticationResponse = {
|
||||
success: boolean
|
||||
authUser?: AuthUserDTO
|
||||
error?: string
|
||||
}
|
||||
|
||||
@@ -11,8 +11,14 @@ import {
|
||||
} from "./common"
|
||||
import { FindConfig } from "../common"
|
||||
import { Context } from "../shared-context"
|
||||
import { AuthenticationResponse } from "./provider"
|
||||
|
||||
export interface IAuthenticationModuleService extends IModuleService {
|
||||
authenticate(
|
||||
provider: string,
|
||||
providerData: Record<string, unknown>
|
||||
): Promise<AuthenticationResponse>
|
||||
|
||||
retrieveAuthProvider(
|
||||
provider: string,
|
||||
config?: FindConfig<AuthProviderDTO>,
|
||||
|
||||
Reference in New Issue
Block a user