hazo_auth 9.1.1 → 10.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.
- package/README.md +24 -6
- package/SETUP_CHECKLIST.md +6 -16
- package/cli-src/cli/init_users.ts +40 -48
- package/cli-src/lib/auth/auth_types.ts +0 -2
- package/cli-src/lib/auth/hazo_get_auth.server.ts +31 -25
- package/cli-src/lib/auth/hazo_get_tenant_auth.server.ts +9 -13
- package/cli-src/lib/constants.ts +2 -0
- package/cli-src/lib/profile_pic_menu_config.server.ts +4 -3
- package/cli-src/lib/schema/sqlite_schema.ts +0 -4
- package/cli-src/lib/scope_hierarchy_config.server.ts +1 -9
- package/cli-src/lib/services/invitation_service.ts +1 -1
- package/cli-src/lib/services/scope_service.ts +2 -76
- package/cli-src/lib/services/user_scope_service.ts +7 -61
- package/dist/cli/init_users.d.ts.map +1 -1
- package/dist/cli/init_users.js +42 -42
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -1
- package/dist/components/layouts/shared/components/profile_pic_menu.d.ts.map +1 -1
- package/dist/components/layouts/shared/components/profile_pic_menu.js +7 -1
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/input-otp.d.ts +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/auth/auth_types.d.ts +0 -2
- package/dist/lib/auth/auth_types.d.ts.map +1 -1
- package/dist/lib/auth/hazo_get_auth.server.d.ts.map +1 -1
- package/dist/lib/auth/hazo_get_auth.server.js +27 -19
- package/dist/lib/auth/hazo_get_tenant_auth.server.d.ts.map +1 -1
- package/dist/lib/auth/hazo_get_tenant_auth.server.js +10 -10
- package/dist/lib/constants.d.ts +1 -0
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +1 -0
- package/dist/lib/profile_pic_menu_config.server.d.ts +2 -1
- package/dist/lib/profile_pic_menu_config.server.d.ts.map +1 -1
- package/dist/lib/profile_pic_menu_config.server.js +1 -1
- package/dist/lib/schema/sqlite_schema.d.ts +1 -1
- package/dist/lib/schema/sqlite_schema.d.ts.map +1 -1
- package/dist/lib/schema/sqlite_schema.js +0 -4
- package/dist/lib/scope_hierarchy_config.server.d.ts +0 -2
- package/dist/lib/scope_hierarchy_config.server.d.ts.map +1 -1
- package/dist/lib/scope_hierarchy_config.server.js +1 -3
- package/dist/lib/services/invitation_service.d.ts +1 -1
- package/dist/lib/services/invitation_service.js +1 -1
- package/dist/lib/services/scope_service.d.ts +1 -14
- package/dist/lib/services/scope_service.d.ts.map +1 -1
- package/dist/lib/services/scope_service.js +2 -67
- package/dist/lib/services/user_scope_service.d.ts +5 -12
- package/dist/lib/services/user_scope_service.d.ts.map +1 -1
- package/dist/lib/services/user_scope_service.js +8 -45
- package/dist/server/routes/invitations.d.ts +1 -1
- package/dist/server/routes/invitations.d.ts.map +1 -1
- package/dist/server/routes/invitations.js +12 -11
- package/package.json +12 -12
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const SQLITE_SCHEMA = "\n-- hazo_auth canonical SQLite schema\n-- This schema creates all tables required by hazo_auth\n\n-- Users table (from migration 011)\nCREATE TABLE IF NOT EXISTS hazo_users (\n id TEXT PRIMARY KEY,\n email_address TEXT NOT NULL UNIQUE,\n password_hash TEXT,\n name TEXT,\n email_verified BOOLEAN DEFAULT false,\n login_attempts INTEGER DEFAULT 0,\n last_logon TEXT,\n profile_picture_url TEXT,\n profile_source TEXT CHECK(profile_source IN ('gravatar', 'custom', 'predefined')),\n mfa_secret TEXT,\n url_on_logon TEXT,\n google_id TEXT UNIQUE,\n auth_providers TEXT DEFAULT 'email',\n user_type TEXT,\n app_user_data TEXT,\n status TEXT DEFAULT 'ACTIVE' CHECK(status IN ('PENDING', 'ACTIVE', 'BLOCKED')),\n managed_by_user_id TEXT REFERENCES hazo_users(id) ON DELETE SET NULL,\n pin_hash TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n changed_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_hazo_users_email ON hazo_users(email_address);\nCREATE INDEX IF NOT EXISTS idx_hazo_users_google_id ON hazo_users(google_id);\nCREATE INDEX IF NOT EXISTS idx_hazo_users_status ON hazo_users(status);\n\n-- Refresh tokens table\n-- Note: runtime (token_service.ts) writes token_hash (argon2-hashed value) on\n-- insert and verifies via argon2.verify(token_hash, plaintext_token) on read.\n-- The plaintext \"token\" column is retained nullable for legacy compatibility\n-- but new writes only set token_hash.\nCREATE TABLE IF NOT EXISTS hazo_refresh_tokens (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,\n token TEXT UNIQUE,\n token_hash TEXT,\n token_type TEXT DEFAULT 'refresh',\n expires_at TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_hazo_refresh_tokens_user ON hazo_refresh_tokens(user_id);\nCREATE INDEX IF NOT EXISTS idx_hazo_refresh_tokens_token ON hazo_refresh_tokens(token);\nCREATE INDEX IF NOT EXISTS idx_hazo_refresh_tokens_token_hash ON hazo_refresh_tokens(token_hash);\n\n-- Roles table\nCREATE TABLE IF NOT EXISTS hazo_roles (\n id TEXT PRIMARY KEY,\n role_name TEXT NOT NULL UNIQUE,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n changed_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Permissions table\nCREATE TABLE IF NOT EXISTS hazo_permissions (\n id TEXT PRIMARY KEY,\n permission_name TEXT NOT NULL UNIQUE,\n description TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n changed_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Role-permission assignments (composite PK, no id column)\nCREATE TABLE IF NOT EXISTS hazo_role_permissions (\n role_id TEXT NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,\n permission_id TEXT NOT NULL REFERENCES hazo_permissions(id) ON DELETE CASCADE,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (role_id, permission_id)\n);\n\n-- Unified scopes table (hierarchical multi-tenancy)\nCREATE TABLE IF NOT EXISTS hazo_scopes (\n id TEXT PRIMARY KEY,\n parent_id TEXT REFERENCES hazo_scopes(id) ON DELETE CASCADE,\n name TEXT NOT NULL,\n level TEXT NOT NULL,\n logo_url TEXT,\n primary_color TEXT,\n secondary_color TEXT,\n tagline TEXT,\n slug TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n changed_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_hazo_scopes_parent ON hazo_scopes(parent_id);\nCREATE INDEX IF NOT EXISTS idx_hazo_scopes_level ON hazo_scopes(level);\nCREATE INDEX IF NOT EXISTS idx_hazo_scopes_slug ON hazo_scopes(slug);\n\n--
|
|
1
|
+
export declare const SQLITE_SCHEMA = "\n-- hazo_auth canonical SQLite schema\n-- This schema creates all tables required by hazo_auth\n\n-- Users table (from migration 011)\nCREATE TABLE IF NOT EXISTS hazo_users (\n id TEXT PRIMARY KEY,\n email_address TEXT NOT NULL UNIQUE,\n password_hash TEXT,\n name TEXT,\n email_verified BOOLEAN DEFAULT false,\n login_attempts INTEGER DEFAULT 0,\n last_logon TEXT,\n profile_picture_url TEXT,\n profile_source TEXT CHECK(profile_source IN ('gravatar', 'custom', 'predefined')),\n mfa_secret TEXT,\n url_on_logon TEXT,\n google_id TEXT UNIQUE,\n auth_providers TEXT DEFAULT 'email',\n user_type TEXT,\n app_user_data TEXT,\n status TEXT DEFAULT 'ACTIVE' CHECK(status IN ('PENDING', 'ACTIVE', 'BLOCKED')),\n managed_by_user_id TEXT REFERENCES hazo_users(id) ON DELETE SET NULL,\n pin_hash TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n changed_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_hazo_users_email ON hazo_users(email_address);\nCREATE INDEX IF NOT EXISTS idx_hazo_users_google_id ON hazo_users(google_id);\nCREATE INDEX IF NOT EXISTS idx_hazo_users_status ON hazo_users(status);\n\n-- Refresh tokens table\n-- Note: runtime (token_service.ts) writes token_hash (argon2-hashed value) on\n-- insert and verifies via argon2.verify(token_hash, plaintext_token) on read.\n-- The plaintext \"token\" column is retained nullable for legacy compatibility\n-- but new writes only set token_hash.\nCREATE TABLE IF NOT EXISTS hazo_refresh_tokens (\n id TEXT PRIMARY KEY,\n user_id TEXT NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,\n token TEXT UNIQUE,\n token_hash TEXT,\n token_type TEXT DEFAULT 'refresh',\n expires_at TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_hazo_refresh_tokens_user ON hazo_refresh_tokens(user_id);\nCREATE INDEX IF NOT EXISTS idx_hazo_refresh_tokens_token ON hazo_refresh_tokens(token);\nCREATE INDEX IF NOT EXISTS idx_hazo_refresh_tokens_token_hash ON hazo_refresh_tokens(token_hash);\n\n-- Roles table\nCREATE TABLE IF NOT EXISTS hazo_roles (\n id TEXT PRIMARY KEY,\n role_name TEXT NOT NULL UNIQUE,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n changed_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Permissions table\nCREATE TABLE IF NOT EXISTS hazo_permissions (\n id TEXT PRIMARY KEY,\n permission_name TEXT NOT NULL UNIQUE,\n description TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n changed_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\n-- Role-permission assignments (composite PK, no id column)\nCREATE TABLE IF NOT EXISTS hazo_role_permissions (\n role_id TEXT NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,\n permission_id TEXT NOT NULL REFERENCES hazo_permissions(id) ON DELETE CASCADE,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (role_id, permission_id)\n);\n\n-- Unified scopes table (hierarchical multi-tenancy)\nCREATE TABLE IF NOT EXISTS hazo_scopes (\n id TEXT PRIMARY KEY,\n parent_id TEXT REFERENCES hazo_scopes(id) ON DELETE CASCADE,\n name TEXT NOT NULL,\n level TEXT NOT NULL,\n logo_url TEXT,\n primary_color TEXT,\n secondary_color TEXT,\n tagline TEXT,\n slug TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n changed_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_hazo_scopes_parent ON hazo_scopes(parent_id);\nCREATE INDEX IF NOT EXISTS idx_hazo_scopes_level ON hazo_scopes(level);\nCREATE INDEX IF NOT EXISTS idx_hazo_scopes_slug ON hazo_scopes(slug);\n\n-- Default system scope (for non-multi-tenancy mode)\nINSERT OR IGNORE INTO hazo_scopes (id, parent_id, name, level, created_at, changed_at)\nVALUES ('00000000-0000-0000-0000-000000000001', NULL, 'System', 'default', datetime('now'), datetime('now'));\n\n-- User-scope assignments (membership model with scope-specific roles)\nCREATE TABLE IF NOT EXISTS hazo_user_scopes (\n user_id TEXT NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,\n scope_id TEXT NOT NULL REFERENCES hazo_scopes(id) ON DELETE CASCADE,\n root_scope_id TEXT NOT NULL REFERENCES hazo_scopes(id) ON DELETE CASCADE,\n role_id TEXT NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,\n status TEXT DEFAULT 'ACTIVE' CHECK (status IN ('INVITED', 'ACTIVE', 'SUSPENDED', 'DEPARTED')),\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n changed_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (user_id, scope_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_hazo_user_scopes_scope ON hazo_user_scopes(scope_id);\nCREATE INDEX IF NOT EXISTS idx_hazo_user_scopes_root ON hazo_user_scopes(root_scope_id);\nCREATE INDEX IF NOT EXISTS idx_hazo_user_scopes_role ON hazo_user_scopes(role_id);\n\n-- Invitations table\nCREATE TABLE IF NOT EXISTS hazo_invitations (\n id TEXT PRIMARY KEY,\n email_address TEXT NOT NULL,\n token TEXT NOT NULL UNIQUE,\n scope_id TEXT NOT NULL REFERENCES hazo_scopes(id) ON DELETE CASCADE,\n root_scope_id TEXT NOT NULL REFERENCES hazo_scopes(id) ON DELETE CASCADE,\n role_id TEXT NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,\n invited_by TEXT REFERENCES hazo_users(id) ON DELETE SET NULL,\n status TEXT NOT NULL DEFAULT 'PENDING' CHECK(status IN ('PENDING', 'ACCEPTED', 'EXPIRED', 'REVOKED')),\n expires_at TEXT NOT NULL,\n accepted_at TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n changed_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_hazo_invitations_email ON hazo_invitations(email_address);\nCREATE INDEX IF NOT EXISTS idx_hazo_invitations_token ON hazo_invitations(token);\nCREATE INDEX IF NOT EXISTS idx_hazo_invitations_scope ON hazo_invitations(scope_id);\nCREATE INDEX IF NOT EXISTS idx_hazo_invitations_status ON hazo_invitations(status);\nCREATE INDEX IF NOT EXISTS idx_hazo_invitations_expires ON hazo_invitations(expires_at);\n\nCREATE INDEX IF NOT EXISTS idx_hazo_users_managed_by ON hazo_users(managed_by_user_id);\n\n-- Relationships table\nCREATE TABLE IF NOT EXISTS hazo_user_relationships (\n id TEXT PRIMARY KEY,\n parent_user_id TEXT NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,\n child_user_id TEXT NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,\n relationship_type TEXT NOT NULL DEFAULT 'parent',\n can_view_progress BOOLEAN DEFAULT true,\n can_edit_profile BOOLEAN DEFAULT true,\n can_delete BOOLEAN DEFAULT false,\n is_self BOOLEAN DEFAULT false,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n UNIQUE(parent_user_id, child_user_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_hazo_user_relationships_parent ON hazo_user_relationships(parent_user_id);\nCREATE INDEX IF NOT EXISTS idx_hazo_user_relationships_child ON hazo_user_relationships(child_user_id);\n\n-- Firm admin role (for firm creators)\nINSERT OR IGNORE INTO hazo_roles (id, role_name, created_at, changed_at)\nVALUES (lower(hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-4' || substr(hex(randomblob(2)),2) || '-' || substr('89ab',abs(random()) % 4 + 1, 1) || substr(hex(randomblob(2)),2) || '-' || hex(randomblob(6))), 'firm_admin', datetime('now'), datetime('now'));\n";
|
|
2
2
|
//# sourceMappingURL=sqlite_schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite_schema.d.ts","sourceRoot":"","sources":["../../../src/lib/schema/sqlite_schema.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"sqlite_schema.d.ts","sourceRoot":"","sources":["../../../src/lib/schema/sqlite_schema.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa,ogOA+JzB,CAAC"}
|
|
@@ -96,10 +96,6 @@ CREATE INDEX IF NOT EXISTS idx_hazo_scopes_parent ON hazo_scopes(parent_id);
|
|
|
96
96
|
CREATE INDEX IF NOT EXISTS idx_hazo_scopes_level ON hazo_scopes(level);
|
|
97
97
|
CREATE INDEX IF NOT EXISTS idx_hazo_scopes_slug ON hazo_scopes(slug);
|
|
98
98
|
|
|
99
|
-
-- Super admin scope
|
|
100
|
-
INSERT OR IGNORE INTO hazo_scopes (id, parent_id, name, level, created_at, changed_at)
|
|
101
|
-
VALUES ('00000000-0000-0000-0000-000000000000', NULL, 'Super Admin', 'system', datetime('now'), datetime('now'));
|
|
102
|
-
|
|
103
99
|
-- Default system scope (for non-multi-tenancy mode)
|
|
104
100
|
INSERT OR IGNORE INTO hazo_scopes (id, parent_id, name, level, created_at, changed_at)
|
|
105
101
|
VALUES ('00000000-0000-0000-0000-000000000001', NULL, 'System', 'default', datetime('now'), datetime('now'));
|
|
@@ -10,8 +10,6 @@ export type ScopeHierarchyConfig = {
|
|
|
10
10
|
scope_cache_ttl_minutes: number;
|
|
11
11
|
/** Maximum entries in scope cache (default: 5000) */
|
|
12
12
|
scope_cache_max_entries: number;
|
|
13
|
-
/** Super admin scope ID */
|
|
14
|
-
super_admin_scope_id: string;
|
|
15
13
|
/** Default system scope ID (for non-multi-tenancy mode) */
|
|
16
14
|
default_system_scope_id: string;
|
|
17
15
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope_hierarchy_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/scope_hierarchy_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAYrB;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,gDAAgD;IAChD,YAAY,EAAE,OAAO,CAAC;IACtB,2DAA2D;IAC3D,uBAAuB,EAAE,MAAM,CAAC;IAChC,qDAAqD;IACrD,uBAAuB,EAAE,MAAM,CAAC;IAChC,
|
|
1
|
+
{"version":3,"file":"scope_hierarchy_config.server.d.ts","sourceRoot":"","sources":["../../src/lib/scope_hierarchy_config.server.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,CAAC;AAYrB;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,gDAAgD;IAChD,YAAY,EAAE,OAAO,CAAC;IACtB,2DAA2D;IAC3D,uBAAuB,EAAE,MAAM,CAAC;IAChC,qDAAqD;IACrD,uBAAuB,EAAE,MAAM,CAAC;IAChC,2DAA2D;IAC3D,uBAAuB,EAAE,MAAM,CAAC;CACjC,CAAC;AAQF;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,oBAAoB,CA6BjE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import "server-only";
|
|
4
4
|
// section: imports
|
|
5
5
|
import { get_config_value, get_config_number, get_config_boolean, } from "./config/config_loader.server.js";
|
|
6
|
-
import {
|
|
6
|
+
import { DEFAULT_SYSTEM_SCOPE_ID } from "./services/scope_service.js";
|
|
7
7
|
// section: constants
|
|
8
8
|
const SECTION_NAME = "hazo_auth__scope_hierarchy";
|
|
9
9
|
// section: helpers
|
|
@@ -19,13 +19,11 @@ export function get_scope_hierarchy_config() {
|
|
|
19
19
|
const scope_cache_ttl_minutes = get_config_number(SECTION_NAME, "scope_cache_ttl_minutes", 15);
|
|
20
20
|
const scope_cache_max_entries = get_config_number(SECTION_NAME, "scope_cache_max_entries", 5000);
|
|
21
21
|
// Scope IDs (with defaults)
|
|
22
|
-
const super_admin_scope_id = get_config_value(SECTION_NAME, "super_admin_scope_id", SUPER_ADMIN_SCOPE_ID);
|
|
23
22
|
const default_system_scope_id = get_config_value(SECTION_NAME, "default_system_scope_id", DEFAULT_SYSTEM_SCOPE_ID);
|
|
24
23
|
return {
|
|
25
24
|
enable_hrbac,
|
|
26
25
|
scope_cache_ttl_minutes,
|
|
27
26
|
scope_cache_max_entries,
|
|
28
|
-
super_admin_scope_id,
|
|
29
27
|
default_system_scope_id,
|
|
30
28
|
};
|
|
31
29
|
}
|
|
@@ -53,7 +53,7 @@ export declare function revoke_invitation(adapter: HazoConnectAdapter, invitatio
|
|
|
53
53
|
*/
|
|
54
54
|
export declare function list_invitations_by_scope(adapter: HazoConnectAdapter, scope_id: string, status?: InvitationStatus): Promise<InvitationServiceResult>;
|
|
55
55
|
/**
|
|
56
|
-
* Lists all invitations (for
|
|
56
|
+
* Lists all invitations (for global admins)
|
|
57
57
|
*/
|
|
58
58
|
export declare function list_all_invitations(adapter: HazoConnectAdapter, status?: InvitationStatus): Promise<InvitationServiceResult>;
|
|
59
59
|
/**
|
|
@@ -365,7 +365,7 @@ export async function list_invitations_by_scope(adapter, scope_id, status) {
|
|
|
365
365
|
}
|
|
366
366
|
}
|
|
367
367
|
/**
|
|
368
|
-
* Lists all invitations (for
|
|
368
|
+
* Lists all invitations (for global admins)
|
|
369
369
|
*/
|
|
370
370
|
export async function list_all_invitations(adapter, status) {
|
|
371
371
|
try {
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import type { HazoConnectAdapter } from "hazo_connect";
|
|
2
|
-
/**
|
|
3
|
-
* Super admin scope ID - special UUID for system-level administrators
|
|
4
|
-
* Users assigned to this scope have global access
|
|
5
|
-
*/
|
|
6
|
-
export declare const SUPER_ADMIN_SCOPE_ID = "00000000-0000-0000-0000-000000000000";
|
|
7
2
|
/**
|
|
8
3
|
* Default system scope ID - for non-multi-tenancy mode
|
|
9
4
|
* All users are assigned to this scope when multi-tenancy is disabled
|
|
@@ -67,16 +62,12 @@ export declare function extract_branding(scope: ScopeRecord): FirmBranding | nul
|
|
|
67
62
|
* Checks if a scope has any branding set
|
|
68
63
|
*/
|
|
69
64
|
export declare function has_branding(scope: ScopeRecord): boolean;
|
|
70
|
-
/**
|
|
71
|
-
* Checks if the given scope_id is the super admin scope
|
|
72
|
-
*/
|
|
73
|
-
export declare function is_super_admin_scope(scope_id: string): boolean;
|
|
74
65
|
/**
|
|
75
66
|
* Checks if the given scope_id is the default system scope
|
|
76
67
|
*/
|
|
77
68
|
export declare function is_default_system_scope(scope_id: string): boolean;
|
|
78
69
|
/**
|
|
79
|
-
* Checks if the given scope_id is a system scope (
|
|
70
|
+
* Checks if the given scope_id is a system scope (default system)
|
|
80
71
|
*/
|
|
81
72
|
export declare function is_system_scope(scope_id: string): boolean;
|
|
82
73
|
/**
|
|
@@ -133,10 +124,6 @@ export declare function get_scope_tree(adapter: HazoConnectAdapter, root_scope_i
|
|
|
133
124
|
tree?: ScopeTreeNode[];
|
|
134
125
|
error?: string;
|
|
135
126
|
}>;
|
|
136
|
-
/**
|
|
137
|
-
* Ensures the super admin scope exists
|
|
138
|
-
*/
|
|
139
|
-
export declare function ensure_super_admin_scope(adapter: HazoConnectAdapter): Promise<ScopeServiceResult>;
|
|
140
127
|
/**
|
|
141
128
|
* Ensures the default system scope exists
|
|
142
129
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/scope_service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAOvD;;;GAGG;AACH,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"scope_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/scope_service.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,11 +2,6 @@ import { createCrudService } from "hazo_connect/server";
|
|
|
2
2
|
import { create_app_logger } from "../app_logger.js";
|
|
3
3
|
import { sanitize_error_for_user } from "../utils/error_sanitizer.js";
|
|
4
4
|
// section: constants
|
|
5
|
-
/**
|
|
6
|
-
* Super admin scope ID - special UUID for system-level administrators
|
|
7
|
-
* Users assigned to this scope have global access
|
|
8
|
-
*/
|
|
9
|
-
export const SUPER_ADMIN_SCOPE_ID = "00000000-0000-0000-0000-000000000000";
|
|
10
5
|
/**
|
|
11
6
|
* Default system scope ID - for non-multi-tenancy mode
|
|
12
7
|
* All users are assigned to this scope when multi-tenancy is disabled
|
|
@@ -52,12 +47,6 @@ export function extract_branding(scope) {
|
|
|
52
47
|
export function has_branding(scope) {
|
|
53
48
|
return !!(scope.logo_url || scope.primary_color || scope.secondary_color || scope.tagline);
|
|
54
49
|
}
|
|
55
|
-
/**
|
|
56
|
-
* Checks if the given scope_id is the super admin scope
|
|
57
|
-
*/
|
|
58
|
-
export function is_super_admin_scope(scope_id) {
|
|
59
|
-
return scope_id === SUPER_ADMIN_SCOPE_ID;
|
|
60
|
-
}
|
|
61
50
|
/**
|
|
62
51
|
* Checks if the given scope_id is the default system scope
|
|
63
52
|
*/
|
|
@@ -65,10 +54,10 @@ export function is_default_system_scope(scope_id) {
|
|
|
65
54
|
return scope_id === DEFAULT_SYSTEM_SCOPE_ID;
|
|
66
55
|
}
|
|
67
56
|
/**
|
|
68
|
-
* Checks if the given scope_id is a system scope (
|
|
57
|
+
* Checks if the given scope_id is a system scope (default system)
|
|
69
58
|
*/
|
|
70
59
|
export function is_system_scope(scope_id) {
|
|
71
|
-
return
|
|
60
|
+
return is_default_system_scope(scope_id);
|
|
72
61
|
}
|
|
73
62
|
// section: crud operations
|
|
74
63
|
/**
|
|
@@ -605,60 +594,6 @@ export async function get_scope_tree(adapter, root_scope_id) {
|
|
|
605
594
|
};
|
|
606
595
|
}
|
|
607
596
|
}
|
|
608
|
-
/**
|
|
609
|
-
* Ensures the super admin scope exists
|
|
610
|
-
*/
|
|
611
|
-
export async function ensure_super_admin_scope(adapter) {
|
|
612
|
-
try {
|
|
613
|
-
// Check if already exists
|
|
614
|
-
const existing = await get_scope_by_id(adapter, SUPER_ADMIN_SCOPE_ID);
|
|
615
|
-
if (existing.success && existing.scope) {
|
|
616
|
-
return existing;
|
|
617
|
-
}
|
|
618
|
-
// Create it
|
|
619
|
-
const scope_service = createCrudService(adapter, "hazo_scopes");
|
|
620
|
-
const now = new Date().toISOString();
|
|
621
|
-
const inserted = await scope_service.insert({
|
|
622
|
-
id: SUPER_ADMIN_SCOPE_ID,
|
|
623
|
-
name: "Super Admin",
|
|
624
|
-
level: "system",
|
|
625
|
-
parent_id: null,
|
|
626
|
-
logo_url: null,
|
|
627
|
-
primary_color: null,
|
|
628
|
-
secondary_color: null,
|
|
629
|
-
tagline: null,
|
|
630
|
-
created_at: now,
|
|
631
|
-
changed_at: now,
|
|
632
|
-
});
|
|
633
|
-
if (!Array.isArray(inserted) || inserted.length === 0) {
|
|
634
|
-
return {
|
|
635
|
-
success: false,
|
|
636
|
-
error: "Failed to create super admin scope",
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
return {
|
|
640
|
-
success: true,
|
|
641
|
-
scope: normalize_scope_record(inserted[0]),
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
catch (error) {
|
|
645
|
-
const logger = create_app_logger();
|
|
646
|
-
const error_message = sanitize_error_for_user(error, {
|
|
647
|
-
logToConsole: true,
|
|
648
|
-
logToLogger: true,
|
|
649
|
-
logger,
|
|
650
|
-
context: {
|
|
651
|
-
filename: "scope_service.ts",
|
|
652
|
-
line_number: 0,
|
|
653
|
-
operation: "ensure_super_admin_scope",
|
|
654
|
-
},
|
|
655
|
-
});
|
|
656
|
-
return {
|
|
657
|
-
success: false,
|
|
658
|
-
error: error_message,
|
|
659
|
-
};
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
597
|
/**
|
|
663
598
|
* Ensures the default system scope exists
|
|
664
599
|
*/
|
|
@@ -20,7 +20,6 @@ export type ScopeAccessCheckResult = {
|
|
|
20
20
|
scope_name?: string;
|
|
21
21
|
};
|
|
22
22
|
user_scopes?: UserScope[];
|
|
23
|
-
is_super_admin?: boolean;
|
|
24
23
|
};
|
|
25
24
|
export type AssignUserScopeData = {
|
|
26
25
|
user_id: string;
|
|
@@ -52,10 +51,6 @@ export declare function update_user_scopes(adapter: HazoConnectAdapter, user_id:
|
|
|
52
51
|
scope_id: string;
|
|
53
52
|
role_id: string;
|
|
54
53
|
}>): Promise<UserScopeResult>;
|
|
55
|
-
/**
|
|
56
|
-
* Checks if a user is a super admin (has super admin scope assigned)
|
|
57
|
-
*/
|
|
58
|
-
export declare function is_user_super_admin(adapter: HazoConnectAdapter, user_id: string): Promise<boolean>;
|
|
59
54
|
/**
|
|
60
55
|
* Checks if a user has any scope assigned
|
|
61
56
|
*/
|
|
@@ -63,9 +58,11 @@ export declare function user_has_any_scope(adapter: HazoConnectAdapter, user_id:
|
|
|
63
58
|
/**
|
|
64
59
|
* Checks if a user has access to a specific scope
|
|
65
60
|
* Access is granted if:
|
|
66
|
-
* 1. User
|
|
67
|
-
* 2. User has
|
|
68
|
-
*
|
|
61
|
+
* 1. User has the exact scope assigned
|
|
62
|
+
* 2. User has access to an ancestor scope (inherited access)
|
|
63
|
+
*
|
|
64
|
+
* Global admin access (hazo_org_global_admin permission) is handled upstream
|
|
65
|
+
* in hazo_get_auth before this function is called.
|
|
69
66
|
*
|
|
70
67
|
* @param adapter - HazoConnect adapter
|
|
71
68
|
* @param user_id - User ID to check
|
|
@@ -85,8 +82,4 @@ export declare function get_user_direct_scopes(adapter: HazoConnectAdapter, user
|
|
|
85
82
|
}>;
|
|
86
83
|
error?: string;
|
|
87
84
|
}>;
|
|
88
|
-
/**
|
|
89
|
-
* Assigns super admin scope to a user
|
|
90
|
-
*/
|
|
91
|
-
export declare function assign_super_admin_scope(adapter: HazoConnectAdapter, user_id: string, role_id: string): Promise<UserScopeResult>;
|
|
92
85
|
//# sourceMappingURL=user_scope_service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user_scope_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/user_scope_service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"user_scope_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/user_scope_service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAuBvD,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAIF;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,CAAC,CA4B1B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC,CA4B1B;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,kBAAkB,EAC3B,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,eAAe,CAAC,CA2E1B;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC,CA2E1B;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GACvD,OAAO,CAAC,eAAe,CAAC,CAwD1B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,sBAAsB,CAAC,CAoEjC;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,KAAK,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA4CD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createCrudService } from "hazo_connect/server";
|
|
2
2
|
import { create_app_logger } from "../app_logger.js";
|
|
3
3
|
import { sanitize_error_for_user } from "../utils/error_sanitizer.js";
|
|
4
|
-
import { get_scope_by_id, get_scope_ancestors, get_root_scope_id,
|
|
4
|
+
import { get_scope_by_id, get_scope_ancestors, get_root_scope_id, } from "./scope_service.js";
|
|
5
5
|
// section: constants
|
|
6
6
|
/**
|
|
7
7
|
* CRUD service options for hazo_user_scopes table
|
|
@@ -274,21 +274,6 @@ export async function update_user_scopes(adapter, user_id, new_scopes) {
|
|
|
274
274
|
};
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
|
-
/**
|
|
278
|
-
* Checks if a user is a super admin (has super admin scope assigned)
|
|
279
|
-
*/
|
|
280
|
-
export async function is_user_super_admin(adapter, user_id) {
|
|
281
|
-
try {
|
|
282
|
-
const user_scopes_result = await get_user_scopes(adapter, user_id);
|
|
283
|
-
if (!user_scopes_result.success || !user_scopes_result.scopes) {
|
|
284
|
-
return false;
|
|
285
|
-
}
|
|
286
|
-
return user_scopes_result.scopes.some((scope) => is_super_admin_scope(scope.scope_id));
|
|
287
|
-
}
|
|
288
|
-
catch (_a) {
|
|
289
|
-
return false;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
277
|
/**
|
|
293
278
|
* Checks if a user has any scope assigned
|
|
294
279
|
*/
|
|
@@ -306,9 +291,11 @@ export async function user_has_any_scope(adapter, user_id) {
|
|
|
306
291
|
/**
|
|
307
292
|
* Checks if a user has access to a specific scope
|
|
308
293
|
* Access is granted if:
|
|
309
|
-
* 1. User
|
|
310
|
-
* 2. User has
|
|
311
|
-
*
|
|
294
|
+
* 1. User has the exact scope assigned
|
|
295
|
+
* 2. User has access to an ancestor scope (inherited access)
|
|
296
|
+
*
|
|
297
|
+
* Global admin access (hazo_org_global_admin permission) is handled upstream
|
|
298
|
+
* in hazo_get_auth before this function is called.
|
|
312
299
|
*
|
|
313
300
|
* @param adapter - HazoConnect adapter
|
|
314
301
|
* @param user_id - User ID to check
|
|
@@ -323,20 +310,7 @@ export async function check_user_scope_access(adapter, user_id, target_scope_id)
|
|
|
323
310
|
return { has_access: false };
|
|
324
311
|
}
|
|
325
312
|
const user_scopes = user_scopes_result.scopes;
|
|
326
|
-
// Check 1:
|
|
327
|
-
const has_super_admin = user_scopes.some((scope) => is_super_admin_scope(scope.scope_id));
|
|
328
|
-
if (has_super_admin) {
|
|
329
|
-
return {
|
|
330
|
-
has_access: true,
|
|
331
|
-
access_via: {
|
|
332
|
-
scope_id: SUPER_ADMIN_SCOPE_ID,
|
|
333
|
-
scope_name: "Super Admin",
|
|
334
|
-
},
|
|
335
|
-
user_scopes,
|
|
336
|
-
is_super_admin: true,
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
// Check 2: Does user have exact scope assigned?
|
|
313
|
+
// Check 1: Does user have exact scope assigned?
|
|
340
314
|
for (const user_scope of user_scopes) {
|
|
341
315
|
if (user_scope.scope_id === target_scope_id) {
|
|
342
316
|
const scope_result = await get_scope_by_id(adapter, target_scope_id);
|
|
@@ -352,7 +326,7 @@ export async function check_user_scope_access(adapter, user_id, target_scope_id)
|
|
|
352
326
|
};
|
|
353
327
|
}
|
|
354
328
|
}
|
|
355
|
-
// Check
|
|
329
|
+
// Check 2: Does user have access via an ancestor scope?
|
|
356
330
|
const ancestors_result = await get_scope_ancestors(adapter, target_scope_id);
|
|
357
331
|
if (ancestors_result.success && ancestors_result.scopes) {
|
|
358
332
|
for (const ancestor of ancestors_result.scopes) {
|
|
@@ -436,14 +410,3 @@ export async function get_user_direct_scopes(adapter, user_id) {
|
|
|
436
410
|
};
|
|
437
411
|
}
|
|
438
412
|
}
|
|
439
|
-
/**
|
|
440
|
-
* Assigns super admin scope to a user
|
|
441
|
-
*/
|
|
442
|
-
export async function assign_super_admin_scope(adapter, user_id, role_id) {
|
|
443
|
-
return assign_user_scope(adapter, {
|
|
444
|
-
user_id,
|
|
445
|
-
scope_id: SUPER_ADMIN_SCOPE_ID,
|
|
446
|
-
root_scope_id: SUPER_ADMIN_SCOPE_ID,
|
|
447
|
-
role_id,
|
|
448
|
-
});
|
|
449
|
-
}
|
|
@@ -5,7 +5,7 @@ export declare const dynamic = "force-dynamic";
|
|
|
5
5
|
* Query params:
|
|
6
6
|
* - scope_id: Filter by scope (optional, required for non-super-admins)
|
|
7
7
|
* - status: Filter by status (optional: PENDING, ACCEPTED, EXPIRED, REVOKED)
|
|
8
|
-
*
|
|
8
|
+
* Global admins can see all invitations, others can only see invitations for their scopes
|
|
9
9
|
*/
|
|
10
10
|
export declare function GET(request: NextRequest): Promise<NextResponse<{
|
|
11
11
|
error: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invitations.d.ts","sourceRoot":"","sources":["../../../src/server/routes/invitations.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"invitations.d.ts","sourceRoot":"","sources":["../../../src/server/routes/invitations.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiBxD,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAGvC;;;;;;GAMG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;;;IAqH7C;AAED;;;GAGG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;IAoG9C;AAED;;;GAGG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,WAAW;;;;;IAkG/C;AAED;;;GAGG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,WAAW;;;;IA2FhD"}
|
|
@@ -6,7 +6,8 @@ import { create_app_logger } from "../../lib/app_logger.js";
|
|
|
6
6
|
import { get_filename, get_line_number } from "../../lib/utils/api_route_helpers.js";
|
|
7
7
|
import { hazo_get_auth } from "../../lib/auth/hazo_get_auth.server.js";
|
|
8
8
|
import { create_invitation, list_invitations_by_scope, list_all_invitations, revoke_invitation, get_invitation_by_id, } from "../../lib/services/invitation_service.js";
|
|
9
|
-
import {
|
|
9
|
+
import { get_user_scopes } from "../../lib/services/user_scope_service.js";
|
|
10
|
+
import { GLOBAL_ADMIN_PERMISSION } from "../../lib/constants.js";
|
|
10
11
|
// section: route_config
|
|
11
12
|
export const dynamic = "force-dynamic";
|
|
12
13
|
// section: api_handler
|
|
@@ -15,7 +16,7 @@ export const dynamic = "force-dynamic";
|
|
|
15
16
|
* Query params:
|
|
16
17
|
* - scope_id: Filter by scope (optional, required for non-super-admins)
|
|
17
18
|
* - status: Filter by status (optional: PENDING, ACCEPTED, EXPIRED, REVOKED)
|
|
18
|
-
*
|
|
19
|
+
* Global admins can see all invitations, others can only see invitations for their scopes
|
|
19
20
|
*/
|
|
20
21
|
export async function GET(request) {
|
|
21
22
|
var _a, _b;
|
|
@@ -34,11 +35,11 @@ export async function GET(request) {
|
|
|
34
35
|
const status_param = searchParams.get("status");
|
|
35
36
|
const status = status_param;
|
|
36
37
|
const hazoConnect = get_hazo_connect_instance();
|
|
37
|
-
// Check if user is
|
|
38
|
-
const is_super =
|
|
38
|
+
// Check if user is a global admin
|
|
39
|
+
const is_super = auth.permissions.includes(GLOBAL_ADMIN_PERMISSION);
|
|
39
40
|
let result;
|
|
40
41
|
if (is_super) {
|
|
41
|
-
//
|
|
42
|
+
// Global admin can see all invitations
|
|
42
43
|
if (scope_id) {
|
|
43
44
|
result = await list_invitations_by_scope(hazoConnect, scope_id, status);
|
|
44
45
|
}
|
|
@@ -124,8 +125,8 @@ export async function POST(request) {
|
|
|
124
125
|
return NextResponse.json({ error: "Invalid email address format" }, { status: 400 });
|
|
125
126
|
}
|
|
126
127
|
const hazoConnect = get_hazo_connect_instance();
|
|
127
|
-
// Check if user is
|
|
128
|
-
const is_super =
|
|
128
|
+
// Check if user is a global admin or has access to the scope
|
|
129
|
+
const is_super = auth.permissions.includes(GLOBAL_ADMIN_PERMISSION);
|
|
129
130
|
if (!is_super) {
|
|
130
131
|
const user_scopes = await get_user_scopes(hazoConnect, auth.user.id);
|
|
131
132
|
const has_scope_access = (_a = user_scopes.scopes) === null || _a === void 0 ? void 0 : _a.some((s) => s.scope_id === scope_id);
|
|
@@ -196,8 +197,8 @@ export async function PATCH(request) {
|
|
|
196
197
|
if (!invitation_result.success || !invitation_result.invitation) {
|
|
197
198
|
return NextResponse.json({ error: "Invitation not found" }, { status: 404 });
|
|
198
199
|
}
|
|
199
|
-
// Check if user is
|
|
200
|
-
const is_super =
|
|
200
|
+
// Check if user is a global admin or has access to the invitation's scope
|
|
201
|
+
const is_super = auth.permissions.includes(GLOBAL_ADMIN_PERMISSION);
|
|
201
202
|
if (!is_super) {
|
|
202
203
|
const user_scopes = await get_user_scopes(hazoConnect, auth.user.id);
|
|
203
204
|
const has_scope_access = (_a = user_scopes.scopes) === null || _a === void 0 ? void 0 : _a.some((s) => { var _a; return s.scope_id === ((_a = invitation_result.invitation) === null || _a === void 0 ? void 0 : _a.scope_id); });
|
|
@@ -257,8 +258,8 @@ export async function DELETE(request) {
|
|
|
257
258
|
if (!invitation_result.success || !invitation_result.invitation) {
|
|
258
259
|
return NextResponse.json({ error: "Invitation not found" }, { status: 404 });
|
|
259
260
|
}
|
|
260
|
-
// Check if user is
|
|
261
|
-
const is_super =
|
|
261
|
+
// Check if user is a global admin or has access to the invitation's scope
|
|
262
|
+
const is_super = auth.permissions.includes(GLOBAL_ADMIN_PERMISSION);
|
|
262
263
|
if (!is_super) {
|
|
263
264
|
const user_scopes = await get_user_scopes(hazoConnect, auth.user.id);
|
|
264
265
|
const has_scope_access = (_a = user_scopes.scopes) === null || _a === void 0 ? void 0 : _a.some((s) => { var _a; return s.scope_id === ((_a = invitation_result.invitation) === null || _a === void 0 ? void 0 : _a.scope_id); });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hazo_auth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0",
|
|
4
4
|
"description": "Zero-config authentication UI components for Next.js with RBAC, OAuth, scope-based multi-tenancy, and invitations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"authentication",
|
|
@@ -252,13 +252,13 @@
|
|
|
252
252
|
"@radix-ui/react-switch": "^1.2.0",
|
|
253
253
|
"@radix-ui/react-tabs": "^1.1.0",
|
|
254
254
|
"@radix-ui/react-tooltip": "^1.2.0",
|
|
255
|
-
"hazo_api": "^2.1
|
|
256
|
-
"hazo_config": "^2.1.
|
|
257
|
-
"hazo_connect": "^3.
|
|
258
|
-
"hazo_core": "^1.
|
|
259
|
-
"hazo_logs": "^2.0.
|
|
260
|
-
"hazo_notify": "^6.1.
|
|
261
|
-
"hazo_ui": "^3.1
|
|
255
|
+
"hazo_api": "^2.3.1",
|
|
256
|
+
"hazo_config": "^2.1.10",
|
|
257
|
+
"hazo_connect": "^3.4.1",
|
|
258
|
+
"hazo_core": "^1.1.0",
|
|
259
|
+
"hazo_logs": "^2.0.3",
|
|
260
|
+
"hazo_notify": "^6.1.3",
|
|
261
|
+
"hazo_ui": "^3.2.1",
|
|
262
262
|
"input-otp": "^1.4.0",
|
|
263
263
|
"lucide-react": "^0.553.0",
|
|
264
264
|
"next": "^14.0.0",
|
|
@@ -388,10 +388,10 @@
|
|
|
388
388
|
"eslint": "^9.39.1",
|
|
389
389
|
"eslint-config-next": "^16.0.4",
|
|
390
390
|
"eslint-plugin-storybook": "^10.0.6",
|
|
391
|
-
"hazo_api": "^2.3.
|
|
392
|
-
"hazo_config": "^2.1.
|
|
393
|
-
"hazo_connect": "^3.
|
|
394
|
-
"hazo_core": "^1.0
|
|
391
|
+
"hazo_api": "^2.3.1",
|
|
392
|
+
"hazo_config": "^2.1.10",
|
|
393
|
+
"hazo_connect": "^3.4.1",
|
|
394
|
+
"hazo_core": "^1.1.0",
|
|
395
395
|
"hazo_logs": "^2.0.3",
|
|
396
396
|
"hazo_notify": "^6.1.3",
|
|
397
397
|
"hazo_ui": "^3.2.1",
|