Skip to content

Commit 391eb85

Browse files
authored
Merge pull request #10 from DouglasNeuroInformatics/fix-type-error
fix: add explicit schema for token payload
2 parents 62987d6 + 1bc1aeb commit 391eb85

File tree

5 files changed

+43
-38
lines changed

5 files changed

+43
-38
lines changed

example/app.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,15 @@ export default await AppContainer.create({
2121
ability.can('manage', 'all');
2222
}
2323
},
24-
loginCredentialsSchema: z.object({
25-
password: z.string().min(1),
26-
username: z.string().min(1)
27-
}),
24+
schemas: {
25+
loginCredentials: z.object({
26+
password: z.string().min(1),
27+
username: z.string().min(1)
28+
}),
29+
tokenPayload: z.object({
30+
isAdmin: z.boolean()
31+
})
32+
},
2833
userQuery: async ({ username }) => {
2934
if (username !== 'admin') {
3035
return null;

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export { CurrentUser } from './decorators/current-user.decorator.js';
33
export { RouteAccess } from './decorators/route-access.decorator.js';
44
export { ValidationSchema } from './decorators/validation-schema.decorator.js';
55
export { DataTransferObject } from './mixins/data-transfer-object.mixin.js';
6-
export type { AuthModuleOptions, UserQuery, UserQueryResult } from './modules/auth/auth.config.js';
6+
export type { AuthModuleOptions } from './modules/auth/auth.config.js';
77
export { AuthModule } from './modules/auth/auth.module.js';
88
export { ConfigService } from './modules/config/config.service.js';
99
export { CryptoService } from './modules/crypto/crypto.service.js';

src/modules/auth/__tests__/auth.module.spec.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ describe('AuthModule', () => {
4343
let jwtStrategy: JwtStrategy;
4444

4545
let defineAbility: Mock<DefineAbility>;
46-
let userQuery: Mock<UserQuery>;
46+
let userQuery: Mock<UserQuery<{ password: string; username: string }, { username: string }>>;
4747

4848
const loginCredentials = {
4949
password: 'password',
@@ -62,10 +62,15 @@ describe('AuthModule', () => {
6262
imports: [
6363
AuthModule.forRoot({
6464
defineAbility,
65-
loginCredentialsSchema: z.object({
66-
password: z.string(),
67-
username: z.string()
68-
}),
65+
schemas: {
66+
loginCredentials: z.object({
67+
password: z.string(),
68+
username: z.string()
69+
}),
70+
tokenPayload: z.object({
71+
username: z.string()
72+
})
73+
},
6974
userQuery: userQuery
7075
}),
7176
ConfigModule.forRoot({

src/modules/auth/auth.config.ts

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,41 +47,37 @@ type BaseLoginCredentials = {
4747

4848
type BaseLoginCredentialsSchema = z.ZodType<BaseLoginCredentials>;
4949

50-
type UserQueryResult = {
51-
hashedPassword: string;
52-
tokenPayload: {
53-
[key: string]: unknown;
54-
};
55-
};
56-
5750
interface JwtPayload {
5851
[key: string]: any;
5952
permissions: Permission[];
6053
}
6154

62-
type UserQuery<TLoginCredentials extends BaseLoginCredentials = BaseLoginCredentials> = (
63-
credentials: TLoginCredentials
64-
) => Promise<null | UserQueryResult>;
55+
type UserQuery<
56+
TLoginCredentials extends BaseLoginCredentials = BaseLoginCredentials,
57+
TPayload extends { [key: string]: unknown } = { [key: string]: unknown }
58+
> = (credentials: TLoginCredentials) => Promise<null | {
59+
hashedPassword: string;
60+
tokenPayload: TPayload;
61+
}>;
6562

6663
type LoginResponseBody = {
6764
accessToken: string;
6865
};
6966

7067
type AuthModuleOptions<
7168
TLoginCredentialsSchema extends BaseLoginCredentialsSchema = BaseLoginCredentialsSchema,
72-
TUserQuery extends UserQuery<z.TypeOf<TLoginCredentialsSchema>> = UserQuery<z.TypeOf<TLoginCredentialsSchema>>
69+
TPayloadSchema extends z.ZodType<{ [key: string]: unknown }> = z.ZodType<{ [key: string]: unknown }>
7370
> = {
74-
defineAbility: TUserQuery extends (...args: any[]) => Promise<infer R>
75-
? R extends { tokenPayload: infer TPayload extends { [key: string]: unknown } }
76-
? DefineAbility<TPayload>
77-
: never
78-
: never;
79-
loginCredentialsSchema: TLoginCredentialsSchema;
80-
userQuery: TUserQuery;
71+
defineAbility: (ability: AbilityBuilder<AppAbility>, tokenPayload: z.TypeOf<TPayloadSchema>) => any;
72+
schemas: {
73+
loginCredentials: TLoginCredentialsSchema;
74+
tokenPayload: TPayloadSchema;
75+
};
76+
userQuery: UserQuery<z.TypeOf<TLoginCredentialsSchema>, z.TypeOf<TPayloadSchema>>;
8177
};
8278

8379
export const { ConfigurableModuleClass: ConfigurableAuthModule, MODULE_OPTIONS_TOKEN: AUTH_MODULE_OPTIONS_TOKEN } =
84-
new ConfigurableModuleBuilder<AuthModuleOptions<any>>()
80+
new ConfigurableModuleBuilder<AuthModuleOptions<any, any>>()
8581
.setClassMethodName('forRoot')
8682
.setExtras({}, (definition) => ({
8783
...definition,
@@ -107,6 +103,5 @@ export type {
107103
JwtPayload,
108104
LoginResponseBody,
109105
Permission,
110-
UserQuery,
111-
UserQueryResult
106+
UserQuery
112107
};

src/modules/auth/auth.module.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { LoginCredentialsDto } from './dto/login-credentials.dto.js';
1919
import { JwtAuthGuard } from './guards/jwt-auth.guard.js';
2020
import { JwtStrategy } from './strategies/jwt.strategy.js';
2121

22-
import type { AuthModuleOptions, BaseLoginCredentialsSchema, UserQuery } from './auth.config.js';
22+
import type { AuthModuleOptions, BaseLoginCredentialsSchema } from './auth.config.js';
2323

2424
@Module({
2525
controllers: [AuthController],
@@ -58,22 +58,22 @@ import type { AuthModuleOptions, BaseLoginCredentialsSchema, UserQuery } from '.
5858
export class AuthModule extends ConfigurableAuthModule implements OnModuleInit {
5959
private readonly loginCredentialsSchema: BaseLoginCredentialsSchema;
6060

61-
constructor(@Inject(AUTH_MODULE_OPTIONS_TOKEN) { loginCredentialsSchema }: AuthModuleOptions) {
61+
constructor(@Inject(AUTH_MODULE_OPTIONS_TOKEN) { schemas }: AuthModuleOptions) {
6262
super();
63-
this.loginCredentialsSchema = loginCredentialsSchema;
63+
this.loginCredentialsSchema = schemas.loginCredentials;
6464
}
6565

6666
static forRoot<
6767
TLoginCredentialsSchema extends BaseLoginCredentialsSchema,
68-
TUserQuery extends UserQuery<z.TypeOf<TLoginCredentialsSchema>>
69-
>(options: AuthModuleOptions<TLoginCredentialsSchema, TUserQuery>): DynamicModule {
68+
TPayloadSchema extends z.ZodType<{ [key: string]: unknown }>
69+
>(options: AuthModuleOptions<TLoginCredentialsSchema, TPayloadSchema>): DynamicModule {
7070
return super.forRoot(options);
7171
}
7272
static forRootAsync<
7373
TLoginCredentialsSchema extends BaseLoginCredentialsSchema,
74-
TUserQuery extends UserQuery<z.TypeOf<TLoginCredentialsSchema>>
74+
TPayloadSchema extends z.ZodType<{ [key: string]: unknown }>
7575
>(
76-
options: ConfigurableModuleAsyncOptions<AuthModuleOptions<TLoginCredentialsSchema, TUserQuery>, 'create'>
76+
options: ConfigurableModuleAsyncOptions<AuthModuleOptions<TLoginCredentialsSchema, TPayloadSchema>, 'create'>
7777
): DynamicModule {
7878
return super.forRootAsync(options);
7979
}

0 commit comments

Comments
 (0)