@api-client/core 0.5.8 → 0.5.11
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/build/browser.d.ts +2 -0
- package/build/browser.js +2 -0
- package/build/browser.js.map +1 -1
- package/build/index.d.ts +2 -0
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/src/lib/calculators/DataCalculator.d.ts +3 -3
- package/build/src/lib/calculators/DataCalculator.js +3 -3
- package/build/src/lib/calculators/DataCalculator.js.map +1 -1
- package/build/src/lib/events/Utils.d.ts +1 -0
- package/build/src/lib/events/Utils.js +6 -0
- package/build/src/lib/events/Utils.js.map +1 -0
- package/build/src/lib/parsers/UriTemplate.d.ts +94 -0
- package/build/src/lib/parsers/UriTemplate.js +419 -0
- package/build/src/lib/parsers/UriTemplate.js.map +1 -0
- package/build/src/lib/parsers/UrlEncoder.d.ts +5 -0
- package/build/src/lib/parsers/UrlEncoder.js +49 -0
- package/build/src/lib/parsers/UrlEncoder.js.map +1 -1
- package/build/src/models/Environment.js +1 -0
- package/build/src/models/Environment.js.map +1 -1
- package/build/src/models/HttpProject.d.ts +4 -1
- package/build/src/models/HttpProject.js +9 -6
- package/build/src/models/HttpProject.js.map +1 -1
- package/build/src/models/ProjectParent.d.ts +9 -0
- package/build/src/models/ProjectParent.js +25 -0
- package/build/src/models/ProjectParent.js.map +1 -1
- package/build/src/models/Property.d.ts +8 -0
- package/build/src/models/Property.js +17 -0
- package/build/src/models/Property.js.map +1 -1
- package/build/src/models/Request.js +1 -1
- package/build/src/models/Request.js.map +1 -1
- package/build/src/models/RequestAuthorization.js +2 -1
- package/build/src/models/RequestAuthorization.js.map +1 -1
- package/build/src/models/Server.d.ts +14 -1
- package/build/src/models/Server.js +31 -1
- package/build/src/models/Server.js.map +1 -1
- package/build/src/models/store/Capabilities.d.ts +1 -1
- package/build/src/models/store/File.d.ts +59 -8
- package/build/src/models/store/File.js +144 -27
- package/build/src/models/store/File.js.map +1 -1
- package/build/src/models/store/Permission.d.ts +16 -1
- package/build/src/models/store/Permission.js +27 -1
- package/build/src/models/store/Permission.js.map +1 -1
- package/build/src/runtime/actions/runnable/DeleteCookieRunnable.d.ts +1 -1
- package/build/src/runtime/actions/runnable/SetCookieRunnable.d.ts +1 -1
- package/build/src/runtime/actions/runnable/SetVariableRunnable.d.ts +1 -1
- package/build/src/runtime/http-engine/CoreEngine.d.ts +1 -1
- package/build/src/runtime/store/FilesSdk.d.ts +16 -0
- package/build/src/runtime/store/FilesSdk.js +53 -0
- package/build/src/runtime/store/FilesSdk.js.map +1 -1
- package/build/src/runtime/store/RouteBuilder.d.ts +4 -0
- package/build/src/runtime/store/RouteBuilder.js +6 -0
- package/build/src/runtime/store/RouteBuilder.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/calculators/DataCalculator.ts +3 -3
- package/src/lib/events/Utils.ts +5 -0
- package/src/lib/parsers/UriTemplate.ts +494 -0
- package/src/lib/parsers/UrlEncoder.ts +51 -0
- package/src/models/Environment.ts +1 -0
- package/src/models/HttpProject.ts +10 -7
- package/src/models/ProjectParent.ts +27 -0
- package/src/models/Property.ts +18 -0
- package/src/models/Request.ts +1 -1
- package/src/models/RequestAuthorization.ts +2 -1
- package/src/models/Server.ts +32 -1
- package/src/models/store/Capabilities.ts +1 -1
- package/src/models/store/File.ts +169 -28
- package/src/models/store/Permission.ts +30 -2
- package/src/runtime/actions/runnable/DeleteCookieRunnable.ts +1 -1
- package/src/runtime/actions/runnable/SetCookieRunnable.ts +1 -1
- package/src/runtime/actions/runnable/SetVariableRunnable.ts +1 -1
- package/src/runtime/http-engine/CoreEngine.ts +1 -1
- package/src/runtime/store/FilesSdk.ts +54 -0
- package/src/runtime/store/RouteBuilder.ts +7 -0
|
@@ -101,9 +101,10 @@ export class RequestAuthorization {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
toJSON(): IRequestAuthorization {
|
|
104
|
+
const { config={} } = this;
|
|
104
105
|
const result:IRequestAuthorization = {
|
|
105
106
|
kind: Kind,
|
|
106
|
-
config:
|
|
107
|
+
config: { ...config },
|
|
107
108
|
enabled: this.enabled || false,
|
|
108
109
|
type: this.type || '' as AuthorizationType,
|
|
109
110
|
valid: this.valid || true,
|
package/src/models/Server.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { IProperty, Property } from './Property.js';
|
|
2
|
+
import { UriTemplate } from '../lib/parsers/UriTemplate.js';
|
|
3
|
+
|
|
1
4
|
export const Kind = 'Core#Server';
|
|
2
5
|
|
|
3
6
|
export interface IServer {
|
|
@@ -129,8 +132,10 @@ export class Server {
|
|
|
129
132
|
|
|
130
133
|
/**
|
|
131
134
|
* Constructs the final URI from the server configuration.
|
|
135
|
+
*
|
|
136
|
+
* @param variables When set it evaluates the generated URI against these variables
|
|
132
137
|
*/
|
|
133
|
-
readUri(): string {
|
|
138
|
+
readUri(variables?: (IProperty | Property)[]): string {
|
|
134
139
|
const { uri, protocol, basePath } = this;
|
|
135
140
|
let result = '';
|
|
136
141
|
if (!uri) {
|
|
@@ -148,6 +153,32 @@ export class Server {
|
|
|
148
153
|
}
|
|
149
154
|
result += basePath.startsWith('/') ? basePath : `/${basePath}`
|
|
150
155
|
}
|
|
156
|
+
if (variables) {
|
|
157
|
+
return this.evaluateUri(result, variables);
|
|
158
|
+
}
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Evaluates the URI against the variables.
|
|
164
|
+
*
|
|
165
|
+
* Note, this doesn't throw errors. When error occurs it returns the input string.
|
|
166
|
+
*
|
|
167
|
+
* @param uri The URI to process
|
|
168
|
+
* @param variables The list of variables to use
|
|
169
|
+
* @returns Expanded URI.
|
|
170
|
+
*/
|
|
171
|
+
protected evaluateUri(uri: string, variables: (IProperty | Property)[]): string {
|
|
172
|
+
if (!variables || !variables.length) {
|
|
173
|
+
return uri;
|
|
174
|
+
}
|
|
175
|
+
let result = uri;
|
|
176
|
+
try {
|
|
177
|
+
const map = Property.toMap(variables);
|
|
178
|
+
result = new UriTemplate(uri).expand(map, { ignoreMissing: true });
|
|
179
|
+
} catch (e) {
|
|
180
|
+
//
|
|
181
|
+
}
|
|
151
182
|
return result;
|
|
152
183
|
}
|
|
153
184
|
}
|
|
@@ -46,7 +46,7 @@ export interface ICapabilities {
|
|
|
46
46
|
*/
|
|
47
47
|
canAddChildren: boolean;
|
|
48
48
|
/**
|
|
49
|
-
* Whether the user can delete the file.
|
|
49
|
+
* Whether the user can permanently delete the file.
|
|
50
50
|
*
|
|
51
51
|
* The permission to edit can be inherited from a containing space so not visible
|
|
52
52
|
* in the file's permissions.
|
package/src/models/store/File.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IPermission } from './Permission.js';
|
|
1
|
+
import { IPermission, Permission, PermissionRole } from './Permission.js';
|
|
2
2
|
import { IModification } from './Modification.js';
|
|
3
3
|
import { IDeletion } from './Deletion.js';
|
|
4
4
|
import { IUser, Kind as UserKind } from './User.js';
|
|
@@ -64,6 +64,11 @@ export interface IStoredFile {
|
|
|
64
64
|
* This is a readonly field and it is ignored when creating / updating the file.
|
|
65
65
|
*/
|
|
66
66
|
capabilities?: ICapabilities;
|
|
67
|
+
/**
|
|
68
|
+
* The color of the icon to render for this file in the file explorer.
|
|
69
|
+
* This should be a hex format, e.g.: #c00 for red.
|
|
70
|
+
*/
|
|
71
|
+
iconColor?: string;
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
/**
|
|
@@ -83,6 +88,15 @@ export interface IFile extends IStoredFile {
|
|
|
83
88
|
permissions: IPermission[];
|
|
84
89
|
}
|
|
85
90
|
|
|
91
|
+
const parentsSymbol = Symbol('parents');
|
|
92
|
+
const deletedSymbol = Symbol('deleted');
|
|
93
|
+
const deletedInfoSymbol = Symbol('deletedInfo');
|
|
94
|
+
const ownerSymbol = Symbol('owner');
|
|
95
|
+
const lastModifiedSymbol = Symbol('lastModified');
|
|
96
|
+
const capabilitiesSymbol = Symbol('capabilities');
|
|
97
|
+
const permissionsSymbol = Symbol('permissions');
|
|
98
|
+
const permissionIdsSymbol = Symbol('permissionIds');
|
|
99
|
+
|
|
86
100
|
export class StoredFile {
|
|
87
101
|
/**
|
|
88
102
|
* The kind of the File
|
|
@@ -96,6 +110,9 @@ export class StoredFile {
|
|
|
96
110
|
* The name of the environment.
|
|
97
111
|
*/
|
|
98
112
|
info: Thing = Thing.fromName('');
|
|
113
|
+
|
|
114
|
+
[parentsSymbol]: string[] = [];
|
|
115
|
+
|
|
99
116
|
/**
|
|
100
117
|
* The list of parents of the object. It is an ordered list of parents
|
|
101
118
|
* from the top (first element) to the lowest parent in the tree (last element).
|
|
@@ -103,39 +120,84 @@ export class StoredFile {
|
|
|
103
120
|
* This property cannot be manipulated directly by the client. Should be treated as
|
|
104
121
|
* opaque value.
|
|
105
122
|
*/
|
|
106
|
-
parents: string[]
|
|
123
|
+
get parents(): string[] {
|
|
124
|
+
return this[parentsSymbol];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
[permissionIdsSymbol]: ReadonlyArray<string> = [];
|
|
128
|
+
|
|
107
129
|
/**
|
|
108
130
|
* The list of permissions to this file object.
|
|
109
131
|
*
|
|
110
132
|
* This property cannot be manipulated directly by the client. Should be treated as
|
|
111
133
|
* opaque value.
|
|
112
134
|
*/
|
|
113
|
-
permissionIds: string
|
|
135
|
+
get permissionIds(): ReadonlyArray<string> {
|
|
136
|
+
return this[permissionIdsSymbol];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
[deletedSymbol]?: boolean;
|
|
140
|
+
|
|
114
141
|
/**
|
|
115
142
|
* Whether the file object is deleted.
|
|
116
143
|
*/
|
|
117
|
-
deleted
|
|
144
|
+
get deleted(): boolean {
|
|
145
|
+
return this[deletedSymbol] || false;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
[deletedInfoSymbol]?: Readonly<IDeletion>;
|
|
149
|
+
|
|
118
150
|
/**
|
|
119
151
|
* The information about the delete information.
|
|
120
152
|
* Always set when the `delete` is true.
|
|
121
153
|
*/
|
|
122
|
-
deletedInfo
|
|
154
|
+
get deletedInfo(): Readonly<IDeletion> | undefined {
|
|
155
|
+
return this[deletedInfoSymbol];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
[ownerSymbol]: string = DefaultOwner;
|
|
159
|
+
|
|
123
160
|
/**
|
|
124
161
|
* The owner of this space. The id of the User object.
|
|
125
162
|
* Set to `default` when there are no users in the system (no authentication).
|
|
126
163
|
*/
|
|
127
|
-
owner
|
|
164
|
+
get owner(): string {
|
|
165
|
+
return this[ownerSymbol];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
[lastModifiedSymbol]: Readonly<IModification> = { user: '', time: 0, byMe: false };
|
|
169
|
+
|
|
128
170
|
/**
|
|
129
171
|
* The last modification made to this file.
|
|
130
172
|
*/
|
|
131
|
-
lastModified: IModification
|
|
173
|
+
get lastModified(): Readonly<IModification> {
|
|
174
|
+
return this[lastModifiedSymbol];
|
|
175
|
+
}
|
|
176
|
+
|
|
132
177
|
/**
|
|
133
178
|
* An arbitrary list of labels applied to the file.
|
|
134
179
|
*/
|
|
135
180
|
labels?: string[];
|
|
136
181
|
|
|
182
|
+
[capabilitiesSymbol]?: Readonly<ICapabilities>;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* This is populated when reading a file from the store.
|
|
186
|
+
* A list of actions the user can perform on the file.
|
|
187
|
+
*
|
|
188
|
+
* This is a readonly field and it is ignored when creating / updating the file.
|
|
189
|
+
*/
|
|
190
|
+
get capabilities(): Readonly<ICapabilities> | undefined {
|
|
191
|
+
return this[capabilitiesSymbol];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* The color of the icon to render for this file in the file explorer.
|
|
196
|
+
*/
|
|
197
|
+
iconColor?: string;
|
|
198
|
+
|
|
137
199
|
new(init: IStoredFile): void {
|
|
138
|
-
const { key = v4(), info, kind, parents=[], permissionIds=[], deleted, deletedInfo, owner = DefaultOwner, lastModified, labels } = init;
|
|
200
|
+
const { key = v4(), info, kind, parents=[], permissionIds=[], deleted, deletedInfo, owner = DefaultOwner, lastModified, labels, iconColor } = init;
|
|
139
201
|
this.key = key;
|
|
140
202
|
this.kind = kind;
|
|
141
203
|
if (info) {
|
|
@@ -143,22 +205,27 @@ export class StoredFile {
|
|
|
143
205
|
} else {
|
|
144
206
|
this.info = Thing.fromName('');
|
|
145
207
|
}
|
|
146
|
-
this
|
|
147
|
-
this
|
|
148
|
-
this
|
|
149
|
-
this
|
|
208
|
+
this[parentsSymbol] = [...parents];
|
|
209
|
+
this[permissionIdsSymbol] = [...permissionIds];
|
|
210
|
+
this[ownerSymbol] = owner;
|
|
211
|
+
this[lastModifiedSymbol] = lastModified ? Object.freeze({ ...lastModified }) : Object.freeze({ user: '', time: 0, byMe: false });
|
|
150
212
|
if (typeof deleted === 'boolean') {
|
|
151
|
-
this
|
|
152
|
-
this
|
|
213
|
+
this[deletedSymbol] = deleted;
|
|
214
|
+
this[deletedInfoSymbol] = deletedInfo ? Object.freeze({ ...deletedInfo }) : undefined;
|
|
153
215
|
} else {
|
|
154
|
-
this
|
|
155
|
-
this
|
|
216
|
+
this[deletedSymbol] = undefined;
|
|
217
|
+
this[deletedInfoSymbol] = undefined;
|
|
156
218
|
}
|
|
157
219
|
if (Array.isArray(labels)) {
|
|
158
|
-
this.labels = labels;
|
|
220
|
+
this.labels = [...labels];
|
|
159
221
|
} else {
|
|
160
222
|
this.labels = undefined;
|
|
161
223
|
}
|
|
224
|
+
if (iconColor) {
|
|
225
|
+
this.iconColor = iconColor;
|
|
226
|
+
} else {
|
|
227
|
+
this.iconColor = undefined;
|
|
228
|
+
}
|
|
162
229
|
}
|
|
163
230
|
|
|
164
231
|
toJSON(): IStoredFile {
|
|
@@ -167,17 +234,20 @@ export class StoredFile {
|
|
|
167
234
|
key: this.key,
|
|
168
235
|
kind: this.kind,
|
|
169
236
|
info: this.info.toJSON(),
|
|
170
|
-
parents: this.parents,
|
|
171
|
-
permissionIds: this.permissionIds,
|
|
172
|
-
lastModified: this.lastModified,
|
|
237
|
+
parents: [...this.parents],
|
|
238
|
+
permissionIds: [...this.permissionIds],
|
|
239
|
+
lastModified: { ...this.lastModified },
|
|
173
240
|
owner,
|
|
174
241
|
};
|
|
175
242
|
if (this.deleted) {
|
|
176
243
|
result.deleted = this.deleted;
|
|
177
|
-
result.deletedInfo = this.deletedInfo;
|
|
244
|
+
result.deletedInfo = { ...this.deletedInfo } as IDeletion;
|
|
178
245
|
}
|
|
179
246
|
if (Array.isArray(this.labels)) {
|
|
180
|
-
result.labels = this.labels;
|
|
247
|
+
result.labels = [...this.labels];
|
|
248
|
+
}
|
|
249
|
+
if (this.iconColor) {
|
|
250
|
+
result.iconColor = this.iconColor;
|
|
181
251
|
}
|
|
182
252
|
return result;
|
|
183
253
|
}
|
|
@@ -195,7 +265,7 @@ export class StoredFile {
|
|
|
195
265
|
if (user.kind !== UserKind) {
|
|
196
266
|
throw new Error(`Invalid value for the user when setting "lastModified".`);
|
|
197
267
|
}
|
|
198
|
-
this
|
|
268
|
+
this[lastModifiedSymbol] = {
|
|
199
269
|
byMe: false,
|
|
200
270
|
time: Date.now(),
|
|
201
271
|
user: user.key,
|
|
@@ -242,35 +312,106 @@ export class StoredFile {
|
|
|
242
312
|
if (user.kind !== UserKind) {
|
|
243
313
|
throw new Error(`Invalid value for the user when setting "lastModified".`);
|
|
244
314
|
}
|
|
245
|
-
this
|
|
246
|
-
this
|
|
315
|
+
this[deletedSymbol] = true;
|
|
316
|
+
this[deletedInfoSymbol] = {
|
|
247
317
|
byMe: false,
|
|
248
318
|
time: Date.now(),
|
|
249
319
|
user: user.key,
|
|
250
320
|
name: user.name,
|
|
251
321
|
};
|
|
252
322
|
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Creates the Capabilities object for a file giving user level.
|
|
326
|
+
*
|
|
327
|
+
* @param file The file object to create the capabilities to. The object is not mutated.
|
|
328
|
+
* @param role The user role to the file.
|
|
329
|
+
*/
|
|
330
|
+
static createFileCapabilities(file: IStoredFile | StoredFile, role?: PermissionRole): ICapabilities {
|
|
331
|
+
const isCommenter = Permission.hasRole('commenter', role);
|
|
332
|
+
const isOwner = Permission.hasRole('owner', role);
|
|
333
|
+
const isReader = Permission.hasRole('reader', role);
|
|
334
|
+
const isWriter = Permission.hasRole('writer', role);
|
|
335
|
+
const result: ICapabilities = {
|
|
336
|
+
canEdit: isWriter,
|
|
337
|
+
canComment: isCommenter,
|
|
338
|
+
// This is open to discussion. Technically sharing is writing to a file resource.
|
|
339
|
+
// However, should we allow to share the file by a user that has read access?
|
|
340
|
+
canShare: isWriter,
|
|
341
|
+
// not yet supported in the store
|
|
342
|
+
canCopy: false,
|
|
343
|
+
// not yet supported in the store. Currently the user can read revisions when they have read access to the file.
|
|
344
|
+
canReadRevisions: isReader,
|
|
345
|
+
canAddChildren: false,
|
|
346
|
+
// debatable, can writer permanently delete a file?
|
|
347
|
+
canDelete: isOwner,
|
|
348
|
+
canListChildren: false,
|
|
349
|
+
canRename: isWriter,
|
|
350
|
+
// debatable, can writer trash a file?
|
|
351
|
+
canTrash: isOwner,
|
|
352
|
+
canUntrash: isOwner,
|
|
353
|
+
canReadMedia: false,
|
|
354
|
+
};
|
|
355
|
+
// Do not use the `WorkspaceKind` reference here as it's circular and creates
|
|
356
|
+
// an error.
|
|
357
|
+
if (file.kind === 'Core#Space' && isWriter) {
|
|
358
|
+
result.canAddChildren = true;
|
|
359
|
+
}
|
|
360
|
+
if (file.kind === 'Core#Space') {
|
|
361
|
+
result.canListChildren = isReader;
|
|
362
|
+
}
|
|
363
|
+
if (file.kind !== 'Core#Space') {
|
|
364
|
+
result.canReadMedia = isReader;
|
|
365
|
+
}
|
|
366
|
+
return result;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
createFileCapabilities(role: PermissionRole): ICapabilities {
|
|
370
|
+
return File.createFileCapabilities(this, role);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Mutates the file object by setting the `byMe` properties (on deleted and modified info)
|
|
375
|
+
*
|
|
376
|
+
* Note, this can be done only on file schema (IFile). The `File` object has
|
|
377
|
+
* this properties frozen.
|
|
378
|
+
*
|
|
379
|
+
* @param file The file to mutate
|
|
380
|
+
* @param user The user key to compare.
|
|
381
|
+
*/
|
|
382
|
+
static updateByMeMeta(file: IFile, user: string): void {
|
|
383
|
+
if (file.deletedInfo) {
|
|
384
|
+
file.deletedInfo.byMe = file.deletedInfo.user === user;
|
|
385
|
+
}
|
|
386
|
+
if (file.lastModified) {
|
|
387
|
+
file.lastModified.byMe = file.lastModified.user === user;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
253
390
|
}
|
|
254
391
|
|
|
255
392
|
export class File extends StoredFile {
|
|
393
|
+
[permissionsSymbol]: ReadonlyArray<IPermission> = [];
|
|
394
|
+
|
|
256
395
|
/**
|
|
257
396
|
* Populated by the server when reading the file. The list of permissions to the object.
|
|
258
397
|
*
|
|
259
398
|
* This property cannot be manipulated directly by the client. Should be treated as
|
|
260
399
|
* opaque value.
|
|
261
400
|
*/
|
|
262
|
-
permissions: IPermission
|
|
401
|
+
get permissions(): ReadonlyArray<IPermission> {
|
|
402
|
+
return this[permissionsSymbol];
|
|
403
|
+
}
|
|
263
404
|
|
|
264
405
|
new(init: IFile): void {
|
|
265
406
|
super.new(init);
|
|
266
407
|
const { permissions=[] } = init;
|
|
267
|
-
this
|
|
408
|
+
this[permissionsSymbol] = permissions.map(i => ({ ...i }));
|
|
268
409
|
}
|
|
269
410
|
|
|
270
411
|
toJSON(): IFile {
|
|
271
412
|
const result: IFile = {
|
|
272
413
|
...super.toJSON(),
|
|
273
|
-
permissions: this.permissions,
|
|
414
|
+
permissions: [...this.permissions],
|
|
274
415
|
};
|
|
275
416
|
return result;
|
|
276
417
|
}
|
|
@@ -4,6 +4,7 @@ export const Kind = 'Core#Permission';
|
|
|
4
4
|
|
|
5
5
|
export type PermissionType = 'user' | 'group' | 'anyone';
|
|
6
6
|
export type PermissionRole = 'owner' | 'reader' | 'commenter' | 'writer';
|
|
7
|
+
const orderedRoles: PermissionRole[] = ["reader", "commenter", "writer", "owner"];
|
|
7
8
|
|
|
8
9
|
interface IBasePermission {
|
|
9
10
|
/**
|
|
@@ -64,7 +65,7 @@ interface IBasePermission {
|
|
|
64
65
|
/**
|
|
65
66
|
* A schema describing a permission to a store object.
|
|
66
67
|
*/
|
|
67
|
-
export interface IPermission extends IBasePermission{
|
|
68
|
+
export interface IPermission extends IBasePermission {
|
|
68
69
|
kind: typeof Kind;
|
|
69
70
|
/**
|
|
70
71
|
* The data store key of the permission.
|
|
@@ -141,6 +142,7 @@ export class Permission {
|
|
|
141
142
|
*
|
|
142
143
|
* @param role The user role to set.
|
|
143
144
|
* @param user The user id that has the role.
|
|
145
|
+
* @param addingUser The key of the user that created this permission
|
|
144
146
|
*/
|
|
145
147
|
static fromUserRole(role: PermissionRole, user: string, addingUser: string): Permission {
|
|
146
148
|
const init: IPermission = {
|
|
@@ -159,6 +161,7 @@ export class Permission {
|
|
|
159
161
|
*
|
|
160
162
|
* @param role The group role to set.
|
|
161
163
|
* @param group The group id that has the role.
|
|
164
|
+
* @param addingUser The key of the user that created this permission
|
|
162
165
|
*/
|
|
163
166
|
static fromGroupRole(role: PermissionRole, group: string, addingUser: string): Permission {
|
|
164
167
|
const init: IPermission = {
|
|
@@ -176,7 +179,7 @@ export class Permission {
|
|
|
176
179
|
* Creates a Permission object for a group.
|
|
177
180
|
*
|
|
178
181
|
* @param role The group role to set.
|
|
179
|
-
* @param
|
|
182
|
+
* @param addingUser The key of the user that created this permission
|
|
180
183
|
*/
|
|
181
184
|
static fromAnyoneRole(role: PermissionRole, addingUser: string): Permission {
|
|
182
185
|
const init: IPermission = {
|
|
@@ -267,6 +270,31 @@ export class Permission {
|
|
|
267
270
|
return true;
|
|
268
271
|
}
|
|
269
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Checks whether the current user role meets the minimum required role.
|
|
275
|
+
*
|
|
276
|
+
* @param minimumLevel The minimum requested role
|
|
277
|
+
* @param currentRole The user role. When not set it always returns false.
|
|
278
|
+
* @returns True if the `currentRole` is at least the `minimumRole`
|
|
279
|
+
*/
|
|
280
|
+
static hasRole(minimumLevel: PermissionRole, currentRole?: PermissionRole): boolean {
|
|
281
|
+
if (!currentRole) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
const currentAccessIndex = orderedRoles.indexOf(currentRole);
|
|
285
|
+
const requestedAccessIndex = orderedRoles.indexOf(minimumLevel);
|
|
286
|
+
// the current must be at least at the index of requested.
|
|
287
|
+
return currentAccessIndex >= requestedAccessIndex;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Link to the `Permission.hasRole(minimumLevel, currentRole)`.
|
|
292
|
+
* @see {@link Permission.hasRole}
|
|
293
|
+
*/
|
|
294
|
+
hasRole(minimumLevel: PermissionRole, currentRole: PermissionRole): boolean {
|
|
295
|
+
return Permission.hasRole(minimumLevel, currentRole);
|
|
296
|
+
}
|
|
297
|
+
|
|
270
298
|
toJSON(): IPermission {
|
|
271
299
|
const result: IPermission = {
|
|
272
300
|
kind: Kind,
|
|
@@ -2,7 +2,7 @@ import { IHttpRequest } from 'src/models/HttpRequest.js';
|
|
|
2
2
|
import { ActionRunnable } from './ActionRunnable.js';
|
|
3
3
|
import { IDeleteCookieAction } from '../../../models/actions/runnable/DeleteCookieAction.js';
|
|
4
4
|
import { Events } from '../../../events/Events.js';
|
|
5
|
-
import { IRequestLog } from '
|
|
5
|
+
import { IRequestLog } from '../../../models/RequestLog.js';
|
|
6
6
|
|
|
7
7
|
export class DeleteCookieRunnable extends ActionRunnable {
|
|
8
8
|
async response(log: IRequestLog): Promise<void> {
|
|
@@ -4,7 +4,7 @@ import { ActionRunnable } from './ActionRunnable.js';
|
|
|
4
4
|
import { ISetCookieAction } from '../../../models/actions/runnable/SetCookieAction.js';
|
|
5
5
|
import { Events } from '../../../events/Events.js';
|
|
6
6
|
import { RequestDataExtractor } from '../../../data/RequestDataExtractor.js';
|
|
7
|
-
import { IRequestLog } from '
|
|
7
|
+
import { IRequestLog } from '../../../models/RequestLog.js';
|
|
8
8
|
|
|
9
9
|
export class SetCookieRunnable extends ActionRunnable {
|
|
10
10
|
async request(request: IHttpRequest): Promise<void> {
|
|
@@ -3,7 +3,7 @@ import { ActionRunnable } from './ActionRunnable.js';
|
|
|
3
3
|
import { ISetVariableAction } from '../../../models/actions/runnable/SetVariableAction.js';
|
|
4
4
|
import { Events } from '../../../events/Events.js';
|
|
5
5
|
import { RequestDataExtractor } from '../../../data/RequestDataExtractor.js';
|
|
6
|
-
import { IRequestLog } from '
|
|
6
|
+
import { IRequestLog } from '../../../models/RequestLog.js';
|
|
7
7
|
|
|
8
8
|
export class SetVariableRunnable extends ActionRunnable {
|
|
9
9
|
async request(request: IHttpRequest): Promise<void> {
|
|
@@ -3,7 +3,7 @@ import tls from 'tls';
|
|
|
3
3
|
import http from 'http';
|
|
4
4
|
import https from 'https';
|
|
5
5
|
import { HttpEngine, HttpEngineOptions, HeadersReceivedDetail } from './HttpEngine.js';
|
|
6
|
-
import { IRequestLog } from '
|
|
6
|
+
import { IRequestLog } from '../../models/RequestLog.js';
|
|
7
7
|
import { IHttpRequest } from '../../models/HttpRequest.js';
|
|
8
8
|
import { Response } from '../../models/Response.js';
|
|
9
9
|
import { SerializableError } from '../../models/SerializableError.js';
|
|
@@ -148,6 +148,44 @@ export class FilesSdk extends SdkBase {
|
|
|
148
148
|
return data;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Reads a number of files in a bulk operation.
|
|
153
|
+
*
|
|
154
|
+
* @param keys The list of keys to read. When the user has no access to the file it returns undefined
|
|
155
|
+
* in that place. It also inserts `undefined` in place of a file that doesn't exist.
|
|
156
|
+
* @param request Optional request options.
|
|
157
|
+
*/
|
|
158
|
+
async readBulk(keys: string[], request: ISdkRequestOptions = {}): Promise<IListResponse<IFile|undefined>> {
|
|
159
|
+
const token = request.token || this.sdk.token;
|
|
160
|
+
const url = this.sdk.getUrl(RouteBuilder.filesBulk());
|
|
161
|
+
const body = JSON.stringify(keys);
|
|
162
|
+
const result = await this.sdk.http.post(url.toString(), { token, body });
|
|
163
|
+
this.inspectCommonStatusCodes(result.status, result.body);
|
|
164
|
+
const E_PREFIX = 'Unable to read files in bulk. ';
|
|
165
|
+
if (result.status !== 200) {
|
|
166
|
+
this.logInvalidResponse(result);
|
|
167
|
+
let e = this.createGenericSdkError(result.body)
|
|
168
|
+
if (!e) {
|
|
169
|
+
e = new SdkError(`${E_PREFIX}${E_RESPONSE_STATUS}${result.status}`, result.status);
|
|
170
|
+
e.response = result.body;
|
|
171
|
+
}
|
|
172
|
+
throw e;
|
|
173
|
+
}
|
|
174
|
+
if (!result.body) {
|
|
175
|
+
throw new Error(`${E_PREFIX}${E_RESPONSE_NO_VALUE}`);
|
|
176
|
+
}
|
|
177
|
+
let data: IListResponse<IFile | undefined>;
|
|
178
|
+
try {
|
|
179
|
+
data = JSON.parse(result.body);
|
|
180
|
+
} catch (e) {
|
|
181
|
+
throw new Error(`${E_PREFIX}${E_INVALID_JSON}.`);
|
|
182
|
+
}
|
|
183
|
+
if (!Array.isArray(data.data)) {
|
|
184
|
+
throw new Error(`${E_PREFIX}${E_RESPONSE_UNKNOWN}.`);
|
|
185
|
+
}
|
|
186
|
+
return data;
|
|
187
|
+
}
|
|
188
|
+
|
|
151
189
|
/**
|
|
152
190
|
* Patches file's meta in the store.
|
|
153
191
|
*
|
|
@@ -300,4 +338,20 @@ export class FilesSdk extends SdkBase {
|
|
|
300
338
|
const url = this.sdk.getUrl(RouteBuilder.files());
|
|
301
339
|
return this.sdk.ws.createAndConnect(url.toString(), token);
|
|
302
340
|
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Creates a WS client that listens to the file events.
|
|
344
|
+
*
|
|
345
|
+
* @param key The file key to observe
|
|
346
|
+
* @param media Whether to observe changes to the file media instead of meta.
|
|
347
|
+
* @param request Optional request options.
|
|
348
|
+
*/
|
|
349
|
+
async observeFile(key: string, media?: boolean, request: ISdkRequestOptions = {}): Promise<WebSocketNode | WebSocket> {
|
|
350
|
+
const token = request.token || this.sdk.token;
|
|
351
|
+
const url = this.sdk.getUrl(RouteBuilder.file(key));
|
|
352
|
+
if (media) {
|
|
353
|
+
url.searchParams.set('alt', 'media');
|
|
354
|
+
}
|
|
355
|
+
return this.sdk.ws.createAndConnect(url.toString(), token);
|
|
356
|
+
}
|
|
303
357
|
}
|