Skip to content

Commit

Permalink
Define more DB models
Browse files Browse the repository at this point in the history
Define `authToken, `participant`, `participantRole`,
`role` and `rolePermittedAction`.

Also, completely port src/auth/role.data.ts and define
method to extract io-ts types from this array of data.
This method needs TypeScript 4.3 to work.
  • Loading branch information
Pl217 committed Aug 13, 2021
1 parent edd1e57 commit f15d37f
Show file tree
Hide file tree
Showing 8 changed files with 351 additions and 1 deletion.
178 changes: 178 additions & 0 deletions src/auth/role.data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/**
* The raw data from the following tables from prod:
*
* * `role`
* * `rolePermittedAction`
*
* @deprecated
*/
export const ROLES = [
{
// Usage: 18
// workflowRole: 382
name: 'hpcadmin',
description: 'HPC Administrator',
targetTypes: [],
permittedActions: [
'accessAllPlans',
'createDisaggregationModel',
'createPlan',
'deletePlan',
'editParticipants',
'updatePermittedActions',
'viewRevisions',
'createProject',
'createProcedure',
'createOperation',
'moveToAnyStep',
'updateProject',
'accessAllFlows',
'editPlanBlueprint',
'editOrganizations',
'manageCategories',
'editAnyProject',
'deleteUploadedFile',
'editPlanRevisionState',
'editAnyParticipantOrganization',
'editRoleAuthenticationKeys',
'editAnyParticipantCountry',
'editFormAssignmentRawData',
'editFormAssignmentCleanData',
'editAssignmentRawData',
],
},
{
// Usage: 30
name: 'rpmadmin',
description: 'RPM Administrator',
targetTypes: [],
permittedActions: [
'editPlanBlueprint',
'deleteUploadedFile',
'accessAllPlans',
'viewRevisions',
'updatePermittedActions',
'editParticipants',
'deletePlan',
'createPlan',
'editPlanRevisionState',
'createOperation',
'createDisaggregationModel',
],
},
{
// Usage: 217
name: 'readonly',
description: 'Read Only',
targetTypes: ['plan'],
permittedActions: [],
},
{
// Usage: 842
name: 'planlead',
description: 'Plan Lead',
targetTypes: ['plan'],
permittedActions: ['moveToAnyStep'],
},
{
// Usage: 1996
// workflowRole: 910
name: 'clusterlead',
description: 'Cluster Lead',
targetTypes: ['governingEntity'],
permittedActions: [],
},
{
// Usage: 18
name: 'ftsadmin',
description: 'FTS Administrator',
targetTypes: [],
permittedActions: [
'editOrganizations',
'manageCategories',
'accessAllFlows',
'deleteUploadedFile',
],
},
{
// Usage: 5
name: 'prismadmin',
description: 'PRISM Administrator',
targetTypes: [],
permittedActions: [
'editAnyParticipantCountry',
'moveToAnyStep',
'editAnyParticipantOrganization',
'editAnyProject',
'deleteUploadedFile',
],
},
{
// Usage: 1 (participant ID = 202, no object)
// workflowRole: 384
name: 'countrylead',
description: 'Country Lead',
targetTypes: ['Country'],
permittedActions: [],
},
{
// Usage: 1 (participant ID = 7859, no object)
// workflowRole: 384
name: 'orglead',
description: 'Organization Lead',
targetTypes: ['organization'],
permittedActions: [],
},
{
// Usage: 0
name: 'rolegranter',
description: 'role Granter',
targetTypes: ['role'],
permittedActions: [],
},
{
// Usage: 1 (participant ID = 554, no object)
// workflowRole: 572
name: 'projectowner',
description: 'Project Owner',
targetTypes: [],
permittedActions: [],
},
{
// Usage:
// roleAuthenticationKey: 1
name: 'omniscient',
description: 'Omniscient',
targetTypes: [],
permittedActions: ['accessAllFlows', 'accessAllPlans'],
},
{
// Usage: 0
name: 'operationLead',
description: 'Operation Lead',
targetTypes: ['operation'],
permittedActions: [],
},
{
// Usage: 0
name: 'opEntityCoordinator',
description: 'Operation entity coordinator',
targetTypes: ['operation', 'opGoverningEntity'],
permittedActions: [],
},
] as const;

export type RoleName = typeof ROLES[number]['name'];

export type PermittedActionIdString =
typeof ROLES[number]['permittedActions'][number];

export function extractRoles<T extends typeof ROLES>(
arr: T
): { [K in T[number]['permittedActions'][number]]: null } {
const permittedActions = new Set(...arr.map((a) => a.permittedActions));

return Object.fromEntries(
Array.from(permittedActions).map((a) => [a, null])
) as { [K in T[number]['permittedActions'][number]]: null };
}
12 changes: 11 additions & 1 deletion src/db/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import Knex = require('knex');
import attachmentVersion from './models/attachmentVersion';
import attachment from './models/attachment';
import attachmentVersion from './models/attachmentVersion';
import authGrant from './models/authGrant';
import authGrantee from './models/authGrantee';
import authGrantLog from './models/authGrantLog';
import authInvite from './models/authInvite';
import authTarget from './models/authTarget';
import authToken from './models/authToken';
import form from './models/form';
import governingEntity from './models/governingEntity';
import operation from './models/operation';
import operationCluster from './models/operationCluster';
import participant from './models/participant';
import participantRole from './models/participantRole';
import reportingWindow from './models/reportingWindow';
import reportingWindowAssignment from './models/reportingWindowAssignment';
import role from './models/role';
import rolePermittedAction from './models/rolePermittedAction';

export default (conn: Knex) => ({
attachment: attachment(conn),
Expand All @@ -21,10 +26,15 @@ export default (conn: Knex) => ({
authGrantLog: authGrantLog(conn),
authInvite: authInvite(conn),
authTarget: authTarget(conn),
authToken: authToken(conn),
form: form(conn),
governingEntity: governingEntity(conn),
operation: operation(conn),
operationCluster: operationCluster(conn),
participant: participant(conn),
participantRole: participantRole(conn),
role: role(conn),
rolePermittedAction: rolePermittedAction(conn),
reportingWindow: reportingWindow(conn),
reportingWindowAssignment: reportingWindowAssignment(conn),
});
18 changes: 18 additions & 0 deletions src/db/models/authToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as t from 'io-ts';
import { DATE } from '../util/datatypes';
import { defineSequelizeModel } from '../util/sequelize-model';
import { PARTICIPANT_ID } from './participant';

export default defineSequelizeModel({
tableName: 'authToken',
fields: {
required: {
participant: { kind: 'branded-integer', brand: PARTICIPANT_ID },
tokenHash: { kind: 'checked', type: t.string },
},
optional: {
expires: { kind: 'checked', type: DATE },
},
},
softDeletionEnabled: false,
});
19 changes: 19 additions & 0 deletions src/db/models/participant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as t from 'io-ts';

import { brandedType } from '../../util/io-ts';
import { Brand } from '../../util/types';
import { defineIDModel } from '../util/id-model';

export type ParticipantId = Brand<
number,
Expand All @@ -10,3 +11,21 @@ export type ParticipantId = Brand<
>;

export const PARTICIPANT_ID = brandedType<number, ParticipantId>(t.number);

export default defineIDModel({
tableName: 'participant',
fields: {
generated: {
id: { kind: 'branded-integer', brand: PARTICIPANT_ID },
},
optional: {
hidId: { kind: 'checked', type: t.string },
email: { kind: 'checked', type: t.string },
name_given: { kind: 'checked', type: t.string },
name_family: { kind: 'checked', type: t.string },
},
required: {},
},
idField: 'id',
softDeletionEnabled: false,
});
41 changes: 41 additions & 0 deletions src/db/models/participantRole.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as t from 'io-ts';

import { brandedType } from '../../util/io-ts';
import { Brand } from '../../util/types';
import { defineIDModel } from '../util/id-model';
import { PARTICIPANT_ID } from './participant';
import { ROLE_ID } from './role';

export type ParticipantRoleId = Brand<
number,
{ readonly s: unique symbol },
'participantRole.id'
>;

export const PARTICIPANT_ROLE_ID = brandedType<number, ParticipantRoleId>(
t.number
);

const PARTICIPANT_ROLE_OBJECT_TYPE = {
governingEntity: null,
plan: null,
};

export default defineIDModel({
tableName: 'participantRole',
fields: {
generated: {
id: { kind: 'branded-integer', brand: PARTICIPANT_ROLE_ID },
},
accidentallyOptional: {
roleId: { kind: 'branded-integer', brand: ROLE_ID },
participantId: { kind: 'branded-integer', brand: PARTICIPANT_ID },
},
optional: {
objectId: { kind: 'checked', type: t.number },
objectType: { kind: 'enum', values: PARTICIPANT_ROLE_OBJECT_TYPE },
},
},
idField: 'id',
softDeletionEnabled: false,
});
4 changes: 4 additions & 0 deletions src/db/models/permittedAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as t from 'io-ts';
import { extractRoles, ROLES } from '../../auth/role.data';

export const PERMITTED_ACTION_ID = t.keyof(extractRoles(ROLES));
43 changes: 43 additions & 0 deletions src/db/models/role.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as t from 'io-ts';

import { brandedType } from '../../util/io-ts';
import { Brand } from '../../util/types';
import { defineIDModel } from '../util/id-model';

export type RoleId = Brand<number, { readonly s: unique symbol }, 'role.id'>;

export const ROLE_ID = brandedType<number, RoleId>(t.number);

const ROLE_NAME = {
clusterlead: null,
countrylead: null,
ftsadmin: null,
hpcadmin: null,
omniscient: null,
opEntityCoordinator: null,
operationLead: null,
orglead: null,
planlead: null,
prismadmin: null,
projectowner: null,
readonly: null,
rolegranter: null,
rpmadmin: null,
};

export default defineIDModel({
tableName: 'role',
fields: {
generated: {
id: { kind: 'branded-integer', brand: ROLE_ID },
},
accidentallyOptional: {
name: { kind: 'enum', values: ROLE_NAME },
description: { kind: 'checked', type: t.string },
targetTypes: { kind: 'checked', type: t.array(t.string) },
},
optional: {},
},
idField: 'id',
softDeletionEnabled: false,
});
37 changes: 37 additions & 0 deletions src/db/models/rolePermittedAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as t from 'io-ts';

import { brandedType } from '../../util/io-ts';
import { Brand } from '../../util/types';
import { defineIDModel } from '../util/id-model';
import { PERMITTED_ACTION_ID } from './permittedAction';
import { ROLE_ID } from './role';

export type RolePermittedActionId = Brand<
number,
{ readonly s: unique symbol },
'rolePermittedAction.id'
>;

export const ROLE_PERMITTED_ACTION_ID = brandedType<
number,
RolePermittedActionId
>(t.number);

export default defineIDModel({
tableName: 'rolePermittedAction',
fields: {
generated: {
id: { kind: 'branded-integer', brand: ROLE_PERMITTED_ACTION_ID },
},
optional: {
roleId: { kind: 'branded-integer', brand: ROLE_ID },
permittedActionId: {
kind: 'checked',
type: PERMITTED_ACTION_ID,
},
},
required: {},
},
idField: 'id',
softDeletionEnabled: false,
});

0 comments on commit f15d37f

Please sign in to comment.