@contextableai/openclaw-memory-rebac 0.1.0 → 0.1.2
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/authorization.d.ts +57 -0
- package/dist/authorization.js +133 -0
- package/dist/backend.d.ts +135 -0
- package/dist/backend.js +11 -0
- package/dist/backends/graphiti.d.ts +72 -0
- package/dist/backends/graphiti.js +222 -0
- package/dist/backends/registry.d.ts +14 -0
- package/dist/backends/registry.js +12 -0
- package/dist/cli.d.ts +23 -0
- package/dist/cli.js +446 -0
- package/dist/config.d.ts +34 -0
- package/dist/config.js +97 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +638 -0
- package/dist/plugin.defaults.json +12 -0
- package/dist/search.d.ts +34 -0
- package/dist/search.js +98 -0
- package/dist/spicedb.d.ts +80 -0
- package/dist/spicedb.js +267 -0
- package/docker/graphiti/.env +50 -0
- package/docker/graphiti/docker-compose.yml +2 -2
- package/docker/graphiti/graphiti_overlay.py +26 -1
- package/docker/graphiti/startup.py +61 -4
- package/docker/spicedb/.env +14 -0
- package/package.json +8 -11
- package/authorization.ts +0 -191
- package/backend.ts +0 -176
- package/backends/backends.json +0 -3
- package/backends/graphiti.test.ts +0 -292
- package/backends/graphiti.ts +0 -345
- package/backends/registry.ts +0 -36
- package/cli.ts +0 -418
- package/config.ts +0 -141
- package/index.ts +0 -711
- package/search.ts +0 -139
- package/spicedb.ts +0 -355
- /package/{backends → dist/backends}/graphiti.defaults.json +0 -0
package/search.ts
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parallel Multi-Group Search + Merge/Re-rank
|
|
3
|
-
*
|
|
4
|
-
* Backend-agnostic: delegates per-group search to MemoryBackend.searchGroup().
|
|
5
|
-
* Issues parallel calls (one per authorized group_id), merges results,
|
|
6
|
-
* deduplicates by UUID, and re-ranks by score then recency.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { MemoryBackend, SearchResult } from "./backend.js";
|
|
10
|
-
|
|
11
|
-
export type { SearchResult };
|
|
12
|
-
|
|
13
|
-
// ============================================================================
|
|
14
|
-
// Search options
|
|
15
|
-
// ============================================================================
|
|
16
|
-
|
|
17
|
-
export type SearchOptions = {
|
|
18
|
-
query: string;
|
|
19
|
-
groupIds: string[];
|
|
20
|
-
limit?: number;
|
|
21
|
-
sessionId?: string;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// ============================================================================
|
|
25
|
-
// Search
|
|
26
|
-
// ============================================================================
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Search across multiple authorized group_ids in parallel.
|
|
30
|
-
* Merges and deduplicates results, returning up to `limit` items sorted by
|
|
31
|
-
* score (desc) then recency (desc).
|
|
32
|
-
*/
|
|
33
|
-
export async function searchAuthorizedMemories(
|
|
34
|
-
backend: MemoryBackend,
|
|
35
|
-
options: SearchOptions,
|
|
36
|
-
): Promise<SearchResult[]> {
|
|
37
|
-
const { query, groupIds, limit = 10, sessionId } = options;
|
|
38
|
-
|
|
39
|
-
if (groupIds.length === 0) {
|
|
40
|
-
return [];
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Fan out parallel searches across all authorized groups
|
|
44
|
-
const promises = groupIds.map((groupId) =>
|
|
45
|
-
backend.searchGroup({ query, groupId, limit, sessionId }),
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
const resultSets = await Promise.allSettled(promises);
|
|
49
|
-
|
|
50
|
-
// Collect all successful results — silently skip failed group searches
|
|
51
|
-
const allResults: SearchResult[] = [];
|
|
52
|
-
for (const result of resultSets) {
|
|
53
|
-
if (result.status === "fulfilled") {
|
|
54
|
-
allResults.push(...result.value);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Deduplicate by UUID
|
|
59
|
-
const seen = new Set<string>();
|
|
60
|
-
const deduped = allResults.filter((r) => {
|
|
61
|
-
if (seen.has(r.uuid)) return false;
|
|
62
|
-
seen.add(r.uuid);
|
|
63
|
-
return true;
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Sort: score descending (when available), then recency descending
|
|
67
|
-
deduped.sort((a, b) => {
|
|
68
|
-
if (a.score !== undefined && b.score !== undefined && a.score !== b.score) {
|
|
69
|
-
return b.score - a.score;
|
|
70
|
-
}
|
|
71
|
-
const dateA = new Date(a.created_at).getTime();
|
|
72
|
-
const dateB = new Date(b.created_at).getTime();
|
|
73
|
-
return dateB - dateA;
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
return deduped.slice(0, limit);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// ============================================================================
|
|
80
|
-
// Format for agent context
|
|
81
|
-
// ============================================================================
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Format search results into a text block for injecting into agent context.
|
|
85
|
-
*/
|
|
86
|
-
export function formatResultsForContext(results: SearchResult[]): string {
|
|
87
|
-
if (results.length === 0) return "";
|
|
88
|
-
return results.map((r, i) => formatResultLine(r, i + 1)).join("\n");
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Format results with long-term and session sections separated.
|
|
93
|
-
* Session group_ids start with "session-".
|
|
94
|
-
*/
|
|
95
|
-
export function formatDualResults(
|
|
96
|
-
longTermResults: SearchResult[],
|
|
97
|
-
sessionResults: SearchResult[],
|
|
98
|
-
): string {
|
|
99
|
-
const parts: string[] = [];
|
|
100
|
-
let idx = 1;
|
|
101
|
-
|
|
102
|
-
for (const r of longTermResults) {
|
|
103
|
-
parts.push(formatResultLine(r, idx++));
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (sessionResults.length > 0) {
|
|
107
|
-
if (longTermResults.length > 0) parts.push("Session memories:");
|
|
108
|
-
for (const r of sessionResults) {
|
|
109
|
-
parts.push(formatResultLine(r, idx++));
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return parts.join("\n");
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Format a single search result line with type-prefixed UUID.
|
|
118
|
-
* e.g. "[fact:da8650cb-...] Eric's birthday is Dec 17th (Eric -[HAS_BIRTHDAY]→ Dec 17th)"
|
|
119
|
-
*/
|
|
120
|
-
function formatResultLine(r: SearchResult, idx: number): string {
|
|
121
|
-
const typeLabel =
|
|
122
|
-
r.type === "node" ? "entity" :
|
|
123
|
-
r.type === "fact" ? "fact" :
|
|
124
|
-
r.type === "chunk" ? "chunk" :
|
|
125
|
-
r.type === "summary" ? "summary" :
|
|
126
|
-
"completion";
|
|
127
|
-
return `${idx}. [${typeLabel}:${r.uuid}] ${r.summary} (${r.context})`;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Deduplicate session results against long-term results (by UUID).
|
|
132
|
-
*/
|
|
133
|
-
export function deduplicateSessionResults(
|
|
134
|
-
longTermResults: SearchResult[],
|
|
135
|
-
sessionResults: SearchResult[],
|
|
136
|
-
): SearchResult[] {
|
|
137
|
-
const longTermIds = new Set(longTermResults.map((r) => r.uuid));
|
|
138
|
-
return sessionResults.filter((r) => !longTermIds.has(r.uuid));
|
|
139
|
-
}
|
package/spicedb.ts
DELETED
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SpiceDB Client Wrapper
|
|
3
|
-
*
|
|
4
|
-
* Wraps @authzed/authzed-node for authorization operations:
|
|
5
|
-
* WriteSchema, WriteRelationships, DeleteRelationships, BulkImportRelationships,
|
|
6
|
-
* LookupResources, CheckPermission.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { v1 } from "@authzed/authzed-node";
|
|
10
|
-
|
|
11
|
-
// ============================================================================
|
|
12
|
-
// Types
|
|
13
|
-
// ============================================================================
|
|
14
|
-
|
|
15
|
-
export type SpiceDbConfig = {
|
|
16
|
-
endpoint: string;
|
|
17
|
-
token: string;
|
|
18
|
-
insecure: boolean;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export type RelationshipTuple = {
|
|
22
|
-
resourceType: string;
|
|
23
|
-
resourceId: string;
|
|
24
|
-
relation: string;
|
|
25
|
-
subjectType: string;
|
|
26
|
-
subjectId: string;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export type ConsistencyMode =
|
|
30
|
-
| { mode: "full" }
|
|
31
|
-
| { mode: "at_least_as_fresh"; token: string }
|
|
32
|
-
| { mode: "minimize_latency" };
|
|
33
|
-
|
|
34
|
-
// ============================================================================
|
|
35
|
-
// Client
|
|
36
|
-
// ============================================================================
|
|
37
|
-
|
|
38
|
-
export class SpiceDbClient {
|
|
39
|
-
private client: ReturnType<typeof v1.NewClient>;
|
|
40
|
-
private promises: ReturnType<typeof v1.NewClient>["promises"];
|
|
41
|
-
|
|
42
|
-
constructor(config: SpiceDbConfig) {
|
|
43
|
-
if (config.insecure) {
|
|
44
|
-
this.client = v1.NewClient(
|
|
45
|
-
config.token,
|
|
46
|
-
config.endpoint,
|
|
47
|
-
v1.ClientSecurity.INSECURE_PLAINTEXT_CREDENTIALS,
|
|
48
|
-
);
|
|
49
|
-
} else {
|
|
50
|
-
this.client = v1.NewClient(config.token, config.endpoint);
|
|
51
|
-
}
|
|
52
|
-
this.promises = this.client.promises;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// --------------------------------------------------------------------------
|
|
56
|
-
// Schema
|
|
57
|
-
// --------------------------------------------------------------------------
|
|
58
|
-
|
|
59
|
-
async writeSchema(schema: string): Promise<void> {
|
|
60
|
-
const request = v1.WriteSchemaRequest.create({ schema });
|
|
61
|
-
await this.promises.writeSchema(request);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async readSchema(): Promise<string> {
|
|
65
|
-
const request = v1.ReadSchemaRequest.create({});
|
|
66
|
-
const response = await this.promises.readSchema(request);
|
|
67
|
-
return response.schemaText;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// --------------------------------------------------------------------------
|
|
71
|
-
// Relationships
|
|
72
|
-
// --------------------------------------------------------------------------
|
|
73
|
-
|
|
74
|
-
async writeRelationships(tuples: RelationshipTuple[]): Promise<string | undefined> {
|
|
75
|
-
const updates = tuples.map((t) =>
|
|
76
|
-
v1.RelationshipUpdate.create({
|
|
77
|
-
operation: v1.RelationshipUpdate_Operation.TOUCH,
|
|
78
|
-
relationship: v1.Relationship.create({
|
|
79
|
-
resource: v1.ObjectReference.create({
|
|
80
|
-
objectType: t.resourceType,
|
|
81
|
-
objectId: t.resourceId,
|
|
82
|
-
}),
|
|
83
|
-
relation: t.relation,
|
|
84
|
-
subject: v1.SubjectReference.create({
|
|
85
|
-
object: v1.ObjectReference.create({
|
|
86
|
-
objectType: t.subjectType,
|
|
87
|
-
objectId: t.subjectId,
|
|
88
|
-
}),
|
|
89
|
-
}),
|
|
90
|
-
}),
|
|
91
|
-
}),
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
const request = v1.WriteRelationshipsRequest.create({ updates });
|
|
95
|
-
const response = await this.promises.writeRelationships(request);
|
|
96
|
-
return response.writtenAt?.token;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async deleteRelationships(tuples: RelationshipTuple[]): Promise<void> {
|
|
100
|
-
const updates = tuples.map((t) =>
|
|
101
|
-
v1.RelationshipUpdate.create({
|
|
102
|
-
operation: v1.RelationshipUpdate_Operation.DELETE,
|
|
103
|
-
relationship: v1.Relationship.create({
|
|
104
|
-
resource: v1.ObjectReference.create({
|
|
105
|
-
objectType: t.resourceType,
|
|
106
|
-
objectId: t.resourceId,
|
|
107
|
-
}),
|
|
108
|
-
relation: t.relation,
|
|
109
|
-
subject: v1.SubjectReference.create({
|
|
110
|
-
object: v1.ObjectReference.create({
|
|
111
|
-
objectType: t.subjectType,
|
|
112
|
-
objectId: t.subjectId,
|
|
113
|
-
}),
|
|
114
|
-
}),
|
|
115
|
-
}),
|
|
116
|
-
}),
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
const request = v1.WriteRelationshipsRequest.create({ updates });
|
|
120
|
-
await this.promises.writeRelationships(request);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async deleteRelationshipsByFilter(params: {
|
|
124
|
-
resourceType: string;
|
|
125
|
-
resourceId: string;
|
|
126
|
-
relation?: string;
|
|
127
|
-
}): Promise<string | undefined> {
|
|
128
|
-
const request = v1.DeleteRelationshipsRequest.create({
|
|
129
|
-
relationshipFilter: v1.RelationshipFilter.create({
|
|
130
|
-
resourceType: params.resourceType,
|
|
131
|
-
optionalResourceId: params.resourceId,
|
|
132
|
-
...(params.relation ? { optionalRelation: params.relation } : {}),
|
|
133
|
-
}),
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
const response = await this.promises.deleteRelationships(request);
|
|
137
|
-
return response.deletedAt?.token;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// --------------------------------------------------------------------------
|
|
141
|
-
// Bulk Import
|
|
142
|
-
// --------------------------------------------------------------------------
|
|
143
|
-
|
|
144
|
-
private toRelationship(t: RelationshipTuple) {
|
|
145
|
-
return v1.Relationship.create({
|
|
146
|
-
resource: v1.ObjectReference.create({
|
|
147
|
-
objectType: t.resourceType,
|
|
148
|
-
objectId: t.resourceId,
|
|
149
|
-
}),
|
|
150
|
-
relation: t.relation,
|
|
151
|
-
subject: v1.SubjectReference.create({
|
|
152
|
-
object: v1.ObjectReference.create({
|
|
153
|
-
objectType: t.subjectType,
|
|
154
|
-
objectId: t.subjectId,
|
|
155
|
-
}),
|
|
156
|
-
}),
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Bulk import relationships using the streaming ImportBulkRelationships RPC.
|
|
162
|
-
* More efficient than individual writeRelationships calls for large batches.
|
|
163
|
-
* Falls back to batched writeRelationships if the streaming RPC is unavailable.
|
|
164
|
-
*/
|
|
165
|
-
async bulkImportRelationships(
|
|
166
|
-
tuples: RelationshipTuple[],
|
|
167
|
-
batchSize = 1000,
|
|
168
|
-
): Promise<number> {
|
|
169
|
-
if (tuples.length === 0) return 0;
|
|
170
|
-
|
|
171
|
-
// Try streaming bulk import first
|
|
172
|
-
if (typeof this.promises.bulkImportRelationships === "function") {
|
|
173
|
-
return this.bulkImportViaStream(tuples, batchSize);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Fallback: batched writeRelationships
|
|
177
|
-
return this.bulkImportViaWrite(tuples, batchSize);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
private bulkImportViaStream(
|
|
181
|
-
tuples: RelationshipTuple[],
|
|
182
|
-
batchSize: number,
|
|
183
|
-
): Promise<number> {
|
|
184
|
-
return new Promise((resolve, reject) => {
|
|
185
|
-
const stream = this.promises.bulkImportRelationships(
|
|
186
|
-
(err: Error | null, response?: { numLoaded?: string }) => {
|
|
187
|
-
if (err) reject(err);
|
|
188
|
-
else resolve(Number(response?.numLoaded ?? tuples.length));
|
|
189
|
-
},
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
stream.on("error", (err: Error) => {
|
|
193
|
-
reject(err);
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
for (let i = 0; i < tuples.length; i += batchSize) {
|
|
197
|
-
const chunk = tuples.slice(i, i + batchSize);
|
|
198
|
-
stream.write(
|
|
199
|
-
v1.BulkImportRelationshipsRequest.create({
|
|
200
|
-
relationships: chunk.map((t) => this.toRelationship(t)),
|
|
201
|
-
}),
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
stream.end();
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
private async bulkImportViaWrite(
|
|
210
|
-
tuples: RelationshipTuple[],
|
|
211
|
-
batchSize: number,
|
|
212
|
-
): Promise<number> {
|
|
213
|
-
let total = 0;
|
|
214
|
-
for (let i = 0; i < tuples.length; i += batchSize) {
|
|
215
|
-
const chunk = tuples.slice(i, i + batchSize);
|
|
216
|
-
await this.writeRelationships(chunk);
|
|
217
|
-
total += chunk.length;
|
|
218
|
-
}
|
|
219
|
-
return total;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// --------------------------------------------------------------------------
|
|
223
|
-
// Read Relationships
|
|
224
|
-
// --------------------------------------------------------------------------
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Read relationships matching a filter. Returns all tuples that match the
|
|
228
|
-
* specified resource type, optional resource ID, optional relation, and
|
|
229
|
-
* optional subject filter. Used by the cleanup command to find which
|
|
230
|
-
* Graphiti episodes have SpiceDB authorization relationships.
|
|
231
|
-
*/
|
|
232
|
-
async readRelationships(params: {
|
|
233
|
-
resourceType: string;
|
|
234
|
-
resourceId?: string;
|
|
235
|
-
relation?: string;
|
|
236
|
-
subjectType?: string;
|
|
237
|
-
subjectId?: string;
|
|
238
|
-
consistency?: ConsistencyMode;
|
|
239
|
-
}): Promise<RelationshipTuple[]> {
|
|
240
|
-
const filterFields: Record<string, unknown> = {
|
|
241
|
-
resourceType: params.resourceType,
|
|
242
|
-
};
|
|
243
|
-
if (params.resourceId) {
|
|
244
|
-
filterFields.optionalResourceId = params.resourceId;
|
|
245
|
-
}
|
|
246
|
-
if (params.relation) {
|
|
247
|
-
filterFields.optionalRelation = params.relation;
|
|
248
|
-
}
|
|
249
|
-
if (params.subjectType) {
|
|
250
|
-
const subjectFilter: Record<string, unknown> = {
|
|
251
|
-
subjectType: params.subjectType,
|
|
252
|
-
};
|
|
253
|
-
if (params.subjectId) {
|
|
254
|
-
subjectFilter.optionalSubjectId = params.subjectId;
|
|
255
|
-
}
|
|
256
|
-
filterFields.optionalSubjectFilter = v1.SubjectFilter.create(subjectFilter);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const request = v1.ReadRelationshipsRequest.create({
|
|
260
|
-
relationshipFilter: v1.RelationshipFilter.create(filterFields),
|
|
261
|
-
consistency: this.buildConsistency(params.consistency),
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
const results = await this.promises.readRelationships(request);
|
|
265
|
-
const tuples: RelationshipTuple[] = [];
|
|
266
|
-
for (const r of results) {
|
|
267
|
-
const rel = r.relationship;
|
|
268
|
-
if (!rel?.resource || !rel.subject?.object) continue;
|
|
269
|
-
tuples.push({
|
|
270
|
-
resourceType: rel.resource.objectType,
|
|
271
|
-
resourceId: rel.resource.objectId,
|
|
272
|
-
relation: rel.relation,
|
|
273
|
-
subjectType: rel.subject.object.objectType,
|
|
274
|
-
subjectId: rel.subject.object.objectId,
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
return tuples;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// --------------------------------------------------------------------------
|
|
281
|
-
// Permissions
|
|
282
|
-
// --------------------------------------------------------------------------
|
|
283
|
-
|
|
284
|
-
private buildConsistency(mode?: ConsistencyMode) {
|
|
285
|
-
if (!mode || mode.mode === "minimize_latency") {
|
|
286
|
-
return v1.Consistency.create({
|
|
287
|
-
requirement: { oneofKind: "minimizeLatency", minimizeLatency: true },
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
if (mode.mode === "at_least_as_fresh") {
|
|
291
|
-
return v1.Consistency.create({
|
|
292
|
-
requirement: {
|
|
293
|
-
oneofKind: "atLeastAsFresh",
|
|
294
|
-
atLeastAsFresh: v1.ZedToken.create({ token: mode.token }),
|
|
295
|
-
},
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
return v1.Consistency.create({
|
|
299
|
-
requirement: { oneofKind: "fullyConsistent", fullyConsistent: true },
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
async checkPermission(params: {
|
|
304
|
-
resourceType: string;
|
|
305
|
-
resourceId: string;
|
|
306
|
-
permission: string;
|
|
307
|
-
subjectType: string;
|
|
308
|
-
subjectId: string;
|
|
309
|
-
consistency?: ConsistencyMode;
|
|
310
|
-
}): Promise<boolean> {
|
|
311
|
-
const request = v1.CheckPermissionRequest.create({
|
|
312
|
-
resource: v1.ObjectReference.create({
|
|
313
|
-
objectType: params.resourceType,
|
|
314
|
-
objectId: params.resourceId,
|
|
315
|
-
}),
|
|
316
|
-
permission: params.permission,
|
|
317
|
-
subject: v1.SubjectReference.create({
|
|
318
|
-
object: v1.ObjectReference.create({
|
|
319
|
-
objectType: params.subjectType,
|
|
320
|
-
objectId: params.subjectId,
|
|
321
|
-
}),
|
|
322
|
-
}),
|
|
323
|
-
consistency: this.buildConsistency(params.consistency),
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
const response = await this.promises.checkPermission(request);
|
|
327
|
-
return (
|
|
328
|
-
response.permissionship ===
|
|
329
|
-
v1.CheckPermissionResponse_Permissionship.HAS_PERMISSION
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
async lookupResources(params: {
|
|
334
|
-
resourceType: string;
|
|
335
|
-
permission: string;
|
|
336
|
-
subjectType: string;
|
|
337
|
-
subjectId: string;
|
|
338
|
-
consistency?: ConsistencyMode;
|
|
339
|
-
}): Promise<string[]> {
|
|
340
|
-
const request = v1.LookupResourcesRequest.create({
|
|
341
|
-
resourceObjectType: params.resourceType,
|
|
342
|
-
permission: params.permission,
|
|
343
|
-
subject: v1.SubjectReference.create({
|
|
344
|
-
object: v1.ObjectReference.create({
|
|
345
|
-
objectType: params.subjectType,
|
|
346
|
-
objectId: params.subjectId,
|
|
347
|
-
}),
|
|
348
|
-
}),
|
|
349
|
-
consistency: this.buildConsistency(params.consistency),
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
const results = await this.promises.lookupResources(request);
|
|
353
|
-
return results.map((r: { resourceObjectId: string }) => r.resourceObjectId);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
File without changes
|