@veap/auth 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +166 -2
- package/dist/actions/auth.actions.d.ts +23 -0
- package/dist/actions/auth.actions.js +40 -0
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/client/auth.context.d.ts +29 -0
- package/dist/client/auth.context.js +64 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +1 -0
- package/dist/common/augment.d.ts +26 -0
- package/dist/common/augment.js +63 -0
- package/dist/common/context.d.ts +29 -0
- package/dist/common/context.js +34 -0
- package/dist/common/index.d.ts +6 -0
- package/dist/common/index.js +6 -0
- package/dist/common/logic.d.ts +64 -0
- package/dist/common/logic.js +133 -0
- package/dist/common/registry.d.ts +28 -0
- package/dist/common/registry.js +76 -0
- package/dist/common/routes.d.ts +2 -0
- package/dist/common/routes.js +1 -0
- package/dist/common/types.d.ts +178 -0
- package/dist/common/types.js +9 -0
- package/dist/crypto/aes-cipher.d.ts +8 -0
- package/dist/crypto/aes-cipher.js +12 -0
- package/dist/crypto/bcrypt-hasher.d.ts +12 -0
- package/dist/crypto/bcrypt-hasher.js +37 -0
- package/dist/crypto/contracts.d.ts +36 -0
- package/dist/crypto/contracts.js +3 -0
- package/dist/crypto/encryption.d.ts +18 -0
- package/dist/crypto/encryption.js +69 -0
- package/dist/crypto/index.d.ts +6 -0
- package/dist/crypto/index.js +6 -0
- package/dist/crypto/password.d.ts +19 -0
- package/dist/crypto/password.js +27 -0
- package/dist/crypto/token-generator.d.ts +10 -0
- package/dist/crypto/token-generator.js +25 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +11 -0
- package/dist/migrations/0001_create_auth_tables.d.ts +4 -0
- package/dist/migrations/0001_create_auth_tables.js +122 -0
- package/dist/migrations/index.d.ts +4 -0
- package/dist/migrations/index.js +7 -0
- package/dist/models/EmailVerification.d.ts +23 -0
- package/dist/models/EmailVerification.js +19 -0
- package/dist/models/PasswordResetSession.d.ts +25 -0
- package/dist/models/PasswordResetSession.js +21 -0
- package/dist/models/Permission.d.ts +20 -0
- package/dist/models/Permission.js +19 -0
- package/dist/models/Role.d.ts +20 -0
- package/dist/models/Role.js +19 -0
- package/dist/models/Session.d.ts +22 -0
- package/dist/models/Session.js +21 -0
- package/dist/models/User.d.ts +32 -0
- package/dist/models/User.js +31 -0
- package/dist/models/index.d.ts +6 -0
- package/dist/models/index.js +6 -0
- package/dist/models.d.ts +1 -0
- package/dist/models.js +1 -0
- package/dist/passwords/contracts.d.ts +28 -0
- package/dist/passwords/contracts.js +2 -0
- package/dist/passwords/index.d.ts +4 -0
- package/dist/passwords/index.js +4 -0
- package/dist/passwords/password-reset.facade.d.ts +14 -0
- package/dist/passwords/password-reset.facade.js +50 -0
- package/dist/passwords/password-reset.repository.d.ts +10 -0
- package/dist/passwords/password-reset.repository.js +39 -0
- package/dist/passwords/password-reset.service.d.ts +38 -0
- package/dist/passwords/password-reset.service.js +242 -0
- package/dist/providers/auth.provider.d.ts +9 -0
- package/dist/providers/auth.provider.js +196 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +2 -0
- package/dist/providers/setup.d.ts +7 -0
- package/dist/providers/setup.js +29 -0
- package/dist/rbac/contracts.d.ts +75 -0
- package/dist/rbac/contracts.js +4 -0
- package/dist/rbac/index.d.ts +4 -0
- package/dist/rbac/index.js +4 -0
- package/dist/rbac/rbac.facade.d.ts +23 -0
- package/dist/rbac/rbac.facade.js +78 -0
- package/dist/rbac/rbac.repository.d.ts +30 -0
- package/dist/rbac/rbac.repository.js +137 -0
- package/dist/rbac/rbac.service.d.ts +35 -0
- package/dist/rbac/rbac.service.js +143 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +3 -0
- package/dist/session/auth.service.d.ts +35 -0
- package/dist/session/auth.service.js +208 -0
- package/dist/session/contracts.d.ts +33 -0
- package/dist/session/contracts.js +2 -0
- package/dist/session/index.d.ts +5 -0
- package/dist/session/index.js +5 -0
- package/dist/session/session.facade.d.ts +14 -0
- package/dist/session/session.facade.js +75 -0
- package/dist/session/session.repository.d.ts +15 -0
- package/dist/session/session.repository.js +55 -0
- package/dist/session/session.service.d.ts +63 -0
- package/dist/session/session.service.js +219 -0
- package/dist/users/contracts.d.ts +32 -0
- package/dist/users/contracts.js +2 -0
- package/dist/users/index.d.ts +4 -0
- package/dist/users/index.js +4 -0
- package/dist/users/user.facade.d.ts +14 -0
- package/dist/users/user.facade.js +62 -0
- package/dist/users/user.repository.d.ts +15 -0
- package/dist/users/user.repository.js +55 -0
- package/dist/users/user.service.d.ts +68 -0
- package/dist/users/user.service.js +183 -0
- package/dist/validation/index.d.ts +95 -0
- package/dist/validation/index.js +55 -0
- package/dist/verification/contracts.d.ts +25 -0
- package/dist/verification/contracts.js +2 -0
- package/dist/verification/index.d.ts +4 -0
- package/dist/verification/index.js +4 -0
- package/dist/verification/verification.facade.d.ts +10 -0
- package/dist/verification/verification.facade.js +42 -0
- package/dist/verification/verification.repository.d.ts +7 -0
- package/dist/verification/verification.repository.js +23 -0
- package/dist/verification/verification.service.d.ts +44 -0
- package/dist/verification/verification.service.js +120 -0
- package/package.json +88 -4
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Validates the email format and length.
|
|
4
|
+
*/
|
|
5
|
+
export declare function verifyEmailInput(email: string): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Checks if an email address is already in use.
|
|
8
|
+
* @returns True if the email is available, false otherwise.
|
|
9
|
+
*/
|
|
10
|
+
export declare function checkEmailAvailability(email: string): Promise<boolean>;
|
|
11
|
+
export declare const loginSchema: z.ZodObject<{
|
|
12
|
+
email: z.ZodString;
|
|
13
|
+
password: z.ZodString;
|
|
14
|
+
remember: z.ZodOptional<z.ZodBoolean>;
|
|
15
|
+
}, "strip", z.ZodTypeAny, {
|
|
16
|
+
email: string;
|
|
17
|
+
password: string;
|
|
18
|
+
remember?: boolean | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
email: string;
|
|
21
|
+
password: string;
|
|
22
|
+
remember?: boolean | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
export declare const registerSchema: z.ZodObject<{
|
|
25
|
+
username: z.ZodString;
|
|
26
|
+
email: z.ZodString;
|
|
27
|
+
password: z.ZodString;
|
|
28
|
+
terms: z.ZodEffects<z.ZodBoolean, boolean, boolean>;
|
|
29
|
+
}, "strip", z.ZodTypeAny, {
|
|
30
|
+
email: string;
|
|
31
|
+
password: string;
|
|
32
|
+
username: string;
|
|
33
|
+
terms: boolean;
|
|
34
|
+
}, {
|
|
35
|
+
email: string;
|
|
36
|
+
password: string;
|
|
37
|
+
username: string;
|
|
38
|
+
terms: boolean;
|
|
39
|
+
}>;
|
|
40
|
+
export declare const forgotPasswordSchema: z.ZodObject<{
|
|
41
|
+
email: z.ZodString;
|
|
42
|
+
}, "strip", z.ZodTypeAny, {
|
|
43
|
+
email: string;
|
|
44
|
+
}, {
|
|
45
|
+
email: string;
|
|
46
|
+
}>;
|
|
47
|
+
export declare const resetPasswordSchema: z.ZodEffects<z.ZodObject<{
|
|
48
|
+
password: z.ZodString;
|
|
49
|
+
confirm: z.ZodString;
|
|
50
|
+
}, "strip", z.ZodTypeAny, {
|
|
51
|
+
password: string;
|
|
52
|
+
confirm: string;
|
|
53
|
+
}, {
|
|
54
|
+
password: string;
|
|
55
|
+
confirm: string;
|
|
56
|
+
}>, {
|
|
57
|
+
password: string;
|
|
58
|
+
confirm: string;
|
|
59
|
+
}, {
|
|
60
|
+
password: string;
|
|
61
|
+
confirm: string;
|
|
62
|
+
}>;
|
|
63
|
+
export declare const verifyEmailSchema: z.ZodObject<{
|
|
64
|
+
code: z.ZodString;
|
|
65
|
+
}, "strip", z.ZodTypeAny, {
|
|
66
|
+
code: string;
|
|
67
|
+
}, {
|
|
68
|
+
code: string;
|
|
69
|
+
}>;
|
|
70
|
+
export declare const totpSetupSchema: z.ZodObject<{
|
|
71
|
+
code: z.ZodString;
|
|
72
|
+
}, "strip", z.ZodTypeAny, {
|
|
73
|
+
code: string;
|
|
74
|
+
}, {
|
|
75
|
+
code: string;
|
|
76
|
+
}>;
|
|
77
|
+
export declare const totpVerifySchema: z.ZodObject<{
|
|
78
|
+
code: z.ZodString;
|
|
79
|
+
}, "strip", z.ZodTypeAny, {
|
|
80
|
+
code: string;
|
|
81
|
+
}, {
|
|
82
|
+
code: string;
|
|
83
|
+
}>;
|
|
84
|
+
export declare const backupCodeSchema: z.ZodObject<{
|
|
85
|
+
code: z.ZodString;
|
|
86
|
+
}, "strip", z.ZodTypeAny, {
|
|
87
|
+
code: string;
|
|
88
|
+
}, {
|
|
89
|
+
code: string;
|
|
90
|
+
}>;
|
|
91
|
+
export type LoginInput = z.infer<typeof loginSchema>;
|
|
92
|
+
export type RegisterInput = z.infer<typeof registerSchema>;
|
|
93
|
+
export type ForgotPasswordInput = z.infer<typeof forgotPasswordSchema>;
|
|
94
|
+
export type ResetPasswordInput = z.infer<typeof resetPasswordSchema>;
|
|
95
|
+
export type VerifyEmailInput = z.infer<typeof verifyEmailSchema>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { User } from "../models";
|
|
3
|
+
/**
|
|
4
|
+
* Validates the email format and length.
|
|
5
|
+
*/
|
|
6
|
+
export function verifyEmailInput(email) {
|
|
7
|
+
return /^.+@.+\..+$/.test(email) && email.length < 256 && email.length > 0;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Checks if an email address is already in use.
|
|
11
|
+
* @returns True if the email is available, false otherwise.
|
|
12
|
+
*/
|
|
13
|
+
export async function checkEmailAvailability(email) {
|
|
14
|
+
const exists = await User.where("email", email).exists();
|
|
15
|
+
return !exists;
|
|
16
|
+
}
|
|
17
|
+
// Auth validation schemas - CLEAN (No DB dependencies for client-side)
|
|
18
|
+
export const loginSchema = z.object({
|
|
19
|
+
email: z.string().email("Invalid email address"),
|
|
20
|
+
password: z.string().min(8),
|
|
21
|
+
remember: z.boolean().optional(),
|
|
22
|
+
});
|
|
23
|
+
export const registerSchema = z.object({
|
|
24
|
+
username: z.string().min(3, "Name must be at least 2 characters"),
|
|
25
|
+
email: z.string().email("Invalid email address"),
|
|
26
|
+
password: z.string().min(8, "Password must be at least 8 characters"),
|
|
27
|
+
terms: z
|
|
28
|
+
.boolean()
|
|
29
|
+
.refine((val) => val === true, "You must accept the terms"),
|
|
30
|
+
});
|
|
31
|
+
export const forgotPasswordSchema = z.object({
|
|
32
|
+
email: z.string().email("Invalid email address"),
|
|
33
|
+
});
|
|
34
|
+
export const resetPasswordSchema = z
|
|
35
|
+
.object({
|
|
36
|
+
password: z.string().min(8, "Password must be at least 8 characters"),
|
|
37
|
+
confirm: z.string(),
|
|
38
|
+
})
|
|
39
|
+
.refine((data) => data.password === data.confirm, {
|
|
40
|
+
message: "Passwords do not match",
|
|
41
|
+
path: ["confirm"],
|
|
42
|
+
});
|
|
43
|
+
export const verifyEmailSchema = z.object({
|
|
44
|
+
code: z.string().min(6).max(6),
|
|
45
|
+
});
|
|
46
|
+
// mfa validation schemas
|
|
47
|
+
export const totpSetupSchema = z.object({
|
|
48
|
+
code: z.string().regex(/^\d{6}$/, "Code must be 6 digits"),
|
|
49
|
+
});
|
|
50
|
+
export const totpVerifySchema = z.object({
|
|
51
|
+
code: z.string().regex(/^\d{6}$/, "Code must be 6 digits"),
|
|
52
|
+
});
|
|
53
|
+
export const backupCodeSchema = z.object({
|
|
54
|
+
code: z.string().min(8).max(12),
|
|
55
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** An email verification request as persisted. */
|
|
2
|
+
export interface EmailVerificationRecord {
|
|
3
|
+
id: string;
|
|
4
|
+
email: string;
|
|
5
|
+
code: string;
|
|
6
|
+
userId?: string;
|
|
7
|
+
user_id?: string;
|
|
8
|
+
expiresAt: Date;
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
}
|
|
11
|
+
export interface CreateEmailVerificationRecord {
|
|
12
|
+
userId: string;
|
|
13
|
+
email: string;
|
|
14
|
+
code: string;
|
|
15
|
+
expiresAt: Date;
|
|
16
|
+
}
|
|
17
|
+
/** Email verification request persistence port. */
|
|
18
|
+
export interface IEmailVerificationRepository {
|
|
19
|
+
create(record: CreateEmailVerificationRecord): Promise<EmailVerificationRecord>;
|
|
20
|
+
/** Finds a single request scoped to its owner. */
|
|
21
|
+
findForUser(userId: string, id: string): Promise<EmailVerificationRecord | null>;
|
|
22
|
+
removeByUserId(userId: string): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
/** Injection token for the email verification repository port. */
|
|
25
|
+
export declare const EMAIL_VERIFICATION_REPOSITORY: unique symbol;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type EmailVerificationRequestType } from "./verification.service";
|
|
2
|
+
export type { EmailVerificationRequestType };
|
|
3
|
+
export declare function initEmailVerification(): Promise<void>;
|
|
4
|
+
export declare function getUserEmailVerificationRequest(userId: string, id: string): Promise<import("./contracts").EmailVerificationRecord | null>;
|
|
5
|
+
export declare function createEmailVerificationRequest(userId: string, email: string): Promise<import("./contracts").EmailVerificationRecord>;
|
|
6
|
+
export declare function deleteUserEmailVerificationRequest(userId: string): Promise<void>;
|
|
7
|
+
export declare function sendVerificationEmail(email: string, code: string): Promise<void>;
|
|
8
|
+
export declare function setEmailVerificationRequestCookie(request: EmailVerificationRequestType): Promise<void>;
|
|
9
|
+
export declare function deleteEmailVerificationRequestCookie(): Promise<void>;
|
|
10
|
+
export declare function getUserEmailVerificationRequestFromRequest(): Promise<import("./contracts").EmailVerificationRecord | null>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { app } from "@veap/kernel";
|
|
3
|
+
import { authContext, isAuthContextBound } from "../common/context";
|
|
4
|
+
import { EmailVerificationService, } from "./verification.service";
|
|
5
|
+
async function resolveVerificationService() {
|
|
6
|
+
if (isAuthContextBound()) {
|
|
7
|
+
return authContext().emailVerification;
|
|
8
|
+
}
|
|
9
|
+
return await app(EmailVerificationService);
|
|
10
|
+
}
|
|
11
|
+
export async function initEmailVerification() {
|
|
12
|
+
const service = await resolveVerificationService();
|
|
13
|
+
return service.initEmailVerification();
|
|
14
|
+
}
|
|
15
|
+
export async function getUserEmailVerificationRequest(userId, id) {
|
|
16
|
+
const service = await resolveVerificationService();
|
|
17
|
+
return service.getUserEmailVerificationRequest(userId, id);
|
|
18
|
+
}
|
|
19
|
+
export async function createEmailVerificationRequest(userId, email) {
|
|
20
|
+
const service = await resolveVerificationService();
|
|
21
|
+
return service.createEmailVerificationRequest(userId, email);
|
|
22
|
+
}
|
|
23
|
+
export async function deleteUserEmailVerificationRequest(userId) {
|
|
24
|
+
const service = await resolveVerificationService();
|
|
25
|
+
return service.deleteUserEmailVerificationRequest(userId);
|
|
26
|
+
}
|
|
27
|
+
export async function sendVerificationEmail(email, code) {
|
|
28
|
+
const service = await resolveVerificationService();
|
|
29
|
+
return service.sendVerificationEmail(email, code);
|
|
30
|
+
}
|
|
31
|
+
export async function setEmailVerificationRequestCookie(request) {
|
|
32
|
+
const service = await resolveVerificationService();
|
|
33
|
+
return service.setEmailVerificationRequestCookie(request);
|
|
34
|
+
}
|
|
35
|
+
export async function deleteEmailVerificationRequestCookie() {
|
|
36
|
+
const service = await resolveVerificationService();
|
|
37
|
+
return service.deleteEmailVerificationRequestCookie();
|
|
38
|
+
}
|
|
39
|
+
export async function getUserEmailVerificationRequestFromRequest() {
|
|
40
|
+
const service = await resolveVerificationService();
|
|
41
|
+
return service.getUserEmailVerificationRequestFromRequest();
|
|
42
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CreateEmailVerificationRecord, EmailVerificationRecord, IEmailVerificationRepository } from "./contracts";
|
|
2
|
+
/** `IEmailVerificationRepository` adapter backed by `EmailVerification`. */
|
|
3
|
+
export declare class ActiveRecordEmailVerificationRepository implements IEmailVerificationRepository {
|
|
4
|
+
create(record: CreateEmailVerificationRecord): Promise<EmailVerificationRecord>;
|
|
5
|
+
findForUser(userId: string, id: string): Promise<EmailVerificationRecord | null>;
|
|
6
|
+
removeByUserId(userId: string): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { EmailVerification } from "../models/EmailVerification";
|
|
2
|
+
/** `IEmailVerificationRepository` adapter backed by `EmailVerification`. */
|
|
3
|
+
export class ActiveRecordEmailVerificationRepository {
|
|
4
|
+
async create(record) {
|
|
5
|
+
const request = await EmailVerification.create({
|
|
6
|
+
userId: record.userId,
|
|
7
|
+
code: record.code,
|
|
8
|
+
email: record.email,
|
|
9
|
+
expiresAt: record.expiresAt,
|
|
10
|
+
});
|
|
11
|
+
return request.toJSON();
|
|
12
|
+
}
|
|
13
|
+
async findForUser(userId, id) {
|
|
14
|
+
const request = await EmailVerification.where({
|
|
15
|
+
id,
|
|
16
|
+
user_id: userId,
|
|
17
|
+
}).first();
|
|
18
|
+
return request ? request.toJSON() : null;
|
|
19
|
+
}
|
|
20
|
+
async removeByUserId(userId) {
|
|
21
|
+
await EmailVerification.where("user_id", userId).delete();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type ICookieStore } from "@veap/kernel";
|
|
2
|
+
import { type ITokenGenerator } from "../crypto/contracts";
|
|
3
|
+
import { SessionService } from "../session/session.service";
|
|
4
|
+
import { type EmailVerificationRecord, type IEmailVerificationRepository } from "./contracts";
|
|
5
|
+
export type EmailVerificationRequestType = EmailVerificationRecord;
|
|
6
|
+
export declare class EmailVerificationService {
|
|
7
|
+
private readonly verifications;
|
|
8
|
+
private readonly tokens;
|
|
9
|
+
private readonly cookieStore;
|
|
10
|
+
private readonly sessions;
|
|
11
|
+
constructor(verifications: IEmailVerificationRepository, tokens: ITokenGenerator, cookieStore: ICookieStore, sessions: SessionService);
|
|
12
|
+
/**
|
|
13
|
+
* Register Email Verification as a Core Security Requirement.
|
|
14
|
+
*/
|
|
15
|
+
initEmailVerification(): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Retrieves a specific email verification request for a user.
|
|
18
|
+
*/
|
|
19
|
+
getUserEmailVerificationRequest(userId: string, id: string): Promise<EmailVerificationRequestType | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new email verification request, deleting any existing one for the user.
|
|
22
|
+
*/
|
|
23
|
+
createEmailVerificationRequest(userId: string, email: string): Promise<EmailVerificationRequestType>;
|
|
24
|
+
/**
|
|
25
|
+
* Deletes all email verification requests for a user.
|
|
26
|
+
*/
|
|
27
|
+
deleteUserEmailVerificationRequest(userId: string): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Sends a verification email with the OTP code.
|
|
30
|
+
*/
|
|
31
|
+
sendVerificationEmail(email: string, code: string): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Sets the email verification request ID in a cookie.
|
|
34
|
+
*/
|
|
35
|
+
setEmailVerificationRequestCookie(request: EmailVerificationRequestType): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Removes the email verification request cookie.
|
|
38
|
+
*/
|
|
39
|
+
deleteEmailVerificationRequestCookie(): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Retrieves the current email verification request based on session and cookie.
|
|
42
|
+
*/
|
|
43
|
+
getUserEmailVerificationRequestFromRequest(): Promise<EmailVerificationRequestType | null>;
|
|
44
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { COOKIE_STORE, Inject, Injectable, } from "@veap/kernel";
|
|
14
|
+
import { sendVerifyEmail } from "@veap/mail";
|
|
15
|
+
import { addMinutes } from "date-fns";
|
|
16
|
+
import { registerSecurityRequirement } from "../common/logic";
|
|
17
|
+
import { TOKEN_GENERATOR } from "../crypto/contracts";
|
|
18
|
+
import { SessionService } from "../session/session.service";
|
|
19
|
+
import { EMAIL_VERIFICATION_REPOSITORY, } from "./contracts";
|
|
20
|
+
let EmailVerificationService = class EmailVerificationService {
|
|
21
|
+
verifications;
|
|
22
|
+
tokens;
|
|
23
|
+
cookieStore;
|
|
24
|
+
sessions;
|
|
25
|
+
constructor(verifications, tokens, cookieStore, sessions) {
|
|
26
|
+
this.verifications = verifications;
|
|
27
|
+
this.tokens = tokens;
|
|
28
|
+
this.cookieStore = cookieStore;
|
|
29
|
+
this.sessions = sessions;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Register Email Verification as a Core Security Requirement.
|
|
33
|
+
*/
|
|
34
|
+
async initEmailVerification() {
|
|
35
|
+
registerSecurityRequirement(async (_session, user) => {
|
|
36
|
+
if (!user.emailVerifiedAt) {
|
|
37
|
+
return {
|
|
38
|
+
satisfied: false,
|
|
39
|
+
redirect: "/verify-email?unverified",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return { satisfied: true };
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Retrieves a specific email verification request for a user.
|
|
47
|
+
*/
|
|
48
|
+
async getUserEmailVerificationRequest(userId, id) {
|
|
49
|
+
return await this.verifications.findForUser(userId, id);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Creates a new email verification request, deleting any existing one for the user.
|
|
53
|
+
*/
|
|
54
|
+
async createEmailVerificationRequest(userId, email) {
|
|
55
|
+
await this.deleteUserEmailVerificationRequest(userId);
|
|
56
|
+
return await this.verifications.create({
|
|
57
|
+
userId,
|
|
58
|
+
code: this.tokens.generateOtp(),
|
|
59
|
+
email,
|
|
60
|
+
expiresAt: new Date(addMinutes(new Date(), 15)),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Deletes all email verification requests for a user.
|
|
65
|
+
*/
|
|
66
|
+
async deleteUserEmailVerificationRequest(userId) {
|
|
67
|
+
await this.verifications.removeByUserId(userId);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Sends a verification email with the OTP code.
|
|
71
|
+
*/
|
|
72
|
+
async sendVerificationEmail(email, code) {
|
|
73
|
+
await sendVerifyEmail(email, code);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Sets the email verification request ID in a cookie.
|
|
77
|
+
*/
|
|
78
|
+
async setEmailVerificationRequestCookie(request) {
|
|
79
|
+
await this.cookieStore.set("email_verification", request.id, {
|
|
80
|
+
httpOnly: true,
|
|
81
|
+
path: "/",
|
|
82
|
+
secure: process.env.NODE_ENV === "production",
|
|
83
|
+
sameSite: "lax",
|
|
84
|
+
expires: request.expiresAt,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Removes the email verification request cookie.
|
|
89
|
+
*/
|
|
90
|
+
async deleteEmailVerificationRequestCookie() {
|
|
91
|
+
await this.cookieStore.delete("email_verification");
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Retrieves the current email verification request based on session and cookie.
|
|
95
|
+
*/
|
|
96
|
+
async getUserEmailVerificationRequestFromRequest() {
|
|
97
|
+
const { user } = await this.sessions.getCurrentSession();
|
|
98
|
+
if (!user) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
const id = await this.cookieStore.get("email_verification");
|
|
102
|
+
if (!id) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const request = await this.getUserEmailVerificationRequest(user.id, id);
|
|
106
|
+
if (!request) {
|
|
107
|
+
await this.deleteEmailVerificationRequestCookie();
|
|
108
|
+
}
|
|
109
|
+
return request;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
EmailVerificationService = __decorate([
|
|
113
|
+
Injectable(),
|
|
114
|
+
__param(0, Inject(EMAIL_VERIFICATION_REPOSITORY)),
|
|
115
|
+
__param(1, Inject(TOKEN_GENERATOR)),
|
|
116
|
+
__param(2, Inject(COOKIE_STORE)),
|
|
117
|
+
__param(3, Inject(SessionService)),
|
|
118
|
+
__metadata("design:paramtypes", [Object, Object, Object, SessionService])
|
|
119
|
+
], EmailVerificationService);
|
|
120
|
+
export { EmailVerificationService };
|
package/package.json
CHANGED
|
@@ -1,6 +1,90 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veap/auth",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Authentication, session management, RBAC, and crypto adapters for Veap",
|
|
5
|
+
"bugs": "https://github.com/veapjs/veap-auth/issues",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/veapjs/veap-auth.git"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"main": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./client": {
|
|
20
|
+
"types": "./dist/client/index.d.ts",
|
|
21
|
+
"default": "./dist/client/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./server": {
|
|
24
|
+
"types": "./dist/server.d.ts",
|
|
25
|
+
"default": "./dist/server.js"
|
|
26
|
+
},
|
|
27
|
+
"./actions": {
|
|
28
|
+
"types": "./dist/actions/index.d.ts",
|
|
29
|
+
"default": "./dist/actions/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./models": {
|
|
32
|
+
"types": "./dist/models.d.ts",
|
|
33
|
+
"default": "./dist/models.js"
|
|
34
|
+
},
|
|
35
|
+
"./migrations": {
|
|
36
|
+
"types": "./dist/migrations/index.d.ts",
|
|
37
|
+
"default": "./dist/migrations/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./package.json": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist"
|
|
43
|
+
],
|
|
44
|
+
"scripts": {
|
|
45
|
+
"clean": "rimraf dist",
|
|
46
|
+
"build": "rimraf dist && tsc",
|
|
47
|
+
"dev": "tsc --watch",
|
|
48
|
+
"test": "vitest run"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@oslojs/binary": "^1.0.0",
|
|
52
|
+
"@oslojs/crypto": "^1.0.1",
|
|
53
|
+
"@oslojs/encoding": "^1.1.0",
|
|
54
|
+
"@veap/database": "^0.1.0",
|
|
55
|
+
"@veap/kernel": "^0.1.0",
|
|
56
|
+
"@veap/mail": "^0.1.0",
|
|
57
|
+
"bcryptjs": "^3.0.3",
|
|
58
|
+
"date-fns": "^4.4.0",
|
|
59
|
+
"zod": "^3.24.2"
|
|
60
|
+
},
|
|
61
|
+
"peerDependencies": {
|
|
62
|
+
"react": "^19",
|
|
63
|
+
"react-dom": "^19",
|
|
64
|
+
"swr": "^2.2.5"
|
|
65
|
+
},
|
|
66
|
+
"peerDependenciesMeta": {
|
|
67
|
+
"react": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
70
|
+
"react-dom": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"swr": {
|
|
74
|
+
"optional": true
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"devDependencies": {
|
|
78
|
+
"@types/bcryptjs": "^2.4.6",
|
|
79
|
+
"@types/node": "^22.20.2",
|
|
80
|
+
"@types/react": "^19.1.9",
|
|
81
|
+
"@types/react-dom": "^19.1.7",
|
|
82
|
+
"better-sqlite3": "^13.0.3",
|
|
83
|
+
"knex": "^3.1.0",
|
|
84
|
+
"react": "^19.3.0",
|
|
85
|
+
"react-dom": "^19.3.0",
|
|
86
|
+
"rimraf": "^6.1.3",
|
|
87
|
+
"typescript": "6.0.3",
|
|
88
|
+
"vitest": "^5.0.0"
|
|
89
|
+
}
|
|
90
|
+
}
|