@logto/schemas 1.8.0 → 1.9.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.
- package/alterations/1.9.0-1693554904-add-possword-policy.ts +21 -0
- package/alterations/1.9.0-1694399696-add-type-col-to-roles-table.ts +55 -0
- package/alterations/1.9.0-1694418765-specify-check-role-type-function-to-be-public-schema.ts +54 -0
- package/alterations/1.9.0-1694484927-remove-deprecated-challenge-flag.ts +100 -0
- package/alterations/1.9.0-1694487524-sie-mfa.ts +26 -0
- package/alterations/1.9.0-1694509714-keep-existing-password-policy.ts +54 -0
- package/alterations/1.9.0-1694746763-user-verifications.ts +20 -0
- package/alterations-js/1.9.0-1693554904-add-possword-policy.d.ts +4 -0
- package/alterations-js/1.9.0-1693554904-add-possword-policy.js +17 -0
- package/alterations-js/1.9.0-1694399696-add-type-col-to-roles-table.d.ts +3 -0
- package/alterations-js/1.9.0-1694399696-add-type-col-to-roles-table.js +44 -0
- package/alterations-js/1.9.0-1694418765-specify-check-role-type-function-to-be-public-schema.d.ts +9 -0
- package/alterations-js/1.9.0-1694418765-specify-check-role-type-function-to-be-public-schema.js +42 -0
- package/alterations-js/1.9.0-1694484927-remove-deprecated-challenge-flag.d.ts +3 -0
- package/alterations-js/1.9.0-1694484927-remove-deprecated-challenge-flag.js +35 -0
- package/alterations-js/1.9.0-1694487524-sie-mfa.d.ts +3 -0
- package/alterations-js/1.9.0-1694487524-sie-mfa.js +21 -0
- package/alterations-js/1.9.0-1694509714-keep-existing-password-policy.d.ts +3 -0
- package/alterations-js/1.9.0-1694509714-keep-existing-password-policy.js +42 -0
- package/alterations-js/1.9.0-1694746763-user-verifications.d.ts +3 -0
- package/alterations-js/1.9.0-1694746763-user-verifications.js +16 -0
- package/lib/db-entries/custom-types.d.ts +4 -0
- package/lib/db-entries/custom-types.js +5 -0
- package/lib/db-entries/role.d.ts +3 -0
- package/lib/db-entries/role.js +5 -0
- package/lib/db-entries/sign-in-experience.d.ts +5 -1
- package/lib/db-entries/sign-in-experience.js +9 -1
- package/lib/db-entries/user.d.ts +3 -1
- package/lib/db-entries/user.js +5 -1
- package/lib/foundations/jsonb-types.d.ts +233 -26
- package/lib/foundations/jsonb-types.js +51 -21
- package/lib/models/tenants.d.ts +4 -4
- package/lib/seeds/cloud-api.d.ts +1 -1
- package/lib/seeds/cloud-api.js +2 -0
- package/lib/seeds/logto-config.js +0 -7
- package/lib/seeds/management-api.d.ts +2 -1
- package/lib/seeds/management-api.js +5 -0
- package/lib/seeds/sign-in-experience.js +6 -1
- package/lib/types/connector.d.ts +4 -4
- package/lib/types/hook.d.ts +13 -2
- package/lib/types/hook.js +4 -0
- package/lib/types/interactions.d.ts +1 -2
- package/lib/types/interactions.js +4 -5
- package/lib/types/logto-config.d.ts +0 -21
- package/lib/types/logto-config.js +0 -8
- package/lib/types/role.d.ts +4 -2
- package/lib/types/scope.d.ts +6 -6
- package/lib/types/system.d.ts +11 -8
- package/lib/types/system.js +6 -5
- package/lib/types/user.d.ts +195 -16
- package/lib/types/user.js +10 -0
- package/package.json +6 -6
- package/tables/applications_roles.sql +5 -1
- package/tables/roles.sql +8 -0
- package/tables/sign_in_experiences.sql +2 -0
- package/tables/users.sql +1 -0
- package/tables/users_roles.sql +5 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { sql } from 'slonik';
|
|
2
|
+
|
|
3
|
+
import type { AlterationScript } from '../lib/types/alteration.js';
|
|
4
|
+
|
|
5
|
+
/** The alteration script for adding `password_policy` column to the sign-in experience table. */
|
|
6
|
+
const alteration: AlterationScript = {
|
|
7
|
+
up: async (pool) => {
|
|
8
|
+
await pool.query(sql`
|
|
9
|
+
alter table sign_in_experiences
|
|
10
|
+
add column password_policy jsonb not null default '{}';
|
|
11
|
+
`);
|
|
12
|
+
},
|
|
13
|
+
down: async (pool) => {
|
|
14
|
+
await pool.query(sql`
|
|
15
|
+
alter table sign_in_experiences
|
|
16
|
+
drop column password_policy;
|
|
17
|
+
`);
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default alteration;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { sql } from 'slonik';
|
|
2
|
+
|
|
3
|
+
import type { AlterationScript } from '../lib/types/alteration.js';
|
|
4
|
+
|
|
5
|
+
enum InternalRole {
|
|
6
|
+
Admin = '#internal:admin',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const alteration: AlterationScript = {
|
|
10
|
+
up: async (pool) => {
|
|
11
|
+
// Get all m2m role ids.
|
|
12
|
+
const { rows: m2mRoleIds } = await pool.query<{ id: string }>(sql`
|
|
13
|
+
select roles.id as "id" from roles
|
|
14
|
+
left join applications_roles on applications_roles.role_id = roles.id and applications_roles.tenant_id = roles.tenant_id
|
|
15
|
+
left join applications on applications.id = applications_roles.application_id and applications.tenant_id = applications_roles.tenant_id
|
|
16
|
+
where applications.type = 'MachineToMachine' or roles.name = ${InternalRole.Admin} group by roles.id;
|
|
17
|
+
`);
|
|
18
|
+
// Add `type` column to `roles` table, and set `type` to 'MachineToMachine' for all m2m roles.
|
|
19
|
+
await pool.query(sql`
|
|
20
|
+
create type role_type as enum ('User', 'MachineToMachine');
|
|
21
|
+
`);
|
|
22
|
+
await pool.query(sql`alter table roles add column type role_type not null default 'User';`);
|
|
23
|
+
await pool.query(sql`
|
|
24
|
+
update roles set type = 'MachineToMachine' where id in (${sql.join(
|
|
25
|
+
m2mRoleIds.map(({ id }) => id),
|
|
26
|
+
sql`, `
|
|
27
|
+
)});
|
|
28
|
+
`);
|
|
29
|
+
// Add role type check function and constraints for recording user/application-role relations.
|
|
30
|
+
await pool.query(sql`
|
|
31
|
+
create function check_role_type(role_id varchar(21), target_type role_type) returns boolean as
|
|
32
|
+
$$ begin
|
|
33
|
+
return (select type from roles where id = role_id) = target_type;
|
|
34
|
+
end; $$ language plpgsql;
|
|
35
|
+
`);
|
|
36
|
+
await pool.query(sql`
|
|
37
|
+
alter table users_roles add constraint users_roles__role_type
|
|
38
|
+
check (check_role_type(role_id, 'User'));
|
|
39
|
+
`);
|
|
40
|
+
await pool.query(
|
|
41
|
+
sql`alter table applications_roles add constraint applications_roles__role_type check (check_role_type(role_id, 'MachineToMachine'));`
|
|
42
|
+
);
|
|
43
|
+
},
|
|
44
|
+
down: async (pool) => {
|
|
45
|
+
await pool.query(
|
|
46
|
+
sql`alter table applications_roles drop constraint applications_roles__role_type;`
|
|
47
|
+
);
|
|
48
|
+
await pool.query(sql`alter table users_roles drop constraint users_roles__role_type;`);
|
|
49
|
+
await pool.query(sql`drop function check_role_type;`);
|
|
50
|
+
await pool.query(sql`alter table roles drop column type;`);
|
|
51
|
+
await pool.query(sql`drop type role_type;`);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default alteration;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { sql } from 'slonik';
|
|
2
|
+
|
|
3
|
+
import type { AlterationScript } from '../lib/types/alteration.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* This alteration is a fix on `check_role_type` function, since this function could be called by
|
|
7
|
+
* cloud (at the time the DB schema is `cloud` and can not find `public` functions/tables).
|
|
8
|
+
*
|
|
9
|
+
* As a result, we need to specify the function to be with `public` schema.
|
|
10
|
+
*/
|
|
11
|
+
const alteration: AlterationScript = {
|
|
12
|
+
up: async (pool) => {
|
|
13
|
+
await pool.query(
|
|
14
|
+
sql`alter table applications_roles drop constraint applications_roles__role_type;`
|
|
15
|
+
);
|
|
16
|
+
await pool.query(sql`alter table users_roles drop constraint users_roles__role_type;`);
|
|
17
|
+
await pool.query(sql`drop function check_role_type;`);
|
|
18
|
+
await pool.query(sql`
|
|
19
|
+
create function public.check_role_type(role_id varchar(21), target_type role_type) returns boolean as
|
|
20
|
+
$$ begin
|
|
21
|
+
return (select type from public.roles where id = role_id) = target_type;
|
|
22
|
+
end; $$ language plpgsql;
|
|
23
|
+
`);
|
|
24
|
+
await pool.query(sql`
|
|
25
|
+
alter table users_roles add constraint users_roles__role_type
|
|
26
|
+
check (public.check_role_type(role_id, 'User'));
|
|
27
|
+
`);
|
|
28
|
+
await pool.query(
|
|
29
|
+
sql`alter table applications_roles add constraint applications_roles__role_type check (public.check_role_type(role_id, 'MachineToMachine'));`
|
|
30
|
+
);
|
|
31
|
+
},
|
|
32
|
+
down: async (pool) => {
|
|
33
|
+
await pool.query(
|
|
34
|
+
sql`alter table applications_roles drop constraint applications_roles__role_type;`
|
|
35
|
+
);
|
|
36
|
+
await pool.query(sql`alter table users_roles drop constraint users_roles__role_type;`);
|
|
37
|
+
await pool.query(sql`drop function public.check_role_type;`);
|
|
38
|
+
await pool.query(sql`
|
|
39
|
+
create function check_role_type(role_id varchar(21), target_type role_type) returns boolean as
|
|
40
|
+
$$ begin
|
|
41
|
+
return (select type from roles where id = role_id) = target_type;
|
|
42
|
+
end; $$ language plpgsql;
|
|
43
|
+
`);
|
|
44
|
+
await pool.query(sql`
|
|
45
|
+
alter table users_roles add constraint users_roles__role_type
|
|
46
|
+
check (check_role_type(role_id, 'User'));
|
|
47
|
+
`);
|
|
48
|
+
await pool.query(
|
|
49
|
+
sql`alter table applications_roles add constraint applications_roles__role_type check (check_role_type(role_id, 'MachineToMachine'));`
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export default alteration;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { DatabaseTransactionConnection } from 'slonik';
|
|
2
|
+
import { sql } from 'slonik';
|
|
3
|
+
|
|
4
|
+
import type { AlterationScript } from '../lib/types/alteration.js';
|
|
5
|
+
|
|
6
|
+
const adminConsoleConfigKey = 'adminConsole';
|
|
7
|
+
|
|
8
|
+
type OldAdminConsoleData = {
|
|
9
|
+
livePreviewChecked: boolean;
|
|
10
|
+
applicationCreated: boolean;
|
|
11
|
+
signInExperienceCustomized: boolean;
|
|
12
|
+
passwordlessConfigured: boolean;
|
|
13
|
+
furtherReadingsChecked: boolean;
|
|
14
|
+
roleCreated: boolean;
|
|
15
|
+
communityChecked: boolean;
|
|
16
|
+
m2mApplicationCreated: boolean;
|
|
17
|
+
} & Record<string, unknown>;
|
|
18
|
+
|
|
19
|
+
type OldLogtoAdminConsoleConfig = {
|
|
20
|
+
tenantId: string;
|
|
21
|
+
value: OldAdminConsoleData;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type NewAdminConsoleData = {
|
|
25
|
+
signInExperienceCustomized: boolean;
|
|
26
|
+
} & Record<string, unknown>;
|
|
27
|
+
|
|
28
|
+
type NewLogtoAdminConsoleConfig = {
|
|
29
|
+
tenantId: string;
|
|
30
|
+
value: NewAdminConsoleData;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const alterAdminConsoleData = async (
|
|
34
|
+
logtoConfig: OldLogtoAdminConsoleConfig,
|
|
35
|
+
pool: DatabaseTransactionConnection
|
|
36
|
+
) => {
|
|
37
|
+
const { tenantId, value: oldAdminConsoleConfig } = logtoConfig;
|
|
38
|
+
|
|
39
|
+
const {
|
|
40
|
+
livePreviewChecked,
|
|
41
|
+
applicationCreated,
|
|
42
|
+
passwordlessConfigured,
|
|
43
|
+
communityChecked,
|
|
44
|
+
furtherReadingsChecked,
|
|
45
|
+
roleCreated,
|
|
46
|
+
m2mApplicationCreated,
|
|
47
|
+
...others
|
|
48
|
+
} = oldAdminConsoleConfig;
|
|
49
|
+
|
|
50
|
+
const newAdminConsoleData: NewAdminConsoleData = {
|
|
51
|
+
...others,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
await pool.query(
|
|
55
|
+
sql`update logto_configs set value = ${JSON.stringify(
|
|
56
|
+
newAdminConsoleData
|
|
57
|
+
)} where tenant_id = ${tenantId} and key = ${adminConsoleConfigKey}`
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const rollbackAdminConsoleData = async (
|
|
62
|
+
logtoConfig: NewLogtoAdminConsoleConfig,
|
|
63
|
+
pool: DatabaseTransactionConnection
|
|
64
|
+
) => {
|
|
65
|
+
const { tenantId, value: newAdminConsoleConfig } = logtoConfig;
|
|
66
|
+
|
|
67
|
+
const oldAdminConsoleData: OldAdminConsoleData = {
|
|
68
|
+
...newAdminConsoleConfig,
|
|
69
|
+
livePreviewChecked: false,
|
|
70
|
+
applicationCreated: false,
|
|
71
|
+
passwordlessConfigured: false,
|
|
72
|
+
communityChecked: false,
|
|
73
|
+
furtherReadingsChecked: false,
|
|
74
|
+
roleCreated: false,
|
|
75
|
+
m2mApplicationCreated: false,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
await pool.query(
|
|
79
|
+
sql`update logto_configs set value = ${JSON.stringify(
|
|
80
|
+
oldAdminConsoleData
|
|
81
|
+
)} where tenant_id = ${tenantId} and key = ${adminConsoleConfigKey}`
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const alteration: AlterationScript = {
|
|
86
|
+
up: async (pool) => {
|
|
87
|
+
const rows = await pool.many<OldLogtoAdminConsoleConfig>(
|
|
88
|
+
sql`select * from logto_configs where key = ${adminConsoleConfigKey}`
|
|
89
|
+
);
|
|
90
|
+
await Promise.all(rows.map(async (row) => alterAdminConsoleData(row, pool)));
|
|
91
|
+
},
|
|
92
|
+
down: async (pool) => {
|
|
93
|
+
const rows = await pool.many<NewLogtoAdminConsoleConfig>(
|
|
94
|
+
sql`select * from logto_configs where key = ${adminConsoleConfigKey}`
|
|
95
|
+
);
|
|
96
|
+
await Promise.all(rows.map(async (row) => rollbackAdminConsoleData(row, pool)));
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export default alteration;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { sql } from 'slonik';
|
|
2
|
+
|
|
3
|
+
import type { AlterationScript } from '../lib/types/alteration.js';
|
|
4
|
+
|
|
5
|
+
const alteration: AlterationScript = {
|
|
6
|
+
up: async (pool) => {
|
|
7
|
+
await pool.query(sql`
|
|
8
|
+
alter table sign_in_experiences
|
|
9
|
+
add column if not exists mfa jsonb not null default '{}'::jsonb;
|
|
10
|
+
`);
|
|
11
|
+
|
|
12
|
+
await pool.query(sql`
|
|
13
|
+
update sign_in_experiences
|
|
14
|
+
set mfa = '{"factors":[],"policy":"UserControlled"}'
|
|
15
|
+
where id = 'default';
|
|
16
|
+
`);
|
|
17
|
+
},
|
|
18
|
+
down: async (pool) => {
|
|
19
|
+
await pool.query(sql`
|
|
20
|
+
alter table sign_in_experiences
|
|
21
|
+
drop column mfa;
|
|
22
|
+
`);
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default alteration;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { yes } from '@silverhand/essentials';
|
|
2
|
+
import { sql } from 'slonik';
|
|
3
|
+
|
|
4
|
+
import type { AlterationScript } from '../lib/types/alteration.js';
|
|
5
|
+
|
|
6
|
+
// In the alteration testing environment, we do not want to run this alteration
|
|
7
|
+
// script since it alters the existing data which does not match the new policy.
|
|
8
|
+
const isAlterationTesting = yes(process.env.ALTERATION_TEST);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Note: The legacy password policy does not separate upper and lower cases into
|
|
12
|
+
* different character types. It is not possible to migrate this behavior.
|
|
13
|
+
*/
|
|
14
|
+
const legacyPasswordPolicy = {
|
|
15
|
+
length: { min: 8 },
|
|
16
|
+
characterTypes: { min: 2 },
|
|
17
|
+
rejects: {
|
|
18
|
+
pwned: false,
|
|
19
|
+
repetitionAndSequence: false,
|
|
20
|
+
userInfo: false,
|
|
21
|
+
words: [],
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const alteration: AlterationScript = {
|
|
26
|
+
up: async (pool) => {
|
|
27
|
+
if (isAlterationTesting) {
|
|
28
|
+
console.warn(
|
|
29
|
+
'Skipping alteration script next-1694509714-keep-existing-password-policy in alteration testing environment.'
|
|
30
|
+
);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await pool.query(sql`
|
|
35
|
+
update sign_in_experiences
|
|
36
|
+
set password_policy = ${sql.jsonb(legacyPasswordPolicy)};
|
|
37
|
+
`);
|
|
38
|
+
},
|
|
39
|
+
down: async (pool) => {
|
|
40
|
+
if (isAlterationTesting) {
|
|
41
|
+
console.warn(
|
|
42
|
+
'Skipping alteration script next-1694509714-keep-existing-password-policy in alteration testing environment.'
|
|
43
|
+
);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
await pool.query(sql`
|
|
48
|
+
update sign_in_experiences
|
|
49
|
+
set password_policy = '{}'::jsonb;
|
|
50
|
+
`);
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export default alteration;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { sql } from 'slonik';
|
|
2
|
+
|
|
3
|
+
import type { AlterationScript } from '../lib/types/alteration.js';
|
|
4
|
+
|
|
5
|
+
const alteration: AlterationScript = {
|
|
6
|
+
up: async (pool) => {
|
|
7
|
+
await pool.query(sql`
|
|
8
|
+
alter table users
|
|
9
|
+
add column if not exists mfa_verifications jsonb not null default '[]'::jsonb;
|
|
10
|
+
`);
|
|
11
|
+
},
|
|
12
|
+
down: async (pool) => {
|
|
13
|
+
await pool.query(sql`
|
|
14
|
+
alter table users
|
|
15
|
+
drop column mfa_verifications;
|
|
16
|
+
`);
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default alteration;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { sql } from 'slonik';
|
|
2
|
+
/** The alteration script for adding `password_policy` column to the sign-in experience table. */
|
|
3
|
+
const alteration = {
|
|
4
|
+
up: async (pool) => {
|
|
5
|
+
await pool.query(sql `
|
|
6
|
+
alter table sign_in_experiences
|
|
7
|
+
add column password_policy jsonb not null default '{}';
|
|
8
|
+
`);
|
|
9
|
+
},
|
|
10
|
+
down: async (pool) => {
|
|
11
|
+
await pool.query(sql `
|
|
12
|
+
alter table sign_in_experiences
|
|
13
|
+
drop column password_policy;
|
|
14
|
+
`);
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
export default alteration;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { sql } from 'slonik';
|
|
2
|
+
var InternalRole;
|
|
3
|
+
(function (InternalRole) {
|
|
4
|
+
InternalRole["Admin"] = "#internal:admin";
|
|
5
|
+
})(InternalRole || (InternalRole = {}));
|
|
6
|
+
const alteration = {
|
|
7
|
+
up: async (pool) => {
|
|
8
|
+
// Get all m2m role ids.
|
|
9
|
+
const { rows: m2mRoleIds } = await pool.query(sql `
|
|
10
|
+
select roles.id as "id" from roles
|
|
11
|
+
left join applications_roles on applications_roles.role_id = roles.id and applications_roles.tenant_id = roles.tenant_id
|
|
12
|
+
left join applications on applications.id = applications_roles.application_id and applications.tenant_id = applications_roles.tenant_id
|
|
13
|
+
where applications.type = 'MachineToMachine' or roles.name = ${InternalRole.Admin} group by roles.id;
|
|
14
|
+
`);
|
|
15
|
+
// Add `type` column to `roles` table, and set `type` to 'MachineToMachine' for all m2m roles.
|
|
16
|
+
await pool.query(sql `
|
|
17
|
+
create type role_type as enum ('User', 'MachineToMachine');
|
|
18
|
+
`);
|
|
19
|
+
await pool.query(sql `alter table roles add column type role_type not null default 'User';`);
|
|
20
|
+
await pool.query(sql `
|
|
21
|
+
update roles set type = 'MachineToMachine' where id in (${sql.join(m2mRoleIds.map(({ id }) => id), sql `, `)});
|
|
22
|
+
`);
|
|
23
|
+
// Add role type check function and constraints for recording user/application-role relations.
|
|
24
|
+
await pool.query(sql `
|
|
25
|
+
create function check_role_type(role_id varchar(21), target_type role_type) returns boolean as
|
|
26
|
+
$$ begin
|
|
27
|
+
return (select type from roles where id = role_id) = target_type;
|
|
28
|
+
end; $$ language plpgsql;
|
|
29
|
+
`);
|
|
30
|
+
await pool.query(sql `
|
|
31
|
+
alter table users_roles add constraint users_roles__role_type
|
|
32
|
+
check (check_role_type(role_id, 'User'));
|
|
33
|
+
`);
|
|
34
|
+
await pool.query(sql `alter table applications_roles add constraint applications_roles__role_type check (check_role_type(role_id, 'MachineToMachine'));`);
|
|
35
|
+
},
|
|
36
|
+
down: async (pool) => {
|
|
37
|
+
await pool.query(sql `alter table applications_roles drop constraint applications_roles__role_type;`);
|
|
38
|
+
await pool.query(sql `alter table users_roles drop constraint users_roles__role_type;`);
|
|
39
|
+
await pool.query(sql `drop function check_role_type;`);
|
|
40
|
+
await pool.query(sql `alter table roles drop column type;`);
|
|
41
|
+
await pool.query(sql `drop type role_type;`);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
export default alteration;
|
package/alterations-js/1.9.0-1694418765-specify-check-role-type-function-to-be-public-schema.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AlterationScript } from '../lib/types/alteration.js';
|
|
2
|
+
/**
|
|
3
|
+
* This alteration is a fix on `check_role_type` function, since this function could be called by
|
|
4
|
+
* cloud (at the time the DB schema is `cloud` and can not find `public` functions/tables).
|
|
5
|
+
*
|
|
6
|
+
* As a result, we need to specify the function to be with `public` schema.
|
|
7
|
+
*/
|
|
8
|
+
declare const alteration: AlterationScript;
|
|
9
|
+
export default alteration;
|
package/alterations-js/1.9.0-1694418765-specify-check-role-type-function-to-be-public-schema.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { sql } from 'slonik';
|
|
2
|
+
/**
|
|
3
|
+
* This alteration is a fix on `check_role_type` function, since this function could be called by
|
|
4
|
+
* cloud (at the time the DB schema is `cloud` and can not find `public` functions/tables).
|
|
5
|
+
*
|
|
6
|
+
* As a result, we need to specify the function to be with `public` schema.
|
|
7
|
+
*/
|
|
8
|
+
const alteration = {
|
|
9
|
+
up: async (pool) => {
|
|
10
|
+
await pool.query(sql `alter table applications_roles drop constraint applications_roles__role_type;`);
|
|
11
|
+
await pool.query(sql `alter table users_roles drop constraint users_roles__role_type;`);
|
|
12
|
+
await pool.query(sql `drop function check_role_type;`);
|
|
13
|
+
await pool.query(sql `
|
|
14
|
+
create function public.check_role_type(role_id varchar(21), target_type role_type) returns boolean as
|
|
15
|
+
$$ begin
|
|
16
|
+
return (select type from public.roles where id = role_id) = target_type;
|
|
17
|
+
end; $$ language plpgsql;
|
|
18
|
+
`);
|
|
19
|
+
await pool.query(sql `
|
|
20
|
+
alter table users_roles add constraint users_roles__role_type
|
|
21
|
+
check (public.check_role_type(role_id, 'User'));
|
|
22
|
+
`);
|
|
23
|
+
await pool.query(sql `alter table applications_roles add constraint applications_roles__role_type check (public.check_role_type(role_id, 'MachineToMachine'));`);
|
|
24
|
+
},
|
|
25
|
+
down: async (pool) => {
|
|
26
|
+
await pool.query(sql `alter table applications_roles drop constraint applications_roles__role_type;`);
|
|
27
|
+
await pool.query(sql `alter table users_roles drop constraint users_roles__role_type;`);
|
|
28
|
+
await pool.query(sql `drop function public.check_role_type;`);
|
|
29
|
+
await pool.query(sql `
|
|
30
|
+
create function check_role_type(role_id varchar(21), target_type role_type) returns boolean as
|
|
31
|
+
$$ begin
|
|
32
|
+
return (select type from roles where id = role_id) = target_type;
|
|
33
|
+
end; $$ language plpgsql;
|
|
34
|
+
`);
|
|
35
|
+
await pool.query(sql `
|
|
36
|
+
alter table users_roles add constraint users_roles__role_type
|
|
37
|
+
check (check_role_type(role_id, 'User'));
|
|
38
|
+
`);
|
|
39
|
+
await pool.query(sql `alter table applications_roles add constraint applications_roles__role_type check (check_role_type(role_id, 'MachineToMachine'));`);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
export default alteration;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { sql } from 'slonik';
|
|
2
|
+
const adminConsoleConfigKey = 'adminConsole';
|
|
3
|
+
const alterAdminConsoleData = async (logtoConfig, pool) => {
|
|
4
|
+
const { tenantId, value: oldAdminConsoleConfig } = logtoConfig;
|
|
5
|
+
const { livePreviewChecked, applicationCreated, passwordlessConfigured, communityChecked, furtherReadingsChecked, roleCreated, m2mApplicationCreated, ...others } = oldAdminConsoleConfig;
|
|
6
|
+
const newAdminConsoleData = {
|
|
7
|
+
...others,
|
|
8
|
+
};
|
|
9
|
+
await pool.query(sql `update logto_configs set value = ${JSON.stringify(newAdminConsoleData)} where tenant_id = ${tenantId} and key = ${adminConsoleConfigKey}`);
|
|
10
|
+
};
|
|
11
|
+
const rollbackAdminConsoleData = async (logtoConfig, pool) => {
|
|
12
|
+
const { tenantId, value: newAdminConsoleConfig } = logtoConfig;
|
|
13
|
+
const oldAdminConsoleData = {
|
|
14
|
+
...newAdminConsoleConfig,
|
|
15
|
+
livePreviewChecked: false,
|
|
16
|
+
applicationCreated: false,
|
|
17
|
+
passwordlessConfigured: false,
|
|
18
|
+
communityChecked: false,
|
|
19
|
+
furtherReadingsChecked: false,
|
|
20
|
+
roleCreated: false,
|
|
21
|
+
m2mApplicationCreated: false,
|
|
22
|
+
};
|
|
23
|
+
await pool.query(sql `update logto_configs set value = ${JSON.stringify(oldAdminConsoleData)} where tenant_id = ${tenantId} and key = ${adminConsoleConfigKey}`);
|
|
24
|
+
};
|
|
25
|
+
const alteration = {
|
|
26
|
+
up: async (pool) => {
|
|
27
|
+
const rows = await pool.many(sql `select * from logto_configs where key = ${adminConsoleConfigKey}`);
|
|
28
|
+
await Promise.all(rows.map(async (row) => alterAdminConsoleData(row, pool)));
|
|
29
|
+
},
|
|
30
|
+
down: async (pool) => {
|
|
31
|
+
const rows = await pool.many(sql `select * from logto_configs where key = ${adminConsoleConfigKey}`);
|
|
32
|
+
await Promise.all(rows.map(async (row) => rollbackAdminConsoleData(row, pool)));
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
export default alteration;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { sql } from 'slonik';
|
|
2
|
+
const alteration = {
|
|
3
|
+
up: async (pool) => {
|
|
4
|
+
await pool.query(sql `
|
|
5
|
+
alter table sign_in_experiences
|
|
6
|
+
add column if not exists mfa jsonb not null default '{}'::jsonb;
|
|
7
|
+
`);
|
|
8
|
+
await pool.query(sql `
|
|
9
|
+
update sign_in_experiences
|
|
10
|
+
set mfa = '{"factors":[],"policy":"UserControlled"}'
|
|
11
|
+
where id = 'default';
|
|
12
|
+
`);
|
|
13
|
+
},
|
|
14
|
+
down: async (pool) => {
|
|
15
|
+
await pool.query(sql `
|
|
16
|
+
alter table sign_in_experiences
|
|
17
|
+
drop column mfa;
|
|
18
|
+
`);
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
export default alteration;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { yes } from '@silverhand/essentials';
|
|
2
|
+
import { sql } from 'slonik';
|
|
3
|
+
// In the alteration testing environment, we do not want to run this alteration
|
|
4
|
+
// script since it alters the existing data which does not match the new policy.
|
|
5
|
+
const isAlterationTesting = yes(process.env.ALTERATION_TEST);
|
|
6
|
+
/**
|
|
7
|
+
* Note: The legacy password policy does not separate upper and lower cases into
|
|
8
|
+
* different character types. It is not possible to migrate this behavior.
|
|
9
|
+
*/
|
|
10
|
+
const legacyPasswordPolicy = {
|
|
11
|
+
length: { min: 8 },
|
|
12
|
+
characterTypes: { min: 2 },
|
|
13
|
+
rejects: {
|
|
14
|
+
pwned: false,
|
|
15
|
+
repetitionAndSequence: false,
|
|
16
|
+
userInfo: false,
|
|
17
|
+
words: [],
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
const alteration = {
|
|
21
|
+
up: async (pool) => {
|
|
22
|
+
if (isAlterationTesting) {
|
|
23
|
+
console.warn('Skipping alteration script next-1694509714-keep-existing-password-policy in alteration testing environment.');
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
await pool.query(sql `
|
|
27
|
+
update sign_in_experiences
|
|
28
|
+
set password_policy = ${sql.jsonb(legacyPasswordPolicy)};
|
|
29
|
+
`);
|
|
30
|
+
},
|
|
31
|
+
down: async (pool) => {
|
|
32
|
+
if (isAlterationTesting) {
|
|
33
|
+
console.warn('Skipping alteration script next-1694509714-keep-existing-password-policy in alteration testing environment.');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
await pool.query(sql `
|
|
37
|
+
update sign_in_experiences
|
|
38
|
+
set password_policy = '{}'::jsonb;
|
|
39
|
+
`);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
export default alteration;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { sql } from 'slonik';
|
|
2
|
+
const alteration = {
|
|
3
|
+
up: async (pool) => {
|
|
4
|
+
await pool.query(sql `
|
|
5
|
+
alter table users
|
|
6
|
+
add column if not exists mfa_verifications jsonb not null default '[]'::jsonb;
|
|
7
|
+
`);
|
|
8
|
+
},
|
|
9
|
+
down: async (pool) => {
|
|
10
|
+
await pool.query(sql `
|
|
11
|
+
alter table users
|
|
12
|
+
drop column mfa_verifications;
|
|
13
|
+
`);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
export default alteration;
|
|
@@ -4,6 +4,10 @@ export declare enum ApplicationType {
|
|
|
4
4
|
Traditional = "Traditional",
|
|
5
5
|
MachineToMachine = "MachineToMachine"
|
|
6
6
|
}
|
|
7
|
+
export declare enum RoleType {
|
|
8
|
+
User = "User",
|
|
9
|
+
MachineToMachine = "MachineToMachine"
|
|
10
|
+
}
|
|
7
11
|
export declare enum SignInMode {
|
|
8
12
|
SignIn = "SignIn",
|
|
9
13
|
Register = "Register",
|
|
@@ -6,6 +6,11 @@ export var ApplicationType;
|
|
|
6
6
|
ApplicationType["Traditional"] = "Traditional";
|
|
7
7
|
ApplicationType["MachineToMachine"] = "MachineToMachine";
|
|
8
8
|
})(ApplicationType || (ApplicationType = {}));
|
|
9
|
+
export var RoleType;
|
|
10
|
+
(function (RoleType) {
|
|
11
|
+
RoleType["User"] = "User";
|
|
12
|
+
RoleType["MachineToMachine"] = "MachineToMachine";
|
|
13
|
+
})(RoleType || (RoleType = {}));
|
|
9
14
|
export var SignInMode;
|
|
10
15
|
(function (SignInMode) {
|
|
11
16
|
SignInMode["SignIn"] = "SignIn";
|
package/lib/db-entries/role.d.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { GeneratedSchema } from './../foundations/index.js';
|
|
2
|
+
import { RoleType } from './custom-types.js';
|
|
2
3
|
export type CreateRole = {
|
|
3
4
|
tenantId?: string;
|
|
4
5
|
id: string;
|
|
5
6
|
name: string;
|
|
6
7
|
description: string;
|
|
8
|
+
type?: RoleType;
|
|
7
9
|
};
|
|
8
10
|
export type Role = {
|
|
9
11
|
tenantId: string;
|
|
10
12
|
id: string;
|
|
11
13
|
name: string;
|
|
12
14
|
description: string;
|
|
15
|
+
type: RoleType;
|
|
13
16
|
};
|
|
14
17
|
export declare const Roles: GeneratedSchema<CreateRole, Role>;
|