feat(auth): Revamp authentication setup (#7387)

* chore: Clean up authentication middlewares

* chore: Rename AuthUser to AuthIdentity

* feat: Define link between user, customer, and auth identity

* feat: Use links for auth, update auth context content

* fix: Adjust user create command with new auth setup

* fix: Make auth login more dynamic, review fixes

* fix: Change test assertions for created by
This commit is contained in:
Stevche Radevski
2024-05-22 10:27:32 +02:00
committed by GitHub
parent b7df447682
commit 5ede560f70
88 changed files with 887 additions and 1014 deletions

View File

@@ -11,40 +11,42 @@ import {
MedusaError,
ModulesSdkUtils,
} from "@medusajs/utils"
import { AuthUser } from "@models"
import { AuthIdentity } from "@models"
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
authUserRepository: DAL.RepositoryService
authIdentityRepository: DAL.RepositoryService
}
export default class AuthUserService<
TEntity extends AuthUser = AuthUser
export default class AuthIdentityService<
TEntity extends AuthIdentity = AuthIdentity
> extends ModulesSdkUtils.internalModuleServiceFactory<InjectedDependencies>(
AuthUser
AuthIdentity
)<TEntity> {
protected readonly authUserRepository_: RepositoryService<TEntity>
protected readonly authIdentityRepository_: RepositoryService<TEntity>
protected baseRepository_: DAL.RepositoryService
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
this.authUserRepository_ = container.authUserRepository
this.authIdentityRepository_ = container.authIdentityRepository
this.baseRepository_ = container.baseRepository
}
@InjectManager("authUserRepository_")
async retrieveByProviderAndEntityId<TEntityMethod = AuthTypes.AuthUserDTO>(
@InjectManager("authIdentityRepository_")
async retrieveByProviderAndEntityId<
TEntityMethod = AuthTypes.AuthIdentityDTO
>(
entityId: string,
provider: string,
config: FindConfig<TEntityMethod> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<AuthTypes.AuthUserDTO> {
): Promise<AuthTypes.AuthIdentityDTO> {
const queryConfig = ModulesSdkUtils.buildQuery<TEntity>(
{ entity_id: entityId, provider },
{ ...config, take: 1 }
)
const [result] = await this.authUserRepository_.find(
const [result] = await this.authIdentityRepository_.find(
queryConfig,
sharedContext
)
@@ -52,10 +54,12 @@ export default class AuthUserService<
if (!result) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`AuthUser with entity_id: "${entityId}" and provider: "${provider}" not found`
`AuthIdentity with entity_id: "${entityId}" and provider: "${provider}" not found`
)
}
return await this.baseRepository_.serialize<AuthTypes.AuthUserDTO>(result)
return await this.baseRepository_.serialize<AuthTypes.AuthIdentityDTO>(
result
)
}
}

View File

@@ -2,17 +2,14 @@ import {
AuthenticationInput,
AuthenticationResponse,
AuthTypes,
AuthUserDTO,
Context,
CreateAuthUserDTO,
DAL,
InternalModuleDeclaration,
ModuleJoinerConfig,
ModulesSdkTypes,
UpdateAuthUserDTO,
} from "@medusajs/types"
import { AuthUser } from "@models"
import { AuthIdentity } from "@models"
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
@@ -26,33 +23,35 @@ import {
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
authUserService: ModulesSdkTypes.InternalModuleService<any>
authIdentityService: ModulesSdkTypes.InternalModuleService<any>
}
const generateMethodForModels = [AuthUser]
const generateMethodForModels = [AuthIdentity]
export default class AuthModuleService<TAuthUser extends AuthUser = AuthUser>
export default class AuthModuleService<
TAuthIdentity extends AuthIdentity = AuthIdentity
>
extends ModulesSdkUtils.abstractModuleServiceFactory<
InjectedDependencies,
AuthTypes.AuthUserDTO,
AuthTypes.AuthIdentityDTO,
{
AuthUser: { dto: AuthUserDTO }
AuthIdentity: { dto: AuthTypes.AuthIdentityDTO }
}
>(AuthUser, generateMethodForModels, entityNameToLinkableKeysMap)
>(AuthIdentity, generateMethodForModels, entityNameToLinkableKeysMap)
implements AuthTypes.IAuthModuleService
{
protected baseRepository_: DAL.RepositoryService
protected authUserService_: ModulesSdkTypes.InternalModuleService<TAuthUser>
protected authIdentityService_: ModulesSdkTypes.InternalModuleService<TAuthIdentity>
constructor(
{ authUserService, baseRepository }: InjectedDependencies,
{ authIdentityService, baseRepository }: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
// @ts-ignore
super(...arguments)
this.baseRepository_ = baseRepository
this.authUserService_ = authUserService
this.authIdentityService_ = authIdentityService
}
__joinerConfig(): ModuleJoinerConfig {
@@ -60,21 +59,27 @@ export default class AuthModuleService<TAuthUser extends AuthUser = AuthUser>
}
create(
data: CreateAuthUserDTO[],
data: AuthTypes.CreateAuthIdentityDTO[],
sharedContext?: Context
): Promise<AuthUserDTO[]>
): Promise<AuthTypes.AuthIdentityDTO[]>
create(data: CreateAuthUserDTO, sharedContext?: Context): Promise<AuthUserDTO>
create(
data: AuthTypes.CreateAuthIdentityDTO,
sharedContext?: Context
): Promise<AuthTypes.AuthIdentityDTO>
@InjectManager("baseRepository_")
async create(
data: CreateAuthUserDTO[] | CreateAuthUserDTO,
data: AuthTypes.CreateAuthIdentityDTO[] | AuthTypes.CreateAuthIdentityDTO,
@MedusaContext() sharedContext: Context = {}
): Promise<AuthTypes.AuthUserDTO | AuthTypes.AuthUserDTO[]> {
const authUsers = await this.authUserService_.create(data, sharedContext)
): Promise<AuthTypes.AuthIdentityDTO | AuthTypes.AuthIdentityDTO[]> {
const authIdentities = await this.authIdentityService_.create(
data,
sharedContext
)
return await this.baseRepository_.serialize<AuthTypes.AuthUserDTO[]>(
authUsers,
return await this.baseRepository_.serialize<AuthTypes.AuthIdentityDTO[]>(
authIdentities,
{
populate: true,
}
@@ -82,22 +87,28 @@ export default class AuthModuleService<TAuthUser extends AuthUser = AuthUser>
}
update(
data: UpdateAuthUserDTO[],
data: AuthTypes.UpdateAuthIdentityDTO[],
sharedContext?: Context
): Promise<AuthUserDTO[]>
): Promise<AuthTypes.AuthIdentityDTO[]>
update(data: UpdateAuthUserDTO, sharedContext?: Context): Promise<AuthUserDTO>
update(
data: AuthTypes.UpdateAuthIdentityDTO,
sharedContext?: Context
): Promise<AuthTypes.AuthIdentityDTO>
// TODO: should be pluralized, see convention about the methods naming or the abstract module service interface definition @engineering
@InjectManager("baseRepository_")
async update(
data: UpdateAuthUserDTO | UpdateAuthUserDTO[],
data: AuthTypes.UpdateAuthIdentityDTO | AuthTypes.UpdateAuthIdentityDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<AuthTypes.AuthUserDTO | AuthTypes.AuthUserDTO[]> {
const updatedUsers = await this.authUserService_.update(data, sharedContext)
): Promise<AuthTypes.AuthIdentityDTO | AuthTypes.AuthIdentityDTO[]> {
const updatedUsers = await this.authIdentityService_.update(
data,
sharedContext
)
const serializedUsers = await this.baseRepository_.serialize<
AuthTypes.AuthUserDTO[]
AuthTypes.AuthIdentityDTO[]
>(updatedUsers, {
populate: true,
})

View File

@@ -1,2 +1,2 @@
export { default as AuthModuleService } from "./auth-module"
export { default as AuthUserService } from "./auth-user"
export { default as AuthIdentityService } from "./auth-identity"