mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor: update seed data (#3044)
This commit is contained in:
parent
201822b772
commit
df1bb9fd38
12 changed files with 113 additions and 43 deletions
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
|
@ -148,7 +148,7 @@ jobs:
|
|||
env:
|
||||
DB_URL: postgres://postgres:postgres@localhost:5432/alteration
|
||||
|
||||
- name: Compare manifests
|
||||
- name: Compare databases
|
||||
working-directory: ./fresh
|
||||
run: node .scripts/compare-database.js fresh alteration
|
||||
# ** End **
|
||||
|
@ -173,6 +173,6 @@ jobs:
|
|||
run: node .scripts/compare-database.js fresh old
|
||||
# ** End **
|
||||
|
||||
- name: Check alteration sequence
|
||||
- name: Check alteration databases
|
||||
working-directory: ./fresh
|
||||
run: node .scripts/check-alterations-sequence.js
|
||||
|
|
|
@ -105,9 +105,41 @@ const queryDatabaseManifest = async (database) => {
|
|||
|
||||
const [,, database1, database2] = process.argv;
|
||||
|
||||
console.log('Compare database manifest between', database1, 'and', database2)
|
||||
console.log('Compare database manifest between', database1, 'and', database2);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
const manifests = [
|
||||
await queryDatabaseManifest(database1),
|
||||
await queryDatabaseManifest(database2),
|
||||
];
|
||||
|
||||
assert.deepStrictEqual(...manifests);
|
||||
|
||||
const queryDatabaseData = async (database) => {
|
||||
const pool = new pg.Pool({ database, user: 'postgres', password: 'postgres' });
|
||||
const result = await Promise.all(manifests[0].tables
|
||||
.filter(({ table_name }) => !['logto_configs', '_logto_configs'].includes(table_name))
|
||||
.map(async ({ table_name }) => {
|
||||
const { rows } = await pool.query(/* sql */`select * from ${table_name};`);
|
||||
|
||||
if (table_name === 'systems') {
|
||||
return [
|
||||
table_name,
|
||||
rows.map(({ value, ...rest }) =>
|
||||
({ ...rest, value: omit(value, 'createdAt', 'updatedAt') })
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
return [table_name, omitArray(rows, 'created_at', 'updated_at', 'secret')];
|
||||
})
|
||||
);
|
||||
|
||||
return Object.fromEntries(result);
|
||||
};
|
||||
|
||||
console.log('Compare database data between', database1, 'and', database2);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
await queryDatabaseData(database1),
|
||||
await queryDatabaseData(database2),
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { ResourceResponse, Scope, ScopeResponse } from '@logto/schemas';
|
||||
import { managementResourceScopeId } from '@logto/schemas';
|
||||
import { managementApiScopeAll } from '@logto/schemas';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
import classNames from 'classnames';
|
||||
import type { ChangeEvent } from 'react';
|
||||
|
@ -79,7 +79,7 @@ const SourceScopesBox = ({ roleId, selectedScopes, onChange }: Props) => {
|
|||
}
|
||||
|
||||
const existingScopeIds = roleScopes?.map(({ id }) => id) ?? [];
|
||||
const excludeScopeIds = new Set([...existingScopeIds, managementResourceScopeId]);
|
||||
const excludeScopeIds = new Set([...existingScopeIds, managementApiScopeAll]);
|
||||
|
||||
return allResources
|
||||
.filter(({ scopes }) => scopes.some(({ id }) => !excludeScopeIds.has(id)))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { CreateRole, Role } from '@logto/schemas';
|
||||
import { adminConsoleAdminRoleId, SearchJointMode, Roles } from '@logto/schemas';
|
||||
import { adminRoleId, SearchJointMode, Roles } from '@logto/schemas';
|
||||
import type { OmitAutoSetFields } from '@logto/shared';
|
||||
import { conditionalArraySql, conditionalSql, convertToIdentifiers } from '@logto/shared';
|
||||
import type { CommonQueryMethods } from 'slonik';
|
||||
|
@ -34,7 +34,7 @@ export const createRolesQueries = (pool: CommonQueryMethods) => {
|
|||
pool.one<{ count: number }>(sql`
|
||||
select count(*)
|
||||
from ${table}
|
||||
where ${fields.id}<>${adminConsoleAdminRoleId}
|
||||
where ${fields.id}<>${adminRoleId}
|
||||
${conditionalArraySql(
|
||||
excludeRoleIds,
|
||||
(value) => sql`and ${fields.id} not in (${sql.join(value, sql`, `)})`
|
||||
|
@ -57,7 +57,7 @@ export const createRolesQueries = (pool: CommonQueryMethods) => {
|
|||
sql`
|
||||
select ${sql.join(Object.values(fields), sql`, `)}
|
||||
from ${table}
|
||||
where ${fields.id}<>${adminConsoleAdminRoleId}
|
||||
where ${fields.id}<>${adminRoleId}
|
||||
${conditionalArraySql(
|
||||
excludeRoleIds,
|
||||
(value) => sql`and ${fields.id} not in (${sql.join(value, sql`, `)})`
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { generateStandardId, buildIdGenerator } from '@logto/core-kit';
|
||||
import { adminConsoleAdminRoleId, Applications } from '@logto/schemas';
|
||||
import { adminRoleId, Applications } from '@logto/schemas';
|
||||
import { boolean, object, string } from 'zod';
|
||||
|
||||
import koaGuard from '#src/middleware/koa-guard.js';
|
||||
|
@ -76,7 +76,7 @@ export default function applicationRoutes<T extends AuthedRouter>(
|
|||
|
||||
ctx.body = {
|
||||
...application,
|
||||
isAdmin: applicationsRoles.some(({ roleId }) => roleId === adminConsoleAdminRoleId),
|
||||
isAdmin: applicationsRoles.some(({ roleId }) => roleId === adminRoleId),
|
||||
};
|
||||
|
||||
return next();
|
||||
|
@ -107,16 +107,14 @@ export default function applicationRoutes<T extends AuthedRouter>(
|
|||
// FIXME @sijie temp solution to set admin access to machine to machine app
|
||||
if (isAdmin !== undefined) {
|
||||
const applicationsRoles = await findApplicationsRolesByApplicationId(id);
|
||||
const originalIsAdmin = applicationsRoles.some(
|
||||
({ roleId }) => roleId === adminConsoleAdminRoleId
|
||||
);
|
||||
const originalIsAdmin = applicationsRoles.some(({ roleId }) => roleId === adminRoleId);
|
||||
|
||||
if (isAdmin && !originalIsAdmin) {
|
||||
await insertApplicationsRoles([
|
||||
{ id: generateStandardId(), applicationId: id, roleId: adminConsoleAdminRoleId },
|
||||
{ id: generateStandardId(), applicationId: id, roleId: adminRoleId },
|
||||
]);
|
||||
} else if (!isAdmin && originalIsAdmin) {
|
||||
await deleteApplicationRole(id, adminConsoleAdminRoleId);
|
||||
await deleteApplicationRole(id, adminRoleId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { adminConsoleAdminRoleId } from '@logto/schemas';
|
||||
import { adminRoleId } from '@logto/schemas';
|
||||
import { HTTPError } from 'got';
|
||||
|
||||
import { assignRolesToUser, getUserRoles, deleteRoleFromUser } from '#src/api/index.js';
|
||||
|
@ -25,8 +25,8 @@ describe('admin console user management (roles)', () => {
|
|||
it('should delete role from user successfully', async () => {
|
||||
const user = await createUserByAdmin();
|
||||
|
||||
await assignRolesToUser(user.id, [adminConsoleAdminRoleId]);
|
||||
await deleteRoleFromUser(user.id, adminConsoleAdminRoleId);
|
||||
await assignRolesToUser(user.id, [adminRoleId]);
|
||||
await deleteRoleFromUser(user.id, adminRoleId);
|
||||
|
||||
const roles = await getUserRoles(user.id);
|
||||
expect(roles.length).toBe(0);
|
||||
|
@ -35,7 +35,7 @@ describe('admin console user management (roles)', () => {
|
|||
it('should delete non-exist-role from user failed', async () => {
|
||||
const user = await createUserByAdmin();
|
||||
|
||||
const response = await deleteRoleFromUser(user.id, adminConsoleAdminRoleId).catch(
|
||||
const response = await deleteRoleFromUser(user.id, adminRoleId).catch(
|
||||
(error: unknown) => error
|
||||
);
|
||||
expect(response instanceof HTTPError && response.response.statusCode === 404).toBe(true);
|
||||
|
|
|
@ -4,7 +4,7 @@ import { fetchTokenByRefreshToken } from '@logto/js';
|
|||
import {
|
||||
managementResource,
|
||||
InteractionEvent,
|
||||
adminConsoleAdminRoleId,
|
||||
adminRoleId,
|
||||
managementResourceScope,
|
||||
} from '@logto/schemas';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
|
@ -27,7 +27,7 @@ describe('get access token', () => {
|
|||
beforeAll(async () => {
|
||||
await createUserByAdmin(guestUsername, password);
|
||||
const user = await createUserByAdmin(username, password);
|
||||
await assignUsersToRole([user.id], adminConsoleAdminRoleId);
|
||||
await assignUsersToRole([user.id], adminRoleId);
|
||||
await enableAllPasswordSignInMethods();
|
||||
});
|
||||
|
||||
|
|
|
@ -25,8 +25,10 @@ const alteration: AlterationScript = {
|
|||
`);
|
||||
}
|
||||
},
|
||||
down: async () => {
|
||||
// This is a hotfix for seed, down script is not needed
|
||||
down: async (pool) => {
|
||||
await pool.query(sql`
|
||||
delete from scopes where id = ${managementResourceScope.id};
|
||||
`);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -11,29 +11,29 @@ const alteration: AlterationScript = {
|
|||
// Fix role id
|
||||
const newRole = await pool.maybeOne(sql`
|
||||
select * from roles
|
||||
where id = ${adminConsoleAdminRoleId}
|
||||
where id = ${adminConsoleAdminRoleId}
|
||||
`);
|
||||
|
||||
if (!newRole) {
|
||||
await pool.query(sql`
|
||||
update roles
|
||||
set id = ${adminConsoleAdminRoleId}
|
||||
where name = ${adminRoleName}
|
||||
set id = ${adminConsoleAdminRoleId}
|
||||
where name = ${adminRoleName}
|
||||
`);
|
||||
}
|
||||
|
||||
// Fix scope role
|
||||
const relation = await pool.maybeOne(sql`
|
||||
select * from roles_scopes
|
||||
where scope_id = ${managementResourceScopeId}
|
||||
and role_id = ${adminConsoleAdminRoleId}
|
||||
where scope_id = ${managementResourceScopeId}
|
||||
and role_id = ${adminConsoleAdminRoleId}
|
||||
`);
|
||||
|
||||
if (!relation) {
|
||||
await pool.query(sql`
|
||||
insert into roles_scopes
|
||||
(role_id, scope_id)
|
||||
values (${adminConsoleAdminRoleId}, ${managementResourceScopeId})
|
||||
(role_id, scope_id)
|
||||
values (${adminConsoleAdminRoleId}, ${managementResourceScopeId})
|
||||
`);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import { sql } from 'slonik';
|
||||
|
||||
import type { AlterationScript } from '../lib/types/alteration.js';
|
||||
|
||||
const alteration: AlterationScript = {
|
||||
up: async (pool) => {
|
||||
await pool.query(sql`
|
||||
update roles
|
||||
set id = 'admin-role'
|
||||
where id = 'ac-admin-id';
|
||||
update scopes
|
||||
set
|
||||
id = 'management-api-all',
|
||||
name = 'all',
|
||||
description = 'Default scope for Management API, allows all permissions.'
|
||||
where id = 'management-api-scope';
|
||||
-- this update is one-way since no need to revert the id column as it's just for seeding not querying
|
||||
update roles_scopes
|
||||
set id = 'admin-role-scope'
|
||||
where role_id = 'admin-role'
|
||||
and scope_id = 'management-api-all';
|
||||
`);
|
||||
},
|
||||
down: async (pool) => {
|
||||
await pool.query(sql`
|
||||
update roles
|
||||
set id = 'ac-admin-id'
|
||||
where id = 'admin-role';
|
||||
update scopes
|
||||
set
|
||||
id = 'management-api-scope',
|
||||
name = 'management-api:default',
|
||||
description = 'Default scope for Management API.'
|
||||
where id = 'management-api-all';
|
||||
`);
|
||||
},
|
||||
};
|
||||
|
||||
export default alteration;
|
|
@ -1,25 +1,24 @@
|
|||
import { generateStandardId } from '@logto/core-kit';
|
||||
|
||||
import type { CreateRole, CreateRolesScope } from '../db-entries/index.js';
|
||||
import { UserRole } from '../types/index.js';
|
||||
import { managementResourceScopeId } from './scope.js';
|
||||
import { managementApiScopeAll } from './scope.js';
|
||||
import { defaultTenantId } from './tenant.js';
|
||||
|
||||
export const adminConsoleAdminRoleId = 'ac-admin-id';
|
||||
export const adminRoleId = 'admin-role';
|
||||
export const adminRoleScopeId = 'admin-role-scope';
|
||||
|
||||
/**
|
||||
* Default Admin Role for Admin Console.
|
||||
*/
|
||||
export const defaultRole: Readonly<CreateRole> = {
|
||||
tenantId: defaultTenantId,
|
||||
id: adminConsoleAdminRoleId,
|
||||
id: adminRoleId,
|
||||
name: UserRole.Admin,
|
||||
description: 'Admin role for Logto.',
|
||||
};
|
||||
|
||||
export const defaultRoleScopeRelation: Readonly<CreateRolesScope> = {
|
||||
id: generateStandardId(),
|
||||
id: adminRoleScopeId,
|
||||
tenantId: defaultTenantId,
|
||||
roleId: adminConsoleAdminRoleId,
|
||||
scopeId: managementResourceScopeId,
|
||||
roleId: adminRoleId,
|
||||
scopeId: managementApiScopeAll,
|
||||
};
|
||||
|
|
|
@ -2,12 +2,12 @@ import type { CreateScope } from '../db-entries/index.js';
|
|||
import { managementResourceId } from './resource.js';
|
||||
import { defaultTenantId } from './tenant.js';
|
||||
|
||||
export const managementResourceScopeId = 'management-api-scope';
|
||||
export const managementApiScopeAll = 'management-api-all';
|
||||
|
||||
export const managementResourceScope: Readonly<CreateScope> = Object.freeze({
|
||||
tenantId: defaultTenantId,
|
||||
id: managementResourceScopeId,
|
||||
name: 'management-api:default',
|
||||
description: 'Default scope for management API',
|
||||
id: managementApiScopeAll,
|
||||
name: 'all',
|
||||
description: 'Default scope for Management API, allows all permissions.',
|
||||
resourceId: managementResourceId,
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue