@mostajs/auth 2.3.0 → 2.3.2

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.
@@ -2,7 +2,7 @@
2
2
  // Author: Dr Hamid MADANI drmdh@msn.com
3
3
  'use client';
4
4
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
5
- import { usePermissions } from '../hooks/usePermissions';
5
+ import { usePermissions } from '../hooks/usePermissions.js';
6
6
  /**
7
7
  * Conditionally renders children based on user permissions.
8
8
  * Admin users bypass all permission checks.
package/dist/index.js CHANGED
@@ -2,11 +2,11 @@
2
2
  // Author: Dr Hamid MADANI drmdh@msn.com
3
3
  // For server-side code (repos, seed, auth handlers), use '@mostajs/auth/server'
4
4
  // Permission helpers (pure utilities — no external dependency)
5
- export { hasPermission, hasAllPermissions, hasAnyPermission } from './helpers/permissions';
5
+ export { hasPermission, hasAllPermissions, hasAnyPermission } from './helpers/permissions.js';
6
6
  // Schemas (re-export from rbac — pure data, no ORM)
7
7
  export { UserSchema, RoleSchema, PermissionSchema, PermissionCategorySchema } from '@mostajs/rbac';
8
8
  // Hooks
9
- export { usePermissions } from './hooks/usePermissions';
9
+ export { usePermissions } from './hooks/usePermissions.js';
10
10
  // Components
11
- export { default as PermissionGuard } from './components/PermissionGuard';
12
- export { default as SessionProvider } from './components/SessionProvider';
11
+ export { default as PermissionGuard } from './components/PermissionGuard.js';
12
+ export { default as SessionProvider } from './components/SessionProvider.js';
@@ -1,7 +1,7 @@
1
1
  // @mosta/auth — Server-side auth guards
2
2
  // Author: Dr Hamid MADANI drmdh@msn.com
3
3
  import { NextResponse } from 'next/server';
4
- import { hasPermission } from '../helpers/permissions';
4
+ import { hasPermission } from '../helpers/permissions.js';
5
5
  import { getPermissionsForRoleFromDB } from '@mostajs/rbac/lib/permissions-server';
6
6
  /**
7
7
  * Create server-side guard functions bound to your auth() instance.
package/dist/lib/auth.js CHANGED
@@ -5,7 +5,7 @@ import NextAuth from 'next-auth';
5
5
  import CredentialsProvider from 'next-auth/providers/credentials';
6
6
  import { getEnv } from '@mostajs/config';
7
7
  import { getRbacRepos } from '@mostajs/rbac/lib/repos-factory';
8
- import { comparePassword } from './password';
8
+ import { comparePassword } from './password.js';
9
9
  /**
10
10
  * Create NextAuth handlers configured for MostaAuth RBAC.
11
11
  *
package/dist/server.js CHANGED
@@ -2,13 +2,13 @@
2
2
  // Author: Dr Hamid MADANI drmdh@msn.com
3
3
  // Import from '@mostajs/auth/server' in API routes and server code
4
4
  // Auth handler factories (depend on ORM via rbac repos)
5
- export { createAuthHandlers } from './lib/auth';
6
- export { createAuthChecks } from './lib/auth-check';
7
- export { createAuthMiddleware } from './middleware/auth-middleware';
5
+ export { createAuthHandlers } from './lib/auth.js';
6
+ export { createAuthChecks } from './lib/auth-check.js';
7
+ export { createAuthMiddleware } from './middleware/auth-middleware.js';
8
8
  // Password utils
9
- export { hashPassword, comparePassword } from './lib/password';
9
+ export { hashPassword, comparePassword } from './lib/password.js';
10
10
  // Framework-agnostic request authorization (apikey + scope checks)
11
- export { checkRequest } from './lib/check-request';
11
+ export { checkRequest } from './lib/check-request.js';
12
12
  // Server-side permission DB lookup (re-export from rbac/server)
13
13
  export { getPermissionsForRoleFromDB } from '@mostajs/rbac/lib/permissions-server';
14
14
  // RBAC seed (re-export from rbac/server)
@@ -20,12 +20,12 @@ export { getSchemas, moduleInfo } from '@mostajs/rbac/lib/module-info';
20
20
  // Repositories (re-export from rbac/server)
21
21
  export { UserRepository, RoleRepository, PermissionRepository, PermissionCategoryRepository } from '@mostajs/rbac/server';
22
22
  // Registration
23
- export { createRegistrationHandler } from './lib/registration';
23
+ export { createRegistrationHandler } from './lib/registration.js';
24
24
  // Email verification
25
- export { createVerificationHandlers, generateVerifyToken } from './lib/email-verification';
25
+ export { createVerificationHandlers, generateVerifyToken } from './lib/email-verification.js';
26
26
  // Password reset
27
- export { createPasswordResetHandlers, generateResetToken } from './lib/password-reset';
27
+ export { createPasswordResetHandlers, generateResetToken } from './lib/password-reset.js';
28
28
  // API key provider
29
- export { createApiKeyProvider } from './lib/apikey-provider';
29
+ export { createApiKeyProvider } from './lib/apikey-provider.js';
30
30
  // Session enrichment
31
- export { enrichTokenWithPlan, enrichSessionWithPlan } from './lib/session-enrichment';
31
+ export { enrichTokenWithPlan, enrichSessionWithPlan } from './lib/session-enrichment.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mostajs/auth",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "description": "Authentication — NextAuth, password hashing, session management",
5
5
  "author": "Dr Hamid MADANI <drmdh@msn.com>",
6
6
  "license": "AGPL-3.0-or-later",
@@ -83,6 +83,11 @@
83
83
  "import": "./dist/lib/apikey-provider.js",
84
84
  "default": "./dist/lib/apikey-provider.js"
85
85
  },
86
+ "./lib/check-request": {
87
+ "types": "./dist/lib/check-request.d.ts",
88
+ "import": "./dist/lib/check-request.js",
89
+ "default": "./dist/lib/check-request.js"
90
+ },
86
91
  "./lib/session-enrichment": {
87
92
  "types": "./dist/lib/session-enrichment.d.ts",
88
93
  "import": "./dist/lib/session-enrichment.js",
@@ -114,7 +119,8 @@
114
119
  "node": ">=18.0.0"
115
120
  },
116
121
  "scripts": {
117
- "build": "tsc",
122
+ "build": "tsc && npm run fix-esm",
123
+ "fix-esm": "find dist -name '*.js' -exec sed -i -E \"s|from '(\\\\.{1,2}/[^']+)'(;?)|from '\\\\1.js'\\\\2|g; s|from \\\"(\\\\.{1,2}/[^\\\"]+)\\\"(;?)|from \\\"\\\\1.js\\\"\\\\2|g\" {} \\; && find dist -name '*.js' -exec sed -i -E \"s|\\\\.js\\\\.js|.js|g\" {} \\;",
118
124
  "prepublishOnly": "npm run build"
119
125
  },
120
126
  "dependencies": {
@@ -1,9 +0,0 @@
1
- /**
2
- * Check if a user has a specific permission.
3
- * Supports wildcard '*' for full access.
4
- */
5
- export declare function hasPermission(userPermissions: string[], requiredPermission: string): boolean;
6
- /**
7
- * Get permissions for a role from a static map.
8
- */
9
- export declare function getPermissionsForRole(rolePermissions: Record<string, string[]>, role: string): string[];
@@ -1,19 +0,0 @@
1
- // @mosta/auth — Permission helpers (client-safe)
2
- // Author: Dr Hamid MADANI drmdh@msn.com
3
- /**
4
- * Check if a user has a specific permission.
5
- * Supports wildcard '*' for full access.
6
- */
7
- export function hasPermission(userPermissions, requiredPermission) {
8
- if (!userPermissions || userPermissions.length === 0)
9
- return false;
10
- if (userPermissions.includes('*'))
11
- return true;
12
- return userPermissions.includes(requiredPermission);
13
- }
14
- /**
15
- * Get permissions for a role from a static map.
16
- */
17
- export function getPermissionsForRole(rolePermissions, role) {
18
- return rolePermissions[role] || [];
19
- }
@@ -1,15 +0,0 @@
1
- import type { CategoryDefinition, PermissionDefinition, RoleDefinition } from '../types/index';
2
- export interface SeedRBACOptions {
3
- categories: CategoryDefinition[];
4
- permissions: PermissionDefinition[];
5
- roles: Record<string, RoleDefinition>;
6
- }
7
- /**
8
- * Idempotent seed of categories, permissions and roles.
9
- * Uses upsert — safe to call multiple times.
10
- */
11
- export declare function seedRBAC(options: SeedRBACOptions): Promise<{
12
- categoryCount: number;
13
- permissionCount: number;
14
- roleCount: number;
15
- }>;
@@ -1,38 +0,0 @@
1
- // @mosta/auth — RBAC Seed function
2
- // Author: Dr Hamid MADANI drmdh@msn.com
3
- import { getDialect } from '@mostajs/orm';
4
- import { PermissionCategoryRepository } from '../repositories/permission-category.repository';
5
- import { PermissionRepository } from '../repositories/permission.repository';
6
- import { RoleRepository } from '../repositories/role.repository';
7
- /**
8
- * Idempotent seed of categories, permissions and roles.
9
- * Uses upsert — safe to call multiple times.
10
- */
11
- export async function seedRBAC(options) {
12
- const dialect = await getDialect();
13
- const catRepo = new PermissionCategoryRepository(dialect);
14
- const permRepo = new PermissionRepository(dialect);
15
- const roleRepo = new RoleRepository(dialect);
16
- // 1. Upsert categories
17
- for (const cat of options.categories) {
18
- await catRepo.upsert({ name: cat.name }, cat);
19
- }
20
- // 2. Upsert permissions — build code→id map
21
- const permissionMap = {};
22
- for (const pDef of options.permissions) {
23
- const perm = await permRepo.upsert({ name: pDef.name }, { name: pDef.name, description: pDef.description, category: pDef.category });
24
- permissionMap[pDef.code] = perm.id;
25
- }
26
- // 3. Upsert roles with permission IDs
27
- for (const [, roleDef] of Object.entries(options.roles)) {
28
- const permissionIds = roleDef.permissions
29
- .map((code) => permissionMap[code])
30
- .filter(Boolean);
31
- await roleRepo.upsert({ name: roleDef.name }, { name: roleDef.name, description: roleDef.description, permissions: permissionIds });
32
- }
33
- return {
34
- categoryCount: options.categories.length,
35
- permissionCount: options.permissions.length,
36
- roleCount: Object.keys(options.roles).length,
37
- };
38
- }
@@ -1,10 +0,0 @@
1
- import { BaseRepository } from '@mostajs/orm';
2
- import type { IDialect } from '@mostajs/orm';
3
- import type { PermissionCategoryDTO } from '../types/index';
4
- export declare class PermissionCategoryRepository extends BaseRepository<PermissionCategoryDTO> {
5
- constructor(dialect: IDialect);
6
- /** Find all sorted by order then name */
7
- findAllOrdered(): Promise<PermissionCategoryDTO[]>;
8
- /** Find by name (unique) */
9
- findByName(name: string): Promise<PermissionCategoryDTO | null>;
10
- }
@@ -1,17 +0,0 @@
1
- // @mosta/auth — PermissionCategoryRepository
2
- // Author: Dr Hamid MADANI drmdh@msn.com
3
- import { BaseRepository } from '@mostajs/orm';
4
- import { PermissionCategorySchema } from '../schemas/permission-category.schema';
5
- export class PermissionCategoryRepository extends BaseRepository {
6
- constructor(dialect) {
7
- super(PermissionCategorySchema, dialect);
8
- }
9
- /** Find all sorted by order then name */
10
- async findAllOrdered() {
11
- return this.findAll({}, { sort: { order: 1, name: 1 } });
12
- }
13
- /** Find by name (unique) */
14
- async findByName(name) {
15
- return this.findOne({ name });
16
- }
17
- }
@@ -1,12 +0,0 @@
1
- import { BaseRepository } from '@mostajs/orm';
2
- import type { IDialect } from '@mostajs/orm';
3
- import type { PermissionDTO } from '../types/index';
4
- export declare class PermissionRepository extends BaseRepository<PermissionDTO> {
5
- constructor(dialect: IDialect);
6
- /** Find all sorted by category then name */
7
- findAllSorted(): Promise<PermissionDTO[]>;
8
- /** Find by name (unique) */
9
- findByName(name: string): Promise<PermissionDTO | null>;
10
- /** Count permissions in a category */
11
- countByCategory(category: string): Promise<number>;
12
- }
@@ -1,21 +0,0 @@
1
- // @mosta/auth — PermissionRepository
2
- // Author: Dr Hamid MADANI drmdh@msn.com
3
- import { BaseRepository } from '@mostajs/orm';
4
- import { PermissionSchema } from '../schemas/permission.schema';
5
- export class PermissionRepository extends BaseRepository {
6
- constructor(dialect) {
7
- super(PermissionSchema, dialect);
8
- }
9
- /** Find all sorted by category then name */
10
- async findAllSorted() {
11
- return this.findAll({}, { sort: { category: 1, name: 1 } });
12
- }
13
- /** Find by name (unique) */
14
- async findByName(name) {
15
- return this.findOne({ name });
16
- }
17
- /** Count permissions in a category */
18
- async countByCategory(category) {
19
- return this.count({ category });
20
- }
21
- }
@@ -1,18 +0,0 @@
1
- import { BaseRepository } from '@mostajs/orm';
2
- import type { IDialect } from '@mostajs/orm';
3
- import type { RoleDTO } from '../types/index';
4
- export declare class RoleRepository extends BaseRepository<RoleDTO> {
5
- constructor(dialect: IDialect);
6
- /** Find all roles with permissions populated */
7
- findAllWithPermissions(): Promise<RoleDTO[]>;
8
- /** Find a role by name */
9
- findByName(name: string): Promise<RoleDTO | null>;
10
- /** Find role by ID with permissions populated */
11
- findByIdWithPermissions(id: string): Promise<RoleDTO | null>;
12
- /** Add a permission to a role */
13
- addPermission(roleId: string, permissionId: string): Promise<RoleDTO | null>;
14
- /** Remove a permission from a role */
15
- removePermission(roleId: string, permissionId: string): Promise<RoleDTO | null>;
16
- /** Remove a permission from ALL roles (cascade) */
17
- removePermissionFromAll(permissionId: string): Promise<number>;
18
- }
@@ -1,33 +0,0 @@
1
- // @mosta/auth — RoleRepository
2
- // Author: Dr Hamid MADANI drmdh@msn.com
3
- import { BaseRepository } from '@mostajs/orm';
4
- import { RoleSchema } from '../schemas/role.schema';
5
- export class RoleRepository extends BaseRepository {
6
- constructor(dialect) {
7
- super(RoleSchema, dialect);
8
- }
9
- /** Find all roles with permissions populated */
10
- async findAllWithPermissions() {
11
- return this.findWithRelations({}, ['permissions']);
12
- }
13
- /** Find a role by name */
14
- async findByName(name) {
15
- return this.findOne({ name });
16
- }
17
- /** Find role by ID with permissions populated */
18
- async findByIdWithPermissions(id) {
19
- return this.findByIdWithRelations(id, ['permissions']);
20
- }
21
- /** Add a permission to a role */
22
- async addPermission(roleId, permissionId) {
23
- return this.addToSet(roleId, 'permissions', permissionId);
24
- }
25
- /** Remove a permission from a role */
26
- async removePermission(roleId, permissionId) {
27
- return this.pull(roleId, 'permissions', permissionId);
28
- }
29
- /** Remove a permission from ALL roles (cascade) */
30
- async removePermissionFromAll(permissionId) {
31
- return this.updateMany({ permissions: permissionId }, { $pull: { permissions: permissionId } });
32
- }
33
- }
@@ -1,24 +0,0 @@
1
- import { BaseRepository } from '@mostajs/orm';
2
- import type { IDialect, FilterQuery, QueryOptions } from '@mostajs/orm';
3
- import type { UserDTO } from '../types/index';
4
- export declare class UserRepository extends BaseRepository<UserDTO> {
5
- constructor(dialect: IDialect);
6
- /** List users without password field */
7
- findAllSafe(filter?: FilterQuery, options?: QueryOptions): Promise<UserDTO[]>;
8
- /** Find a single user by ID without password */
9
- findByIdSafe(id: string): Promise<UserDTO | null>;
10
- /** Find user by email (for authentication) */
11
- findByEmail(email: string): Promise<UserDTO | null>;
12
- /** Update lastLoginAt timestamp */
13
- updateLastLogin(id: string): Promise<void>;
14
- /** Find user by ID with roles populated */
15
- findByIdWithRoles(id: string): Promise<UserDTO | null>;
16
- /** Find all users with roles populated (no password) */
17
- findAllWithRoles(filter?: FilterQuery, options?: QueryOptions): Promise<UserDTO[]>;
18
- /** Count users having a specific role */
19
- countByRole(roleId: string): Promise<number>;
20
- /** Add a role to a user */
21
- addRole(userId: string, roleId: string): Promise<UserDTO | null>;
22
- /** Remove a role from a user */
23
- removeRole(userId: string, roleId: string): Promise<UserDTO | null>;
24
- }
@@ -1,45 +0,0 @@
1
- // @mosta/auth — UserRepository
2
- // Author: Dr Hamid MADANI drmdh@msn.com
3
- import { BaseRepository } from '@mostajs/orm';
4
- import { UserSchema } from '../schemas/user.schema';
5
- export class UserRepository extends BaseRepository {
6
- constructor(dialect) {
7
- super(UserSchema, dialect);
8
- }
9
- /** List users without password field */
10
- async findAllSafe(filter = {}, options) {
11
- return this.findAll(filter, { ...options, exclude: ['password'] });
12
- }
13
- /** Find a single user by ID without password */
14
- async findByIdSafe(id) {
15
- return this.findById(id, { exclude: ['password'] });
16
- }
17
- /** Find user by email (for authentication) */
18
- async findByEmail(email) {
19
- return this.findOne({ email: email.toLowerCase() });
20
- }
21
- /** Update lastLoginAt timestamp */
22
- async updateLastLogin(id) {
23
- await this.update(id, { lastLoginAt: new Date() });
24
- }
25
- /** Find user by ID with roles populated */
26
- async findByIdWithRoles(id) {
27
- return this.findByIdWithRelations(id, ['roles']);
28
- }
29
- /** Find all users with roles populated (no password) */
30
- async findAllWithRoles(filter = {}, options) {
31
- return this.findWithRelations(filter, ['roles'], { ...options, exclude: ['password'] });
32
- }
33
- /** Count users having a specific role */
34
- async countByRole(roleId) {
35
- return this.count({ roles: roleId });
36
- }
37
- /** Add a role to a user */
38
- async addRole(userId, roleId) {
39
- return this.addToSet(userId, 'roles', roleId);
40
- }
41
- /** Remove a role from a user */
42
- async removeRole(userId, roleId) {
43
- return this.pull(userId, 'roles', roleId);
44
- }
45
- }
@@ -1,2 +0,0 @@
1
- import type { EntitySchema } from '@mostajs/orm';
2
- export declare const PermissionCategorySchema: EntitySchema;
@@ -1,17 +0,0 @@
1
- export const PermissionCategorySchema = {
2
- name: 'PermissionCategory',
3
- collection: 'permission_categories',
4
- timestamps: true,
5
- fields: {
6
- name: { type: 'string', required: true, unique: true, lowercase: true, trim: true },
7
- label: { type: 'string', required: true, trim: true },
8
- description: { type: 'string' },
9
- icon: { type: 'string' },
10
- order: { type: 'number', default: 0 },
11
- system: { type: 'boolean', default: false },
12
- },
13
- relations: {},
14
- indexes: [
15
- { fields: { order: 'asc', name: 'asc' } },
16
- ],
17
- };
@@ -1,2 +0,0 @@
1
- import type { EntitySchema } from '@mostajs/orm';
2
- export declare const PermissionSchema: EntitySchema;
@@ -1,12 +0,0 @@
1
- export const PermissionSchema = {
2
- name: 'Permission',
3
- collection: 'permissions',
4
- timestamps: true,
5
- fields: {
6
- name: { type: 'string', required: true, unique: true },
7
- description: { type: 'string' },
8
- category: { type: 'string' },
9
- },
10
- relations: {},
11
- indexes: [],
12
- };
@@ -1,2 +0,0 @@
1
- import type { EntitySchema } from '@mostajs/orm';
2
- export declare const RoleSchema: EntitySchema;
@@ -1,13 +0,0 @@
1
- export const RoleSchema = {
2
- name: 'Role',
3
- collection: 'roles',
4
- timestamps: true,
5
- fields: {
6
- name: { type: 'string', required: true, unique: true },
7
- description: { type: 'string' },
8
- },
9
- relations: {
10
- permissions: { target: 'Permission', type: 'many-to-many', through: 'role_permissions' },
11
- },
12
- indexes: [],
13
- };
@@ -1,2 +0,0 @@
1
- import type { EntitySchema } from '@mostajs/orm';
2
- export declare const UserSchema: EntitySchema;
@@ -1,20 +0,0 @@
1
- export const UserSchema = {
2
- name: 'User',
3
- collection: 'users',
4
- timestamps: true,
5
- fields: {
6
- email: { type: 'string', required: true, unique: true, lowercase: true, trim: true },
7
- password: { type: 'string', required: true },
8
- firstName: { type: 'string', required: true, trim: true },
9
- lastName: { type: 'string', required: true, trim: true },
10
- phone: { type: 'string', trim: true },
11
- status: { type: 'string', enum: ['active', 'locked', 'disabled'], default: 'active' },
12
- lastLoginAt: { type: 'date' },
13
- },
14
- relations: {
15
- roles: { target: 'Role', type: 'many-to-many', through: 'user_roles' },
16
- },
17
- indexes: [
18
- { fields: { status: 'asc' } },
19
- ],
20
- };