@things-factory/worklist 10.1.182 → 10.1.184

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.
@@ -1,6 +1,11 @@
1
1
  import { ActivityApproval } from '../../service/activity-approval/activity-approval.js';
2
2
  import { ActivityInstance } from '../../service/activity-instance/activity-instance.js';
3
3
  import { ActivityThread } from '../../service/activity-thread/activity-thread.js';
4
+ /**
5
+ * Whether the caller takes part in this instance or reads every case - for a module whose record hangs on a case and
6
+ * opens to the same people (an expense's receipt to its approvers, ADR-0139).
7
+ */
8
+ export declare function mayReadInstance(instance: ActivityInstance, context: ResolverContext): Promise<boolean>;
4
9
  /**
5
10
  * Throws a named refusal unless the caller takes part in this instance or reads every case.
6
11
  *
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mayReadInstance = mayReadInstance;
3
4
  exports.assertMayReadInstance = assertMayReadInstance;
4
5
  exports.assertMayReadThread = assertMayReadThread;
5
6
  exports.assertMayReadApproval = assertMayReadApproval;
@@ -60,6 +61,13 @@ async function readerOf(context) {
60
61
  const roleIds = (withRoles?.roles || []).filter(role => role.domainId === domain.id).map(role => role.id);
61
62
  return { domainId: domain.id, userId: user.id, roleIds };
62
63
  }
64
+ /**
65
+ * Whether the caller takes part in this instance or reads every case - for a module whose record hangs on a case and
66
+ * opens to the same people (an expense's receipt to its approvers, ADR-0139).
67
+ */
68
+ async function mayReadInstance(instance, context) {
69
+ return (0, participates_js_1.participates)(await factsOfInstance(instance), await readerOf(context)) || (await readsEveryCase(context));
70
+ }
63
71
  /**
64
72
  * Throws a named refusal unless the caller takes part in this instance or reads every case.
65
73
  *
@@ -1 +1 @@
1
- {"version":3,"file":"assert-may-read.js","sourceRoot":"","sources":["../../../server/controllers/activity-read/assert-may-read.ts"],"names":[],"mappings":"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","sourcesContent":["import { checkPermission, User } from '@things-factory/auth-base'\nimport { In } from 'typeorm'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { ActivityApproval } from '../../service/activity-approval/activity-approval.js'\nimport { ActivityInstance } from '../../service/activity-instance/activity-instance.js'\nimport { ActivityThread } from '../../service/activity-thread/activity-thread.js'\nimport { CaseFacts, participates } from './participates.js'\n\n/** Whoever may read every instance may read this one. */\nasync function readsEveryCase(context: ResolverContext): Promise<boolean> {\n const { domain, user, unsafeIP, prohibitedPrivileges } = context.state\n\n return await checkPermission(\n { category: 'activity-instance', privilege: 'query', owner: true },\n user,\n domain,\n unsafeIP,\n prohibitedPrivileges\n )\n}\n\nasync function factsOf(thread: ActivityThread): Promise<CaseFacts> {\n const instance = thread.activityInstanceId\n ? await getRepository(ActivityInstance).findOne({\n where: { domain: { id: thread.domainId }, id: thread.activityInstanceId }\n })\n : null\n\n const approvals = await getRepository(ActivityApproval).find({\n where: { domain: { id: thread.domainId }, activityThread: { id: thread.id } }\n })\n\n return {\n domainId: thread.domainId,\n assigneeIds: [thread.assigneeId],\n issuerId: instance?.issuerId,\n creatorId: instance?.creatorId,\n starterId: instance?.starterId,\n supervisoryRoleId: instance?.supervisoryRoleId,\n approvals: approvals.map(one => ({ approverId: one.approverId, approverRoleId: one.approverRoleId }))\n }\n}\n\nasync function factsOfInstance(instance: ActivityInstance): Promise<CaseFacts> {\n const threads = await getRepository(ActivityThread).find({\n where: { domain: { id: instance.domainId }, activityInstance: { id: instance.id } }\n })\n\n const approvals = threads.length\n ? await getRepository(ActivityApproval).find({\n where: { domain: { id: instance.domainId }, activityThread: { id: In(threads.map(one => one.id)) } }\n })\n : []\n\n return {\n domainId: instance.domainId,\n assigneeIds: threads.map(one => one.assigneeId),\n waitingRoleId: instance.assigneeRoleId,\n issuerId: instance.issuerId,\n creatorId: instance.creatorId,\n starterId: instance.starterId,\n supervisoryRoleId: instance.supervisoryRoleId,\n approvals: approvals.map(one => ({ approverId: one.approverId, approverRoleId: one.approverRoleId }))\n }\n}\n\nasync function readerOf(context: ResolverContext) {\n const { domain, user } = context.state\n\n const withRoles = await getRepository(User).findOne({ where: { id: user.id }, relations: ['roles'] })\n const roleIds = (withRoles?.roles || []).filter(role => role.domainId === domain.id).map(role => role.id)\n\n return { domainId: domain.id, userId: user.id, roleIds }\n}\n\n/**\n * Throws a named refusal unless the caller takes part in this instance or reads every case.\n *\n * The draft screen reopens an instance by id. Four of plant's working roles (OPERATOR and the other\n * hands-on roles) hold no activity-instance query privilege, so while this door asked it they could\n * write a draft, see it under \"raised by me\", and not open it again.\n */\nexport async function assertMayReadInstance(instance: ActivityInstance, context: ResolverContext): Promise<void> {\n if (participates(await factsOfInstance(instance), await readerOf(context))) return\n if (await readsEveryCase(context)) return\n\n throw new Error(context.t('error.activity-case not a participant'))\n}\n\n/** Throws a named refusal unless the caller takes part in this thread or reads every case. */\nexport async function assertMayReadThread(thread: ActivityThread, context: ResolverContext): Promise<void> {\n if (participates(await factsOf(thread), await readerOf(context))) return\n if (await readsEveryCase(context)) return\n\n throw new Error(context.t('error.activity-case not a participant'))\n}\n\n/** An approval is read through its thread: the same people, the same refusal. */\nexport async function assertMayReadApproval(approval: ActivityApproval, context: ResolverContext): Promise<void> {\n const { domain } = context.state\n\n const thread = approval.activityThreadId\n ? await getRepository(ActivityThread).findOne({ where: { domain: { id: domain.id }, id: approval.activityThreadId } })\n : null\n\n if (!thread) {\n /* An approval with no thread in this domain has nobody to take part in it. */\n if (await readsEveryCase(context)) return\n throw new Error(context.t('error.activity-case not a participant'))\n }\n\n await assertMayReadThread(thread, context)\n}\n"]}
1
+ {"version":3,"file":"assert-may-read.js","sourceRoot":"","sources":["../../../server/controllers/activity-read/assert-may-read.ts"],"names":[],"mappings":"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","sourcesContent":["import { checkPermission, User } from '@things-factory/auth-base'\nimport { In } from 'typeorm'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { ActivityApproval } from '../../service/activity-approval/activity-approval.js'\nimport { ActivityInstance } from '../../service/activity-instance/activity-instance.js'\nimport { ActivityThread } from '../../service/activity-thread/activity-thread.js'\nimport { CaseFacts, participates } from './participates.js'\n\n/** Whoever may read every instance may read this one. */\nasync function readsEveryCase(context: ResolverContext): Promise<boolean> {\n const { domain, user, unsafeIP, prohibitedPrivileges } = context.state\n\n return await checkPermission(\n { category: 'activity-instance', privilege: 'query', owner: true },\n user,\n domain,\n unsafeIP,\n prohibitedPrivileges\n )\n}\n\nasync function factsOf(thread: ActivityThread): Promise<CaseFacts> {\n const instance = thread.activityInstanceId\n ? await getRepository(ActivityInstance).findOne({\n where: { domain: { id: thread.domainId }, id: thread.activityInstanceId }\n })\n : null\n\n const approvals = await getRepository(ActivityApproval).find({\n where: { domain: { id: thread.domainId }, activityThread: { id: thread.id } }\n })\n\n return {\n domainId: thread.domainId,\n assigneeIds: [thread.assigneeId],\n issuerId: instance?.issuerId,\n creatorId: instance?.creatorId,\n starterId: instance?.starterId,\n supervisoryRoleId: instance?.supervisoryRoleId,\n approvals: approvals.map(one => ({ approverId: one.approverId, approverRoleId: one.approverRoleId }))\n }\n}\n\nasync function factsOfInstance(instance: ActivityInstance): Promise<CaseFacts> {\n const threads = await getRepository(ActivityThread).find({\n where: { domain: { id: instance.domainId }, activityInstance: { id: instance.id } }\n })\n\n const approvals = threads.length\n ? await getRepository(ActivityApproval).find({\n where: { domain: { id: instance.domainId }, activityThread: { id: In(threads.map(one => one.id)) } }\n })\n : []\n\n return {\n domainId: instance.domainId,\n assigneeIds: threads.map(one => one.assigneeId),\n waitingRoleId: instance.assigneeRoleId,\n issuerId: instance.issuerId,\n creatorId: instance.creatorId,\n starterId: instance.starterId,\n supervisoryRoleId: instance.supervisoryRoleId,\n approvals: approvals.map(one => ({ approverId: one.approverId, approverRoleId: one.approverRoleId }))\n }\n}\n\nasync function readerOf(context: ResolverContext) {\n const { domain, user } = context.state\n\n const withRoles = await getRepository(User).findOne({ where: { id: user.id }, relations: ['roles'] })\n const roleIds = (withRoles?.roles || []).filter(role => role.domainId === domain.id).map(role => role.id)\n\n return { domainId: domain.id, userId: user.id, roleIds }\n}\n\n/**\n * Whether the caller takes part in this instance or reads every case - for a module whose record hangs on a case and\n * opens to the same people (an expense's receipt to its approvers, ADR-0139).\n */\nexport async function mayReadInstance(instance: ActivityInstance, context: ResolverContext): Promise<boolean> {\n return participates(await factsOfInstance(instance), await readerOf(context)) || (await readsEveryCase(context))\n}\n\n/**\n * Throws a named refusal unless the caller takes part in this instance or reads every case.\n *\n * The draft screen reopens an instance by id. Four of plant's working roles (OPERATOR and the other\n * hands-on roles) hold no activity-instance query privilege, so while this door asked it they could\n * write a draft, see it under \"raised by me\", and not open it again.\n */\nexport async function assertMayReadInstance(instance: ActivityInstance, context: ResolverContext): Promise<void> {\n if (participates(await factsOfInstance(instance), await readerOf(context))) return\n if (await readsEveryCase(context)) return\n\n throw new Error(context.t('error.activity-case not a participant'))\n}\n\n/** Throws a named refusal unless the caller takes part in this thread or reads every case. */\nexport async function assertMayReadThread(thread: ActivityThread, context: ResolverContext): Promise<void> {\n if (participates(await factsOf(thread), await readerOf(context))) return\n if (await readsEveryCase(context)) return\n\n throw new Error(context.t('error.activity-case not a participant'))\n}\n\n/** An approval is read through its thread: the same people, the same refusal. */\nexport async function assertMayReadApproval(approval: ActivityApproval, context: ResolverContext): Promise<void> {\n const { domain } = context.state\n\n const thread = approval.activityThreadId\n ? await getRepository(ActivityThread).findOne({ where: { domain: { id: domain.id }, id: approval.activityThreadId } })\n : null\n\n if (!thread) {\n /* An approval with no thread in this domain has nobody to take part in it. */\n if (await readsEveryCase(context)) return\n throw new Error(context.t('error.activity-case not a participant'))\n }\n\n await assertMayReadThread(thread, context)\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  export * from './activity-approval/approval-line.js';
2
2
  export * from './activity-installation/activity-installation-controller.js';
3
3
  export * from './activity-instance/index.js';
4
+ export { mayReadInstance } from './activity-read/assert-may-read.js';
4
5
  export * from './common.js';
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mayReadInstance = void 0;
3
4
  const tslib_1 = require("tslib");
4
5
  /*
5
6
  * **결재선 규칙을 밖으로 낸다** — 소비처가 그 판정을 베끼지 않게.
@@ -11,5 +12,7 @@ const tslib_1 = require("tslib");
11
12
  tslib_1.__exportStar(require("./activity-approval/approval-line.js"), exports);
12
13
  tslib_1.__exportStar(require("./activity-installation/activity-installation-controller.js"), exports);
13
14
  tslib_1.__exportStar(require("./activity-instance/index.js"), exports);
15
+ var assert_may_read_js_1 = require("./activity-read/assert-may-read.js");
16
+ Object.defineProperty(exports, "mayReadInstance", { enumerable: true, get: function () { return assert_may_read_js_1.mayReadInstance; } });
14
17
  tslib_1.__exportStar(require("./common.js"), exports);
15
18
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/controllers/index.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACH,+EAAoD;AACpD,sGAA2E;AAC3E,uEAA4C;AAC5C,sDAA2B","sourcesContent":["/*\n * **결재선 규칙을 밖으로 낸다** — 소비처가 그 판정을 베끼지 않게.\n *\n * `operato-twin` 이 조치를 올리기 전에 「결재자가 낸 사람뿐인가」를 봐야 한다. 그 판단에 필요한\n * 「이 항목이 결재인가」를 그쪽에서 다시 쓰면 규칙이 두 벌이 되고, `participation` 이 늘 때 한쪽만\n * 고쳐진다. 판정은 한 자리에 있고 다른 패키지가 그것을 부른다.\n */\nexport * from './activity-approval/approval-line.js'\nexport * from './activity-installation/activity-installation-controller.js'\nexport * from './activity-instance/index.js'\nexport * from './common.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/controllers/index.ts"],"names":[],"mappings":";;;;AAAA;;;;;;GAMG;AACH,+EAAoD;AACpD,sGAA2E;AAC3E,uEAA4C;AAC5C,yEAAoE;AAA3D,qHAAA,eAAe,OAAA;AACxB,sDAA2B","sourcesContent":["/*\n * **결재선 규칙을 밖으로 낸다** — 소비처가 그 판정을 베끼지 않게.\n *\n * `operato-twin` 이 조치를 올리기 전에 「결재자가 낸 사람뿐인가」를 봐야 한다. 그 판단에 필요한\n * 「이 항목이 결재인가」를 그쪽에서 다시 쓰면 규칙이 두 벌이 되고, `participation` 이 늘 때 한쪽만\n * 고쳐진다. 판정은 한 자리에 있고 다른 패키지가 그것을 부른다.\n */\nexport * from './activity-approval/approval-line.js'\nexport * from './activity-installation/activity-installation-controller.js'\nexport * from './activity-instance/index.js'\nexport { mayReadInstance } from './activity-read/assert-may-read.js'\nexport * from './common.js'\n"]}