@logto/schemas 1.44.0 → 1.45.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.
@@ -0,0 +1,38 @@
1
+ import { sql } from '@silverhand/slonik';
2
+
3
+ import type { AlterationScript } from '../lib/types/alteration.js';
4
+
5
+ const alteration: AlterationScript = {
6
+ up: async (pool) => {
7
+ // Cloud region databases other than the admin tenant's own have no `admin` tenant to hold the role.
8
+ const adminTenant = await pool.maybeOne(sql`
9
+ select id from tenants where id = 'admin'
10
+ `);
11
+
12
+ if (!adminTenant) {
13
+ return;
14
+ }
15
+
16
+ await pool.query(sql`
17
+ update organization_scopes
18
+ set description = 'Write the tenant data.'
19
+ where tenant_id = 'admin' and id = 'write-data';
20
+ insert into organization_roles (tenant_id, id, name, description, type)
21
+ values ('admin', 'viewer', 'viewer', 'Viewer of the tenant, who can read the tenant data and members but cannot change anything.', 'User');
22
+ insert into organization_role_scope_relations (tenant_id, organization_role_id, organization_scope_id)
23
+ values ('admin', 'viewer', 'read-data'),
24
+ ('admin', 'viewer', 'read-member');
25
+ `);
26
+ },
27
+ down: async (pool) => {
28
+ await pool.query(sql`
29
+ delete from organization_roles
30
+ where tenant_id = 'admin' and id = 'viewer';
31
+ update organization_scopes
32
+ set description = 'Write the tenant data, including creating and updating the tenant.'
33
+ where tenant_id = 'admin' and id = 'write-data';
34
+ `);
35
+ },
36
+ };
37
+
38
+ export default alteration;
@@ -0,0 +1,32 @@
1
+ import { sql } from '@silverhand/slonik';
2
+ const alteration = {
3
+ up: async (pool) => {
4
+ // Cloud region databases other than the admin tenant's own have no `admin` tenant to hold the role.
5
+ const adminTenant = await pool.maybeOne(sql `
6
+ select id from tenants where id = 'admin'
7
+ `);
8
+ if (!adminTenant) {
9
+ return;
10
+ }
11
+ await pool.query(sql `
12
+ update organization_scopes
13
+ set description = 'Write the tenant data.'
14
+ where tenant_id = 'admin' and id = 'write-data';
15
+ insert into organization_roles (tenant_id, id, name, description, type)
16
+ values ('admin', 'viewer', 'viewer', 'Viewer of the tenant, who can read the tenant data and members but cannot change anything.', 'User');
17
+ insert into organization_role_scope_relations (tenant_id, organization_role_id, organization_scope_id)
18
+ values ('admin', 'viewer', 'read-data'),
19
+ ('admin', 'viewer', 'read-member');
20
+ `);
21
+ },
22
+ down: async (pool) => {
23
+ await pool.query(sql `
24
+ delete from organization_roles
25
+ where tenant_id = 'admin' and id = 'viewer';
26
+ update organization_scopes
27
+ set description = 'Write the tenant data, including creating and updating the tenant.'
28
+ where tenant_id = 'admin' and id = 'write-data';
29
+ `);
30
+ },
31
+ };
32
+ export default alteration;
@@ -107,7 +107,7 @@ export declare const licenseQuotaOverridesGuard: z.ZodObject<{
107
107
  }>;
108
108
  export type LicenseQuotaOverrides = z.infer<typeof licenseQuotaOverridesGuard>;
109
109
  /**
110
- * The payload of a license key, i.e. the claims of the Ed25519-signed JWT an operator installs on a
110
+ * The payload of a license key, i.e. the claims of the ES256-signed JWT an operator installs on a
111
111
  * self-hosted instance.
112
112
  *
113
113
  * The signature is what makes the payload trustworthy, so none of it is editable after issuing.
@@ -298,7 +298,7 @@ export declare const cloudflareGuard: Readonly<{
298
298
  * one license no matter how many instances share the database.
299
299
  */
300
300
  export declare const installedLicenseGuard: z.ZodObject<{
301
- /** The raw Ed25519-signed license key JWT, exactly as it was installed. */
301
+ /** The raw ES256-signed license key JWT, exactly as it was installed. */
302
302
  jwt: z.ZodString;
303
303
  /** When the key was installed, as an ISO 8601 timestamp. */
304
304
  installedAt: z.ZodString;
@@ -162,7 +162,7 @@ export const cloudflareGuard = Object.freeze({
162
162
  * one license no matter how many instances share the database.
163
163
  */
164
164
  export const installedLicenseGuard = z.object({
165
- /** The raw Ed25519-signed license key JWT, exactly as it was installed. */
165
+ /** The raw ES256-signed license key JWT, exactly as it was installed. */
166
166
  jwt: z.string(),
167
167
  /** When the key was installed, as an ISO 8601 timestamp. */
168
168
  installedAt: z.string(),
@@ -39,7 +39,7 @@ export declare const getTenantOrganizationCreateData: (tenantId: string) => Read
39
39
  export declare enum TenantScope {
40
40
  /** Read the tenant data. */
41
41
  ReadData = "read:data",
42
- /** Write the tenant data, including creating and updating the tenant. */
42
+ /** Write the tenant data. */
43
43
  WriteData = "write:data",
44
44
  /** Delete data of the tenant. */
45
45
  DeleteData = "delete:data",
@@ -83,7 +83,9 @@ export declare enum TenantRole {
83
83
  /** Admin of the tenant, who has all permissions. */
84
84
  Admin = "admin",
85
85
  /** Collaborator of the tenant, who has permissions to operate the tenant data, but not the tenant settings. */
86
- Collaborator = "collaborator"
86
+ Collaborator = "collaborator",
87
+ /** Viewer of the tenant, who can read the tenant data and members but cannot change anything. */
88
+ Viewer = "viewer"
87
89
  }
88
90
  /**
89
91
  * Given a tenant role, return the corresponding organization role data in the admin tenant.
@@ -50,7 +50,7 @@ export var TenantScope;
50
50
  (function (TenantScope) {
51
51
  /** Read the tenant data. */
52
52
  TenantScope["ReadData"] = "read:data";
53
- /** Write the tenant data, including creating and updating the tenant. */
53
+ /** Write the tenant data. */
54
54
  TenantScope["WriteData"] = "write:data";
55
55
  /** Delete data of the tenant. */
56
56
  TenantScope["DeleteData"] = "delete:data";
@@ -92,7 +92,7 @@ export const getTenantScope = (scope) => Object.freeze({
92
92
  });
93
93
  const tenantScopeDescriptions = Object.freeze({
94
94
  [TenantScope.ReadData]: 'Read the tenant data.',
95
- [TenantScope.WriteData]: 'Write the tenant data, including creating and updating the tenant.',
95
+ [TenantScope.WriteData]: 'Write the tenant data.',
96
96
  [TenantScope.DeleteData]: 'Delete data of the tenant.',
97
97
  [TenantScope.ReadMember]: 'Read members of the tenant.',
98
98
  [TenantScope.InviteMember]: 'Invite members to the tenant.',
@@ -112,10 +112,13 @@ export var TenantRole;
112
112
  TenantRole["Admin"] = "admin";
113
113
  /** Collaborator of the tenant, who has permissions to operate the tenant data, but not the tenant settings. */
114
114
  TenantRole["Collaborator"] = "collaborator";
115
+ /** Viewer of the tenant, who can read the tenant data and members but cannot change anything. */
116
+ TenantRole["Viewer"] = "viewer";
115
117
  })(TenantRole || (TenantRole = {}));
116
118
  const tenantRoleDescriptions = Object.freeze({
117
119
  [TenantRole.Admin]: 'Admin of the tenant, who has all permissions.',
118
120
  [TenantRole.Collaborator]: 'Collaborator of the tenant, who has permissions to operate the tenant data, but not the tenant settings.',
121
+ [TenantRole.Viewer]: 'Viewer of the tenant, who can read the tenant data and members but cannot change anything.',
119
122
  });
120
123
  /**
121
124
  * Given a tenant role, return the corresponding organization role data in the admin tenant.
@@ -155,4 +158,5 @@ export const tenantRoleScopes = Object.freeze({
155
158
  TenantScope.DeleteData,
156
159
  TenantScope.ReadMember,
157
160
  ],
161
+ [TenantRole.Viewer]: [TenantScope.ReadData, TenantScope.ReadMember],
158
162
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { TenantRole, TenantScope, tenantRoleScopes } from './tenant-organization.js';
3
+ describe('tenantRoleScopes', () => {
4
+ it('grants each tenant role its scopes', () => {
5
+ expect(tenantRoleScopes).toEqual({
6
+ [TenantRole.Admin]: Object.values(TenantScope),
7
+ [TenantRole.Collaborator]: [
8
+ TenantScope.ReadData,
9
+ TenantScope.WriteData,
10
+ TenantScope.DeleteData,
11
+ TenantScope.ReadMember,
12
+ ],
13
+ [TenantRole.Viewer]: [TenantScope.ReadData, TenantScope.ReadMember],
14
+ });
15
+ });
16
+ });
@@ -1 +1,6 @@
1
+ /**
2
+ * The pattern of Management API resource indicators, e.g. `https://default.logto.app/api`. It is
3
+ * valid in both JavaScript and PostgreSQL regular expressions.
4
+ */
5
+ export declare const managementApiIndicatorPattern: string;
1
6
  export declare const isManagementApi: (indicator: string) => boolean;
@@ -1 +1,7 @@
1
- export const isManagementApi = (indicator) => /^https:\/\/[^.]+\.logto\.app\/api$/.test(indicator);
1
+ /**
2
+ * The pattern of Management API resource indicators, e.g. `https://default.logto.app/api`. It is
3
+ * valid in both JavaScript and PostgreSQL regular expressions.
4
+ */
5
+ export const managementApiIndicatorPattern = String.raw `^https://[^.]+\.logto\.app/api$`;
6
+ const managementApiIndicatorRegExp = new RegExp(managementApiIndicatorPattern);
7
+ export const isManagementApi = (indicator) => managementApiIndicatorRegExp.test(indicator);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logto/schemas",
3
- "version": "1.44.0",
3
+ "version": "1.45.0",
4
4
  "author": "Silverhand Inc. <contact@silverhand.io>",
5
5
  "license": "MPL-2.0",
6
6
  "type": "module",
@@ -66,11 +66,11 @@
66
66
  "@withtyped/server": "^0.14.0",
67
67
  "nanoid": "^5.0.9",
68
68
  "@logto/connector-kit": "^5.1.2",
69
- "@logto/phrases": "^1.32.0",
70
69
  "@logto/language-kit": "^1.4.0",
70
+ "@logto/core-kit": "^2.13.0",
71
71
  "@logto/phrases-experience": "^1.15.0",
72
72
  "@logto/shared": "^3.4.3",
73
- "@logto/core-kit": "^2.13.0"
73
+ "@logto/phrases": "^1.32.1"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "zod": "3.24.3"