@memberjunction/core-entities 6.2.0-edge.4 → 6.2.0-edge.6
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/dist/.tsbuildinfo +1 -1
- package/dist/custom/ConversationWriteAccess.d.ts +5 -0
- package/dist/custom/ConversationWriteAccess.d.ts.map +1 -1
- package/dist/custom/ConversationWriteAccess.js +6 -6
- package/dist/custom/ConversationWriteAccess.js.map +1 -1
- package/dist/custom/MJConversationDetailEntityExtended.d.ts +70 -4
- package/dist/custom/MJConversationDetailEntityExtended.d.ts.map +1 -1
- package/dist/custom/MJConversationDetailEntityExtended.js +268 -28
- package/dist/custom/MJConversationDetailEntityExtended.js.map +1 -1
- package/dist/custom/MJQueryEntityExtended.d.ts +37 -1
- package/dist/custom/MJQueryEntityExtended.d.ts.map +1 -1
- package/dist/custom/MJQueryEntityExtended.js +92 -5
- package/dist/custom/MJQueryEntityExtended.js.map +1 -1
- package/dist/custom/MJThemeEntityExtended.d.ts +13 -0
- package/dist/custom/MJThemeEntityExtended.d.ts.map +1 -0
- package/dist/custom/MJThemeEntityExtended.js +37 -0
- package/dist/custom/MJThemeEntityExtended.js.map +1 -0
- package/dist/custom/MJUserViewEntityExtended.d.ts +39 -4
- package/dist/custom/MJUserViewEntityExtended.d.ts.map +1 -1
- package/dist/custom/MJUserViewEntityExtended.js +111 -18
- package/dist/custom/MJUserViewEntityExtended.js.map +1 -1
- package/dist/custom/approvals.d.ts +55 -0
- package/dist/custom/approvals.d.ts.map +1 -0
- package/dist/custom/approvals.js +120 -0
- package/dist/custom/approvals.js.map +1 -0
- package/dist/engines/InstanceConfigEngine.d.ts.map +1 -1
- package/dist/engines/InstanceConfigEngine.js +13 -3
- package/dist/engines/InstanceConfigEngine.js.map +1 -1
- package/dist/engines/PermissionEngine.d.ts +5 -4
- package/dist/engines/PermissionEngine.d.ts.map +1 -1
- package/dist/engines/PermissionEngine.js +7 -5
- package/dist/engines/PermissionEngine.js.map +1 -1
- package/dist/engines/QueryEngine.d.ts +81 -6
- package/dist/engines/QueryEngine.d.ts.map +1 -1
- package/dist/engines/QueryEngine.js +283 -4
- package/dist/engines/QueryEngine.js.map +1 -1
- package/dist/engines/UserInfoEngine.d.ts +48 -2
- package/dist/engines/UserInfoEngine.d.ts.map +1 -1
- package/dist/engines/UserInfoEngine.js +65 -8
- package/dist/engines/UserInfoEngine.js.map +1 -1
- package/dist/engines/conversations.d.ts +19 -1
- package/dist/engines/conversations.d.ts.map +1 -1
- package/dist/engines/conversations.js +125 -22
- package/dist/engines/conversations.js.map +1 -1
- package/dist/engines/knowledgeHubMetadata.d.ts +8 -3
- package/dist/engines/knowledgeHubMetadata.d.ts.map +1 -1
- package/dist/engines/knowledgeHubMetadata.js +19 -2
- package/dist/engines/knowledgeHubMetadata.js.map +1 -1
- package/dist/generated/entities/__mj.d.ts +4142 -111
- package/dist/generated/entities/__mj.d.ts.map +1 -1
- package/dist/generated/entities/__mj.js +5895 -262
- package/dist/generated/entities/__mj.js.map +1 -1
- package/dist/generated/remote_operations.d.ts +17 -5
- package/dist/generated/remote_operations.d.ts.map +1 -1
- package/dist/generated/remote_operations.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
|
@@ -6,6 +6,11 @@ export interface ConversationWriteDecision {
|
|
|
6
6
|
Reason: string | null;
|
|
7
7
|
/** True only when the conversation loaded and the user is its owner. */
|
|
8
8
|
IsOwner: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* True when the conversation loaded for the user. A conversation that did not load is `Allowed` whether it is
|
|
11
|
+
* missing or hidden from the user by a row filter, so a caller that must tell those apart checks this.
|
|
12
|
+
*/
|
|
13
|
+
Loaded: boolean;
|
|
9
14
|
}
|
|
10
15
|
/**
|
|
11
16
|
* Whether a user may write rows that belong to a conversation: the owner, or a user with
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationWriteAccess.d.ts","sourceRoot":"","sources":["../../src/custom/ConversationWriteAccess.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKnE,4EAA4E;AAC5E,eAAO,MAAM,8BAA8B,yCAAyC,CAAC;AAErF,MAAM,WAAW,yBAAyB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ConversationWriteAccess.d.ts","sourceRoot":"","sources":["../../src/custom/ConversationWriteAccess.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKnE,4EAA4E;AAC5E,eAAO,MAAM,8BAA8B,yCAAyC,CAAC;AAErF,MAAM,WAAW,yBAAyB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC1C,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,SAAS,EACjC,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC,yBAAyB,CAAC,CAuBpC"}
|
|
@@ -9,14 +9,14 @@ export const CONVERSATIONS_RESOURCE_TYPE_ID = '81D4BC3D-9FEB-EF11-B01A-286B35C04
|
|
|
9
9
|
*/
|
|
10
10
|
export async function UserMayWriteConversation(provider, user, conversationId) {
|
|
11
11
|
if (provider?.ProviderType !== 'Database' || !user) {
|
|
12
|
-
return { Allowed: true, Reason: null, IsOwner: false };
|
|
12
|
+
return { Allowed: true, Reason: null, IsOwner: false, Loaded: false };
|
|
13
13
|
}
|
|
14
14
|
const conversation = await provider.GetEntityObject('MJ: Conversations', user);
|
|
15
15
|
if (!(await conversation.Load(conversationId))) {
|
|
16
|
-
return { Allowed: true, Reason: null, IsOwner: false };
|
|
16
|
+
return { Allowed: true, Reason: null, IsOwner: false, Loaded: false };
|
|
17
17
|
}
|
|
18
18
|
if (conversation.UserID && UUIDsEqual(conversation.UserID, user.ID)) {
|
|
19
|
-
return { Allowed: true, Reason: null, IsOwner: true };
|
|
19
|
+
return { Allowed: true, Reason: null, IsOwner: true, Loaded: true };
|
|
20
20
|
}
|
|
21
21
|
const engine = ResourcePermissionEngine.GetProviderInstance(provider, ResourcePermissionEngine);
|
|
22
22
|
await engine.Config(false, user);
|
|
@@ -24,11 +24,11 @@ export async function UserMayWriteConversation(provider, user, conversationId) {
|
|
|
24
24
|
.GetUserAvailableResources(user, CONVERSATIONS_RESOURCE_TYPE_ID)
|
|
25
25
|
.find((p) => UUIDsEqual(p.ResourceRecordID, conversationId));
|
|
26
26
|
if (!grant) {
|
|
27
|
-
return { Allowed: false, Reason: 'You do not have access to this conversation.', IsOwner: false };
|
|
27
|
+
return { Allowed: false, Reason: 'You do not have access to this conversation.', IsOwner: false, Loaded: true };
|
|
28
28
|
}
|
|
29
29
|
if (grant.PermissionLevel === 'Edit' || grant.PermissionLevel === 'Owner') {
|
|
30
|
-
return { Allowed: true, Reason: null, IsOwner: false };
|
|
30
|
+
return { Allowed: true, Reason: null, IsOwner: false, Loaded: true };
|
|
31
31
|
}
|
|
32
|
-
return { Allowed: false, Reason: 'You have view-only access to this conversation.', IsOwner: false };
|
|
32
|
+
return { Allowed: false, Reason: 'You have view-only access to this conversation.', IsOwner: false, Loaded: true };
|
|
33
33
|
}
|
|
34
34
|
//# sourceMappingURL=ConversationWriteAccess.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationWriteAccess.js","sourceRoot":"","sources":["../../src/custom/ConversationWriteAccess.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gDAAgD,CAAC;AAE1F,4EAA4E;AAC5E,MAAM,CAAC,MAAM,8BAA8B,GAAG,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"ConversationWriteAccess.js","sourceRoot":"","sources":["../../src/custom/ConversationWriteAccess.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gDAAgD,CAAC;AAE1F,4EAA4E;AAC5E,MAAM,CAAC,MAAM,8BAA8B,GAAG,sCAAsC,CAAC;AAcrF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC1C,QAA2B,EAC3B,IAAiC,EACjC,cAAsB;IAEtB,IAAI,QAAQ,EAAE,YAAY,KAAK,UAAU,IAAI,CAAC,IAAI,EAAE,CAAC;QACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC1E,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAuB,mBAAmB,EAAE,IAAI,CAAC,CAAC;IACrG,IAAI,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;QAC7C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC1E,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,IAAI,UAAU,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAClE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACxE,CAAC;IACD,MAAM,MAAM,GAAG,wBAAwB,CAAC,mBAAmB,CAA2B,QAAQ,EAAE,wBAAwB,CAA6B,CAAC;IACtJ,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,MAAM;SACf,yBAAyB,CAAC,IAAI,EAAE,8BAA8B,CAAC;SAC/D,IAAI,CAAC,CAAC,CAA6B,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC,CAAC;IAC7F,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,8CAA8C,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACpH,CAAC;IACD,IAAI,KAAK,CAAC,eAAe,KAAK,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,OAAO,EAAE,CAAC;QACxE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACzE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,iDAAiD,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACvH,CAAC"}
|
|
@@ -15,6 +15,28 @@ import { MJConversationDetailEntity } from '../generated/entity_subclasses.js';
|
|
|
15
15
|
* owner-only — even users with `Edit`-level grants on the conversation are
|
|
16
16
|
* blocked from changing them, because the storage is a single value per
|
|
17
17
|
* message (it represents the owner's evaluation, not per-grantee opinions).
|
|
18
|
+
*
|
|
19
|
+
* **Who a message is from** (A19, the rules for people's messages). For a `Role='User'` message, the owner and
|
|
20
|
+
* grantees alike:
|
|
21
|
+
* - post only as themselves: a new message naming another person's `UserID` is refused, and a grantee's message
|
|
22
|
+
* with no `UserID` gets the grantee's (an empty one reads as the conversation's owner). The owner's stays empty,
|
|
23
|
+
* since it already means them;
|
|
24
|
+
* - change who wrote it and what it says ({@link AUTHORED_FIELDS}) only when they wrote it, and never its role;
|
|
25
|
+
* - never move it to another conversation or fork ({@link PLACEMENT_FIELDS});
|
|
26
|
+
* - delete it only when they wrote it, or own the conversation.
|
|
27
|
+
*
|
|
28
|
+
* The system user is exempt from these authorship rules, since server code writes on people's behalf, but it still
|
|
29
|
+
* needs to own the conversation or hold a grant on it, as before: some server paths elevate an anonymous visitor to
|
|
30
|
+
* the system user (MJ#4791), and this gate keeps those paths out of other people's conversations, so no transaction
|
|
31
|
+
* variable may set the row or conversation it writes ({@link ACCESS_GATED_FIELDS}) for it either.
|
|
32
|
+
*
|
|
33
|
+
* **Only the server writes an agent's reply** (A19, second half). A reply (`Role` `AI` or `Error`) is created, and
|
|
34
|
+
* what it says ({@link REPLY_FIELDS}) changed, only on an instance server code marked with
|
|
35
|
+
* {@link MarkServerAuthoredReply}. The marker is not a field: no GraphQL input, `OldValues___` or transaction
|
|
36
|
+
* variable reaches it, so a person's save of a reply is refused whatever its user, and so is an unmarked save as the
|
|
37
|
+
* system user. A marked write still needs its context user (the person the reply is for, or whoever runs a
|
|
38
|
+
* host-driven turn) to own the conversation or hold a grant on it, so being the system user grants nothing new.
|
|
39
|
+
* Pinning, hiding, the owner's rating and other bookkeeping keep the conversation-level rules.
|
|
18
40
|
* MJ's permissions engine has no native primitive for per-field row-conditional
|
|
19
41
|
* write rules, so this gate lives here rather than in `MJ: Entity Permissions`.
|
|
20
42
|
*
|
|
@@ -24,15 +46,59 @@ import { MJConversationDetailEntity } from '../generated/entity_subclasses.js';
|
|
|
24
46
|
* round trips for permission lookups.
|
|
25
47
|
*/
|
|
26
48
|
export declare class MJConversationDetailEntityExtended extends MJConversationDetailEntity {
|
|
49
|
+
private serverAuthoredReply;
|
|
50
|
+
/**
|
|
51
|
+
* Marks this instance as server code writing an agent's reply, so it may create a reply (`Role` `AI` or `Error`)
|
|
52
|
+
* and change what one says. Call it before `Save()`; it stays on the instance for every later save, like
|
|
53
|
+
* `SetCloneContext()`. The context user still needs to own the conversation or hold a grant on it.
|
|
54
|
+
*
|
|
55
|
+
* It is not a field: no GraphQL input, `OldValues___` or transaction variable can set it, and the browser's copy of
|
|
56
|
+
* this class never sends it. It has no effect on a person's message.
|
|
57
|
+
*/
|
|
58
|
+
MarkServerAuthoredReply(): void;
|
|
59
|
+
/** Whether {@link MarkServerAuthoredReply} was called on this instance. */
|
|
60
|
+
get IsServerAuthoredReply(): boolean;
|
|
27
61
|
Save(options?: EntitySaveOptions): Promise<boolean>;
|
|
28
62
|
Delete(options?: EntityDeleteOptions): Promise<boolean>;
|
|
29
63
|
private currentUserMayWrite;
|
|
30
64
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
65
|
+
* Why the user may not write to this message's conversation at all, or `null` when they may. The owner may. Anyone
|
|
66
|
+
* else may not change the rating fields, which are the owner's alone, and needs an `Edit` or `Owner` grant. A
|
|
67
|
+
* conversation that does not load for the user is hidden from them when it exists (a row filter), and they may not
|
|
68
|
+
* write to it; when no one can find it, it is missing or being created in this same transaction, and the foreign
|
|
69
|
+
* key and the base save decide, as before.
|
|
70
|
+
*/
|
|
71
|
+
private accessRefusal;
|
|
72
|
+
/**
|
|
73
|
+
* Why this write would put words in an agent's mouth, or `null` when it does not: an unmarked save that creates a
|
|
74
|
+
* reply, turns a message into one, or changes what one says ({@link REPLY_FIELDS}). Applies to every user, the
|
|
75
|
+
* system user included. Deleting a reply keeps the conversation-level rules.
|
|
76
|
+
*/
|
|
77
|
+
private replyRefusal;
|
|
78
|
+
/**
|
|
79
|
+
* Why this write breaks the rules for people's messages (see the class doc), or `null` when it does not. On a new
|
|
80
|
+
* message from a grantee with no `UserID`, fills in the grantee's.
|
|
81
|
+
*/
|
|
82
|
+
private authorshipRefusal;
|
|
83
|
+
/** A new person's message names its author as the poster, or names no one (filled in for a grantee). */
|
|
84
|
+
private postRefusal;
|
|
85
|
+
/**
|
|
86
|
+
* An existing person's message: only its author changes who wrote it and what it says, no one its role (to or
|
|
87
|
+
* from `User`), and no one moves it to another conversation or fork. A message with no `UserID` is the owner's.
|
|
88
|
+
*/
|
|
89
|
+
private changeRefusal;
|
|
90
|
+
/** A person's message is deleted by its author or by the conversation's owner (whose it is with no `UserID`). */
|
|
91
|
+
private deleteRefusal;
|
|
92
|
+
/** Whether the conversation exists, read as the system user; false when there is no system user to ask. */
|
|
93
|
+
private conversationExists;
|
|
94
|
+
/**
|
|
95
|
+
* Whether a transaction variable of this message's group sets one of `fields` on it. The field is resolved the way
|
|
96
|
+
* `Set` resolves it at submit (trimmed, any case).
|
|
34
97
|
*/
|
|
35
|
-
private
|
|
98
|
+
private fieldSetByTransactionVariable;
|
|
99
|
+
private isFieldDirty;
|
|
100
|
+
/** A field's value as loaded, before this save's changes; `null` when it was empty or is not text. */
|
|
101
|
+
private originalFieldText;
|
|
36
102
|
/**
|
|
37
103
|
* Records WHY the write was refused as a NEW `ResultHistory` entry, so callers that read
|
|
38
104
|
* `LatestResult.CompleteMessage` see the reason (issue #4791).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJConversationDetailEntityExtended.d.ts","sourceRoot":"","sources":["../../src/custom/MJConversationDetailEntityExtended.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,mBAAmB,
|
|
1
|
+
{"version":3,"file":"MJConversationDetailEntityExtended.d.ts","sourceRoot":"","sources":["../../src/custom/MJConversationDetailEntityExtended.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,mBAAmB,EAEnB,iBAAiB,EAKpB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,0BAA0B,EAAwB,MAAM,gCAAgC,CAAC;AAuFlG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,qBACa,kCAAmC,SAAQ,0BAA0B;IAC9E,OAAO,CAAC,mBAAmB,CAAS;IAEpC;;;;;;;OAOG;IACI,uBAAuB,IAAI,IAAI;IAItC,2EAA2E;IAC3E,IAAW,qBAAqB,IAAI,OAAO,CAE1C;IAEc,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAYnD,MAAM,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;YAOxD,mBAAmB;IA2DjC;;;;;;OAMG;YACW,aAAa;IAoB3B;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAWpB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAOzB,wGAAwG;IACxG,OAAO,CAAC,WAAW;IAgBnB;;;OAGG;IACH,OAAO,CAAC,aAAa;IA2BrB,iHAAiH;IACjH,OAAO,CAAC,aAAa;IASrB,2GAA2G;YAC7F,kBAAkB;IAahC;;;OAGG;IACH,OAAO,CAAC,6BAA6B;IAOrC,OAAO,CAAC,YAAY;IAIpB,sGAAsG;IACtG,OAAO,CAAC,iBAAiB;IAKzB;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;CASvB;AAED,6FAA6F;AAC7F,wBAAgB,sCAAsC,IAAI,IAAI,CAE7D"}
|
|
@@ -4,8 +4,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { BaseEntity, BaseEntityResult, LogError } from '@memberjunction/core';
|
|
8
|
-
import { RegisterClass } from '@memberjunction/global';
|
|
7
|
+
import { BaseEntity, BaseEntityResult, EntityFieldInfo, LogError, WellKnownUserSource } from '@memberjunction/core';
|
|
8
|
+
import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
|
|
9
9
|
import { MJConversationDetailEntity } from '../generated/entity_subclasses.js';
|
|
10
10
|
import { UserMayWriteConversation } from './ConversationWriteAccess.js';
|
|
11
11
|
/**
|
|
@@ -15,6 +15,74 @@ import { UserMayWriteConversation } from './ConversationWriteAccess.js';
|
|
|
15
15
|
* the parent conversation cannot retroactively rewrite the owner's rating.
|
|
16
16
|
*/
|
|
17
17
|
const OWNER_ONLY_RATING_FIELDS = ['UserRating', 'UserFeedback'];
|
|
18
|
+
/**
|
|
19
|
+
* The fields of a person's (`Role='User'`) message that say who wrote it and what it says: its author, its role, its
|
|
20
|
+
* text, its attachment, its media type and where it sits in a thread. Only its author may change them, except
|
|
21
|
+
* `Role`, which no one may change. Other fields (pinning, hiding, bookkeeping the server writes) keep the
|
|
22
|
+
* conversation-level rules.
|
|
23
|
+
*/
|
|
24
|
+
const AUTHORED_FIELDS = ['UserID', 'Role', 'Message', 'ArtifactID', 'ArtifactVersionID', 'MediaType', 'ParentID'];
|
|
25
|
+
/**
|
|
26
|
+
* Where a message sits: its conversation and its fork (`BranchID`, null is Main). No one moves a person's message,
|
|
27
|
+
* its author included: moving it takes it out of the thread it was written in.
|
|
28
|
+
*/
|
|
29
|
+
const PLACEMENT_FIELDS = ['ConversationID', 'BranchID'];
|
|
30
|
+
/**
|
|
31
|
+
* The fields the access and reply-authorship rules, which hold for everyone (including the system user unless
|
|
32
|
+
* explicitly marked), decide on: which row is written (`ID`; an update's SQL is rebuilt with the variable's value at
|
|
33
|
+
* submit, so it would write another row), its conversation, its role (`Role` — a transaction variable setting `AI` or
|
|
34
|
+
* `Error` at submit would bypass the unmarked reply check), and the owner's rating. A transaction variable sets its
|
|
35
|
+
* field at submit, after the gate has run, so none of these may take its value from one.
|
|
36
|
+
*/
|
|
37
|
+
const ACCESS_GATED_FIELDS = ['ID', 'ConversationID', 'Role', ...OWNER_ONLY_RATING_FIELDS];
|
|
38
|
+
/**
|
|
39
|
+
* {@link ACCESS_GATED_FIELDS} plus `BranchID` (placement on a fork) and the remaining {@link AUTHORED_FIELDS}
|
|
40
|
+
* (`Role` is already in {@link ACCESS_GATED_FIELDS}), which the authorship rules decide on and the system user skips.
|
|
41
|
+
*/
|
|
42
|
+
const GATED_FIELDS = [
|
|
43
|
+
...ACCESS_GATED_FIELDS,
|
|
44
|
+
'BranchID',
|
|
45
|
+
...AUTHORED_FIELDS.filter(field => field !== 'Role')
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* The fields of an agent's reply (`Role` `AI` or `Error`) that say what the agent said, who said it, and where it sits:
|
|
49
|
+
* the authored fields ({@link AUTHORED_FIELDS}: `UserID`, `Role`, `Message`, `ArtifactID`, `ArtifactVersionID`,
|
|
50
|
+
* `MediaType`, `ParentID`), plus its conversation (`ConversationID`) and fork (`BranchID`), its agent (`AgentID`),
|
|
51
|
+
* its status (`Status`) and error (`Error`), the form (`ResponseForm`), commands (`ActionableCommands`,
|
|
52
|
+
* `AutomaticCommands`), suggested replies (`SuggestedResponses`) and reflection (`ReflectionInsights`) it offers, and
|
|
53
|
+
* the turn timing and external reference (`CompletionTime`, `ExternalID`). Only a server write marked with
|
|
54
|
+
* {@link MJConversationDetailEntityExtended.MarkServerAuthoredReply} changes them. Pinning, hiding, the owner's rating
|
|
55
|
+
* and the other bookkeeping keep the conversation-level rules.
|
|
56
|
+
*/
|
|
57
|
+
const REPLY_FIELDS = [
|
|
58
|
+
...AUTHORED_FIELDS,
|
|
59
|
+
'ConversationID',
|
|
60
|
+
'BranchID',
|
|
61
|
+
'AgentID',
|
|
62
|
+
'Status',
|
|
63
|
+
'Error',
|
|
64
|
+
'ResponseForm',
|
|
65
|
+
'ActionableCommands',
|
|
66
|
+
'AutomaticCommands',
|
|
67
|
+
'SuggestedResponses',
|
|
68
|
+
'ReflectionInsights',
|
|
69
|
+
'CompletionTime',
|
|
70
|
+
'ExternalID'
|
|
71
|
+
];
|
|
72
|
+
/** The refusal for a write that would put words in an agent's mouth. */
|
|
73
|
+
const REPLY_REFUSAL = "Only the server writes an agent's reply.";
|
|
74
|
+
/**
|
|
75
|
+
* Whether a `Role` value is a person's message. Compared the way validation and the database's CHECK constraint
|
|
76
|
+
* compare it (trimmed, any case), so `'user'` or `'User '`, which both store, cannot slip past these rules.
|
|
77
|
+
*/
|
|
78
|
+
function isPersonRole(role) {
|
|
79
|
+
return role != null && EntityFieldInfo.NormalizeValueListValue(role) === 'user';
|
|
80
|
+
}
|
|
81
|
+
/** Whether a `Role` value is an agent's reply (`AI` or `Error`), compared as {@link isPersonRole} compares. */
|
|
82
|
+
function isReplyRole(role) {
|
|
83
|
+
const normalized = role == null ? null : EntityFieldInfo.NormalizeValueListValue(role);
|
|
84
|
+
return normalized === 'ai' || normalized === 'error';
|
|
85
|
+
}
|
|
18
86
|
/**
|
|
19
87
|
* Server-side defense-in-depth for conversation sharing. The Angular chat UI
|
|
20
88
|
* disables the message input when the current user only holds `View` access,
|
|
@@ -30,6 +98,28 @@ const OWNER_ONLY_RATING_FIELDS = ['UserRating', 'UserFeedback'];
|
|
|
30
98
|
* owner-only — even users with `Edit`-level grants on the conversation are
|
|
31
99
|
* blocked from changing them, because the storage is a single value per
|
|
32
100
|
* message (it represents the owner's evaluation, not per-grantee opinions).
|
|
101
|
+
*
|
|
102
|
+
* **Who a message is from** (A19, the rules for people's messages). For a `Role='User'` message, the owner and
|
|
103
|
+
* grantees alike:
|
|
104
|
+
* - post only as themselves: a new message naming another person's `UserID` is refused, and a grantee's message
|
|
105
|
+
* with no `UserID` gets the grantee's (an empty one reads as the conversation's owner). The owner's stays empty,
|
|
106
|
+
* since it already means them;
|
|
107
|
+
* - change who wrote it and what it says ({@link AUTHORED_FIELDS}) only when they wrote it, and never its role;
|
|
108
|
+
* - never move it to another conversation or fork ({@link PLACEMENT_FIELDS});
|
|
109
|
+
* - delete it only when they wrote it, or own the conversation.
|
|
110
|
+
*
|
|
111
|
+
* The system user is exempt from these authorship rules, since server code writes on people's behalf, but it still
|
|
112
|
+
* needs to own the conversation or hold a grant on it, as before: some server paths elevate an anonymous visitor to
|
|
113
|
+
* the system user (MJ#4791), and this gate keeps those paths out of other people's conversations, so no transaction
|
|
114
|
+
* variable may set the row or conversation it writes ({@link ACCESS_GATED_FIELDS}) for it either.
|
|
115
|
+
*
|
|
116
|
+
* **Only the server writes an agent's reply** (A19, second half). A reply (`Role` `AI` or `Error`) is created, and
|
|
117
|
+
* what it says ({@link REPLY_FIELDS}) changed, only on an instance server code marked with
|
|
118
|
+
* {@link MarkServerAuthoredReply}. The marker is not a field: no GraphQL input, `OldValues___` or transaction
|
|
119
|
+
* variable reaches it, so a person's save of a reply is refused whatever its user, and so is an unmarked save as the
|
|
120
|
+
* system user. A marked write still needs its context user (the person the reply is for, or whoever runs a
|
|
121
|
+
* host-driven turn) to own the conversation or hold a grant on it, so being the system user grants nothing new.
|
|
122
|
+
* Pinning, hiding, the owner's rating and other bookkeeping keep the conversation-level rules.
|
|
33
123
|
* MJ's permissions engine has no native primitive for per-field row-conditional
|
|
34
124
|
* write rules, so this gate lives here rather than in `MJ: Entity Permissions`.
|
|
35
125
|
*
|
|
@@ -39,11 +129,35 @@ const OWNER_ONLY_RATING_FIELDS = ['UserRating', 'UserFeedback'];
|
|
|
39
129
|
* round trips for permission lookups.
|
|
40
130
|
*/
|
|
41
131
|
let MJConversationDetailEntityExtended = class MJConversationDetailEntityExtended extends MJConversationDetailEntity {
|
|
132
|
+
constructor() {
|
|
133
|
+
super(...arguments);
|
|
134
|
+
this.serverAuthoredReply = false;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Marks this instance as server code writing an agent's reply, so it may create a reply (`Role` `AI` or `Error`)
|
|
138
|
+
* and change what one says. Call it before `Save()`; it stays on the instance for every later save, like
|
|
139
|
+
* `SetCloneContext()`. The context user still needs to own the conversation or hold a grant on it.
|
|
140
|
+
*
|
|
141
|
+
* It is not a field: no GraphQL input, `OldValues___` or transaction variable can set it, and the browser's copy of
|
|
142
|
+
* this class never sends it. It has no effect on a person's message.
|
|
143
|
+
*/
|
|
144
|
+
MarkServerAuthoredReply() {
|
|
145
|
+
this.serverAuthoredReply = true;
|
|
146
|
+
}
|
|
147
|
+
/** Whether {@link MarkServerAuthoredReply} was called on this instance. */
|
|
148
|
+
get IsServerAuthoredReply() {
|
|
149
|
+
return this.serverAuthoredReply;
|
|
150
|
+
}
|
|
42
151
|
async Save(options) {
|
|
152
|
+
const callerUserID = this.UserID; // the gate may fill in a grantee's; a save that fails keeps the caller's
|
|
43
153
|
if (!(await this.currentUserMayWrite('save'))) {
|
|
44
154
|
return false;
|
|
45
155
|
}
|
|
46
|
-
|
|
156
|
+
const saved = await super.Save(options);
|
|
157
|
+
if (!saved) {
|
|
158
|
+
this.UserID = callerUserID;
|
|
159
|
+
}
|
|
160
|
+
return saved;
|
|
47
161
|
}
|
|
48
162
|
async Delete(options) {
|
|
49
163
|
if (!(await this.currentUserMayWrite('delete'))) {
|
|
@@ -63,6 +177,19 @@ let MJConversationDetailEntityExtended = class MJConversationDetailEntityExtende
|
|
|
63
177
|
// No user context on a server save = system operation; allow.
|
|
64
178
|
return true;
|
|
65
179
|
}
|
|
180
|
+
// The system user skips the authorship rules (server code writes on people's behalf) but, like anyone, must own
|
|
181
|
+
// the conversation or hold a grant on it: some server paths elevate an anonymous visitor to the system user
|
|
182
|
+
// (MJ#4791), and this gate is what keeps those paths out of other people's conversations.
|
|
183
|
+
const isSystemUser = WellKnownUserSource.Instance.IsSystemUser(user);
|
|
184
|
+
const variableGated = isSystemUser ? ACCESS_GATED_FIELDS : GATED_FIELDS;
|
|
185
|
+
const touchesReply = isReplyRole(this.Role) || isReplyRole(this.originalFieldText('Role'));
|
|
186
|
+
if (operation === 'save' && this.fieldSetByTransactionVariable(touchesReply && !this.serverAuthoredReply ? [...variableGated, ...REPLY_FIELDS] : variableGated)) {
|
|
187
|
+
// A transaction variable sets its field after this check has passed, at submit, to any value an earlier
|
|
188
|
+
// item in the group produced: a message would be checked as one row, author or conversation and saved as
|
|
189
|
+
// another, and an unmarked save could rewrite what an agent's reply says.
|
|
190
|
+
this.recordDenied('A conversation message cannot take its values from a transaction variable.', resultType);
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
66
193
|
// A message created by the record-cloning engine, as part of copying a conversation into a
|
|
67
194
|
// new user's account. The engine has already authorized that copy (Owner-only, the clone
|
|
68
195
|
// authorization, and conversations are copyable only from a template user), and the
|
|
@@ -72,20 +199,12 @@ let MJConversationDetailEntityExtended = class MJConversationDetailEntityExtende
|
|
|
72
199
|
return true;
|
|
73
200
|
}
|
|
74
201
|
try {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
// and UserFeedback represent the owner's evaluation of an AI
|
|
82
|
-
// message and there is no per-user storage to overwrite.
|
|
83
|
-
if (this.dirtyRatingFieldNames().length > 0) {
|
|
84
|
-
this.recordDenied('Only the conversation owner can set or change the rating and feedback on this message.', resultType);
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
if (!decision.Allowed) {
|
|
88
|
-
this.recordDenied(decision.Reason ?? 'Permission denied.', resultType);
|
|
202
|
+
const access = await UserMayWriteConversation(provider, user, this.ConversationID);
|
|
203
|
+
const refusal = (await this.accessRefusal(provider, access))
|
|
204
|
+
?? (isSystemUser ? null : this.authorshipRefusal(operation, user, access.IsOwner))
|
|
205
|
+
?? this.replyRefusal(operation);
|
|
206
|
+
if (refusal) {
|
|
207
|
+
this.recordDenied(refusal, resultType);
|
|
89
208
|
return false;
|
|
90
209
|
}
|
|
91
210
|
return true;
|
|
@@ -100,18 +219,139 @@ let MJConversationDetailEntityExtended = class MJConversationDetailEntityExtende
|
|
|
100
219
|
}
|
|
101
220
|
}
|
|
102
221
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
222
|
+
* Why the user may not write to this message's conversation at all, or `null` when they may. The owner may. Anyone
|
|
223
|
+
* else may not change the rating fields, which are the owner's alone, and needs an `Edit` or `Owner` grant. A
|
|
224
|
+
* conversation that does not load for the user is hidden from them when it exists (a row filter), and they may not
|
|
225
|
+
* write to it; when no one can find it, it is missing or being created in this same transaction, and the foreign
|
|
226
|
+
* key and the base save decide, as before.
|
|
106
227
|
*/
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
228
|
+
async accessRefusal(provider, access) {
|
|
229
|
+
if (access.IsOwner) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
// Non-owners are *never* allowed to touch the rating fields, even
|
|
233
|
+
// when they hold Edit/Owner grants on the conversation. UserRating
|
|
234
|
+
// and UserFeedback represent the owner's evaluation of an AI
|
|
235
|
+
// message and there is no per-user storage to overwrite.
|
|
236
|
+
if (OWNER_ONLY_RATING_FIELDS.some((name) => this.isFieldDirty(name))) {
|
|
237
|
+
return 'Only the conversation owner can set or change the rating and feedback on this message.';
|
|
238
|
+
}
|
|
239
|
+
if (!access.Allowed) {
|
|
240
|
+
return access.Reason ?? 'Permission denied.';
|
|
241
|
+
}
|
|
242
|
+
if (!access.Loaded && (await this.conversationExists(provider))) {
|
|
243
|
+
return 'You do not have access to this conversation.';
|
|
244
|
+
}
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Why this write would put words in an agent's mouth, or `null` when it does not: an unmarked save that creates a
|
|
249
|
+
* reply, turns a message into one, or changes what one says ({@link REPLY_FIELDS}). Applies to every user, the
|
|
250
|
+
* system user included. Deleting a reply keeps the conversation-level rules.
|
|
251
|
+
*/
|
|
252
|
+
replyRefusal(operation) {
|
|
253
|
+
if (operation === 'delete' || this.serverAuthoredReply) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
if (!this.IsSaved) {
|
|
257
|
+
return isReplyRole(this.Role) ? REPLY_REFUSAL : null;
|
|
258
|
+
}
|
|
259
|
+
const touchesReply = isReplyRole(this.originalFieldText('Role')) || isReplyRole(this.Role);
|
|
260
|
+
return touchesReply && REPLY_FIELDS.some((name) => this.isFieldDirty(name)) ? REPLY_REFUSAL : null;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Why this write breaks the rules for people's messages (see the class doc), or `null` when it does not. On a new
|
|
264
|
+
* message from a grantee with no `UserID`, fills in the grantee's.
|
|
265
|
+
*/
|
|
266
|
+
authorshipRefusal(operation, user, isOwner) {
|
|
267
|
+
if (operation === 'delete') {
|
|
268
|
+
return this.deleteRefusal(user, isOwner);
|
|
269
|
+
}
|
|
270
|
+
return this.IsSaved ? this.changeRefusal(user, isOwner) : this.postRefusal(user, isOwner);
|
|
271
|
+
}
|
|
272
|
+
/** A new person's message names its author as the poster, or names no one (filled in for a grantee). */
|
|
273
|
+
postRefusal(user, isOwner) {
|
|
274
|
+
if (!isPersonRole(this.Role)) {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
if (!this.UserID) {
|
|
278
|
+
// An empty UserID reads as the conversation's owner. A grantee's message gets the grantee's ID; the
|
|
279
|
+
// owner's stays empty, so server code writing as the owner (a room transcript of what other people said)
|
|
280
|
+
// is not stamped with the owner's ID.
|
|
281
|
+
if (!isOwner) {
|
|
282
|
+
this.UserID = user.ID;
|
|
283
|
+
}
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
return UUIDsEqual(this.UserID, user.ID) ? null : 'You can post a message only as yourself.';
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* An existing person's message: only its author changes who wrote it and what it says, no one its role (to or
|
|
290
|
+
* from `User`), and no one moves it to another conversation or fork. A message with no `UserID` is the owner's.
|
|
291
|
+
*/
|
|
292
|
+
changeRefusal(user, isOwner) {
|
|
293
|
+
const wasPerson = isPersonRole(this.originalFieldText('Role'));
|
|
294
|
+
if (this.isFieldDirty('Role') && (wasPerson || isPersonRole(this.Role))) {
|
|
295
|
+
return "A message's role cannot be changed.";
|
|
296
|
+
}
|
|
297
|
+
if (!wasPerson) {
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
if (PLACEMENT_FIELDS.some((name) => this.isFieldDirty(name))) {
|
|
301
|
+
// Moving it would take it out of the thread it was written in (a delete) and put it in one its author never
|
|
302
|
+
// wrote in, and, with no UserID, make it read as another conversation's owner's.
|
|
303
|
+
return 'A message cannot be moved to another conversation or fork.';
|
|
304
|
+
}
|
|
305
|
+
const changed = AUTHORED_FIELDS.filter((name) => this.isFieldDirty(name));
|
|
306
|
+
if (changed.length === 0) {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
const author = this.originalFieldText('UserID') ?? (isOwner ? user.ID : null);
|
|
310
|
+
if (!author || !UUIDsEqual(author, user.ID)) {
|
|
311
|
+
return 'Only the person who wrote this message can change it.';
|
|
312
|
+
}
|
|
313
|
+
if (changed.includes('UserID') && !(this.UserID && UUIDsEqual(this.UserID, user.ID))) {
|
|
314
|
+
return 'You can post a message only as yourself.';
|
|
315
|
+
}
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
/** A person's message is deleted by its author or by the conversation's owner (whose it is with no `UserID`). */
|
|
319
|
+
deleteRefusal(user, isOwner) {
|
|
320
|
+
if (!isPersonRole(this.Role) || isOwner) {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
return this.UserID && UUIDsEqual(this.UserID, user.ID)
|
|
324
|
+
? null
|
|
325
|
+
: "Only the message's author or the conversation's owner can delete it.";
|
|
326
|
+
}
|
|
327
|
+
/** Whether the conversation exists, read as the system user; false when there is no system user to ask. */
|
|
328
|
+
async conversationExists(provider) {
|
|
329
|
+
const systemUser = await WellKnownUserSource.Instance.GetSystemUser(provider);
|
|
330
|
+
if (!systemUser) {
|
|
331
|
+
LogError(`MJConversationDetailEntityExtended: no system user to check whether conversation ${this.ConversationID} ` +
|
|
332
|
+
'exists; treating it as missing.');
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
const conversation = await provider.GetEntityObject('MJ: Conversations', systemUser);
|
|
336
|
+
return conversation.Load(this.ConversationID);
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Whether a transaction variable of this message's group sets one of `fields` on it. The field is resolved the way
|
|
340
|
+
* `Set` resolves it at submit (trimmed, any case).
|
|
341
|
+
*/
|
|
342
|
+
fieldSetByTransactionVariable(fields) {
|
|
343
|
+
return !!this.TransactionGroup?.Variables.some((v) => {
|
|
344
|
+
const name = v.EntityObject === this && v.Type === 'Use' ? this.GetFieldByName(v.FieldName)?.Name : null;
|
|
345
|
+
return !!name && fields.includes(name);
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
isFieldDirty(name) {
|
|
349
|
+
return !!this.GetFieldByName(name)?.Dirty;
|
|
350
|
+
}
|
|
351
|
+
/** A field's value as loaded, before this save's changes; `null` when it was empty or is not text. */
|
|
352
|
+
originalFieldText(name) {
|
|
353
|
+
const original = this.GetFieldByName(name)?.OldValue;
|
|
354
|
+
return typeof original === 'string' && original.length > 0 ? original : null;
|
|
115
355
|
}
|
|
116
356
|
/**
|
|
117
357
|
* Records WHY the write was refused as a NEW `ResultHistory` entry, so callers that read
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJConversationDetailEntityExtended.js","sourceRoot":"","sources":["../../src/custom/MJConversationDetailEntityExtended.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EACH,UAAU,EACV,gBAAgB,
|
|
1
|
+
{"version":3,"file":"MJConversationDetailEntityExtended.js","sourceRoot":"","sources":["../../src/custom/MJConversationDetailEntityExtended.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { UserInfo, QueryCacheConfig } from "@memberjunction/core";
|
|
1
|
+
import { UserInfo, QueryCacheConfig, EntityInfo, FieldSecurityViolation } from "@memberjunction/core";
|
|
2
|
+
import { SQLScreeningDialect } from "@memberjunction/global";
|
|
2
3
|
import { MJQueryEntity, MJQueryFieldEntity, MJQueryParameterEntity, MJQueryEntityEntity, MJQueryPermissionEntity, MJQueryDependencyEntity, MJQueryCategoryEntity } from "../generated/entity_subclasses.js";
|
|
3
4
|
import type { DatabasePlatform } from "@memberjunction/core";
|
|
4
5
|
/**
|
|
@@ -61,6 +62,41 @@ export declare class MJQueryEntityExtended extends MJQueryEntity {
|
|
|
61
62
|
canRun: boolean;
|
|
62
63
|
deniedEntities: string[];
|
|
63
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* SECURITY — the run-time half of {@link UserCanRun}: the checks that need the SQL a run will
|
|
67
|
+
* actually execute, after composition and template rendering. Call it with that SQL in addition
|
|
68
|
+
* to {@link UserCanRun}, never instead of it.
|
|
69
|
+
*
|
|
70
|
+
* 1. A query with `MJ: Query Permissions` rows is authorized by its role list alone: a user who
|
|
71
|
+
* holds one of those roles may run it whatever it reads (stored-procedure semantics), and one
|
|
72
|
+
* who holds none may not.
|
|
73
|
+
* 2. Otherwise every entity whose base view or base table the SQL reads as a relation must be
|
|
74
|
+
* readable by the user ({@link FieldSecuritySQLGate.RelationEntities}). These come from the
|
|
75
|
+
* SQL, so a query whose `QueryEntities` rows are missing or stale is still checked. SQL that
|
|
76
|
+
* cannot be read is refused for a user who cannot read every entity in the catalog.
|
|
77
|
+
* 3. The SQL must not reference a field the user is denied anywhere it could leak one: the
|
|
78
|
+
* select list, WHERE, JOIN, GROUP BY, ORDER BY or HAVING, inside expressions and aggregates
|
|
79
|
+
* included. A whole-row construct (`SELECT *`, `alias.*`) over an entity the user is denied a
|
|
80
|
+
* field on, and SQL that cannot be read, are refused too ({@link FieldSecuritySQLGate.FindViolation}).
|
|
81
|
+
* So is a relation that is not a CTE or a catalog entity's base view or base table (a custom
|
|
82
|
+
* view, synonym, table-valued function, temp table or cross-database name), whose reads
|
|
83
|
+
* cannot be checked. A user denied no field on any entity is not scanned.
|
|
84
|
+
*
|
|
85
|
+
* The result never names a denied field, so a refusal says only that the query cannot be run.
|
|
86
|
+
* `QueryFields` metadata plays no part: it is documentation, not a security source.
|
|
87
|
+
*
|
|
88
|
+
* @param user The user the query runs for
|
|
89
|
+
* @param renderedSQL The SQL the run will execute
|
|
90
|
+
* @param catalog Every entity the executing provider knows
|
|
91
|
+
* @param dialect The database dialect the SQL runs under
|
|
92
|
+
*/
|
|
93
|
+
UserCanRunRenderedSQL(user: UserInfo, renderedSQL: string, catalog: readonly EntityInfo[], dialect: SQLScreeningDialect): {
|
|
94
|
+
canRun: boolean;
|
|
95
|
+
deniedEntities: string[];
|
|
96
|
+
fieldSecurityViolation?: FieldSecurityViolation;
|
|
97
|
+
};
|
|
98
|
+
/** The catalog entities this query's `QueryEntities` rows name; stale rows are left out. */
|
|
99
|
+
private declaredEntities;
|
|
64
100
|
/** Whether this query has been formally approved for production use */
|
|
65
101
|
get IsApproved(): boolean;
|
|
66
102
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJQueryEntityExtended.d.ts","sourceRoot":"","sources":["../../src/custom/MJQueryEntityExtended.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,QAAQ,EAAE,gBAAgB,EAAqB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"MJQueryEntityExtended.d.ts","sourceRoot":"","sources":["../../src/custom/MJQueryEntityExtended.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,QAAQ,EAAE,gBAAgB,EAAqB,UAAU,EAAwB,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC3J,OAAO,EAA0C,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACrG,OAAO,EACH,aAAa,EACb,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,qBAAqB,EACxB,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;;;;;;GAOG;AACH,qBACa,qBAAsB,SAAQ,aAAa;IAIpD,2CAA2C;IAC3C,IAAW,WAAW,IAAI,kBAAkB,EAAE,CAE7C;IAED,+CAA+C;IAC/C,IAAW,eAAe,IAAI,sBAAsB,EAAE,CAErD;IAED,6CAA6C;IAC7C,IAAW,aAAa,IAAI,mBAAmB,EAAE,CAEhD;IAED,4CAA4C;IAC5C,IAAW,gBAAgB,IAAI,uBAAuB,EAAE,CAEvD;IAED,oGAAoG;IACpG,IAAW,iBAAiB,IAAI,uBAAuB,EAAE,CAExD;IAED,+EAA+E;IAC/E,IAAW,eAAe,IAAI,uBAAuB,EAAE,CAEtD;IAID,6EAA6E;IAC7E,IAAW,cAAc,IAAI,qBAAqB,GAAG,SAAS,CAG7D;IAED,OAAO,CAAC,aAAa,CAAuB;IAE5C;;;OAGG;IACH,IAAW,YAAY,IAAI,MAAM,CAKhC;IAED;;OAEG;IACI,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAmBpD;;;;;OAKG;IACI,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO;IAkBrD;;;;;;;;;;;;;;;OAeG;IACI,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,MAAM,EAAE,CAAA;KAAE;IA2ExG;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACI,qBAAqB,CACxB,IAAI,EAAE,QAAQ,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,OAAO,EAAE,mBAAmB,GAC7B;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,MAAM,EAAE,CAAC;QAAC,sBAAsB,CAAC,EAAE,sBAAsB,CAAA;KAAE;IA0BjG,4FAA4F;IAC5F,OAAO,CAAC,gBAAgB;IAcxB,uEAAuE;IACvE,IAAW,UAAU,IAAI,OAAO,CAE/B;IAED;;;OAGG;IACH,IAAW,YAAY,IAAI,OAAO,CAEjC;IAID;;;;;OAKG;IACI,cAAc,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM;IAgBzD,OAAO,CAAC,YAAY,CAAiC;IAErD;;;;OAIG;IACH,IAAW,WAAW,IAAI,gBAAgB,CAuBzC;IAED,OAAO,CAAC,uBAAuB;CAqBlC"}
|