Initial commit: add .gitignore and README
This commit is contained in:
31
packages/shared-auth/package.json
Normal file
31
packages/shared-auth/package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@workspace/shared-auth",
|
||||
"version": "1.0.0",
|
||||
"description": "Shared authentication and authorization utilities",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "vitest",
|
||||
"lint": "eslint src",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"bcryptjs": "^2.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.5.4",
|
||||
"@types/jsonwebtoken": "^9.0.4",
|
||||
"@types/bcryptjs": "^2.4.6",
|
||||
"vitest": "^1.2.0"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "restricted"
|
||||
}
|
||||
}
|
||||
|
||||
10
packages/shared-auth/src/index.ts
Normal file
10
packages/shared-auth/src/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @workspace/shared-auth
|
||||
* Shared authentication and authorization utilities
|
||||
*/
|
||||
|
||||
export * from './jwt';
|
||||
export * from './password';
|
||||
export * from './permissions';
|
||||
export * from './types';
|
||||
|
||||
55
packages/shared-auth/src/jwt.ts
Normal file
55
packages/shared-auth/src/jwt.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* JWT token utilities
|
||||
*/
|
||||
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
export interface TokenPayload {
|
||||
userId: string;
|
||||
email: string;
|
||||
roles?: string[];
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface TokenOptions {
|
||||
expiresIn?: string | number;
|
||||
issuer?: string;
|
||||
audience?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate JWT token
|
||||
*/
|
||||
export function generateToken(
|
||||
payload: TokenPayload,
|
||||
secret: string,
|
||||
options?: TokenOptions
|
||||
): string {
|
||||
return jwt.sign(payload, secret, {
|
||||
expiresIn: options?.expiresIn || '24h',
|
||||
issuer: options?.issuer,
|
||||
audience: options?.audience,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify JWT token
|
||||
*/
|
||||
export function verifyToken<T extends TokenPayload>(
|
||||
token: string,
|
||||
secret: string
|
||||
): T {
|
||||
return jwt.verify(token, secret) as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode JWT token (without verification)
|
||||
*/
|
||||
export function decodeToken<T extends TokenPayload>(token: string): T | null {
|
||||
try {
|
||||
return jwt.decode(token) as T;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
25
packages/shared-auth/src/password.ts
Normal file
25
packages/shared-auth/src/password.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Password hashing utilities
|
||||
*/
|
||||
|
||||
import bcrypt from 'bcryptjs';
|
||||
|
||||
const SALT_ROUNDS = 10;
|
||||
|
||||
/**
|
||||
* Hash password
|
||||
*/
|
||||
export async function hashPassword(password: string): Promise<string> {
|
||||
return bcrypt.hash(password, SALT_ROUNDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify password
|
||||
*/
|
||||
export async function verifyPassword(
|
||||
password: string,
|
||||
hash: string
|
||||
): Promise<boolean> {
|
||||
return bcrypt.compare(password, hash);
|
||||
}
|
||||
|
||||
63
packages/shared-auth/src/permissions.ts
Normal file
63
packages/shared-auth/src/permissions.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Permission checking utilities
|
||||
*/
|
||||
|
||||
export type Permission = string;
|
||||
export type Role = string;
|
||||
|
||||
export interface UserPermissions {
|
||||
roles: Role[];
|
||||
permissions: Permission[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has role
|
||||
*/
|
||||
export function hasRole(user: UserPermissions, role: Role): boolean {
|
||||
return user.roles.includes(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has permission
|
||||
*/
|
||||
export function hasPermission(
|
||||
user: UserPermissions,
|
||||
permission: Permission
|
||||
): boolean {
|
||||
return user.permissions.includes(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has any of the required roles
|
||||
*/
|
||||
export function hasAnyRole(user: UserPermissions, roles: Role[]): boolean {
|
||||
return roles.some((role) => hasRole(user, role));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has all required roles
|
||||
*/
|
||||
export function hasAllRoles(user: UserPermissions, roles: Role[]): boolean {
|
||||
return roles.every((role) => hasRole(user, role));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has any of the required permissions
|
||||
*/
|
||||
export function hasAnyPermission(
|
||||
user: UserPermissions,
|
||||
permissions: Permission[]
|
||||
): boolean {
|
||||
return permissions.some((permission) => hasPermission(user, permission));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has all required permissions
|
||||
*/
|
||||
export function hasAllPermissions(
|
||||
user: UserPermissions,
|
||||
permissions: Permission[]
|
||||
): boolean {
|
||||
return permissions.every((permission) => hasPermission(user, permission));
|
||||
}
|
||||
|
||||
23
packages/shared-auth/src/types.ts
Normal file
23
packages/shared-auth/src/types.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Authentication and authorization types
|
||||
*/
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
roles: string[];
|
||||
permissions: string[];
|
||||
}
|
||||
|
||||
export interface AuthContext {
|
||||
user: User | null;
|
||||
isAuthenticated: boolean;
|
||||
}
|
||||
|
||||
export interface Session {
|
||||
userId: string;
|
||||
token: string;
|
||||
expiresAt: Date;
|
||||
refreshToken?: string;
|
||||
}
|
||||
|
||||
20
packages/shared-auth/tsconfig.json
Normal file
20
packages/shared-auth/tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2022"],
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user