@mostajs/auth 1.0.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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -0
  3. package/dist/components/PermissionGuard.d.ts +19 -0
  4. package/dist/components/PermissionGuard.js +23 -0
  5. package/dist/components/SessionProvider.d.ts +4 -0
  6. package/dist/components/SessionProvider.js +11 -0
  7. package/dist/hooks/usePermissions.d.ts +15 -0
  8. package/dist/hooks/usePermissions.js +48 -0
  9. package/dist/index.d.ts +20 -0
  10. package/dist/index.js +55 -0
  11. package/dist/lib/auth-check.d.ts +42 -0
  12. package/dist/lib/auth-check.js +55 -0
  13. package/dist/lib/auth.d.ts +14 -0
  14. package/dist/lib/auth.js +139 -0
  15. package/dist/lib/password.d.ts +2 -0
  16. package/dist/lib/password.js +17 -0
  17. package/dist/lib/permissions-server.d.ts +5 -0
  18. package/dist/lib/permissions-server.js +27 -0
  19. package/dist/lib/permissions.d.ts +9 -0
  20. package/dist/lib/permissions.js +23 -0
  21. package/dist/lib/rbac-seed.d.ts +15 -0
  22. package/dist/lib/rbac-seed.js +41 -0
  23. package/dist/middleware/auth-middleware.d.ts +13 -0
  24. package/dist/middleware/auth-middleware.js +33 -0
  25. package/dist/repositories/permission-category.repository.d.ts +10 -0
  26. package/dist/repositories/permission-category.repository.js +21 -0
  27. package/dist/repositories/permission.repository.d.ts +12 -0
  28. package/dist/repositories/permission.repository.js +25 -0
  29. package/dist/repositories/role.repository.d.ts +18 -0
  30. package/dist/repositories/role.repository.js +37 -0
  31. package/dist/repositories/user.repository.d.ts +24 -0
  32. package/dist/repositories/user.repository.js +49 -0
  33. package/dist/schemas/permission-category.schema.d.ts +2 -0
  34. package/dist/schemas/permission-category.schema.js +20 -0
  35. package/dist/schemas/permission.schema.d.ts +2 -0
  36. package/dist/schemas/permission.schema.js +15 -0
  37. package/dist/schemas/role.schema.d.ts +2 -0
  38. package/dist/schemas/role.schema.js +16 -0
  39. package/dist/schemas/user.schema.d.ts +2 -0
  40. package/dist/schemas/user.schema.js +23 -0
  41. package/dist/types/index.d.ts +81 -0
  42. package/dist/types/index.js +4 -0
  43. package/package.json +79 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Dr Hamid MADANI <drmdh@msn.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # @mostajs/auth
2
+
3
+ > Reusable authentication and RBAC module — NextAuth + Users + Roles + Permissions.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@mostajs/auth.svg)](https://www.npmjs.com/package/@mostajs/auth)
6
+ [![license](https://img.shields.io/npm/l/@mostajs/auth.svg)](LICENSE)
7
+
8
+ Part of the [@mosta suite](https://mostajs.dev).
9
+
10
+ ---
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @mostajs/auth @mostajs/orm bcryptjs next-auth@beta
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ### 1. Register schemas
21
+
22
+ ```typescript
23
+ import { registerSchemas } from '@mostajs/orm'
24
+ import { UserSchema, RoleSchema, PermissionSchema, PermissionCategorySchema } from '@mostajs/auth'
25
+
26
+ registerSchemas([UserSchema, RoleSchema, PermissionSchema, PermissionCategorySchema])
27
+ ```
28
+
29
+ ### 2. Create auth handlers
30
+
31
+ ```typescript
32
+ import { createAuthHandlers, createAuthChecks } from '@mostajs/auth'
33
+
34
+ const ROLE_PERMISSIONS = {
35
+ admin: ['*'],
36
+ editor: ['dashboard:view', 'user:view'],
37
+ }
38
+
39
+ const { handlers, auth, signIn, signOut } = createAuthHandlers(ROLE_PERMISSIONS)
40
+ const { checkAuth, checkPermission } = createAuthChecks(auth, ROLE_PERMISSIONS)
41
+
42
+ export { handlers, auth, checkAuth, checkPermission }
43
+ ```
44
+
45
+ ### 3. Protect API routes
46
+
47
+ ```typescript
48
+ export async function GET(req: Request) {
49
+ const { error, session } = await checkPermission('user:view')
50
+ if (error) return error
51
+ // ...
52
+ }
53
+ ```
54
+
55
+ ### 4. Client-side permission guard
56
+
57
+ ```tsx
58
+ import PermissionGuard from '@mostajs/auth/components/PermissionGuard'
59
+
60
+ <PermissionGuard permissions={['user:delete']}>
61
+ <DeleteButton />
62
+ </PermissionGuard>
63
+ ```
64
+
65
+ ## API Reference
66
+
67
+ | Export | Description |
68
+ |--------|-------------|
69
+ | `createAuthHandlers()` | NextAuth configuration factory |
70
+ | `createAuthChecks()` | Server-side `checkAuth()` / `checkPermission()` |
71
+ | `createAuthMiddleware()` | Next.js middleware for route protection |
72
+ | `seedRBAC()` | Idempotent seed of categories, permissions, roles |
73
+ | `hashPassword()` / `comparePassword()` | bcryptjs wrappers |
74
+ | `hasPermission()` / `getPermissionsForRole()` | Client-safe permission helpers |
75
+ | `usePermissions()` | React hook for permission checking |
76
+ | `PermissionGuard` | Conditional render component |
77
+ | `SessionProvider` | NextAuth session wrapper |
78
+ | `UserRepository` / `RoleRepository` / `PermissionRepository` | Database repositories |
79
+
80
+ ## Related Packages
81
+
82
+ - [@mostajs/orm](https://www.npmjs.com/package/@mostajs/orm) — Multi-dialect ORM (required)
83
+ - [@mostajs/audit](https://www.npmjs.com/package/@mostajs/audit) — Audit logging
84
+
85
+ ## License
86
+
87
+ MIT — © 2025 Dr Hamid MADANI <drmdh@msn.com>
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ interface PermissionGuardProps {
3
+ /** Required permissions */
4
+ permissions: string[];
5
+ /** Require ALL permissions (AND) vs any (OR). Default: false (OR). */
6
+ requireAll?: boolean;
7
+ /** Content shown if authorized */
8
+ children: React.ReactNode;
9
+ /** Content shown if unauthorized (default: null) */
10
+ fallback?: React.ReactNode;
11
+ /** Admin role name for bypass (default: 'admin') */
12
+ adminRole?: string;
13
+ }
14
+ /**
15
+ * Conditionally renders children based on user permissions.
16
+ * Admin users bypass all permission checks.
17
+ */
18
+ export default function PermissionGuard({ permissions, requireAll, children, fallback, adminRole, }: PermissionGuardProps): import("react/jsx-runtime").JSX.Element;
19
+ export {};
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ // @mosta/auth — PermissionGuard component
3
+ // Author: Dr Hamid MADANI drmdh@msn.com
4
+ 'use client';
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = PermissionGuard;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const usePermissions_1 = require("../hooks/usePermissions");
9
+ /**
10
+ * Conditionally renders children based on user permissions.
11
+ * Admin users bypass all permission checks.
12
+ */
13
+ function PermissionGuard({ permissions, requireAll = false, children, fallback = null, adminRole = 'admin', }) {
14
+ const { hasPermission, hasAnyPermission, isAdmin } = (0, usePermissions_1.usePermissions)(adminRole);
15
+ if (isAdmin())
16
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
17
+ const hasAccess = requireAll
18
+ ? permissions.every((p) => hasPermission(p))
19
+ : hasAnyPermission(permissions);
20
+ if (!hasAccess)
21
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: fallback });
22
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
23
+ }
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export default function SessionProvider({ children }: {
3
+ children: React.ReactNode;
4
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ // @mosta/auth — NextAuth SessionProvider wrapper
3
+ // Author: Dr Hamid MADANI drmdh@msn.com
4
+ 'use client';
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = SessionProvider;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_1 = require("next-auth/react");
9
+ function SessionProvider({ children }) {
10
+ return (0, jsx_runtime_1.jsx)(react_1.SessionProvider, { children: children });
11
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Client-side hook for permission checking.
3
+ * Reads permissions from the NextAuth session.
4
+ *
5
+ * @param adminRole - The role name considered as admin (default: 'admin')
6
+ */
7
+ export declare function usePermissions(adminRole?: string): {
8
+ permissions: string[];
9
+ role: string;
10
+ hasPermission: (permission: string) => boolean;
11
+ hasAnyPermission: (permissions: string[]) => boolean;
12
+ hasRole: (role: string) => boolean;
13
+ isAdmin: () => boolean;
14
+ canAccess: (permission: string) => boolean;
15
+ };
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ // @mosta/auth — usePermissions hook (client-side)
3
+ // Author: Dr Hamid MADANI drmdh@msn.com
4
+ 'use client';
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.usePermissions = usePermissions;
7
+ const react_1 = require("next-auth/react");
8
+ /**
9
+ * Client-side hook for permission checking.
10
+ * Reads permissions from the NextAuth session.
11
+ *
12
+ * @param adminRole - The role name considered as admin (default: 'admin')
13
+ */
14
+ function usePermissions(adminRole = 'admin') {
15
+ const { data: session } = (0, react_1.useSession)();
16
+ const userPermissions = session?.user?.permissions || [];
17
+ const userRole = session?.user?.role || '';
18
+ function hasPermission(permission) {
19
+ if (!userPermissions || userPermissions.length === 0)
20
+ return false;
21
+ if (userPermissions.includes('*'))
22
+ return true;
23
+ return userPermissions.includes(permission);
24
+ }
25
+ function hasAnyPermission(permissions) {
26
+ return permissions.some((p) => hasPermission(p));
27
+ }
28
+ function hasRole(role) {
29
+ return userRole === role;
30
+ }
31
+ function isAdmin() {
32
+ return userRole === adminRole;
33
+ }
34
+ function canAccess(permission) {
35
+ if (isAdmin())
36
+ return true;
37
+ return hasPermission(permission);
38
+ }
39
+ return {
40
+ permissions: userPermissions,
41
+ role: userRole,
42
+ hasPermission,
43
+ hasAnyPermission,
44
+ hasRole,
45
+ isAdmin,
46
+ canAccess,
47
+ };
48
+ }
@@ -0,0 +1,20 @@
1
+ export { createAuthHandlers } from './lib/auth';
2
+ export { createAuthChecks } from './lib/auth-check';
3
+ export { createAuthMiddleware } from './middleware/auth-middleware';
4
+ export { hashPassword, comparePassword } from './lib/password';
5
+ export { hasPermission, getPermissionsForRole } from './lib/permissions';
6
+ export { getPermissionsForRoleFromDB } from './lib/permissions-server';
7
+ export { seedRBAC } from './lib/rbac-seed';
8
+ export type { SeedRBACOptions } from './lib/rbac-seed';
9
+ export { UserSchema } from './schemas/user.schema';
10
+ export { RoleSchema } from './schemas/role.schema';
11
+ export { PermissionSchema } from './schemas/permission.schema';
12
+ export { PermissionCategorySchema } from './schemas/permission-category.schema';
13
+ export { UserRepository } from './repositories/user.repository';
14
+ export { RoleRepository } from './repositories/role.repository';
15
+ export { PermissionRepository } from './repositories/permission.repository';
16
+ export { PermissionCategoryRepository } from './repositories/permission-category.repository';
17
+ export { usePermissions } from './hooks/usePermissions';
18
+ export { default as PermissionGuard } from './components/PermissionGuard';
19
+ export { default as SessionProvider } from './components/SessionProvider';
20
+ export type { MostaAuthConfig, PermissionDefinition, RoleDefinition, CategoryDefinition, UserDTO, RoleDTO, PermissionDTO, PermissionCategoryDTO, } from './types';
package/dist/index.js ADDED
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ // @mosta/auth — Barrel exports
3
+ // Author: Dr Hamid MADANI drmdh@msn.com
4
+ var __importDefault = (this && this.__importDefault) || function (mod) {
5
+ return (mod && mod.__esModule) ? mod : { "default": mod };
6
+ };
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.SessionProvider = exports.PermissionGuard = exports.usePermissions = exports.PermissionCategoryRepository = exports.PermissionRepository = exports.RoleRepository = exports.UserRepository = exports.PermissionCategorySchema = exports.PermissionSchema = exports.RoleSchema = exports.UserSchema = exports.seedRBAC = exports.getPermissionsForRoleFromDB = exports.getPermissionsForRole = exports.hasPermission = exports.comparePassword = exports.hashPassword = exports.createAuthMiddleware = exports.createAuthChecks = exports.createAuthHandlers = void 0;
9
+ // Auth factory
10
+ var auth_1 = require("./lib/auth");
11
+ Object.defineProperty(exports, "createAuthHandlers", { enumerable: true, get: function () { return auth_1.createAuthHandlers; } });
12
+ var auth_check_1 = require("./lib/auth-check");
13
+ Object.defineProperty(exports, "createAuthChecks", { enumerable: true, get: function () { return auth_check_1.createAuthChecks; } });
14
+ var auth_middleware_1 = require("./middleware/auth-middleware");
15
+ Object.defineProperty(exports, "createAuthMiddleware", { enumerable: true, get: function () { return auth_middleware_1.createAuthMiddleware; } });
16
+ // Password utils
17
+ var password_1 = require("./lib/password");
18
+ Object.defineProperty(exports, "hashPassword", { enumerable: true, get: function () { return password_1.hashPassword; } });
19
+ Object.defineProperty(exports, "comparePassword", { enumerable: true, get: function () { return password_1.comparePassword; } });
20
+ // Permission helpers (client-safe)
21
+ var permissions_1 = require("./lib/permissions");
22
+ Object.defineProperty(exports, "hasPermission", { enumerable: true, get: function () { return permissions_1.hasPermission; } });
23
+ Object.defineProperty(exports, "getPermissionsForRole", { enumerable: true, get: function () { return permissions_1.getPermissionsForRole; } });
24
+ // Server-side permission DB lookup
25
+ var permissions_server_1 = require("./lib/permissions-server");
26
+ Object.defineProperty(exports, "getPermissionsForRoleFromDB", { enumerable: true, get: function () { return permissions_server_1.getPermissionsForRoleFromDB; } });
27
+ // RBAC seed
28
+ var rbac_seed_1 = require("./lib/rbac-seed");
29
+ Object.defineProperty(exports, "seedRBAC", { enumerable: true, get: function () { return rbac_seed_1.seedRBAC; } });
30
+ // Schemas
31
+ var user_schema_1 = require("./schemas/user.schema");
32
+ Object.defineProperty(exports, "UserSchema", { enumerable: true, get: function () { return user_schema_1.UserSchema; } });
33
+ var role_schema_1 = require("./schemas/role.schema");
34
+ Object.defineProperty(exports, "RoleSchema", { enumerable: true, get: function () { return role_schema_1.RoleSchema; } });
35
+ var permission_schema_1 = require("./schemas/permission.schema");
36
+ Object.defineProperty(exports, "PermissionSchema", { enumerable: true, get: function () { return permission_schema_1.PermissionSchema; } });
37
+ var permission_category_schema_1 = require("./schemas/permission-category.schema");
38
+ Object.defineProperty(exports, "PermissionCategorySchema", { enumerable: true, get: function () { return permission_category_schema_1.PermissionCategorySchema; } });
39
+ // Repositories
40
+ var user_repository_1 = require("./repositories/user.repository");
41
+ Object.defineProperty(exports, "UserRepository", { enumerable: true, get: function () { return user_repository_1.UserRepository; } });
42
+ var role_repository_1 = require("./repositories/role.repository");
43
+ Object.defineProperty(exports, "RoleRepository", { enumerable: true, get: function () { return role_repository_1.RoleRepository; } });
44
+ var permission_repository_1 = require("./repositories/permission.repository");
45
+ Object.defineProperty(exports, "PermissionRepository", { enumerable: true, get: function () { return permission_repository_1.PermissionRepository; } });
46
+ var permission_category_repository_1 = require("./repositories/permission-category.repository");
47
+ Object.defineProperty(exports, "PermissionCategoryRepository", { enumerable: true, get: function () { return permission_category_repository_1.PermissionCategoryRepository; } });
48
+ // Hooks
49
+ var usePermissions_1 = require("./hooks/usePermissions");
50
+ Object.defineProperty(exports, "usePermissions", { enumerable: true, get: function () { return usePermissions_1.usePermissions; } });
51
+ // Components
52
+ var PermissionGuard_1 = require("./components/PermissionGuard");
53
+ Object.defineProperty(exports, "PermissionGuard", { enumerable: true, get: function () { return __importDefault(PermissionGuard_1).default; } });
54
+ var SessionProvider_1 = require("./components/SessionProvider");
55
+ Object.defineProperty(exports, "SessionProvider", { enumerable: true, get: function () { return __importDefault(SessionProvider_1).default; } });
@@ -0,0 +1,42 @@
1
+ import { NextResponse } from 'next/server';
2
+ type AuthFn = () => Promise<any>;
3
+ /**
4
+ * Create server-side guard functions bound to your auth() instance.
5
+ *
6
+ * Usage:
7
+ * const { checkAuth, checkPermission, getUserFromSession } = createAuthChecks(auth)
8
+ */
9
+ export declare function createAuthChecks(auth: AuthFn, fallbackMap?: Record<string, string[]>): {
10
+ checkAuth: () => Promise<{
11
+ error: NextResponse<{
12
+ error: {
13
+ code: string;
14
+ message: string;
15
+ };
16
+ }>;
17
+ session: null;
18
+ } | {
19
+ error: null;
20
+ session: any;
21
+ }>;
22
+ checkPermission: (requiredPermission: string) => Promise<{
23
+ error: NextResponse<{
24
+ error: {
25
+ code: string;
26
+ message: string;
27
+ };
28
+ }>;
29
+ session: null;
30
+ } | {
31
+ error: null;
32
+ session: any;
33
+ }>;
34
+ getUserFromSession: (session: any) => {
35
+ id: any;
36
+ email: any;
37
+ name: any;
38
+ role: any;
39
+ permissions: any;
40
+ };
41
+ };
42
+ export {};
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAuthChecks = createAuthChecks;
4
+ // @mosta/auth — Server-side auth guards
5
+ // Author: Dr Hamid MADANI drmdh@msn.com
6
+ const server_1 = require("next/server");
7
+ const permissions_1 = require("./permissions");
8
+ const permissions_server_1 = require("./permissions-server");
9
+ /**
10
+ * Create server-side guard functions bound to your auth() instance.
11
+ *
12
+ * Usage:
13
+ * const { checkAuth, checkPermission, getUserFromSession } = createAuthChecks(auth)
14
+ */
15
+ function createAuthChecks(auth, fallbackMap) {
16
+ async function checkAuth() {
17
+ const session = await auth();
18
+ if (!session?.user) {
19
+ return {
20
+ error: server_1.NextResponse.json({ error: { code: 'UNAUTHORIZED', message: 'Non authentifié' } }, { status: 401 }),
21
+ session: null,
22
+ };
23
+ }
24
+ return { error: null, session };
25
+ }
26
+ async function checkPermission(requiredPermission) {
27
+ const { error, session } = await checkAuth();
28
+ if (error)
29
+ return { error, session: null };
30
+ let userPermissions = session.user.permissions || [];
31
+ if (userPermissions.length === 0) {
32
+ const role = session.user.role;
33
+ if (role) {
34
+ userPermissions = await (0, permissions_server_1.getPermissionsForRoleFromDB)(role, fallbackMap);
35
+ }
36
+ }
37
+ if (!(0, permissions_1.hasPermission)(userPermissions, requiredPermission)) {
38
+ return {
39
+ error: server_1.NextResponse.json({ error: { code: 'FORBIDDEN', message: 'Permission insuffisante' } }, { status: 403 }),
40
+ session: null,
41
+ };
42
+ }
43
+ return { error: null, session: session };
44
+ }
45
+ function getUserFromSession(session) {
46
+ return {
47
+ id: session.user.id,
48
+ email: session.user.email,
49
+ name: session.user.name,
50
+ role: session.user.role,
51
+ permissions: session.user.permissions || [],
52
+ };
53
+ }
54
+ return { checkAuth, checkPermission, getUserFromSession };
55
+ }
@@ -0,0 +1,14 @@
1
+ import type { MostaAuthConfig } from '../types';
2
+ /**
3
+ * Create NextAuth handlers configured for MostaAuth RBAC.
4
+ *
5
+ * @param rolePermissions - Static role→permissions map (used as fallback)
6
+ * @param config - Optional MostaAuthConfig overrides
7
+ */
8
+ export declare function createAuthHandlers(rolePermissions: Record<string, string[]>, config?: MostaAuthConfig): {
9
+ handlers: any;
10
+ auth: any;
11
+ signIn: any;
12
+ signOut: any;
13
+ getServerSession: any;
14
+ };
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createAuthHandlers = createAuthHandlers;
7
+ // @mosta/auth — NextAuth configuration factory
8
+ // Author: Dr Hamid MADANI drmdh@msn.com
9
+ const next_auth_1 = __importDefault(require("next-auth"));
10
+ const credentials_1 = __importDefault(require("next-auth/providers/credentials"));
11
+ const orm_1 = require("@mostajs/orm");
12
+ const user_repository_1 = require("../repositories/user.repository");
13
+ const role_repository_1 = require("../repositories/role.repository");
14
+ const password_1 = require("./password");
15
+ /**
16
+ * Create NextAuth handlers configured for MostaAuth RBAC.
17
+ *
18
+ * @param rolePermissions - Static role→permissions map (used as fallback)
19
+ * @param config - Optional MostaAuthConfig overrides
20
+ */
21
+ function createAuthHandlers(rolePermissions, config) {
22
+ const { handlers, auth, signIn, signOut } = (0, next_auth_1.default)({
23
+ secret: process.env.AUTH_SECRET || process.env.NEXTAUTH_SECRET,
24
+ trustHost: true,
25
+ debug: false,
26
+ useSecureCookies: false,
27
+ cookies: {
28
+ sessionToken: {
29
+ name: 'authjs.session-token',
30
+ options: { httpOnly: true, sameSite: 'lax', path: '/', secure: false },
31
+ },
32
+ },
33
+ providers: [
34
+ (0, credentials_1.default)({
35
+ name: 'credentials',
36
+ credentials: {
37
+ email: { label: 'Email', type: 'email' },
38
+ password: { label: 'Password', type: 'password' },
39
+ },
40
+ async authorize(credentials) {
41
+ if (!credentials?.email || !credentials?.password)
42
+ return null;
43
+ const uRepo = new user_repository_1.UserRepository(await (0, orm_1.getDialect)());
44
+ const user = await uRepo.findByEmail(credentials.email);
45
+ if (!user)
46
+ return null;
47
+ if (user.status !== 'active')
48
+ return null;
49
+ const valid = await (0, password_1.comparePassword)(credentials.password, user.password);
50
+ if (!valid)
51
+ return null;
52
+ await uRepo.updateLastLogin(user.id);
53
+ const { roleNames, permissions } = await resolveUserPermissions(user.id, rolePermissions);
54
+ return {
55
+ id: user.id,
56
+ email: user.email,
57
+ name: `${user.firstName} ${user.lastName}`,
58
+ role: roleNames[0] || '',
59
+ roles: roleNames,
60
+ permissions,
61
+ };
62
+ },
63
+ }),
64
+ ],
65
+ session: { strategy: 'jwt' },
66
+ callbacks: {
67
+ async jwt({ token, user }) {
68
+ if (user) {
69
+ token.role = user.role;
70
+ token.roles = user.roles;
71
+ token.permissions = user.permissions;
72
+ }
73
+ if (token.role && (!token.permissions || token.permissions.length === 0)) {
74
+ token.permissions = rolePermissions[token.role] || [];
75
+ }
76
+ return token;
77
+ },
78
+ async session({ session, token }) {
79
+ if (token && session.user) {
80
+ session.user.id = token.sub;
81
+ session.user.role = token.role;
82
+ session.user.roles = token.roles;
83
+ session.user.permissions = token.permissions;
84
+ }
85
+ return session;
86
+ },
87
+ },
88
+ pages: {
89
+ signIn: config?.pages?.signIn || '/login',
90
+ error: config?.pages?.error || '/login',
91
+ },
92
+ });
93
+ return { handlers, auth, signIn, signOut, getServerSession: auth };
94
+ }
95
+ // ─── Internal: resolve user→roles→permissions ─────────────────
96
+ async function resolveUserPermissions(userId, fallbackMap) {
97
+ try {
98
+ const uRepo = new user_repository_1.UserRepository(await (0, orm_1.getDialect)());
99
+ const rRepo = new role_repository_1.RoleRepository(await (0, orm_1.getDialect)());
100
+ const userWithRoles = await uRepo.findByIdWithRoles(userId);
101
+ if (userWithRoles?.roles?.length) {
102
+ const roleNames = [];
103
+ const permissions = [];
104
+ for (const roleObj of userWithRoles.roles) {
105
+ const roleName = typeof roleObj === 'string' ? roleObj : roleObj?.name;
106
+ const roleId = typeof roleObj === 'string' ? roleObj : roleObj?.id;
107
+ if (roleName)
108
+ roleNames.push(roleName);
109
+ if (roleId) {
110
+ const roleWithPerms = await rRepo.findByIdWithPermissions(roleId);
111
+ if (roleWithPerms?.permissions) {
112
+ for (const perm of roleWithPerms.permissions) {
113
+ const permName = typeof perm === 'string' ? perm : perm?.name;
114
+ if (permName && !permissions.includes(permName))
115
+ permissions.push(permName);
116
+ }
117
+ }
118
+ }
119
+ else if (roleName) {
120
+ for (const p of fallbackMap[roleName] || []) {
121
+ if (!permissions.includes(p))
122
+ permissions.push(p);
123
+ }
124
+ }
125
+ }
126
+ if (roleNames.length > 0)
127
+ return { roleNames, permissions };
128
+ }
129
+ // Legacy: user.role = string
130
+ const raw = userWithRoles;
131
+ if (raw?.role && typeof raw.role === 'string') {
132
+ return { roleNames: [raw.role], permissions: fallbackMap[raw.role] || [] };
133
+ }
134
+ }
135
+ catch (err) {
136
+ console.error('[MostaAuth] Error resolving permissions:', err);
137
+ }
138
+ return { roleNames: [], permissions: [] };
139
+ }
@@ -0,0 +1,2 @@
1
+ export declare function hashPassword(plain: string, rounds?: number): Promise<string>;
2
+ export declare function comparePassword(plain: string, hashed: string): Promise<boolean>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.hashPassword = hashPassword;
7
+ exports.comparePassword = comparePassword;
8
+ // @mosta/auth — Password hashing wrapper
9
+ // Author: Dr Hamid MADANI drmdh@msn.com
10
+ const bcryptjs_1 = __importDefault(require("bcryptjs"));
11
+ const DEFAULT_ROUNDS = 12;
12
+ async function hashPassword(plain, rounds = DEFAULT_ROUNDS) {
13
+ return bcryptjs_1.default.hash(plain, rounds);
14
+ }
15
+ async function comparePassword(plain, hashed) {
16
+ return bcryptjs_1.default.compare(plain, hashed);
17
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Resolve permissions for a role by querying the database.
3
+ * Falls back to the provided static map if DB lookup fails.
4
+ */
5
+ export declare function getPermissionsForRoleFromDB(role: string, fallbackMap?: Record<string, string[]>): Promise<string[]>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPermissionsForRoleFromDB = getPermissionsForRoleFromDB;
4
+ // @mosta/auth — Server-side permission lookup (DO NOT import client-side)
5
+ // Author: Dr Hamid MADANI drmdh@msn.com
6
+ const orm_1 = require("@mostajs/orm");
7
+ const role_repository_1 = require("../repositories/role.repository");
8
+ /**
9
+ * Resolve permissions for a role by querying the database.
10
+ * Falls back to the provided static map if DB lookup fails.
11
+ */
12
+ async function getPermissionsForRoleFromDB(role, fallbackMap) {
13
+ try {
14
+ const repo = new role_repository_1.RoleRepository(await (0, orm_1.getDialect)());
15
+ const dbRole = await repo.findByName(role);
16
+ if (dbRole) {
17
+ const roleWithPerms = await repo.findByIdWithPermissions(dbRole.id);
18
+ if (roleWithPerms?.permissions && roleWithPerms.permissions.length > 0) {
19
+ return roleWithPerms.permissions.map((p) => typeof p === 'string' ? p : p.name || p);
20
+ }
21
+ }
22
+ }
23
+ catch (err) {
24
+ console.error('[MostaAuth] DB permission lookup failed, using fallback:', err);
25
+ }
26
+ return fallbackMap?.[role] || [];
27
+ }
@@ -0,0 +1,9 @@
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[];
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ // @mosta/auth — Permission helpers (client-safe)
3
+ // Author: Dr Hamid MADANI drmdh@msn.com
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.hasPermission = hasPermission;
6
+ exports.getPermissionsForRole = getPermissionsForRole;
7
+ /**
8
+ * Check if a user has a specific permission.
9
+ * Supports wildcard '*' for full access.
10
+ */
11
+ function hasPermission(userPermissions, requiredPermission) {
12
+ if (!userPermissions || userPermissions.length === 0)
13
+ return false;
14
+ if (userPermissions.includes('*'))
15
+ return true;
16
+ return userPermissions.includes(requiredPermission);
17
+ }
18
+ /**
19
+ * Get permissions for a role from a static map.
20
+ */
21
+ function getPermissionsForRole(rolePermissions, role) {
22
+ return rolePermissions[role] || [];
23
+ }
@@ -0,0 +1,15 @@
1
+ import type { CategoryDefinition, PermissionDefinition, RoleDefinition } from '../types';
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
+ }>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.seedRBAC = seedRBAC;
4
+ // @mosta/auth — RBAC Seed function
5
+ // Author: Dr Hamid MADANI drmdh@msn.com
6
+ const orm_1 = require("@mostajs/orm");
7
+ const permission_category_repository_1 = require("../repositories/permission-category.repository");
8
+ const permission_repository_1 = require("../repositories/permission.repository");
9
+ const role_repository_1 = require("../repositories/role.repository");
10
+ /**
11
+ * Idempotent seed of categories, permissions and roles.
12
+ * Uses upsert — safe to call multiple times.
13
+ */
14
+ async function seedRBAC(options) {
15
+ const dialect = await (0, orm_1.getDialect)();
16
+ const catRepo = new permission_category_repository_1.PermissionCategoryRepository(dialect);
17
+ const permRepo = new permission_repository_1.PermissionRepository(dialect);
18
+ const roleRepo = new role_repository_1.RoleRepository(dialect);
19
+ // 1. Upsert categories
20
+ for (const cat of options.categories) {
21
+ await catRepo.upsert({ name: cat.name }, cat);
22
+ }
23
+ // 2. Upsert permissions — build code→id map
24
+ const permissionMap = {};
25
+ for (const pDef of options.permissions) {
26
+ const perm = await permRepo.upsert({ name: pDef.name }, { name: pDef.name, description: pDef.description, category: pDef.category });
27
+ permissionMap[pDef.code] = perm.id;
28
+ }
29
+ // 3. Upsert roles with permission IDs
30
+ for (const [, roleDef] of Object.entries(options.roles)) {
31
+ const permissionIds = roleDef.permissions
32
+ .map((code) => permissionMap[code])
33
+ .filter(Boolean);
34
+ await roleRepo.upsert({ name: roleDef.name }, { name: roleDef.name, description: roleDef.description, permissions: permissionIds });
35
+ }
36
+ return {
37
+ categoryCount: options.categories.length,
38
+ permissionCount: options.permissions.length,
39
+ roleCount: Object.keys(options.roles).length,
40
+ };
41
+ }
@@ -0,0 +1,13 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ export interface AuthMiddlewareOptions {
3
+ /** Paths that don't require authentication (default: ['/login', '/api/auth', '/setup', '/api/setup']) */
4
+ publicPaths?: string[];
5
+ /** Path prefixes that require authentication (default: ['/dashboard', '/admin', '/agent']) */
6
+ protectedPrefixes?: string[];
7
+ /** Redirect path when unauthenticated (default: '/login') */
8
+ loginPath?: string;
9
+ }
10
+ /**
11
+ * Create a Next.js middleware that protects routes based on session cookie.
12
+ */
13
+ export declare function createAuthMiddleware(options?: AuthMiddlewareOptions): (req: NextRequest) => NextResponse<unknown>;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAuthMiddleware = createAuthMiddleware;
4
+ // @mosta/auth — Configurable authentication middleware for Next.js
5
+ // Author: Dr Hamid MADANI drmdh@msn.com
6
+ const server_1 = require("next/server");
7
+ /**
8
+ * Create a Next.js middleware that protects routes based on session cookie.
9
+ */
10
+ function createAuthMiddleware(options) {
11
+ const publicPaths = options?.publicPaths ?? ['/login', '/api/auth', '/setup', '/api/setup'];
12
+ const protectedPrefixes = options?.protectedPrefixes ?? ['/dashboard', '/admin', '/agent'];
13
+ const loginPath = options?.loginPath ?? '/login';
14
+ return function middleware(req) {
15
+ const { pathname } = req.nextUrl;
16
+ // Allow public paths
17
+ if (publicPaths.some((p) => pathname.startsWith(p))) {
18
+ return server_1.NextResponse.next();
19
+ }
20
+ // Allow static files
21
+ if (pathname.startsWith('/_next') || pathname.startsWith('/favicon') || pathname.includes('.')) {
22
+ return server_1.NextResponse.next();
23
+ }
24
+ // Check for session token
25
+ const token = req.cookies.get('authjs.session-token')?.value ||
26
+ req.cookies.get('__Secure-authjs.session-token')?.value;
27
+ // Redirect protected routes to login if no session
28
+ if (!token && protectedPrefixes.some((p) => pathname.startsWith(p))) {
29
+ return server_1.NextResponse.redirect(new URL(loginPath, req.url));
30
+ }
31
+ return server_1.NextResponse.next();
32
+ };
33
+ }
@@ -0,0 +1,10 @@
1
+ import { BaseRepository } from '@mostajs/orm';
2
+ import type { IDialect } from '@mostajs/orm';
3
+ import type { PermissionCategoryDTO } from '../types';
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
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PermissionCategoryRepository = void 0;
4
+ // @mosta/auth — PermissionCategoryRepository
5
+ // Author: Dr Hamid MADANI drmdh@msn.com
6
+ const orm_1 = require("@mostajs/orm");
7
+ const permission_category_schema_1 = require("../schemas/permission-category.schema");
8
+ class PermissionCategoryRepository extends orm_1.BaseRepository {
9
+ constructor(dialect) {
10
+ super(permission_category_schema_1.PermissionCategorySchema, dialect);
11
+ }
12
+ /** Find all sorted by order then name */
13
+ async findAllOrdered() {
14
+ return this.findAll({}, { sort: { order: 1, name: 1 } });
15
+ }
16
+ /** Find by name (unique) */
17
+ async findByName(name) {
18
+ return this.findOne({ name });
19
+ }
20
+ }
21
+ exports.PermissionCategoryRepository = PermissionCategoryRepository;
@@ -0,0 +1,12 @@
1
+ import { BaseRepository } from '@mostajs/orm';
2
+ import type { IDialect } from '@mostajs/orm';
3
+ import type { PermissionDTO } from '../types';
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
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PermissionRepository = void 0;
4
+ // @mosta/auth — PermissionRepository
5
+ // Author: Dr Hamid MADANI drmdh@msn.com
6
+ const orm_1 = require("@mostajs/orm");
7
+ const permission_schema_1 = require("../schemas/permission.schema");
8
+ class PermissionRepository extends orm_1.BaseRepository {
9
+ constructor(dialect) {
10
+ super(permission_schema_1.PermissionSchema, dialect);
11
+ }
12
+ /** Find all sorted by category then name */
13
+ async findAllSorted() {
14
+ return this.findAll({}, { sort: { category: 1, name: 1 } });
15
+ }
16
+ /** Find by name (unique) */
17
+ async findByName(name) {
18
+ return this.findOne({ name });
19
+ }
20
+ /** Count permissions in a category */
21
+ async countByCategory(category) {
22
+ return this.count({ category });
23
+ }
24
+ }
25
+ exports.PermissionRepository = PermissionRepository;
@@ -0,0 +1,18 @@
1
+ import { BaseRepository } from '@mostajs/orm';
2
+ import type { IDialect } from '@mostajs/orm';
3
+ import type { RoleDTO } from '../types';
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
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RoleRepository = void 0;
4
+ // @mosta/auth — RoleRepository
5
+ // Author: Dr Hamid MADANI drmdh@msn.com
6
+ const orm_1 = require("@mostajs/orm");
7
+ const role_schema_1 = require("../schemas/role.schema");
8
+ class RoleRepository extends orm_1.BaseRepository {
9
+ constructor(dialect) {
10
+ super(role_schema_1.RoleSchema, dialect);
11
+ }
12
+ /** Find all roles with permissions populated */
13
+ async findAllWithPermissions() {
14
+ return this.findWithRelations({}, ['permissions']);
15
+ }
16
+ /** Find a role by name */
17
+ async findByName(name) {
18
+ return this.findOne({ name });
19
+ }
20
+ /** Find role by ID with permissions populated */
21
+ async findByIdWithPermissions(id) {
22
+ return this.findByIdWithRelations(id, ['permissions']);
23
+ }
24
+ /** Add a permission to a role */
25
+ async addPermission(roleId, permissionId) {
26
+ return this.addToSet(roleId, 'permissions', permissionId);
27
+ }
28
+ /** Remove a permission from a role */
29
+ async removePermission(roleId, permissionId) {
30
+ return this.pull(roleId, 'permissions', permissionId);
31
+ }
32
+ /** Remove a permission from ALL roles (cascade) */
33
+ async removePermissionFromAll(permissionId) {
34
+ return this.updateMany({ permissions: permissionId }, { $pull: { permissions: permissionId } });
35
+ }
36
+ }
37
+ exports.RoleRepository = RoleRepository;
@@ -0,0 +1,24 @@
1
+ import { BaseRepository } from '@mostajs/orm';
2
+ import type { IDialect, FilterQuery, QueryOptions } from '@mostajs/orm';
3
+ import type { UserDTO } from '../types';
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
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserRepository = void 0;
4
+ // @mosta/auth — UserRepository
5
+ // Author: Dr Hamid MADANI drmdh@msn.com
6
+ const orm_1 = require("@mostajs/orm");
7
+ const user_schema_1 = require("../schemas/user.schema");
8
+ class UserRepository extends orm_1.BaseRepository {
9
+ constructor(dialect) {
10
+ super(user_schema_1.UserSchema, dialect);
11
+ }
12
+ /** List users without password field */
13
+ async findAllSafe(filter = {}, options) {
14
+ return this.findAll(filter, { ...options, exclude: ['password'] });
15
+ }
16
+ /** Find a single user by ID without password */
17
+ async findByIdSafe(id) {
18
+ return this.findById(id, { exclude: ['password'] });
19
+ }
20
+ /** Find user by email (for authentication) */
21
+ async findByEmail(email) {
22
+ return this.findOne({ email: email.toLowerCase() });
23
+ }
24
+ /** Update lastLoginAt timestamp */
25
+ async updateLastLogin(id) {
26
+ await this.update(id, { lastLoginAt: new Date() });
27
+ }
28
+ /** Find user by ID with roles populated */
29
+ async findByIdWithRoles(id) {
30
+ return this.findByIdWithRelations(id, ['roles']);
31
+ }
32
+ /** Find all users with roles populated (no password) */
33
+ async findAllWithRoles(filter = {}, options) {
34
+ return this.findWithRelations(filter, ['roles'], { ...options, exclude: ['password'] });
35
+ }
36
+ /** Count users having a specific role */
37
+ async countByRole(roleId) {
38
+ return this.count({ roles: roleId });
39
+ }
40
+ /** Add a role to a user */
41
+ async addRole(userId, roleId) {
42
+ return this.addToSet(userId, 'roles', roleId);
43
+ }
44
+ /** Remove a role from a user */
45
+ async removeRole(userId, roleId) {
46
+ return this.pull(userId, 'roles', roleId);
47
+ }
48
+ }
49
+ exports.UserRepository = UserRepository;
@@ -0,0 +1,2 @@
1
+ import type { EntitySchema } from '@mostajs/orm';
2
+ export declare const PermissionCategorySchema: EntitySchema;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PermissionCategorySchema = void 0;
4
+ exports.PermissionCategorySchema = {
5
+ name: 'PermissionCategory',
6
+ collection: 'permission_categories',
7
+ timestamps: true,
8
+ fields: {
9
+ name: { type: 'string', required: true, unique: true, lowercase: true, trim: true },
10
+ label: { type: 'string', required: true, trim: true },
11
+ description: { type: 'string' },
12
+ icon: { type: 'string' },
13
+ order: { type: 'number', default: 0 },
14
+ system: { type: 'boolean', default: false },
15
+ },
16
+ relations: {},
17
+ indexes: [
18
+ { fields: { order: 'asc', name: 'asc' } },
19
+ ],
20
+ };
@@ -0,0 +1,2 @@
1
+ import type { EntitySchema } from '@mostajs/orm';
2
+ export declare const PermissionSchema: EntitySchema;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PermissionSchema = void 0;
4
+ exports.PermissionSchema = {
5
+ name: 'Permission',
6
+ collection: 'permissions',
7
+ timestamps: true,
8
+ fields: {
9
+ name: { type: 'string', required: true, unique: true },
10
+ description: { type: 'string' },
11
+ category: { type: 'string' },
12
+ },
13
+ relations: {},
14
+ indexes: [],
15
+ };
@@ -0,0 +1,2 @@
1
+ import type { EntitySchema } from '@mostajs/orm';
2
+ export declare const RoleSchema: EntitySchema;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RoleSchema = void 0;
4
+ exports.RoleSchema = {
5
+ name: 'Role',
6
+ collection: 'roles',
7
+ timestamps: true,
8
+ fields: {
9
+ name: { type: 'string', required: true, unique: true },
10
+ description: { type: 'string' },
11
+ },
12
+ relations: {
13
+ permissions: { target: 'Permission', type: 'many-to-many', through: 'role_permissions' },
14
+ },
15
+ indexes: [],
16
+ };
@@ -0,0 +1,2 @@
1
+ import type { EntitySchema } from '@mostajs/orm';
2
+ export declare const UserSchema: EntitySchema;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserSchema = void 0;
4
+ exports.UserSchema = {
5
+ name: 'User',
6
+ collection: 'users',
7
+ timestamps: true,
8
+ fields: {
9
+ email: { type: 'string', required: true, unique: true, lowercase: true, trim: true },
10
+ password: { type: 'string', required: true },
11
+ firstName: { type: 'string', required: true, trim: true },
12
+ lastName: { type: 'string', required: true, trim: true },
13
+ phone: { type: 'string', trim: true },
14
+ status: { type: 'string', enum: ['active', 'locked', 'disabled'], default: 'active' },
15
+ lastLoginAt: { type: 'date' },
16
+ },
17
+ relations: {
18
+ roles: { target: 'Role', type: 'many-to-many', through: 'user_roles' },
19
+ },
20
+ indexes: [
21
+ { fields: { status: 'asc' } },
22
+ ],
23
+ };
@@ -0,0 +1,81 @@
1
+ export interface MostaAuthConfig {
2
+ /** Extra fields to add to the User schema */
3
+ extraUserFields?: Record<string, any>;
4
+ /** Default roles to seed */
5
+ defaultRoles?: Record<string, RoleDefinition>;
6
+ /** Default permissions to seed */
7
+ defaultPermissions?: PermissionDefinition[];
8
+ /** Default permission categories to seed */
9
+ defaultCategories?: CategoryDefinition[];
10
+ /** bcrypt salt rounds (default: 12) */
11
+ bcryptRounds?: number;
12
+ /** NextAuth pages */
13
+ pages?: {
14
+ signIn?: string;
15
+ error?: string;
16
+ };
17
+ /** Public paths (not requiring auth) */
18
+ publicPaths?: string[];
19
+ /** Protected path prefixes (redirect to login if no session) */
20
+ protectedPrefixes?: string[];
21
+ }
22
+ export interface PermissionDefinition {
23
+ code: string;
24
+ name: string;
25
+ description: string;
26
+ category: string;
27
+ }
28
+ export interface RoleDefinition {
29
+ name: string;
30
+ description: string;
31
+ system: boolean;
32
+ permissions: string[];
33
+ }
34
+ export interface CategoryDefinition {
35
+ name: string;
36
+ label: string;
37
+ description: string;
38
+ icon: string;
39
+ order: number;
40
+ system: boolean;
41
+ }
42
+ export interface UserDTO {
43
+ id: string;
44
+ email: string;
45
+ password?: string;
46
+ firstName: string;
47
+ lastName: string;
48
+ phone?: string;
49
+ roles: any[];
50
+ status: 'active' | 'locked' | 'disabled';
51
+ lastLoginAt?: string;
52
+ createdAt: string;
53
+ updatedAt: string;
54
+ }
55
+ export interface RoleDTO {
56
+ id: string;
57
+ name: string;
58
+ description?: string;
59
+ permissions: any[];
60
+ createdAt: string;
61
+ updatedAt: string;
62
+ }
63
+ export interface PermissionDTO {
64
+ id: string;
65
+ name: string;
66
+ description?: string;
67
+ category?: string;
68
+ createdAt: string;
69
+ updatedAt: string;
70
+ }
71
+ export interface PermissionCategoryDTO {
72
+ id: string;
73
+ name: string;
74
+ label: string;
75
+ description?: string;
76
+ icon?: string;
77
+ order: number;
78
+ system: boolean;
79
+ createdAt: string;
80
+ updatedAt: string;
81
+ }
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // @mosta/auth — Types
3
+ // Author: Dr Hamid MADANI drmdh@msn.com
4
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@mostajs/auth",
3
+ "version": "1.0.0",
4
+ "description": "Reusable authentication and RBAC module — NextAuth + Users + Roles + Permissions",
5
+ "author": "Dr Hamid MADANI <drmdh@msn.com>",
6
+ "license": "MIT",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./components/SessionProvider": {
17
+ "types": "./dist/components/SessionProvider.d.ts",
18
+ "import": "./dist/components/SessionProvider.js",
19
+ "require": "./dist/components/SessionProvider.js",
20
+ "default": "./dist/components/SessionProvider.js"
21
+ },
22
+ "./components/PermissionGuard": {
23
+ "types": "./dist/components/PermissionGuard.d.ts",
24
+ "import": "./dist/components/PermissionGuard.js",
25
+ "require": "./dist/components/PermissionGuard.js",
26
+ "default": "./dist/components/PermissionGuard.js"
27
+ },
28
+ "./hooks/usePermissions": {
29
+ "types": "./dist/hooks/usePermissions.d.ts",
30
+ "import": "./dist/hooks/usePermissions.js",
31
+ "require": "./dist/hooks/usePermissions.js",
32
+ "default": "./dist/hooks/usePermissions.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "LICENSE",
38
+ "README.md"
39
+ ],
40
+ "keywords": [
41
+ "authentication",
42
+ "authorization",
43
+ "rbac",
44
+ "nextauth",
45
+ "permissions",
46
+ "roles",
47
+ "nextjs",
48
+ "mosta"
49
+ ],
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "https://github.com/apolocine/mosta-auth"
53
+ },
54
+ "homepage": "https://mostajs.dev/packages/auth",
55
+ "engines": {
56
+ "node": ">=18.0.0"
57
+ },
58
+ "scripts": {
59
+ "build": "tsc",
60
+ "prepublishOnly": "npm run build"
61
+ },
62
+ "dependencies": {
63
+ "@mostajs/orm": "^1.0.0",
64
+ "bcryptjs": "^2.4.3",
65
+ "next-auth": "5.0.0-beta.25"
66
+ },
67
+ "peerDependencies": {
68
+ "next": ">=14",
69
+ "react": ">=18"
70
+ },
71
+ "devDependencies": {
72
+ "@types/bcryptjs": "^2.4.0",
73
+ "@types/node": "^25.3.3",
74
+ "@types/react": "^19.0.0",
75
+ "next": "^15.0.0",
76
+ "react": "^19.0.0",
77
+ "typescript": "^5.6.0"
78
+ }
79
+ }