Feat(authentication): Load auth providers (#6023)

* initial providers loader implementation

* registerAdd providers

* remove comment

* remove comment
This commit is contained in:
Philip Korsholm
2024-01-09 10:02:02 +01:00
committed by GitHub
parent fe81a5e49a
commit f065581736
11 changed files with 148 additions and 15 deletions

View File

@@ -37,20 +37,22 @@ describe("AuthenticationModuleService - AuthProvider", () => {
const authProviders = await service.listAuthProviders()
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(serialized).toEqual([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "disabled",
}),
expect.objectContaining({
provider: "store",
}),
expect.objectContaining({
provider: "admin",
}),
])
expect(serialized).toEqual(
expect.arrayContaining([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "disabled",
}),
expect.objectContaining({
provider: "store",
}),
expect.objectContaining({
provider: "admin",
}),
])
)
})
it("should list authProviders by id", async () => {

View File

@@ -0,0 +1,45 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
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"
jest.setTimeout(30000)
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,
},
})
})
afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
MedusaModule.clearInstances()
})
describe("listAuthProviders", () => {
it("should list default AuthProviders", async () => {
const authProviders = await service.listAuthProviders()
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(serialized).toEqual([
expect.objectContaining({
provider: "usernamePassword",
name: "Username/Password Authentication",
}),
])
})
})
})

View File

@@ -4,6 +4,7 @@ module.exports = {
"^@services": "<rootDir>/src/services",
"^@repositories": "<rootDir>/src/repositories",
"^@types": "<rootDir>/src/types",
"^@providers": "<rootDir>/src/providers",
},
transform: {
"^.+\\.[jt]s?$": [

View File

@@ -1,2 +1,3 @@
export * from "./connection"
export * from "./container"
export * from "./providers"

View File

@@ -0,0 +1,49 @@
import { LoaderOptions, ModulesSdkTypes } from "@medusajs/types"
import { asClass } from "awilix"
import * as defaultProviders from "@providers"
import { AuthProviderService } from "@services"
import { ServiceTypes } from "@types"
export default async ({
container,
options,
}: LoaderOptions<
| ModulesSdkTypes.ModuleServiceInitializeOptions
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions
>): Promise<void> => {
// if(options.providers?.length) {
// TODO: implement plugin provider registration
// }
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,
})
}
await authProviderService.create(providersToCreate)
}

View File

@@ -2,9 +2,10 @@ import { ModuleExports } from "@medusajs/types"
import { AuthenticationModuleService } from "@services"
import loadConnection from "./loaders/connection"
import loadContainer from "./loaders/container"
import loadProviders from "./loaders/providers"
const service = AuthenticationModuleService
const loaders = [loadContainer, loadConnection] as any
const loaders = [loadContainer, loadConnection, loadProviders] as any
export const moduleDefinition: ModuleExports = {
service,

View File

@@ -0,0 +1 @@
export { default as UsernamePasswordProvider } from "./username-password"

View File

@@ -0,0 +1,21 @@
import { AuthUserService } from "@services"
import { AbstractAuthenticationModuleProvider } from "@medusajs/types"
class UsernamePasswordProvider extends AbstractAuthenticationModuleProvider {
public static PROVIDER = "usernamePassword"
public static DISPLAY_NAME = "Username/Password Authentication"
protected readonly authUserSerivce_: AuthUserService
constructor({ authUserService: AuthUserService }) {
super()
this.authUserSerivce_ = AuthUserService
}
async authenticate(userData: Record<string, unknown>) {
return {}
}
}
export default UsernamePasswordProvider

View File

@@ -34,6 +34,9 @@
],
"@types": [
"./src/types"
],
"@providers": [
"./src/providers"
]
}
},

View File

@@ -1,2 +1,3 @@
export * from "./service"
export * from "./common"
export * from "./provider"

View File

@@ -0,0 +1,8 @@
export abstract class AbstractAuthenticationModuleProvider {
public static PROVIDER: string
public static DISPLAY_NAME: string
abstract authenticate(
data: Record<string, unknown>
): Promise<Record<string, unknown>>
}