0
Fork 0
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:
Gao Sun 2023-02-02 18:36:18 +08:00 committed by GitHub
parent 201822b772
commit df1bb9fd38
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 113 additions and 43 deletions

View file

@ -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

View file

@ -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),
);

View file

@ -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)))

View file

@ -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`, `)})`

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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();
});

View file

@ -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};
`);
},
};

View file

@ -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})
`);
}
},

View file

@ -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;

View file

@ -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,
};

View file

@ -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,
});