@xeplr/auth 1.0.0 → 1.0.1

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 (59) hide show
  1. package/bin/migrate.js +43 -24
  2. package/bin/server.js +12 -30
  3. package/index.js +135 -51
  4. package/lib/adminRouter.js +20 -92
  5. package/lib/authHelper.js +26 -3
  6. package/lib/authMiddleware.js +39 -13
  7. package/lib/authRouter.js +140 -11
  8. package/lib/authService.js +327 -9
  9. package/lib/hooks.js +50 -0
  10. package/lib/mtMembershipMiddleware.js +61 -0
  11. package/lib/seed.js +74 -0
  12. package/lib/sessionService.js +54 -6
  13. package/lib/ticketService.js +88 -0
  14. package/lib/tokenDecision.js +45 -0
  15. package/migrations/0001_extensions.sql +9 -0
  16. package/migrations/0002_users.sql +31 -0
  17. package/migrations/0003_catalog_tables.sql +82 -0
  18. package/migrations/0004_role_mappings.sql +78 -0
  19. package/migrations/0005_user_tenants_mapping.sql +39 -0
  20. package/migrations/0006_seed_catalog.sql +120 -0
  21. package/models/Api.js +3 -0
  22. package/models/ApisRolesMapping.js +3 -0
  23. package/models/Menu.js +3 -0
  24. package/models/MenuRolesMapping.js +3 -0
  25. package/models/Role.js +8 -0
  26. package/models/UiElement.js +3 -0
  27. package/models/UiElementsRolesMapping.js +3 -0
  28. package/models/UiPage.js +3 -0
  29. package/models/UiPagesRolesMapping.js +3 -0
  30. package/models/User.js +3 -13
  31. package/models/UserRolesMapping.js +3 -0
  32. package/models/UserTenantsMapping.js +20 -2
  33. package/models/index.js +0 -2
  34. package/package.json +26 -5
  35. package/migrations/0001_users.js +0 -22
  36. package/migrations/0002_menus.js +0 -16
  37. package/migrations/0003_apis.js +0 -16
  38. package/migrations/0004_uiPages.js +0 -16
  39. package/migrations/0005_uiElements.js +0 -16
  40. package/migrations/0006_roles.js +0 -15
  41. package/migrations/0007_apisRolesMapping.js +0 -16
  42. package/migrations/0008_uiPagesRolesMapping.js +0 -16
  43. package/migrations/0009_uiElementsRolesMapping.js +0 -16
  44. package/migrations/0010_menuRolesMapping.js +0 -16
  45. package/migrations/0011_userRolesMapping.js +0 -16
  46. package/migrations/0012_users_add_reset_token.js +0 -13
  47. package/migrations/0013_add_isPublic.js +0 -27
  48. package/migrations/0014_users_add_activation_token.js +0 -13
  49. package/migrations/0015_add_mt_columns.js +0 -41
  50. package/migrations/0016_tenants.js +0 -23
  51. package/migrations/0017_userTenantsMapping.js +0 -20
  52. package/models/Tenant.js +0 -63
  53. package/seeds/001_roles.js +0 -26
  54. package/seeds/002_apis.js +0 -70
  55. package/seeds/003_pages.js +0 -41
  56. package/seeds/004_elements.js +0 -46
  57. package/seeds/005_menus.js +0 -35
  58. package/seeds/006_default_tenant.js +0 -50
  59. package/seeds/zzz_admin_access.js +0 -49
@@ -1,41 +0,0 @@
1
- var TABLES = [
2
- 'users',
3
- 'roles',
4
- 'apis',
5
- 'uiPages',
6
- 'uiElements',
7
- 'menus',
8
- 'userRolesMapping',
9
- 'apisRolesMapping',
10
- 'uiPagesRolesMapping',
11
- 'uiElementsRolesMapping',
12
- 'menuRolesMapping'
13
- ];
14
-
15
- exports.up = async function(knex) {
16
- for (var i = 0; i < TABLES.length; i++) {
17
- var exists = await knex.schema.hasColumn(TABLES[i], 'mtId1');
18
- if (!exists) {
19
- await knex.schema.alterTable(TABLES[i], function(table) {
20
- table.string('mtId1', 25);
21
- table.string('mtId2', 25);
22
- table.string('mtId3', 25);
23
- table.string('mtId4', 25);
24
- });
25
- }
26
- }
27
- };
28
-
29
- exports.down = async function(knex) {
30
- for (var i = 0; i < TABLES.length; i++) {
31
- var exists = await knex.schema.hasColumn(TABLES[i], 'mtId1');
32
- if (exists) {
33
- await knex.schema.alterTable(TABLES[i], function(table) {
34
- table.dropColumn('mtId1');
35
- table.dropColumn('mtId2');
36
- table.dropColumn('mtId3');
37
- table.dropColumn('mtId4');
38
- });
39
- }
40
- }
41
- };
@@ -1,23 +0,0 @@
1
- exports.up = function(knex) {
2
- return knex.schema.createTable('tenants', function(table) {
3
- table.string('id', 25).primary();
4
- table.string('name', 255).notNullable();
5
- table.string('code', 50);
6
- table.integer('level').defaultTo(1);
7
- table.string('parentId', 25);
8
- table.string('description', 500);
9
- table.string('mtId1', 25);
10
- table.string('mtId2', 25);
11
- table.string('mtId3', 25);
12
- table.string('mtId4', 25);
13
- table.boolean('isActive').defaultTo(true);
14
- table.timestamp('recordCreatedDate');
15
- table.timestamp('recordModifiedDate');
16
- table.string('recordCreatedBy', 25);
17
- table.string('recordModifiedBy', 25);
18
- });
19
- };
20
-
21
- exports.down = function(knex) {
22
- return knex.schema.dropTableIfExists('tenants');
23
- };
@@ -1,20 +0,0 @@
1
- exports.up = function(knex) {
2
- return knex.schema.createTable('userTenantsMapping', function(table) {
3
- table.string('id', 25).primary();
4
- table.string('userId', 25).notNullable().references('id').inTable('users');
5
- table.string('tenantId', 25).notNullable().references('id').inTable('tenants');
6
- table.string('mtId1', 25);
7
- table.string('mtId2', 25);
8
- table.string('mtId3', 25);
9
- table.string('mtId4', 25);
10
- table.boolean('isActive').defaultTo(true);
11
- table.timestamp('recordCreatedDate');
12
- table.timestamp('recordModifiedDate');
13
- table.string('recordCreatedBy', 25);
14
- table.string('recordModifiedBy', 25);
15
- });
16
- };
17
-
18
- exports.down = function(knex) {
19
- return knex.schema.dropTableIfExists('userTenantsMapping');
20
- };
package/models/Tenant.js DELETED
@@ -1,63 +0,0 @@
1
- const { BaseModel } = require('@xeplr/db');
2
-
3
- class Tenant extends BaseModel {
4
- static get tableName() {
5
- return 'tenants';
6
- }
7
-
8
- static get idColumn() {
9
- return 'id';
10
- }
11
-
12
- // Tenants are global — not filtered by tenant context
13
- static get multiTenant() {
14
- return false;
15
- }
16
-
17
- static get jsonSchema() {
18
- return {
19
- type: 'object',
20
- required: ['id', 'name'],
21
- properties: {
22
- id: { type: 'string', maxLength: 25 },
23
- name: { type: 'string', maxLength: 255 },
24
- code: { type: ['string', 'null'], maxLength: 50 },
25
- level: { type: 'integer' },
26
- parentId: { type: ['string', 'null'], maxLength: 25 },
27
- description: { type: ['string', 'null'], maxLength: 500 },
28
- mtId1: { type: ['string', 'null'], maxLength: 25 },
29
- mtId2: { type: ['string', 'null'], maxLength: 25 },
30
- mtId3: { type: ['string', 'null'], maxLength: 25 },
31
- mtId4: { type: ['string', 'null'], maxLength: 25 },
32
- isActive: { type: 'boolean' },
33
- recordCreatedDate: { type: ['string', 'null'] },
34
- recordModifiedDate: { type: ['string', 'null'] },
35
- recordCreatedBy: { type: ['string', 'null'], maxLength: 25 },
36
- recordModifiedBy: { type: ['string', 'null'], maxLength: 25 }
37
- }
38
- };
39
- }
40
-
41
- static get relationMappings() {
42
- return {
43
- children: {
44
- relation: BaseModel.HasManyRelation,
45
- modelClass: Tenant,
46
- join: {
47
- from: 'tenants.id',
48
- to: 'tenants.parentId'
49
- }
50
- },
51
- parent: {
52
- relation: BaseModel.BelongsToOneRelation,
53
- modelClass: Tenant,
54
- join: {
55
- from: 'tenants.parentId',
56
- to: 'tenants.id'
57
- }
58
- }
59
- };
60
- }
61
- }
62
-
63
- module.exports = Tenant;
@@ -1,26 +0,0 @@
1
- var crypto = require('crypto');
2
-
3
- function generateId() {
4
- return crypto.randomBytes(12).toString('hex').substring(0, 25);
5
- }
6
-
7
- var now = new Date().toISOString();
8
- var MT_ALL = '*';
9
-
10
- var ROLES = ['Super Admin', 'Admin', 'Editor', 'Viewer'];
11
-
12
- exports.seed = async function(knex) {
13
- for (var i = 0; i < ROLES.length; i++) {
14
- var exists = await knex('roles').where({ name: ROLES[i] }).first();
15
- if (!exists) {
16
- await knex('roles').insert({
17
- id: generateId(),
18
- name: ROLES[i],
19
- isActive: true,
20
- recordCreatedDate: now,
21
- recordModifiedDate: now,
22
- mtId1: MT_ALL
23
- });
24
- }
25
- }
26
- };
package/seeds/002_apis.js DELETED
@@ -1,70 +0,0 @@
1
- var crypto = require('crypto');
2
-
3
- function generateId() {
4
- return crypto.randomBytes(12).toString('hex').substring(0, 25);
5
- }
6
-
7
- var now = new Date().toISOString();
8
- var MT_ALL = '*';
9
-
10
- var APIS = [
11
- // Auth APIs (public — no role needed)
12
- { name: '/auth/api/register', apiGroup: '', isPublic: true },
13
- { name: '/auth/api/activate', apiGroup: '', isPublic: true },
14
- { name: '/auth/api/login', apiGroup: '', isPublic: true },
15
- { name: '/auth/api/forgot-password', apiGroup: '', isPublic: true },
16
- { name: '/auth/api/reset-password', apiGroup: '', isPublic: true },
17
- { name: '/auth/api/refresh', apiGroup: '', isPublic: true },
18
- { name: '/auth/api/logout', apiGroup: '', isPublic: true },
19
- { name: '/auth/api/me', apiGroup: 'account:view', isPublic: false },
20
-
21
- // Admin APIs — user/role management
22
- { name: '/auth/api/admin/users', apiGroup: 'users:view', isPublic: false },
23
- { name: '/auth/api/admin/roles', apiGroup: 'users:view', isPublic: false },
24
- { name: '/auth/api/admin/user-role', apiGroup: 'users:edit', isPublic: false },
25
- { name: '/auth/api/admin/access-items', apiGroup: 'access:view', isPublic: false },
26
- { name: '/auth/api/admin/access-role', apiGroup: 'access:edit', isPublic: false },
27
- { name: '/auth/api/admin/module-role', apiGroup: 'access:edit', isPublic: false },
28
-
29
- // Admin APIs — tenant management
30
- { name: '/auth/api/admin/tenants', apiGroup: 'tenants:view', isPublic: false },
31
- { name: '/auth/api/admin/tenants/save', apiGroup: 'tenants:edit', isPublic: false },
32
- { name: '/auth/api/admin/tenants/delete', apiGroup: 'tenants:delete', isPublic: false },
33
- { name: '/auth/api/admin/tenants/assign-user', apiGroup: 'tenants:edit', isPublic: false },
34
-
35
- // Admin APIs — master settings
36
- { name: '/auth/api/admin/master/roles', apiGroup: 'settings:view', isPublic: false },
37
- { name: '/auth/api/admin/master/roles/save', apiGroup: 'settings:edit', isPublic: false },
38
- { name: '/auth/api/admin/master/roles/delete', apiGroup: 'settings:delete', isPublic: false },
39
- { name: '/auth/api/admin/master/apis', apiGroup: 'settings:view', isPublic: false },
40
- { name: '/auth/api/admin/master/apis/save', apiGroup: 'settings:edit', isPublic: false },
41
- { name: '/auth/api/admin/master/apis/delete', apiGroup: 'settings:delete', isPublic: false },
42
- { name: '/auth/api/admin/master/pages', apiGroup: 'settings:view', isPublic: false },
43
- { name: '/auth/api/admin/master/pages/save', apiGroup: 'settings:edit', isPublic: false },
44
- { name: '/auth/api/admin/master/pages/delete', apiGroup: 'settings:delete', isPublic: false },
45
- { name: '/auth/api/admin/master/elements', apiGroup: 'settings:view', isPublic: false },
46
- { name: '/auth/api/admin/master/elements/save', apiGroup: 'settings:edit', isPublic: false },
47
- { name: '/auth/api/admin/master/elements/delete', apiGroup: 'settings:delete', isPublic: false },
48
- { name: '/auth/api/admin/master/menus', apiGroup: 'settings:view', isPublic: false },
49
- { name: '/auth/api/admin/master/menus/save', apiGroup: 'settings:edit', isPublic: false },
50
- { name: '/auth/api/admin/master/menus/delete', apiGroup: 'settings:delete', isPublic: false },
51
- ];
52
-
53
- exports.seed = async function(knex) {
54
- for (var i = 0; i < APIS.length; i++) {
55
- var api = APIS[i];
56
- var exists = await knex('apis').where({ name: api.name }).first();
57
- if (!exists) {
58
- await knex('apis').insert({
59
- id: generateId(),
60
- name: api.name,
61
- apiGroup: api.apiGroup,
62
- isPublic: api.isPublic,
63
- isActive: true,
64
- recordCreatedDate: now,
65
- recordModifiedDate: now,
66
- mtId1: MT_ALL
67
- });
68
- }
69
- }
70
- };
@@ -1,41 +0,0 @@
1
- var crypto = require('crypto');
2
-
3
- function generateId() {
4
- return crypto.randomBytes(12).toString('hex').substring(0, 25);
5
- }
6
-
7
- var now = new Date().toISOString();
8
- var MT_ALL = '*';
9
-
10
- var PAGES = [
11
- { name: 'Login', uiPagesGroup: '', isPublic: true },
12
- { name: 'Register', uiPagesGroup: '', isPublic: true },
13
- { name: 'Forgot Password', uiPagesGroup: '', isPublic: true },
14
- { name: 'Reset Password', uiPagesGroup: '', isPublic: true },
15
- { name: 'Activate Account', uiPagesGroup: '', isPublic: true },
16
- { name: 'Profile', uiPagesGroup: 'account:view', isPublic: false },
17
- { name: 'Change Password', uiPagesGroup: 'account:edit', isPublic: false },
18
- { name: 'User Roles', uiPagesGroup: 'users:view', isPublic: false },
19
- { name: 'Access Matrix', uiPagesGroup: 'access:view', isPublic: false },
20
- { name: 'Master Settings', uiPagesGroup: 'settings:view', isPublic: false },
21
- { name: 'Tenant Management', uiPagesGroup: 'tenants:view', isPublic: false },
22
- ];
23
-
24
- exports.seed = async function(knex) {
25
- for (var i = 0; i < PAGES.length; i++) {
26
- var page = PAGES[i];
27
- var exists = await knex('uiPages').where({ name: page.name }).first();
28
- if (!exists) {
29
- await knex('uiPages').insert({
30
- id: generateId(),
31
- name: page.name,
32
- uiPagesGroup: page.uiPagesGroup,
33
- isPublic: page.isPublic,
34
- isActive: true,
35
- recordCreatedDate: now,
36
- recordModifiedDate: now,
37
- mtId1: MT_ALL
38
- });
39
- }
40
- }
41
- };
@@ -1,46 +0,0 @@
1
- var crypto = require('crypto');
2
-
3
- function generateId() {
4
- return crypto.randomBytes(12).toString('hex').substring(0, 25);
5
- }
6
-
7
- var now = new Date().toISOString();
8
- var MT_ALL = '*';
9
-
10
- var ELEMENTS = [
11
- { name: 'Assign Role Button', uiElementsGroup: 'users:edit' },
12
- { name: 'Remove Role Button', uiElementsGroup: 'users:edit' },
13
- { name: 'Toggle Access Checkbox', uiElementsGroup: 'access:edit' },
14
- { name: 'Toggle Module Access Checkbox', uiElementsGroup: 'access:edit' },
15
- { name: 'Add Role Button', uiElementsGroup: 'settings:edit' },
16
- { name: 'Delete Role Button', uiElementsGroup: 'settings:delete' },
17
- { name: 'Add API Button', uiElementsGroup: 'settings:edit' },
18
- { name: 'Delete API Button', uiElementsGroup: 'settings:delete' },
19
- { name: 'Add Page Button', uiElementsGroup: 'settings:edit' },
20
- { name: 'Delete Page Button', uiElementsGroup: 'settings:delete' },
21
- { name: 'Add Element Button', uiElementsGroup: 'settings:edit' },
22
- { name: 'Delete Element Button', uiElementsGroup: 'settings:delete' },
23
- { name: 'Add Menu Button', uiElementsGroup: 'settings:edit' },
24
- { name: 'Delete Menu Button', uiElementsGroup: 'settings:delete' },
25
- { name: 'Add Tenant Button', uiElementsGroup: 'tenants:edit' },
26
- { name: 'Delete Tenant Button', uiElementsGroup: 'tenants:delete' },
27
- { name: 'Assign User Tenant', uiElementsGroup: 'tenants:edit' },
28
- ];
29
-
30
- exports.seed = async function(knex) {
31
- for (var i = 0; i < ELEMENTS.length; i++) {
32
- var el = ELEMENTS[i];
33
- var exists = await knex('uiElements').where({ name: el.name }).first();
34
- if (!exists) {
35
- await knex('uiElements').insert({
36
- id: generateId(),
37
- name: el.name,
38
- uiElementsGroup: el.uiElementsGroup,
39
- isActive: true,
40
- recordCreatedDate: now,
41
- recordModifiedDate: now,
42
- mtId1: MT_ALL
43
- });
44
- }
45
- }
46
- };
@@ -1,35 +0,0 @@
1
- var crypto = require('crypto');
2
-
3
- function generateId() {
4
- return crypto.randomBytes(12).toString('hex').substring(0, 25);
5
- }
6
-
7
- var now = new Date().toISOString();
8
- var MT_ALL = '*';
9
-
10
- var MENUS = [
11
- { name: 'Profile', menuGroup: 'account:view', isPublic: false },
12
- { name: 'User Roles', menuGroup: 'users:view', isPublic: false },
13
- { name: 'Access Matrix', menuGroup: 'access:view', isPublic: false },
14
- { name: 'Master Settings', menuGroup: 'settings:view', isPublic: false },
15
- { name: 'Tenant Management', menuGroup: 'tenants:view', isPublic: false },
16
- ];
17
-
18
- exports.seed = async function(knex) {
19
- for (var i = 0; i < MENUS.length; i++) {
20
- var menu = MENUS[i];
21
- var exists = await knex('menus').where({ name: menu.name }).first();
22
- if (!exists) {
23
- await knex('menus').insert({
24
- id: generateId(),
25
- name: menu.name,
26
- menuGroup: menu.menuGroup,
27
- isPublic: menu.isPublic,
28
- isActive: true,
29
- recordCreatedDate: now,
30
- recordModifiedDate: now,
31
- mtId1: MT_ALL
32
- });
33
- }
34
- }
35
- };
@@ -1,50 +0,0 @@
1
- var crypto = require('crypto');
2
-
3
- function generateId() {
4
- return crypto.randomBytes(12).toString('hex').substring(0, 25);
5
- }
6
-
7
- var now = new Date().toISOString();
8
- var MT_ALL = '*';
9
- var DEFAULT_TENANT_NAME = 'Default';
10
- var DEFAULT_TENANT_CODE = 'default';
11
-
12
- exports.seed = async function(knex) {
13
- // Create default tenant if not exists
14
- var tenant = await knex('tenants').where({ code: DEFAULT_TENANT_CODE }).first();
15
- if (!tenant) {
16
- var tenantId = generateId();
17
- await knex('tenants').insert({
18
- id: tenantId,
19
- name: DEFAULT_TENANT_NAME,
20
- code: DEFAULT_TENANT_CODE,
21
- level: 1,
22
- description: 'Default tenant',
23
- mtId1: MT_ALL,
24
- isActive: true,
25
- recordCreatedDate: now,
26
- recordModifiedDate: now
27
- });
28
- tenant = { id: tenantId };
29
- }
30
-
31
- // Assign all Super Admin users to the default tenant
32
- var superAdminRole = await knex('roles').where({ name: 'Super Admin' }).first();
33
- if (!superAdminRole) return;
34
-
35
- var superAdminMappings = await knex('userRolesMapping').where({ roleId: superAdminRole.id });
36
- for (var i = 0; i < superAdminMappings.length; i++) {
37
- var userId = superAdminMappings[i].userId;
38
- var exists = await knex('userTenantsMapping').where({ userId: userId, tenantId: tenant.id }).first();
39
- if (!exists) {
40
- await knex('userTenantsMapping').insert({
41
- id: generateId(),
42
- userId: userId,
43
- tenantId: tenant.id,
44
- isActive: true,
45
- recordCreatedDate: now,
46
- recordModifiedDate: now
47
- });
48
- }
49
- }
50
- };
@@ -1,49 +0,0 @@
1
- var crypto = require('crypto');
2
-
3
- function generateId() {
4
- return crypto.randomBytes(12).toString('hex').substring(0, 25);
5
- }
6
-
7
- var now = new Date().toISOString();
8
- var MT_ALL = '*';
9
-
10
- var ADMIN_ROLES = ['Super Admin', 'Admin'];
11
-
12
- var MAPPINGS = [
13
- { table: 'apisRolesMapping', source: 'apis', fk: 'apiId' },
14
- { table: 'uiPagesRolesMapping', source: 'uiPages', fk: 'uiPageId' },
15
- { table: 'uiElementsRolesMapping', source: 'uiElements', fk: 'uiElementId' },
16
- { table: 'menuRolesMapping', source: 'menus', fk: 'menuId' },
17
- ];
18
-
19
- exports.seed = async function(knex) {
20
- var roles = await knex('roles').whereIn('name', ADMIN_ROLES).select('id', 'name');
21
- if (roles.length === 0) return;
22
-
23
- for (var m = 0; m < MAPPINGS.length; m++) {
24
- var mapping = MAPPINGS[m];
25
- var items = await knex(mapping.source).select('id');
26
-
27
- for (var r = 0; r < roles.length; r++) {
28
- var roleId = roles[r].id;
29
-
30
- for (var i = 0; i < items.length; i++) {
31
- var where = { roleId: roleId };
32
- where[mapping.fk] = items[i].id;
33
-
34
- var exists = await knex(mapping.table).where(where).first();
35
- if (!exists) {
36
- var row = {
37
- id: generateId(),
38
- roleId: roleId,
39
- recordCreatedDate: now,
40
- recordModifiedDate: now,
41
- mtId1: MT_ALL
42
- };
43
- row[mapping.fk] = items[i].id;
44
- await knex(mapping.table).insert(row);
45
- }
46
- }
47
- }
48
- }
49
- };