feat(authentication, types): Create authentication entities and services (#5979)

* create authentication entities

* ensure hashes are not returned

* re-add integration test argument

* update filterableprops

* update type

* pr feedback

* update serialization

* move finding existing entities and validation to service layer

* update types

* update models

* update user model

* pr feedback

* fix build

* pr feedback

* update integration test fixtures

---------

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Philip Korsholm
2024-01-08 09:50:12 +01:00
committed by GitHub
parent 6b0b3fed7a
commit 479a8b82a9
36 changed files with 2394 additions and 32 deletions

View File

@@ -0,0 +1,41 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AuthProvider } from "@models"
export async function createAuthProviders(
manager: SqlEntityManager,
providerData: any[] = [
{
provider: "manual",
name: "manual",
is_active: true,
},
{
provider: "disabled",
name: "disabled",
},
{
provider: "store",
name: "store",
domain: "store",
is_active: true,
},
{
provider: "admin",
name: "admin",
domain: "admin",
is_active: true,
},
]
): Promise<AuthProvider[]> {
const authProviders: AuthProvider[] = []
for (const provider of providerData) {
const authProvider = manager.create(AuthProvider, provider)
authProviders.push(authProvider)
}
await manager.persistAndFlush(authProviders)
return authProviders
}

View File

@@ -0,0 +1,31 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AuthUser } from "@models"
export async function createAuthUsers(
manager: SqlEntityManager,
userData: any[] = [
{
id: "test-id",
provider: "manual",
},
{
id: "test-id-1",
provider: "manual",
},
{
provider: "store",
},
]
): Promise<AuthUser[]> {
const authUsers: AuthUser[] = []
for (const user of userData) {
const authUser = manager.create(AuthUser, user)
authUsers.push(authUser)
}
await manager.persistAndFlush(authUsers)
return authUsers
}

View File

@@ -1,5 +0,0 @@
describe("Noop test", () => {
it("noop check", async () => {
expect(true).toBe(true)
})
})

View File

@@ -0,0 +1,270 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AuthProviderRepository } from "@repositories"
import { AuthProviderService } from "@services"
import { MikroOrmWrapper } from "../../../utils"
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
jest.setTimeout(30000)
describe("AuthProvider Service", () => {
let service: AuthProviderService
let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager
beforeEach(async () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager()
const authProviderRepository = new AuthProviderRepository({
manager: repositoryManager,
})
service = new AuthProviderService({
authProviderRepository,
})
await createAuthProviders(testManager)
})
afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
})
describe("list", () => {
it("should list AuthProviders", async () => {
const authProviders = await service.list()
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",
}),
])
})
it("should list authProviders by provider id", async () => {
const authProviders = await service.list({
provider: ["manual"],
})
expect(authProviders).toEqual([
expect.objectContaining({
provider: "manual",
}),
])
})
it("should list active authProviders", async () => {
const authProviders = await service.list({
is_active: true,
})
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(serialized).toEqual([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "store",
}),
expect.objectContaining({
provider: "admin",
}),
])
})
})
describe("listAndCount", () => {
it("should list AuthProviders", async () => {
const [authProviders, count] = await service.listAndCount()
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(count).toEqual(4)
expect(serialized).toEqual([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "disabled",
}),
expect.objectContaining({
provider: "store",
}),
expect.objectContaining({
provider: "admin",
}),
])
})
it("should listAndCount authProviders by provider", async () => {
const [authProviders, count] = await service.listAndCount({
provider: ["manual"],
})
expect(count).toEqual(1)
expect(authProviders).toEqual([
expect.objectContaining({
provider: "manual",
}),
])
})
it("should listAndCount active authProviders", async () => {
const [authProviders, count] = await service.listAndCount({
is_active: true,
})
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(count).toEqual(3)
expect(serialized).toEqual([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "store",
}),
expect.objectContaining({
provider: "admin",
}),
])
})
})
describe("retrieve", () => {
const provider = "manual"
it("should return an authProvider for the given provider", async () => {
const authProvider = await service.retrieve(provider)
expect(authProvider).toEqual(
expect.objectContaining({
provider,
})
)
})
it("should throw an error when an authProvider with the given provider does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"AuthProvider with provider: does-not-exist was not found"
)
})
it("should throw an error when a provider is not provided", async () => {
let error
try {
await service.retrieve(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual('"authProviderProvider" must be defined')
})
it("should return authProvider based on config select param", async () => {
const authProvider = await service.retrieve(provider, {
select: ["provider"],
})
const serialized = JSON.parse(JSON.stringify(authProvider))
expect(serialized).toEqual({
provider,
})
})
})
describe("delete", () => {
const provider = "manual"
it("should delete the authProviders given a provider successfully", async () => {
await service.delete([provider])
const authProviders = await service.list({
provider: [provider],
})
expect(authProviders).toHaveLength(0)
})
})
describe("update", () => {
const provider = "manual"
it("should throw an error when a id does not exist", async () => {
let error
try {
await service.update([
{
provider: "does-not-exist",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual(
'AuthProvider with provider "does-not-exist" not found'
)
})
it("should update authProvider", async () => {
await service.update([
{
provider: "manual",
name: "test",
},
])
const [provider] = await service.list({ provider: ["manual"] })
expect(provider).toEqual(
expect.objectContaining({
name: "test",
})
)
})
})
describe("create", () => {
it("should create a authProvider successfully", async () => {
await service.create([
{
provider: "test",
name: "test provider",
},
])
const [authProvider] = await service.list({
provider: ["test"],
})
expect(authProvider).toEqual(
expect.objectContaining({
provider: "test",
})
)
})
})
})

View File

@@ -0,0 +1,245 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AuthUserRepository } from "@repositories"
import { AuthUserService } from "@services"
import { MikroOrmWrapper } from "../../../utils"
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
import { createAuthUsers } from "../../../__fixtures__/auth-user"
jest.setTimeout(30000)
describe("AuthUser Service", () => {
let service: AuthUserService
let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager
beforeEach(async () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = await MikroOrmWrapper.forkManager()
testManager = await MikroOrmWrapper.forkManager()
const authUserRepository = new AuthUserRepository({
manager: repositoryManager,
})
service = new AuthUserService({
authUserRepository,
})
await createAuthProviders(testManager)
await createAuthUsers(testManager)
})
afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
})
describe("list", () => {
it("should list authUsers", async () => {
const authUsers = await service.list()
const serialized = JSON.parse(JSON.stringify(authUsers))
expect(serialized).toEqual([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "store",
}),
])
})
it("should list authUsers by id", async () => {
const authUsers = await service.list({
id: ["test-id"],
})
expect(authUsers).toEqual([
expect.objectContaining({
id: "test-id",
}),
])
})
it("should list authUsers by provider_id", async () => {
const authUsers = await service.list({
provider_id: "manual",
})
const serialized = JSON.parse(JSON.stringify(authUsers))
expect(serialized).toEqual([
expect.objectContaining({
id: "test-id",
}),
expect.objectContaining({
id: "test-id-1",
}),
])
})
})
describe("listAndCount", () => {
it("should list authUsers", async () => {
const [authUsers, count] = await service.listAndCount()
const serialized = JSON.parse(JSON.stringify(authUsers))
expect(count).toEqual(3)
expect(serialized).toEqual([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "store",
}),
])
})
it("should listAndCount authUsers by provider_id", async () => {
const [authUsers, count] = await service.listAndCount({
provider_id: "manual",
})
expect(count).toEqual(2)
expect(authUsers).toEqual([
expect.objectContaining({
id: "test-id",
}),
expect.objectContaining({
id: "test-id-1",
}),
])
})
})
describe("retrieve", () => {
const id = "test-id"
it("should return an authUser for the given id", async () => {
const authUser = await service.retrieve(id)
expect(authUser).toEqual(
expect.objectContaining({
id,
})
)
})
it("should return authUser based on config select param", async () => {
const authUser = await service.retrieve(id, {
select: ["id"],
})
const serialized = JSON.parse(JSON.stringify(authUser))
expect(serialized).toEqual({
id,
})
})
it("should throw an error when an authUser with the given id does not exist", async () => {
let error
try {
await service.retrieve("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"AuthUser with id: does-not-exist was not found"
)
})
it("should throw an error when a authUserId is not provided", async () => {
let error
try {
await service.retrieve(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual('"authUserId" must be defined')
})
})
describe("delete", () => {
it("should delete the authUsers given an id successfully", async () => {
const id = "test-id"
await service.delete([id])
const authUsers = await service.list({
id: [id],
})
expect(authUsers).toHaveLength(0)
})
})
describe("update", () => {
it("should throw an error when a id does not exist", async () => {
let error
try {
await service.update([
{
id: "does-not-exist",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual(
'AuthUser with id "does-not-exist" not found'
)
})
it("should update authUser", async () => {
const id = "test-id"
await service.update([
{
id,
provider_metadata: { email: "test@email.com" },
},
])
const [authUser] = await service.list({ id: [id] })
expect(authUser).toEqual(
expect.objectContaining({
provider_metadata: { email: "test@email.com" },
})
)
})
})
describe("create", () => {
it("should create a authUser successfully", async () => {
await service.create([
{
id: "test",
provider_id: "manual",
},
])
const [authUser] = await service.list({
id: ["test"],
})
expect(authUser).toEqual(
expect.objectContaining({
id: "test",
})
)
})
})
})

View File

@@ -0,0 +1,272 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { MikroOrmWrapper } from "../../../utils"
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
import { IAuthenticationModuleService } from "@medusajs/types"
import { initialize } from "../../../../src"
import { DB_URL } from "@medusajs/pricing/integration-tests/utils"
import { createAuthUsers } from "../../../__fixtures__/auth-user"
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,
},
})
await createAuthProviders(testManager)
await createAuthUsers(testManager)
})
afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
})
describe("listAuthProviders", () => {
it("should list AuthProviders", async () => {
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",
}),
])
})
it("should list authProviders by id", async () => {
const authProviders = await service.listAuthProviders({
provider: ["manual"],
})
expect(authProviders).toEqual([
expect.objectContaining({
provider: "manual",
}),
])
})
it("should list active authProviders", async () => {
const authProviders = await service.listAuthProviders({
is_active: true,
})
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(serialized).toEqual([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "store",
}),
expect.objectContaining({
provider: "admin",
}),
])
})
})
describe("listAndCountAuthProviders", () => {
it("should list and count AuthProviders", async () => {
const [authProviders, count] = await service.listAndCountAuthProviders()
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(count).toEqual(4)
expect(serialized).toEqual([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "disabled",
}),
expect.objectContaining({
provider: "store",
}),
expect.objectContaining({
provider: "admin",
}),
])
})
it("should list and count authProviders by provider", async () => {
const [authProviders, count] = await service.listAndCountAuthProviders({
provider: ["manual"],
})
expect(count).toEqual(1)
expect(authProviders).toEqual([
expect.objectContaining({
provider: "manual",
}),
])
})
it("should list and count active authProviders", async () => {
const [authProviders, count] = await service.listAndCountAuthProviders({
is_active: true,
})
const serialized = JSON.parse(JSON.stringify(authProviders))
expect(count).toEqual(3)
expect(serialized).toEqual([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "store",
}),
expect.objectContaining({
provider: "admin",
}),
])
})
})
describe("retrieveAuthProvider", () => {
const provider = "manual"
it("should return an authProvider for the given provider", async () => {
const authProvider = await service.retrieveAuthProvider(provider)
expect(authProvider).toEqual(
expect.objectContaining({
provider,
})
)
})
it("should return authProvider based on config select param", async () => {
const authProvider = await service.retrieveAuthProvider(provider, {
select: ["provider"],
})
const serialized = JSON.parse(JSON.stringify(authProvider))
expect(serialized).toEqual({
provider,
})
})
it("should throw an error when an authProvider with the given provider does not exist", async () => {
let error
try {
await service.retrieveAuthProvider("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"AuthProvider with provider: does-not-exist was not found"
)
})
it("should throw an error when a provider is not provided", async () => {
let error
try {
await service.retrieveAuthProvider(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual('"authProviderProvider" must be defined')
})
})
describe("deleteAuthProvider", () => {
const provider = "manual"
it("should delete the authProviders given a provider successfully", async () => {
await service.deleteAuthProvider([provider])
const authProviders = await service.listAuthProviders({
provider: [provider],
})
expect(authProviders).toHaveLength(0)
})
})
describe("updateAuthProvider", () => {
const provider = "manual"
it("should throw an error when a id does not exist", async () => {
let error
try {
await service.updateAuthProvider([
{
provider: "does-not-exist",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual(
'AuthProvider with provider "does-not-exist" not found'
)
})
it("should update authProvider", async () => {
await service.updateAuthProvider([
{
provider: "manual",
name: "test",
},
])
const [provider] = await service.listAuthProviders({
provider: ["manual"],
})
expect(provider).toEqual(
expect.objectContaining({
name: "test",
})
)
})
})
describe("createAuthProvider", () => {
it("should create a authProvider successfully", async () => {
await service.createAuthProvider([
{
provider: "test",
name: "test provider",
},
])
const [authProvider] = await service.listAuthProviders({
provider: ["test"],
})
expect(authProvider).toEqual(
expect.objectContaining({
provider: "test",
})
)
})
})
})

View File

@@ -0,0 +1,255 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { MikroOrmWrapper } from "../../../utils"
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
import { createAuthUsers } from "../../../__fixtures__/auth-user"
import { DB_URL } from "@medusajs/pricing/integration-tests/utils"
import { IAuthenticationModuleService } from "@medusajs/types"
import { initialize } from "../../../../src"
jest.setTimeout(30000)
describe("AuthenticationModuleService - AuthUser", () => {
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,
},
})
await createAuthProviders(testManager)
await createAuthUsers(testManager)
})
afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
})
describe("listAuthUsers", () => {
it("should list authUsers", async () => {
const authUsers = await service.listAuthUsers()
const serialized = JSON.parse(JSON.stringify(authUsers))
expect(serialized).toEqual([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "store",
}),
])
})
it("should list authUsers by id", async () => {
const authUsers = await service.listAuthUsers({
id: ["test-id"],
})
expect(authUsers).toEqual([
expect.objectContaining({
id: "test-id",
}),
])
})
it("should list authUsers by provider_id", async () => {
const authUsers = await service.listAuthUsers({
provider_id: "manual",
})
const serialized = JSON.parse(JSON.stringify(authUsers))
expect(serialized).toEqual([
expect.objectContaining({
id: "test-id",
}),
expect.objectContaining({
id: "test-id-1",
}),
])
})
})
describe("listAndCountAuthUsers", () => {
it("should list and count authUsers", async () => {
const [authUsers, count] = await service.listAndCountAuthUsers()
const serialized = JSON.parse(JSON.stringify(authUsers))
expect(count).toEqual(3)
expect(serialized).toEqual([
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "manual",
}),
expect.objectContaining({
provider: "store",
}),
])
})
it("should listAndCount authUsers by provider_id", async () => {
const [authUsers, count] = await service.listAndCountAuthUsers({
provider_id: "manual",
})
expect(count).toEqual(2)
expect(authUsers).toEqual([
expect.objectContaining({
id: "test-id",
}),
expect.objectContaining({
id: "test-id-1",
}),
])
})
})
describe("retrieveAuthUser", () => {
const id = "test-id"
it("should return an authUser for the given id", async () => {
const authUser = await service.retrieveAuthUser(id)
expect(authUser).toEqual(
expect.objectContaining({
id,
})
)
})
it("should throw an error when an authUser with the given id does not exist", async () => {
let error
try {
await service.retrieveAuthUser("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"AuthUser with id: does-not-exist was not found"
)
})
it("should not return an authUser with password hash", async () => {
const authUser = await service.retrieveAuthUser("test-id-1")
expect(authUser).toEqual(
expect.objectContaining({
id: "test-id-1",
})
)
expect(authUser["password_hash"]).toEqual(undefined)
})
it("should throw an error when a authUserId is not provided", async () => {
let error
try {
await service.retrieveAuthUser(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual('"authUserId" must be defined')
})
it("should return authUser based on config select param", async () => {
const authUser = await service.retrieveAuthUser(id, {
select: ["id"],
})
const serialized = JSON.parse(JSON.stringify(authUser))
expect(serialized).toEqual({
id,
})
})
})
describe("deleteAuthUser", () => {
const id = "test-id"
it("should delete the authUsers given an id successfully", async () => {
await service.deleteAuthUser([id])
const authUsers = await service.listAuthUsers({
id: [id],
})
expect(authUsers).toHaveLength(0)
})
})
describe("updateAuthUser", () => {
const id = "test-id"
it("should throw an error when a id does not exist", async () => {
let error
try {
await service.updateAuthUser([
{
id: "does-not-exist",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual(
'AuthUser with id "does-not-exist" not found'
)
})
it("should update authUser", async () => {
await service.updateAuthUser([
{
id,
provider_metadata: { email: "test@email.com" },
},
])
const [authUser] = await service.listAuthUsers({ id: [id] })
expect(authUser).toEqual(
expect.objectContaining({
provider_metadata: { email: "test@email.com" },
})
)
})
})
describe("createAuthUser", () => {
it("should create a authUser successfully", async () => {
await service.createAuthUser([
{
id: "test",
provider_id: "manual",
},
])
const [authUser, count] = await service.listAndCountAuthUsers({
id: ["test"],
})
expect(count).toEqual(1)
expect(authUser[0]).toEqual(
expect.objectContaining({
id: "test",
})
)
})
})
})

View File

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

View File

@@ -10,7 +10,10 @@ import { moduleDefinition } from "../module-definition"
import { InitializeModuleInjectableDependencies } from "../types"
export const initialize = async (
options?: ModulesSdkTypes.ModuleBootstrapDeclaration,
options?:
| ModulesSdkTypes.ModuleBootstrapDeclaration
| ModulesSdkTypes.ModuleServiceInitializeOptions
| ModulesSdkTypes.ModuleServiceInitializeCustomDataLayerOptions,
injectedDependencies?: InitializeModuleInjectableDependencies
): Promise<IAuthenticationModuleService> => {
const loaded = await MedusaModule.bootstrap<IAuthenticationModuleService>({

View File

@@ -1,4 +1,5 @@
import * as defaultRepositories from "@repositories"
import * as defaultServices from "@services"
import { LoaderOptions } from "@medusajs/modules-sdk"
import { ModulesSdkTypes } from "@medusajs/types"
@@ -17,7 +18,10 @@ export default async ({
)?.repositories
container.register({
// authenticationService: asClass(defaultServices.AuthenticationService).singleton(),
authUserService: asClass(defaultServices.AuthUserService).singleton(),
authProviderService: asClass(
defaultServices.AuthProviderService
).singleton(),
})
if (customRepositories) {
@@ -34,5 +38,11 @@ export default async ({
function loadDefaultRepositories({ container }) {
container.register({
baseRepository: asClass(defaultRepositories.BaseRepository).singleton(),
authUserRepository: asClass(
defaultRepositories.AuthUserRepository
).singleton(),
authProviderRepository: asClass(
defaultRepositories.AuthProviderRepository
).singleton(),
})
}

View File

@@ -4,6 +4,68 @@
],
"name": "public",
"tables": [
{
"columns": {
"provider": {
"name": "provider",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"name": {
"name": "name",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"domain": {
"name": "domain",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"default": "'all'",
"enumItems": [
"all",
"store",
"admin"
],
"mappedType": "enum"
},
"is_active": {
"name": "is_active",
"type": "boolean",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"default": "false",
"mappedType": "boolean"
}
},
"name": "auth_provider",
"schema": "public",
"indexes": [
{
"keyName": "auth_provider_pkey",
"columnNames": [
"provider"
],
"composite": false,
"primary": true,
"unique": true
}
],
"checks": [],
"foreignKeys": {}
},
{
"columns": {
"id": {
@@ -14,6 +76,42 @@
"primary": false,
"nullable": false,
"mappedType": "text"
},
"provider_id": {
"name": "provider_id",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"user_metadata": {
"name": "user_metadata",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
},
"app_metadata": {
"name": "app_metadata",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
},
"provider_metadata": {
"name": "provider_metadata",
"type": "jsonb",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "json"
}
},
"name": "auth_user",
@@ -30,7 +128,20 @@
}
],
"checks": [],
"foreignKeys": {}
"foreignKeys": {
"auth_user_provider_id_foreign": {
"constraintName": "auth_user_provider_id_foreign",
"columnNames": [
"provider_id"
],
"localTableName": "public.auth_user",
"referencedColumnNames": [
"provider"
],
"referencedTableName": "public.auth_provider",
"deleteRule": "cascade"
}
}
}
]
}

View File

@@ -1,13 +0,0 @@
import { Migration } from '@mikro-orm/migrations';
export class Migration20231220132440 extends Migration {
async up(): Promise<void> {
this.addSql('create table "auth_user" ("id" text not null, constraint "auth_user_pkey" primary key ("id"));');
}
async down(): Promise<void> {
this.addSql('drop table if exists "auth_user" cascade;');
}
}

View File

@@ -0,0 +1,21 @@
import { Migration } from '@mikro-orm/migrations';
export class Migration20240104154451 extends Migration {
async up(): Promise<void> {
this.addSql('create table "auth_provider" ("provider" text not null, "name" text not null, "domain" text check ("domain" in (\'all\', \'store\', \'admin\')) not null default \'all\', "is_active" boolean not null default false, constraint "auth_provider_pkey" primary key ("provider"));');
this.addSql('create table "auth_user" ("id" text not null, "provider_id" text null, "user_metadata" jsonb null, "app_metadata" jsonb null, "provider_metadata" jsonb null, constraint "auth_user_pkey" primary key ("id"));');
this.addSql('alter table "auth_user" add constraint "auth_user_provider_id_foreign" foreign key ("provider_id") references "auth_provider" ("provider") on delete cascade;');
}
async down(): Promise<void> {
this.addSql('alter table "auth_user" drop constraint "auth_user_provider_id_foreign";');
this.addSql('drop table if exists "auth_provider" cascade;');
this.addSql('drop table if exists "auth_user" cascade;');
}
}

View File

@@ -0,0 +1,27 @@
import {
Entity,
Enum,
OptionalProps,
PrimaryKey,
Property,
} from "@mikro-orm/core"
import { ProviderDomain } from "../types/repositories/auth-provider"
type OptionalFields = "domain" | "is_active"
@Entity()
export default class AuthProvider {
[OptionalProps]: OptionalFields
@PrimaryKey({ columnType: "text" })
provider!: string
@Property({ columnType: "text" })
name: string
@Enum({ items: () => ProviderDomain, default: ProviderDomain.ALL })
domain: ProviderDomain = ProviderDomain.ALL
@Property({ columnType: "boolean", default: false })
is_active = false
}

View File

@@ -1,11 +1,41 @@
import { generateEntityId } from "@medusajs/utils"
import { BeforeCreate, Entity, OnInit, PrimaryKey } from "@mikro-orm/core"
import {
BeforeCreate,
Cascade,
Entity,
ManyToOne,
OnInit,
OptionalProps,
PrimaryKey,
Property,
} from "@mikro-orm/core"
import AuthProvider from "./auth-provider"
type OptionalFields = "provider_metadata" | "app_metadata" | "user_metadata"
@Entity()
export default class AuthUser {
[OptionalProps]: OptionalFields
@PrimaryKey({ columnType: "text" })
id!: string
@ManyToOne(() => AuthProvider, {
joinColumn: "provider",
fieldName: "provider_id",
cascade: [Cascade.REMOVE],
})
provider: AuthProvider
@Property({ columnType: "jsonb", nullable: true })
user_metadata: Record<string, unknown> | null
@Property({ columnType: "jsonb", nullable: true })
app_metadata: Record<string, unknown> | null
@Property({ columnType: "jsonb", nullable: true })
provider_metadata: Record<string, unknown> | null
@BeforeCreate()
onCreate() {
this.id = generateEntityId(this.id, "authusr")

View File

@@ -1 +1,2 @@
export { default as AuthUser } from "./auth-user"
export { default as AuthProvider } from "./auth-provider"

View File

@@ -0,0 +1,98 @@
import { Context, DAL } from "@medusajs/types"
import { DALUtils } from "@medusajs/utils"
import {
FilterQuery as MikroFilterQuery,
FindOptions as MikroOptions,
LoadStrategy,
} from "@mikro-orm/core"
import { AuthProvider } from "@models"
import { RepositoryTypes } from "@types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
export class AuthProviderRepository extends DALUtils.MikroOrmBaseRepository {
protected readonly manager_: SqlEntityManager
constructor({ manager }: { manager: SqlEntityManager }) {
// @ts-ignore
// eslint-disable-next-line prefer-rest-params
super(...arguments)
this.manager_ = manager
}
async find(
findOptions: DAL.FindOptions<AuthProvider> = { where: {} },
context: Context = {}
): Promise<AuthProvider[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const findOptions_ = { ...findOptions }
findOptions_.options ??= {}
Object.assign(findOptions_.options, {
strategy: LoadStrategy.SELECT_IN,
})
return await manager.find(
AuthProvider,
findOptions_.where as MikroFilterQuery<AuthProvider>,
findOptions_.options as MikroOptions<AuthProvider>
)
}
async findAndCount(
findOptions: DAL.FindOptions<AuthProvider> = { where: {} },
context: Context = {}
): Promise<[AuthProvider[], number]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const findOptions_ = { ...findOptions }
findOptions_.options ??= {}
Object.assign(findOptions_.options, {
strategy: LoadStrategy.SELECT_IN,
})
return await manager.findAndCount(
AuthProvider,
findOptions_.where as MikroFilterQuery<AuthProvider>,
findOptions_.options as MikroOptions<AuthProvider>
)
}
async delete(ids: string[], context: Context = {}): Promise<void> {
const manager = this.getActiveManager<SqlEntityManager>(context)
await manager.nativeDelete(AuthProvider, { provider: { $in: ids } }, {})
}
async create(
data: RepositoryTypes.CreateAuthProviderDTO[],
context: Context = {}
): Promise<AuthProvider[]> {
const manager: SqlEntityManager =
this.getActiveManager<SqlEntityManager>(context)
const authProviders = data.map((authProviderData) => {
return manager.create(AuthProvider, authProviderData)
})
manager.persist(authProviders)
return authProviders
}
async update(
data: RepositoryTypes.UpdateAuthProviderDTO[],
context: Context = {}
): Promise<AuthProvider[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const authProviders = data.map(({ provider, update }) => {
return manager.assign(provider, update)
})
manager.persist(authProviders)
return authProviders
}
}

View File

@@ -0,0 +1,106 @@
import { Context, DAL } from "@medusajs/types"
import { DALUtils } from "@medusajs/utils"
import {
FilterQuery as MikroFilterQuery,
FindOptions as MikroOptions,
LoadStrategy,
} from "@mikro-orm/core"
import { AuthUser } from "@models"
import { RepositoryTypes } from "@types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
export class AuthUserRepository extends DALUtils.MikroOrmBaseRepository {
protected readonly manager_: SqlEntityManager
constructor({ manager }: { manager: SqlEntityManager }) {
// @ts-ignore
// eslint-disable-next-line prefer-rest-params
super(...arguments)
this.manager_ = manager
}
async find(
findOptions: DAL.FindOptions<AuthUser> = { where: {} },
context: Context = {}
): Promise<AuthUser[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const findOptions_ = { ...findOptions }
findOptions_.options ??= {}
Object.assign(findOptions_.options, {
strategy: LoadStrategy.SELECT_IN,
})
return await manager.find(
AuthUser,
findOptions_.where as MikroFilterQuery<AuthUser>,
findOptions_.options as MikroOptions<AuthUser>
)
}
async findAndCount(
findOptions: DAL.FindOptions<AuthUser> = { where: {} },
context: Context = {}
): Promise<[AuthUser[], number]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const findOptions_ = { ...findOptions }
findOptions_.options ??= {}
Object.assign(findOptions_.options, {
strategy: LoadStrategy.SELECT_IN,
})
return await manager.findAndCount(
AuthUser,
findOptions_.where as MikroFilterQuery<AuthUser>,
findOptions_.options as MikroOptions<AuthUser>
)
}
async delete(ids: string[], context: Context = {}): Promise<void> {
const manager = this.getActiveManager<SqlEntityManager>(context)
await manager.nativeDelete(AuthUser, { id: { $in: ids } }, {})
}
async create(
data: RepositoryTypes.CreateAuthUserDTO[],
context: Context = {}
): Promise<AuthUser[]> {
const manager: SqlEntityManager =
this.getActiveManager<SqlEntityManager>(context)
const toCreate = data.map((authUser) => {
const authUserClone = { ...authUser } as any
authUserClone.provider ??= authUser.provider_id
return authUserClone
})
const authUsers = toCreate.map((authUserData) => {
return manager.create(AuthUser, authUserData)
})
manager.persist(authUsers)
return authUsers
}
async update(
data: RepositoryTypes.UpdateAuthUserDTO[],
context: Context = {}
): Promise<AuthUser[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const authUsers = data.map(({ user, update }) => {
return manager.assign(user, update)
})
manager.persist(authUsers)
return authUsers
}
}

View File

@@ -1 +1,3 @@
export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils"
export { AuthProviderRepository } from "./auth-provider"
export { AuthUserRepository } from "./auth-user"

View File

@@ -0,0 +1,139 @@
import { Context, DAL, FindConfig } from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
MedusaError,
ModulesSdkUtils,
retrieveEntity,
} from "@medusajs/utils"
import { AuthProvider } from "@models"
import { AuthProviderRepository } from "@repositories"
import { RepositoryTypes, ServiceTypes } from "@types"
type InjectedDependencies = {
authProviderRepository: DAL.RepositoryService
}
export default class AuthProviderService<
TEntity extends AuthProvider = AuthProvider
> {
protected readonly authProviderRepository_: DAL.RepositoryService
constructor({ authProviderRepository }: InjectedDependencies) {
this.authProviderRepository_ = authProviderRepository
}
@InjectManager("authProviderRepository_")
async retrieve(
provider: string,
config: FindConfig<ServiceTypes.AuthProviderDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity> {
return (await retrieveEntity<AuthProvider, ServiceTypes.AuthProviderDTO>({
id: provider,
identifierColumn: "provider",
entityName: AuthProvider.name,
repository: this.authProviderRepository_,
config,
sharedContext,
})) as TEntity
}
@InjectManager("authProviderRepository_")
async list(
filters: ServiceTypes.FilterableAuthProviderProps = {},
config: FindConfig<ServiceTypes.AuthProviderDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
const queryConfig = ModulesSdkUtils.buildQuery<AuthProvider>(
filters,
config
)
return (await this.authProviderRepository_.find(
queryConfig,
sharedContext
)) as TEntity[]
}
@InjectManager("authProviderRepository_")
async listAndCount(
filters: ServiceTypes.FilterableAuthProviderProps = {},
config: FindConfig<ServiceTypes.AuthProviderDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<[TEntity[], number]> {
const queryConfig = ModulesSdkUtils.buildQuery<AuthProvider>(
filters,
config
)
return (await this.authProviderRepository_.findAndCount(
queryConfig,
sharedContext
)) as [TEntity[], number]
}
@InjectTransactionManager("authProviderRepository_")
async create(
data: ServiceTypes.CreateAuthProviderDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return (await (
this.authProviderRepository_ as AuthProviderRepository
).create(data, sharedContext)) as TEntity[]
}
@InjectTransactionManager("authProviderRepository_")
async update(
data: ServiceTypes.UpdateAuthProviderDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
const authProviderIds = data.map(
(authProviderData) => authProviderData.provider
)
const existingAuthProviders = await this.list(
{
provider: authProviderIds,
},
{},
sharedContext
)
const updates: RepositoryTypes.UpdateAuthProviderDTO[] = []
const existingAuthProvidersMap = new Map(
existingAuthProviders.map<[string, AuthProvider]>((authProvider) => [
authProvider.provider,
authProvider,
])
)
for (const update of data) {
const provider = existingAuthProvidersMap.get(update.provider)
if (!provider) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`AuthProvider with provider "${update.provider}" not found`
)
}
updates.push({ update, provider })
}
return (await (
this.authProviderRepository_ as AuthProviderRepository
).update(updates, sharedContext)) as TEntity[]
}
@InjectTransactionManager("authProviderRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
await this.authProviderRepository_.delete(ids, sharedContext)
}
}

View File

@@ -0,0 +1,126 @@
import { Context, DAL, FindConfig } from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
MedusaError,
ModulesSdkUtils,
retrieveEntity,
} from "@medusajs/utils"
import { AuthUser } from "@models"
import { AuthUserRepository } from "@repositories"
import { RepositoryTypes, ServiceTypes } from "@types"
type InjectedDependencies = {
authUserRepository: DAL.RepositoryService
}
export default class AuthUserService<TEntity extends AuthUser = AuthUser> {
protected readonly authUserRepository_: DAL.RepositoryService
constructor({ authUserRepository }: InjectedDependencies) {
this.authUserRepository_ = authUserRepository
}
@InjectManager("authUserRepository_")
async retrieve(
provider: string,
config: FindConfig<ServiceTypes.AuthUserDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity> {
return (await retrieveEntity<AuthUser, ServiceTypes.AuthUserDTO>({
id: provider,
entityName: AuthUser.name,
repository: this.authUserRepository_,
config,
sharedContext,
})) as TEntity
}
@InjectManager("authUserRepository_")
async list(
filters: ServiceTypes.FilterableAuthProviderProps = {},
config: FindConfig<ServiceTypes.AuthUserDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
const queryConfig = ModulesSdkUtils.buildQuery<AuthUser>(filters, config)
return (await this.authUserRepository_.find(
queryConfig,
sharedContext
)) as TEntity[]
}
@InjectManager("authUserRepository_")
async listAndCount(
filters: ServiceTypes.FilterableAuthUserProps = {},
config: FindConfig<ServiceTypes.AuthUserDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<[TEntity[], number]> {
const queryConfig = ModulesSdkUtils.buildQuery<AuthUser>(filters, config)
return (await this.authUserRepository_.findAndCount(
queryConfig,
sharedContext
)) as [TEntity[], number]
}
@InjectTransactionManager("authUserRepository_")
async create(
data: ServiceTypes.CreateAuthUserDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return (await (this.authUserRepository_ as AuthUserRepository).create(
data,
sharedContext
)) as TEntity[]
}
@InjectTransactionManager("authUserRepository_")
async update(
data: ServiceTypes.UpdateAuthUserDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
const existingUsers = await this.list(
{ id: data.map(({ id }) => id) },
{},
sharedContext
)
const existingUsersMap = new Map(
existingUsers.map<[string, AuthUser]>((authUser) => [
authUser.id,
authUser,
])
)
const updates: RepositoryTypes.UpdateAuthUserDTO[] = []
for (const update of data) {
const user = existingUsersMap.get(update.id)
if (!user) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`AuthUser with id "${update.id}" not found`
)
}
updates.push({ update, user })
}
return (await (this.authUserRepository_ as AuthUserRepository).update(
updates,
sharedContext
)) as TEntity[]
}
@InjectTransactionManager("authUserRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
await this.authUserRepository_.delete(ids, sharedContext)
}
}

View File

@@ -1,29 +1,339 @@
import {
AuthenticationTypes,
Context,
DAL,
FindConfig,
InternalModuleDeclaration,
ModuleJoinerConfig,
} from "@medusajs/types"
import { AuthUser } from "@models"
import { AuthProvider, AuthUser } from "@models"
import { joinerConfig } from "../joiner-config"
import { AuthProviderService, AuthUserService } from "@services"
import {
InjectManager,
InjectTransactionManager,
MedusaContext,
} from "@medusajs/utils"
import {
AuthProviderDTO,
AuthUserDTO,
CreateAuthProviderDTO,
CreateAuthUserDTO,
FilterableAuthProviderProps,
FilterableAuthUserProps,
UpdateAuthUserDTO,
} from "@medusajs/types/dist/authentication/common"
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
authUserService: AuthUserService<any>
authProviderService: AuthProviderService<any>
}
export default class AuthenticationModuleService<
TAuthUser extends AuthUser = AuthUser
TAuthUser extends AuthUser = AuthUser,
TAuthProvider extends AuthProvider = AuthProvider
> implements AuthenticationTypes.IAuthenticationModuleService
{
protected baseRepository_: DAL.RepositoryService
protected authUserService_: AuthUserService<TAuthUser>
protected authProviderService_: AuthProviderService<TAuthProvider>
constructor(
{ baseRepository }: InjectedDependencies,
{
authUserService,
authProviderService,
baseRepository,
}: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
this.baseRepository_ = baseRepository
this.authUserService_ = authUserService
this.authProviderService_ = authProviderService
}
async retrieveAuthProvider(
provider: string,
config: FindConfig<AuthProviderDTO> = {},
sharedContext: Context = {}
): Promise<AuthProviderDTO> {
const authProvider = await this.authProviderService_.retrieve(
provider,
config,
sharedContext
)
return await this.baseRepository_.serialize<AuthenticationTypes.AuthProviderDTO>(
authProvider,
{ populate: true }
)
}
async listAuthProviders(
filters: FilterableAuthProviderProps = {},
config: FindConfig<AuthProviderDTO> = {},
sharedContext: Context = {}
): Promise<AuthProviderDTO[]> {
const authProviders = await this.authProviderService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<
AuthenticationTypes.AuthProviderDTO[]
>(authProviders, { populate: true })
}
@InjectManager("baseRepository_")
async listAndCountAuthProviders(
filters: FilterableAuthProviderProps = {},
config: FindConfig<AuthProviderDTO>,
@MedusaContext() sharedContext: Context = {}
): Promise<[AuthenticationTypes.AuthProviderDTO[], number]> {
const [authProviders, count] = await this.authProviderService_.listAndCount(
filters,
config,
sharedContext
)
return [
await this.baseRepository_.serialize<
AuthenticationTypes.AuthProviderDTO[]
>(authProviders, { populate: true }),
count,
]
}
async createAuthProvider(
data: CreateAuthProviderDTO[],
sharedContext?: Context
): Promise<AuthProviderDTO[]>
async createAuthProvider(
data: CreateAuthProviderDTO,
sharedContext?: Context
): Promise<AuthProviderDTO>
@InjectManager("baseRepository_")
async createAuthProvider(
data: CreateAuthProviderDTO | CreateAuthProviderDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<
AuthenticationTypes.AuthProviderDTO | AuthenticationTypes.AuthProviderDTO[]
> {
const input = Array.isArray(data) ? data : [data]
const providers = await this.createAuthProviders_(input, sharedContext)
const serializedProviders = await this.baseRepository_.serialize<
AuthenticationTypes.AuthProviderDTO[]
>(providers, {
populate: true,
})
return Array.isArray(data) ? serializedProviders : serializedProviders[0]
}
@InjectTransactionManager("baseRepository_")
protected async createAuthProviders_(
data: any[],
@MedusaContext() sharedContext: Context
): Promise<AuthenticationTypes.AuthProviderDTO[]> {
return await this.authProviderService_.create(data, sharedContext)
}
updateAuthProvider(
data: AuthenticationTypes.UpdateAuthProviderDTO[],
sharedContext?: Context
): Promise<AuthProviderDTO[]>
updateAuthProvider(
data: AuthenticationTypes.UpdateAuthProviderDTO,
sharedContext?: Context
): Promise<AuthProviderDTO>
@InjectManager("baseRepository_")
async updateAuthProvider(
data:
| AuthenticationTypes.UpdateAuthProviderDTO[]
| AuthenticationTypes.UpdateAuthProviderDTO,
@MedusaContext() sharedContext: Context = {}
): Promise<
AuthenticationTypes.AuthProviderDTO | AuthenticationTypes.AuthProviderDTO[]
> {
const input = Array.isArray(data) ? data : [data]
const providers = await this.updateAuthProvider_(input, sharedContext)
const serializedProviders = await this.baseRepository_.serialize<
AuthenticationTypes.AuthProviderDTO[]
>(providers, {
populate: true,
})
return Array.isArray(data) ? serializedProviders : serializedProviders[0]
}
async updateAuthProvider_(
data: AuthenticationTypes.UpdateAuthProviderDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<AuthProviderDTO[]> {
return await this.authProviderService_.update(data, sharedContext)
}
@InjectTransactionManager("baseRepository_")
async deleteAuthProvider(
ids: string[],
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
await this.authProviderService_.delete(ids, sharedContext)
}
@InjectManager("baseRepository_")
async retrieveAuthUser(
id: string,
config: FindConfig<AuthUserDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<AuthUserDTO> {
const authUser = await this.authUserService_.retrieve(
id,
config,
sharedContext
)
return await this.baseRepository_.serialize<AuthenticationTypes.AuthUserDTO>(
authUser,
{
exclude: ["password_hash"],
}
)
}
@InjectManager("baseRepository_")
async listAuthUsers(
filters: FilterableAuthUserProps = {},
config: FindConfig<AuthUserDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<AuthUserDTO[]> {
const authUsers = await this.authUserService_.list(
filters,
config,
sharedContext
)
return await this.baseRepository_.serialize<
AuthenticationTypes.AuthUserDTO[]
>(authUsers, {
populate: true,
})
}
@InjectManager("baseRepository_")
async listAndCountAuthUsers(
filters: FilterableAuthUserProps = {},
config: FindConfig<AuthUserDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<[AuthUserDTO[], number]> {
const [authUsers, count] = await this.authUserService_.listAndCount(
filters,
config,
sharedContext
)
return [
await this.baseRepository_.serialize<AuthenticationTypes.AuthUserDTO[]>(
authUsers,
{
populate: true,
}
),
count,
]
}
createAuthUser(
data: CreateAuthUserDTO[],
sharedContext?: Context
): Promise<AuthUserDTO[]>
createAuthUser(
data: CreateAuthUserDTO,
sharedContext?: Context
): Promise<AuthUserDTO>
@InjectManager("baseRepository_")
async createAuthUser(
data: CreateAuthUserDTO[] | CreateAuthUserDTO,
@MedusaContext() sharedContext: Context = {}
): Promise<
AuthenticationTypes.AuthUserDTO | AuthenticationTypes.AuthUserDTO[]
> {
const input = Array.isArray(data) ? data : [data]
const authUsers = await this.createAuthUsers_(input, sharedContext)
const serializedUsers = await this.baseRepository_.serialize<
AuthenticationTypes.AuthUserDTO[]
>(authUsers, {
populate: true,
})
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
}
@InjectTransactionManager("baseRepository_")
protected async createAuthUsers_(
data: CreateAuthUserDTO[],
@MedusaContext() sharedContext: Context
): Promise<TAuthUser[]> {
return await this.authUserService_.create(data, sharedContext)
}
updateAuthUser(
data: UpdateAuthUserDTO[],
sharedContext?: Context
): Promise<AuthUserDTO[]>
updateAuthUser(
data: UpdateAuthUserDTO,
sharedContext?: Context
): Promise<AuthUserDTO>
@InjectManager("baseRepository_")
async updateAuthUser(
data: UpdateAuthUserDTO | UpdateAuthUserDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<
AuthenticationTypes.AuthUserDTO | AuthenticationTypes.AuthUserDTO[]
> {
const input = Array.isArray(data) ? data : [data]
const updatedUsers = await this.updateAuthUsers_(input, sharedContext)
const serializedUsers = await this.baseRepository_.serialize<
AuthenticationTypes.AuthUserDTO[]
>(updatedUsers, {
populate: true,
})
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
}
@InjectTransactionManager("baseRepository_")
protected async updateAuthUsers_(
data: UpdateAuthUserDTO[],
@MedusaContext() sharedContext: Context
): Promise<TAuthUser[]> {
return await this.authUserService_.update(data, sharedContext)
}
@InjectTransactionManager("baseRepository_")
async deleteAuthUser(
ids: string[],
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
await this.authUserService_.delete(ids, sharedContext)
}
__joinerConfig(): ModuleJoinerConfig {

View File

@@ -1 +1,3 @@
export { default as AuthenticationModuleService } from "./authentication-module"
export { default as AuthProviderService } from "./auth-provider"
export { default as AuthUserService } from "./auth-user"

View File

@@ -3,3 +3,6 @@ import { Logger } from "@medusajs/types"
export type InitializeModuleInjectableDependencies = {
logger?: Logger
}
export * as RepositoryTypes from "./repositories"
export * as ServiceTypes from "./services"

View File

@@ -0,0 +1,24 @@
import { AuthProvider } from "@models"
export type CreateAuthProviderDTO = {
provider: string
name: string
domain?: ProviderDomain
is_active?: boolean
}
export type UpdateAuthProviderDTO = {
update: {
provider: string
name?: string
domain?: ProviderDomain
is_active?: boolean
}
provider: AuthProvider
}
export enum ProviderDomain {
ALL = "all",
STORE = "store",
ADMIN = "admin",
}

View File

@@ -0,0 +1,18 @@
import { AuthUser } from "@models"
export type CreateAuthUserDTO = {
provider_id: string
provider_metadata?: Record<string, unknown>
user_metadata?: Record<string, unknown>
app_metadata?: Record<string, unknown>
}
export type UpdateAuthUserDTO = {
update: {
id: string
provider_metadata?: Record<string, unknown>
user_metadata?: Record<string, unknown>
app_metadata?: Record<string, unknown>
}
user: AuthUser
}

View File

@@ -0,0 +1,2 @@
export * from "./auth-user"
export * from "./auth-provider"

View File

@@ -0,0 +1,28 @@
export type AuthProviderDTO = {
provider: string
name: string
domain: ProviderDomain
is_active: boolean
}
export type CreateAuthProviderDTO = {
provider: string
name: string
domain?: ProviderDomain
is_active?: boolean
}
export type UpdateAuthProviderDTO = {
provider: string
name?: string
domain?: ProviderDomain
is_active?: boolean
}
export enum ProviderDomain {
ALL = "all",
STORE = "store",
ADMIN = "admin",
}
export type FilterableAuthProviderProps = {}

View File

@@ -0,0 +1,26 @@
import { AuthProviderDTO } from "./auth-provider"
export type AuthUserDTO = {
id: string
provider_id: string
provider: AuthProviderDTO
provider_metadata?: Record<string, unknown>
user_metadata: Record<string, unknown>
app_metadata: Record<string, unknown>
}
export type CreateAuthUserDTO = {
provider_id: string
provider_metadata?: Record<string, unknown>
user_metadata?: Record<string, unknown>
app_metadata?: Record<string, unknown>
}
export type UpdateAuthUserDTO = {
id: string
provider_metadata?: Record<string, unknown>
user_metadata?: Record<string, unknown>
app_metadata?: Record<string, unknown>
}
export type FilterableAuthUserProps = {}

View File

@@ -0,0 +1,2 @@
export * from "./auth-user"
export * from "./auth-provider"

View File

@@ -1,6 +1,8 @@
{
"compilerOptions": {
"lib": ["es2020"],
"lib": [
"es2020"
],
"target": "es2020",
"outDir": "./dist",
"esModuleInterop": true,
@@ -16,16 +18,28 @@
"noImplicitThis": true,
"allowJs": true,
"skipLibCheck": true,
"downlevelIteration": true, // to use ES5 specific tooling
"downlevelIteration": true,
// to use ES5 specific tooling
"baseUrl": ".",
"resolveJsonModule": true,
"paths": {
"@models": ["./src/models"],
"@services": ["./src/services"],
"@repositories": ["./src/repositories"]
"@models": [
"./src/models"
],
"@services": [
"./src/services"
],
"@repositories": [
"./src/repositories"
],
"@types": [
"./src/types"
]
}
},
"include": ["src"],
"include": [
"src"
],
"exclude": [
"dist",
"./src/**/__tests__",

View File

@@ -0,0 +1,36 @@
import { BaseFilterable } from "../../dal"
export type AuthProviderDTO = {
provider: string
name: string
domain: ProviderDomain
is_active: boolean
}
export type CreateAuthProviderDTO = {
provider: string
name: string
domain?: ProviderDomain
is_active?: boolean
}
export type UpdateAuthProviderDTO = {
provider: string
name?: string
domain?: ProviderDomain
is_active?: boolean
}
export enum ProviderDomain {
ALL = "all",
STORE = "store",
ADMIN = "admin",
}
export interface FilterableAuthProviderProps
extends BaseFilterable<FilterableAuthProviderProps> {
provider?: string[]
is_active?: boolean
domain?: ProviderDomain[]
name?: string[]
}

View File

@@ -0,0 +1,31 @@
import { BaseFilterable } from "../../dal"
import { AuthProviderDTO } from "./auth-provider"
export type AuthUserDTO = {
id: string
provider_id: string
provider: AuthProviderDTO
provider_metadata?: Record<string, unknown>
user_metadata: Record<string, unknown>
app_metadata: Record<string, unknown>
}
export type CreateAuthUserDTO = {
provider_id: string
provider_metadata?: Record<string, unknown>
user_metadata?: Record<string, unknown>
app_metadata?: Record<string, unknown>
}
export type UpdateAuthUserDTO = {
id: string
provider_metadata?: Record<string, unknown>
user_metadata?: Record<string, unknown>
app_metadata?: Record<string, unknown>
}
export interface FilterableAuthUserProps
extends BaseFilterable<FilterableAuthUserProps> {
id?: string[]
provider?: string[] | string
}

View File

@@ -0,0 +1,2 @@
export * from "./auth-user"
export * from "./auth-provider"

View File

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

View File

@@ -1,3 +1,95 @@
import { IModuleService } from "../modules-sdk"
import {
AuthProviderDTO,
AuthUserDTO,
CreateAuthProviderDTO,
CreateAuthUserDTO,
FilterableAuthProviderProps,
FilterableAuthUserProps,
UpdateAuthProviderDTO,
UpdateAuthUserDTO,
} from "./common"
import { FindConfig } from "../common"
import { Context } from "../shared-context"
export interface IAuthenticationModuleService extends IModuleService {}
export interface IAuthenticationModuleService extends IModuleService {
retrieveAuthProvider(
provider: string,
config?: FindConfig<AuthProviderDTO>,
sharedContext?: Context
): Promise<AuthProviderDTO>
listAuthProviders(
filters?: FilterableAuthProviderProps,
config?: FindConfig<AuthProviderDTO>,
sharedContext?: Context
): Promise<AuthProviderDTO[]>
listAndCountAuthProviders(
filters?: FilterableAuthProviderProps,
config?: FindConfig<AuthProviderDTO>,
sharedContext?: Context
): Promise<[AuthProviderDTO[], number]>
createAuthProvider(
data: CreateAuthProviderDTO[],
sharedContext?: Context
): Promise<AuthProviderDTO[]>
createAuthProvider(
data: CreateAuthProviderDTO,
sharedContext?: Context
): Promise<AuthProviderDTO>
updateAuthProvider(
data: UpdateAuthProviderDTO[],
sharedContext?: Context
): Promise<AuthProviderDTO[]>
updateAuthProvider(
data: UpdateAuthProviderDTO,
sharedContext?: Context
): Promise<AuthProviderDTO>
deleteAuthProvider(ids: string[], sharedContext?: Context): Promise<void>
retrieveAuthUser(
id: string,
config?: FindConfig<AuthUserDTO>,
sharedContext?: Context
): Promise<AuthUserDTO>
listAuthUsers(
filters?: FilterableAuthProviderProps,
config?: FindConfig<AuthUserDTO>,
sharedContext?: Context
): Promise<AuthUserDTO[]>
listAndCountAuthUsers(
filters?: FilterableAuthUserProps,
config?: FindConfig<AuthUserDTO>,
sharedContext?: Context
): Promise<[AuthUserDTO[], number]>
createAuthUser(
data: CreateAuthUserDTO[],
sharedContext?: Context
): Promise<AuthUserDTO[]>
createAuthUser(
data: CreateAuthUserDTO,
sharedContext?: Context
): Promise<AuthUserDTO>
updateAuthUser(
data: UpdateAuthUserDTO[],
sharedContext?: Context
): Promise<AuthUserDTO[]>
updateAuthUser(
data: UpdateAuthUserDTO,
sharedContext?: Context
): Promise<AuthUserDTO>
deleteAuthUser(ids: string[], sharedContext?: Context): Promise<void>
}