mirror of
https://github.com/documenso/documenso.git
synced 2025-11-20 19:51:32 +10:00
wip
This commit is contained in:
27
packages/auth/server/error-codes.ts
Normal file
27
packages/auth/server/error-codes.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import type { ContentfulStatusCode } from 'hono/utils/http-status';
|
||||
|
||||
export const AuthenticationErrorCode = {
|
||||
Unauthorized: 'UNAUTHORIZED',
|
||||
InvalidCredentials: 'INVALID_CREDENTIALS',
|
||||
SessionNotFound: 'SESSION_NOT_FOUND',
|
||||
SessionExpired: 'SESSION_EXPIRED',
|
||||
InvalidToken: 'INVALID_TOKEN',
|
||||
MissingToken: 'MISSING_TOKEN',
|
||||
} as const;
|
||||
|
||||
export type AuthenticationErrorCode =
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
(typeof AuthenticationErrorCode)[keyof typeof AuthenticationErrorCode] | (string & {});
|
||||
|
||||
export const ErrorStatusMap: Record<AuthenticationErrorCode, ContentfulStatusCode> = {
|
||||
[AuthenticationErrorCode.Unauthorized]: 401,
|
||||
[AuthenticationErrorCode.InvalidCredentials]: 401,
|
||||
[AuthenticationErrorCode.SessionNotFound]: 401,
|
||||
[AuthenticationErrorCode.SessionExpired]: 401,
|
||||
[AuthenticationErrorCode.InvalidToken]: 401,
|
||||
[AuthenticationErrorCode.MissingToken]: 400,
|
||||
};
|
||||
|
||||
export function getErrorStatus(code: AuthenticationErrorCode) {
|
||||
return ErrorStatusMap[code] ?? 400;
|
||||
}
|
||||
42
packages/auth/server/errors.ts
Normal file
42
packages/auth/server/errors.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import type { Context } from 'hono';
|
||||
import type { ContentfulStatusCode } from 'hono/utils/http-status';
|
||||
|
||||
import type { AuthenticationErrorCode } from './error-codes';
|
||||
import { getErrorStatus } from './error-codes';
|
||||
|
||||
interface ErrorResponse {
|
||||
error: string;
|
||||
message: string;
|
||||
stack?: string;
|
||||
}
|
||||
|
||||
export class AuthenticationError extends Error {
|
||||
code: AuthenticationErrorCode;
|
||||
statusCode: ContentfulStatusCode;
|
||||
|
||||
constructor(code: AuthenticationErrorCode, message?: string, statusCode?: ContentfulStatusCode) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.name = 'AuthenticationError';
|
||||
// Use provided status code or look it up from the map
|
||||
this.statusCode = statusCode ?? getErrorStatus(code);
|
||||
}
|
||||
|
||||
toJSON(): ErrorResponse {
|
||||
return {
|
||||
error: this.code,
|
||||
message: this.message,
|
||||
...(process.env.NODE_ENV === 'development' && { stack: this.stack }),
|
||||
};
|
||||
}
|
||||
|
||||
toHonoResponse(c: Context) {
|
||||
return c.json(
|
||||
{
|
||||
success: false,
|
||||
...this.toJSON(),
|
||||
},
|
||||
this.statusCode,
|
||||
);
|
||||
}
|
||||
}
|
||||
30
packages/auth/server/lib/session.ts
Normal file
30
packages/auth/server/lib/session.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { AuthenticationErrorCode } from '../error-codes';
|
||||
import { AuthenticationError } from '../errors';
|
||||
|
||||
export const getSession = async (token: string) => {
|
||||
const result = await prisma.session.findUnique({
|
||||
where: {
|
||||
sessionToken: token,
|
||||
},
|
||||
include: {
|
||||
user: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
throw new AuthenticationError(AuthenticationErrorCode.SessionNotFound);
|
||||
}
|
||||
|
||||
if (result.expires < new Date()) {
|
||||
throw new AuthenticationError(AuthenticationErrorCode.SessionExpired);
|
||||
}
|
||||
|
||||
const { user, ...session } = result;
|
||||
|
||||
return {
|
||||
session,
|
||||
user,
|
||||
};
|
||||
};
|
||||
5
packages/auth/server/lib/tokens.ts
Normal file
5
packages/auth/server/lib/tokens.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { customAlphabet } from 'nanoid';
|
||||
|
||||
const sessionTokenId = customAlphabet('abcdefhiklmnorstuvwxz', 10);
|
||||
|
||||
export const createSessionToken = (length = 10) => `session_${sessionTokenId(length)}` as const;
|
||||
Reference in New Issue
Block a user