@forestadmin/agent 1.65.1 → 1.66.1
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/agent/services/chart.d.ts +102 -0
- package/dist/agent/services/chart.js +114 -0
- package/dist/routes/access/api-chart.d.ts +16 -0
- package/dist/routes/access/api-chart.js +47 -0
- package/dist/routes/access/csv-related.js +2 -2
- package/dist/routes/access/csv.js +2 -2
- package/dist/routes/modification/action.d.ts +16 -0
- package/dist/routes/modification/action.js +121 -0
- package/dist/services/authorization/internal/action-permission.d.ts +20 -0
- package/dist/services/authorization/internal/action-permission.js +98 -0
- package/dist/services/authorization/internal/generate-action-identifier.d.ts +12 -0
- package/dist/services/authorization/internal/generate-action-identifier.js +15 -0
- package/dist/services/authorization/internal/generate-actions-from-permissions.d.ts +12 -0
- package/dist/services/authorization/internal/generate-actions-from-permissions.js +139 -0
- package/dist/services/authorization/internal/generate-user-scope.d.ts +10 -0
- package/dist/services/authorization/internal/generate-user-scope.js +45 -0
- package/dist/services/authorization/internal/hash-chart.d.ts +5 -0
- package/dist/services/authorization/internal/hash-chart.js +58 -0
- package/dist/services/authorization/internal/rendering-permission.d.ts +39 -0
- package/dist/services/authorization/internal/rendering-permission.js +121 -0
- package/dist/services/authorization/internal/types.d.ts +255 -0
- package/dist/services/authorization/internal/types.js +54 -0
- package/dist/services/authorization/internal/user-permission.d.ts +16 -0
- package/dist/services/authorization/internal/user-permission.js +46 -0
- package/dist/services/permissions.d.ts +19 -0
- package/dist/services/permissions.js +85 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.js +1 -1
- package/dist/utils/csv-generator.d.ts +1 -1
- package/dist/utils/csv-generator.js +12 -5
- package/dist/utils/forest-http-api.d.ts +37 -0
- package/dist/utils/forest-http-api.js +100 -0
- package/dist/utils/forest-schema/column-schema-validation.d.ts +5 -0
- package/dist/utils/forest-schema/column-schema-validation.js +14 -0
- package/dist/utils/forest-schema/emitter.d.ts +17 -0
- package/dist/utils/forest-schema/emitter.js +38 -0
- package/dist/utils/forest-schema/schema-generator.d.ts +6 -0
- package/dist/utils/forest-schema/schema-generator.js +13 -0
- package/dist/utils/forest-schema/schema-serializer.d.ts +12 -0
- package/dist/utils/forest-schema/schema-serializer.js +35 -0
- package/dist/utils/forest-schema/types.d.ts +85 -0
- package/dist/utils/forest-schema/types.js +16 -0
- package/dist/utils/options-validator.js +2 -1
- package/package.json +9 -6
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { GenericTree } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
|
|
3
|
+
export declare type EnvironmentPermissionsV4 = EnvironmentPermissionsV4Remote | true;
|
|
4
|
+
export declare type RightDescriptionWithRolesV4 = {
|
|
5
|
+
roles: number[];
|
|
6
|
+
};
|
|
7
|
+
export declare type RightDescriptionV4 = boolean | RightDescriptionWithRolesV4;
|
|
8
|
+
export interface EnvironmentCollectionAccessPermissionsV4 {
|
|
9
|
+
browseEnabled: RightDescriptionV4;
|
|
10
|
+
readEnabled: RightDescriptionV4;
|
|
11
|
+
editEnabled: RightDescriptionV4;
|
|
12
|
+
addEnabled: RightDescriptionV4;
|
|
13
|
+
deleteEnabled: RightDescriptionV4;
|
|
14
|
+
exportEnabled: RightDescriptionV4;
|
|
15
|
+
}
|
|
16
|
+
export interface EnvironmentSmartActionPermissionsV4 {
|
|
17
|
+
triggerEnabled: RightDescriptionV4;
|
|
18
|
+
approvalRequired: RightDescriptionV4;
|
|
19
|
+
userApprovalEnabled: RightDescriptionV4;
|
|
20
|
+
selfApprovalEnabled: RightDescriptionV4;
|
|
21
|
+
}
|
|
22
|
+
export interface EnvironmentCollectionActionPermissionsV4 {
|
|
23
|
+
[actionName: string]: EnvironmentSmartActionPermissionsV4;
|
|
24
|
+
}
|
|
25
|
+
export interface EnvironmentCollectionPermissionsV4 {
|
|
26
|
+
collection: EnvironmentCollectionAccessPermissionsV4;
|
|
27
|
+
actions: EnvironmentCollectionActionPermissionsV4;
|
|
28
|
+
}
|
|
29
|
+
export interface EnvironmentCollectionsPermissionsV4 {
|
|
30
|
+
[id: string]: EnvironmentCollectionPermissionsV4;
|
|
31
|
+
}
|
|
32
|
+
export interface EnvironmentPermissionsV4Remote {
|
|
33
|
+
collections: EnvironmentCollectionsPermissionsV4;
|
|
34
|
+
}
|
|
35
|
+
export declare enum PermissionLevel {
|
|
36
|
+
Admin = 'admin',
|
|
37
|
+
Developer = 'developer',
|
|
38
|
+
Editor = 'editor',
|
|
39
|
+
User = 'user',
|
|
40
|
+
}
|
|
41
|
+
export declare type UserPermissionV4 = {
|
|
42
|
+
id: number;
|
|
43
|
+
firstName: string;
|
|
44
|
+
lastName: string;
|
|
45
|
+
email: string;
|
|
46
|
+
permissionLevel: PermissionLevel;
|
|
47
|
+
tags: Record<string, string>;
|
|
48
|
+
roleId: number;
|
|
49
|
+
};
|
|
50
|
+
export declare enum CollectionActionEvent {
|
|
51
|
+
Browse = 'browse',
|
|
52
|
+
Export = 'export',
|
|
53
|
+
Read = 'read',
|
|
54
|
+
Edit = 'edit',
|
|
55
|
+
Delete = 'delete',
|
|
56
|
+
Add = 'add',
|
|
57
|
+
}
|
|
58
|
+
export declare enum CustomActionEvent {
|
|
59
|
+
Trigger = 'trigger',
|
|
60
|
+
Approve = 'approve',
|
|
61
|
+
SelfApprove = 'self-approve',
|
|
62
|
+
RequireApproval = 'require-approval',
|
|
63
|
+
}
|
|
64
|
+
export declare enum ChartType {
|
|
65
|
+
Pie = 'Pie',
|
|
66
|
+
Value = 'Value',
|
|
67
|
+
Leaderboard = 'Leaderboard',
|
|
68
|
+
Line = 'Line',
|
|
69
|
+
Objective = 'Objective',
|
|
70
|
+
Percentage = 'Percentage',
|
|
71
|
+
Smart = 'Smart',
|
|
72
|
+
}
|
|
73
|
+
export interface DisplaySettings {
|
|
74
|
+
x: number;
|
|
75
|
+
y: number;
|
|
76
|
+
width: number;
|
|
77
|
+
height: number;
|
|
78
|
+
}
|
|
79
|
+
export interface BaseChart {
|
|
80
|
+
type: ChartType;
|
|
81
|
+
}
|
|
82
|
+
export interface SmartRouteChart extends BaseChart {
|
|
83
|
+
type: Exclude<ChartType, ChartType.Smart>;
|
|
84
|
+
smartRoute: string;
|
|
85
|
+
}
|
|
86
|
+
export interface ApiRouteChart extends BaseChart {
|
|
87
|
+
type: Exclude<ChartType, ChartType.Smart>;
|
|
88
|
+
apiRoute: string;
|
|
89
|
+
}
|
|
90
|
+
export interface QueryChart extends BaseChart {
|
|
91
|
+
type: Exclude<ChartType, ChartType.Smart>;
|
|
92
|
+
query: string;
|
|
93
|
+
filter?: Record<string, any>;
|
|
94
|
+
}
|
|
95
|
+
export interface S3Versions {
|
|
96
|
+
'component.js': string;
|
|
97
|
+
'template.hbs': string;
|
|
98
|
+
}
|
|
99
|
+
export interface FilterableChart extends BaseChart {
|
|
100
|
+
filter?: string;
|
|
101
|
+
}
|
|
102
|
+
export interface AggregatedChart extends BaseChart {
|
|
103
|
+
aggregator: 'Sum' | 'Count';
|
|
104
|
+
aggregateFieldName: string | null;
|
|
105
|
+
}
|
|
106
|
+
export interface CollectionChart extends BaseChart {
|
|
107
|
+
sourceCollectionName: string | number;
|
|
108
|
+
}
|
|
109
|
+
export interface GroupedByChart extends BaseChart {
|
|
110
|
+
groupByFieldName: string | null;
|
|
111
|
+
}
|
|
112
|
+
export interface SmartChart extends BaseChart {
|
|
113
|
+
type: ChartType.Smart;
|
|
114
|
+
s3Versions: S3Versions & {
|
|
115
|
+
'style.css': string;
|
|
116
|
+
};
|
|
117
|
+
id: string;
|
|
118
|
+
}
|
|
119
|
+
export interface LeaderboardChart extends BaseChart, AggregatedChart, CollectionChart {
|
|
120
|
+
type: ChartType.Leaderboard;
|
|
121
|
+
labelFieldName: string;
|
|
122
|
+
relationshipFieldName: string;
|
|
123
|
+
limit: number;
|
|
124
|
+
}
|
|
125
|
+
export interface LineChart
|
|
126
|
+
extends BaseChart,
|
|
127
|
+
FilterableChart,
|
|
128
|
+
AggregatedChart,
|
|
129
|
+
CollectionChart,
|
|
130
|
+
GroupedByChart {
|
|
131
|
+
type: ChartType.Line;
|
|
132
|
+
timeRange: 'Day' | 'Week' | 'Month' | 'Year';
|
|
133
|
+
}
|
|
134
|
+
export interface ObjectiveChart
|
|
135
|
+
extends BaseChart,
|
|
136
|
+
FilterableChart,
|
|
137
|
+
AggregatedChart,
|
|
138
|
+
CollectionChart {
|
|
139
|
+
type: ChartType.Objective;
|
|
140
|
+
objective: number;
|
|
141
|
+
}
|
|
142
|
+
export interface PercentageChart extends BaseChart {
|
|
143
|
+
type: ChartType.Percentage;
|
|
144
|
+
numeratorChartId: string;
|
|
145
|
+
denominatorChartId: string;
|
|
146
|
+
}
|
|
147
|
+
export interface PieChart
|
|
148
|
+
extends BaseChart,
|
|
149
|
+
FilterableChart,
|
|
150
|
+
AggregatedChart,
|
|
151
|
+
CollectionChart,
|
|
152
|
+
GroupedByChart {
|
|
153
|
+
type: ChartType.Pie;
|
|
154
|
+
}
|
|
155
|
+
export interface ValueChart extends BaseChart, FilterableChart, AggregatedChart, CollectionChart {
|
|
156
|
+
type: ChartType.Value;
|
|
157
|
+
}
|
|
158
|
+
export declare type Chart =
|
|
159
|
+
| SmartChart
|
|
160
|
+
| ApiRouteChart
|
|
161
|
+
| QueryChart
|
|
162
|
+
| SmartRouteChart
|
|
163
|
+
| LeaderboardChart
|
|
164
|
+
| LineChart
|
|
165
|
+
| ObjectiveChart
|
|
166
|
+
| PercentageChart
|
|
167
|
+
| PieChart
|
|
168
|
+
| ValueChart;
|
|
169
|
+
export interface CollectionColumn {
|
|
170
|
+
id: string | number;
|
|
171
|
+
fieldName: string;
|
|
172
|
+
position: number | null;
|
|
173
|
+
isVisible: boolean;
|
|
174
|
+
}
|
|
175
|
+
export interface BaseCollectionSegment {
|
|
176
|
+
id: string | number;
|
|
177
|
+
type: 'manual' | 'smart';
|
|
178
|
+
name: string;
|
|
179
|
+
position: number;
|
|
180
|
+
defaultSortingFieldName: string | null;
|
|
181
|
+
defaultSortingFieldOrder: 'ascending' | 'descending' | null;
|
|
182
|
+
isVisible: boolean;
|
|
183
|
+
hasColumnsConfiguration: boolean;
|
|
184
|
+
columns: CollectionColumn[];
|
|
185
|
+
}
|
|
186
|
+
export interface FilterCondition {
|
|
187
|
+
id: string;
|
|
188
|
+
value: boolean | number | string | string[];
|
|
189
|
+
fieldName: string | null;
|
|
190
|
+
subFieldName: string | null;
|
|
191
|
+
embeddedFieldName?: string | null;
|
|
192
|
+
operator: string;
|
|
193
|
+
embeddedField?: {
|
|
194
|
+
id?: number;
|
|
195
|
+
type: string;
|
|
196
|
+
field: string;
|
|
197
|
+
enums?: Array<string | number | Record<string, string>>;
|
|
198
|
+
} | null;
|
|
199
|
+
}
|
|
200
|
+
export interface Filter {
|
|
201
|
+
id?: string;
|
|
202
|
+
type: 'and' | 'or';
|
|
203
|
+
conditions: FilterCondition[] | null;
|
|
204
|
+
}
|
|
205
|
+
export interface ManualCollectionSegment extends BaseCollectionSegment {
|
|
206
|
+
type: 'manual';
|
|
207
|
+
filter: Filter | null;
|
|
208
|
+
query: string | null;
|
|
209
|
+
}
|
|
210
|
+
export interface SmartCollectionSegment extends BaseCollectionSegment {
|
|
211
|
+
type: 'smart';
|
|
212
|
+
}
|
|
213
|
+
export declare type CollectionSegment = ManualCollectionSegment | SmartCollectionSegment;
|
|
214
|
+
export declare type DynamicScopesValues = {
|
|
215
|
+
users: Record<string, Record<string, string | number>>;
|
|
216
|
+
};
|
|
217
|
+
export declare type CollectionRenderingPermissionV4 = {
|
|
218
|
+
scope: GenericTree | null;
|
|
219
|
+
segments: CollectionSegment[];
|
|
220
|
+
};
|
|
221
|
+
export declare type Team = {
|
|
222
|
+
id: number;
|
|
223
|
+
name: string;
|
|
224
|
+
};
|
|
225
|
+
export declare type RenderingPermissionV4 = {
|
|
226
|
+
team: Team;
|
|
227
|
+
collections: Record<string, CollectionRenderingPermissionV4>;
|
|
228
|
+
stats: Chart[];
|
|
229
|
+
};
|
|
230
|
+
export declare type User = Record<string, any> & {
|
|
231
|
+
id: number;
|
|
232
|
+
tags: Record<string, string>;
|
|
233
|
+
};
|
|
234
|
+
export interface ActionApprovalAttributes {
|
|
235
|
+
requester_id: number;
|
|
236
|
+
ids: Array<string>;
|
|
237
|
+
collection_name: string;
|
|
238
|
+
smart_action_id: string;
|
|
239
|
+
values: any | null;
|
|
240
|
+
parent_collection_name: string | null;
|
|
241
|
+
parent_collection_id: string | null;
|
|
242
|
+
parent_association_name: string | null;
|
|
243
|
+
all_records: boolean;
|
|
244
|
+
all_records_subset_query: null;
|
|
245
|
+
}
|
|
246
|
+
export declare type ActionApprovalJWT = {
|
|
247
|
+
data: {
|
|
248
|
+
id: string | number;
|
|
249
|
+
type: string;
|
|
250
|
+
attributes: ActionApprovalAttributes;
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
export declare class JTWUnableToVerifyError extends Error {}
|
|
254
|
+
export declare class JTWTokenExpiredError extends Error {}
|
|
255
|
+
// # sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
|
+
exports.JTWTokenExpiredError =
|
|
3
|
+
exports.JTWUnableToVerifyError =
|
|
4
|
+
exports.ChartType =
|
|
5
|
+
exports.CustomActionEvent =
|
|
6
|
+
exports.CollectionActionEvent =
|
|
7
|
+
exports.PermissionLevel =
|
|
8
|
+
void 0;
|
|
9
|
+
let PermissionLevel;
|
|
10
|
+
|
|
11
|
+
(function (PermissionLevel) {
|
|
12
|
+
PermissionLevel.Admin = 'admin';
|
|
13
|
+
PermissionLevel.Developer = 'developer';
|
|
14
|
+
PermissionLevel.Editor = 'editor';
|
|
15
|
+
PermissionLevel.User = 'user';
|
|
16
|
+
})((PermissionLevel = exports.PermissionLevel || (exports.PermissionLevel = {})));
|
|
17
|
+
|
|
18
|
+
let CollectionActionEvent;
|
|
19
|
+
|
|
20
|
+
(function (CollectionActionEvent) {
|
|
21
|
+
CollectionActionEvent.Browse = 'browse';
|
|
22
|
+
CollectionActionEvent.Export = 'export';
|
|
23
|
+
CollectionActionEvent.Read = 'read';
|
|
24
|
+
CollectionActionEvent.Edit = 'edit';
|
|
25
|
+
CollectionActionEvent.Delete = 'delete';
|
|
26
|
+
CollectionActionEvent.Add = 'add';
|
|
27
|
+
})((CollectionActionEvent = exports.CollectionActionEvent || (exports.CollectionActionEvent = {})));
|
|
28
|
+
|
|
29
|
+
let CustomActionEvent;
|
|
30
|
+
|
|
31
|
+
(function (CustomActionEvent) {
|
|
32
|
+
CustomActionEvent.Trigger = 'trigger';
|
|
33
|
+
CustomActionEvent.Approve = 'approve';
|
|
34
|
+
CustomActionEvent.SelfApprove = 'self-approve';
|
|
35
|
+
CustomActionEvent.RequireApproval = 'require-approval';
|
|
36
|
+
})((CustomActionEvent = exports.CustomActionEvent || (exports.CustomActionEvent = {})));
|
|
37
|
+
|
|
38
|
+
let ChartType;
|
|
39
|
+
|
|
40
|
+
(function (ChartType) {
|
|
41
|
+
ChartType.Pie = 'Pie';
|
|
42
|
+
ChartType.Value = 'Value';
|
|
43
|
+
ChartType.Leaderboard = 'Leaderboard';
|
|
44
|
+
ChartType.Line = 'Line';
|
|
45
|
+
ChartType.Objective = 'Objective';
|
|
46
|
+
ChartType.Percentage = 'Percentage';
|
|
47
|
+
ChartType.Smart = 'Smart';
|
|
48
|
+
})((ChartType = exports.ChartType || (exports.ChartType = {})));
|
|
49
|
+
|
|
50
|
+
class JTWUnableToVerifyError extends Error {}
|
|
51
|
+
exports.JTWUnableToVerifyError = JTWUnableToVerifyError;
|
|
52
|
+
class JTWTokenExpiredError extends Error {}
|
|
53
|
+
exports.JTWTokenExpiredError = JTWTokenExpiredError;
|
|
54
|
+
// # sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2VydmljZXMvYXV0aG9yaXphdGlvbi9pbnRlcm5hbC90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUF5Q0EsSUFBWSxlQUtYO0FBTEQsV0FBWSxlQUFlO0lBQ3pCLGtDQUFlLENBQUE7SUFDZiwwQ0FBdUIsQ0FBQTtJQUN2QixvQ0FBaUIsQ0FBQTtJQUNqQixnQ0FBYSxDQUFBO0FBQ2YsQ0FBQyxFQUxXLGVBQWUsR0FBZix1QkFBZSxLQUFmLHVCQUFlLFFBSzFCO0FBWUQsSUFBWSxxQkFPWDtBQVBELFdBQVkscUJBQXFCO0lBQy9CLDBDQUFpQixDQUFBO0lBQ2pCLDBDQUFpQixDQUFBO0lBQ2pCLHNDQUFhLENBQUE7SUFDYixzQ0FBYSxDQUFBO0lBQ2IsMENBQWlCLENBQUE7SUFDakIsb0NBQVcsQ0FBQTtBQUNiLENBQUMsRUFQVyxxQkFBcUIsR0FBckIsNkJBQXFCLEtBQXJCLDZCQUFxQixRQU9oQztBQUVELElBQVksaUJBS1g7QUFMRCxXQUFZLGlCQUFpQjtJQUMzQix3Q0FBbUIsQ0FBQTtJQUNuQix3Q0FBbUIsQ0FBQTtJQUNuQixpREFBNEIsQ0FBQTtJQUM1Qix5REFBb0MsQ0FBQTtBQUN0QyxDQUFDLEVBTFcsaUJBQWlCLEdBQWpCLHlCQUFpQixLQUFqQix5QkFBaUIsUUFLNUI7QUFFRCxJQUFZLFNBUVg7QUFSRCxXQUFZLFNBQVM7SUFDbkIsd0JBQVcsQ0FBQTtJQUNYLDRCQUFlLENBQUE7SUFDZix3Q0FBMkIsQ0FBQTtJQUMzQiwwQkFBYSxDQUFBO0lBQ2Isb0NBQXVCLENBQUE7SUFDdkIsc0NBQXlCLENBQUE7SUFDekIsNEJBQWUsQ0FBQTtBQUNqQixDQUFDLEVBUlcsU0FBUyxHQUFULGlCQUFTLEtBQVQsaUJBQVMsUUFRcEI7QUErTUQsTUFBYSxzQkFBdUIsU0FBUSxLQUFLO0NBQUc7QUFBcEQsd0RBQW9EO0FBQ3BELE1BQWEsb0JBQXFCLFNBQVEsS0FBSztDQUFHO0FBQWxELG9EQUFrRCJ9
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AgentOptionsWithDefaults } from '../../../types';
|
|
2
|
+
import { UserPermissionV4 } from './types';
|
|
3
|
+
|
|
4
|
+
export declare type UserPermissionOptions = Pick<
|
|
5
|
+
AgentOptionsWithDefaults,
|
|
6
|
+
'forestServerUrl' | 'envSecret' | 'isProduction' | 'permissionsCacheDurationInSeconds' | 'logger'
|
|
7
|
+
>;
|
|
8
|
+
export default class UserPermissionService {
|
|
9
|
+
private readonly options;
|
|
10
|
+
private cacheExpirationTimestamp;
|
|
11
|
+
private userInfoById;
|
|
12
|
+
constructor(options: UserPermissionOptions);
|
|
13
|
+
getUserInfo(userId: number): Promise<UserPermissionV4 | undefined>;
|
|
14
|
+
clearCache(): void;
|
|
15
|
+
}
|
|
16
|
+
// # sourceMappingURL=user-permission.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const __importDefault =
|
|
2
|
+
(this && this.__importDefault) ||
|
|
3
|
+
function (mod) {
|
|
4
|
+
return mod && mod.__esModule ? mod : { default: mod };
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
8
|
+
const forest_http_api_1 = __importDefault(require('../../../utils/forest-http-api'));
|
|
9
|
+
|
|
10
|
+
class UserPermissionService {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.options = options;
|
|
13
|
+
this.cacheExpirationTimestamp = 0;
|
|
14
|
+
// The trick here is to keep the cache as a Promise and not a Map
|
|
15
|
+
// in order to avoid doing the same HTTP request twice when
|
|
16
|
+
// 2 calls are made to getUserInfo at the same time.
|
|
17
|
+
this.userInfoById = null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async getUserInfo(userId) {
|
|
21
|
+
if (
|
|
22
|
+
!this.cacheExpirationTimestamp ||
|
|
23
|
+
this.cacheExpirationTimestamp < Date.now() ||
|
|
24
|
+
!(await this.userInfoById).has(userId)
|
|
25
|
+
) {
|
|
26
|
+
this.cacheExpirationTimestamp =
|
|
27
|
+
Date.now() + this.options.permissionsCacheDurationInSeconds * 1000;
|
|
28
|
+
this.options.logger('Debug', `Refreshing user permissions cache`);
|
|
29
|
+
// The response here is not awaited in order to be set in the cache
|
|
30
|
+
// allowing subsequent calls to getUserInfo to use the cache even if
|
|
31
|
+
// the response is not yet available.
|
|
32
|
+
this.userInfoById = forest_http_api_1.default
|
|
33
|
+
.getUsers(this.options)
|
|
34
|
+
.then(users => new Map(users.map(user => [user.id, user])));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (await this.userInfoById).get(userId);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
clearCache() {
|
|
41
|
+
this.userInfoById = null;
|
|
42
|
+
this.cacheExpirationTimestamp = Number.NEGATIVE_INFINITY;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.default = UserPermissionService;
|
|
46
|
+
// # sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci1wZXJtaXNzaW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3NlcnZpY2VzL2F1dGhvcml6YXRpb24vaW50ZXJuYWwvdXNlci1wZXJtaXNzaW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBRUEscUZBQTJEO0FBTzNELE1BQXFCLHFCQUFxQjtJQVF4QyxZQUE2QixPQUE4QjtRQUE5QixZQUFPLEdBQVAsT0FBTyxDQUF1QjtRQVBuRCw2QkFBd0IsR0FBRyxDQUFDLENBQUM7UUFFckMsaUVBQWlFO1FBQ2pFLDJEQUEyRDtRQUMzRCxvREFBb0Q7UUFDNUMsaUJBQVksR0FBMkMsSUFBSSxDQUFDO0lBRU4sQ0FBQztJQUV4RCxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQWM7UUFDckMsSUFDRSxDQUFDLElBQUksQ0FBQyx3QkFBd0I7WUFDOUIsSUFBSSxDQUFDLHdCQUF3QixHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUU7WUFDMUMsQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFDdEM7WUFDQSxJQUFJLENBQUMsd0JBQXdCO2dCQUMzQixJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQ0FBaUMsR0FBRyxJQUFJLENBQUM7WUFFckUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLG1DQUFtQyxDQUFDLENBQUM7WUFFbEUsbUVBQW1FO1lBQ25FLG9FQUFvRTtZQUNwRSxxQ0FBcUM7WUFDckMsSUFBSSxDQUFDLFlBQVksR0FBRyx5QkFBYSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUMzRCxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUNyRCxDQUFDO1NBQ0g7UUFFRCxPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFFTSxVQUFVO1FBQ2YsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7UUFDekIsSUFBSSxDQUFDLHdCQUF3QixHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztJQUMzRCxDQUFDO0NBQ0Y7QUFwQ0Qsd0NBb0NDIn0=
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Collection, ConditionTree } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { Context } from 'koa';
|
|
3
|
+
import { AgentOptionsWithDefaults } from '../types';
|
|
4
|
+
declare type RolesOptions = Pick<AgentOptionsWithDefaults, 'forestServerUrl' | 'envSecret' | 'isProduction' | 'permissionsCacheDurationInSeconds'>;
|
|
5
|
+
export default class PermissionService {
|
|
6
|
+
private options;
|
|
7
|
+
private cache;
|
|
8
|
+
constructor(options: RolesOptions);
|
|
9
|
+
invalidateCache(renderingId: number): void;
|
|
10
|
+
/** Checks that a charting query is in the list of allowed queries */
|
|
11
|
+
canChart(context: Context): Promise<void>;
|
|
12
|
+
/** Check if a user is allowed to perform a specific action */
|
|
13
|
+
can(context: Context, action: string, allowRefetch?: boolean): Promise<void>;
|
|
14
|
+
getScope(collection: Collection, context: Context): Promise<ConditionTree>;
|
|
15
|
+
/** Get cached version of "rendering permissions" */
|
|
16
|
+
private getRenderingPermissions;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const lru_cache_1 = __importDefault(require("lru-cache"));
|
|
7
|
+
const object_hash_1 = __importDefault(require("object-hash"));
|
|
8
|
+
const types_1 = require("../types");
|
|
9
|
+
const condition_tree_parser_1 = __importDefault(require("../utils/condition-tree-parser"));
|
|
10
|
+
const forest_http_api_1 = __importDefault(require("../utils/forest-http-api"));
|
|
11
|
+
class PermissionService {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
this.options = options;
|
|
14
|
+
this.cache = new lru_cache_1.default({
|
|
15
|
+
max: 256,
|
|
16
|
+
ttl: this.options.permissionsCacheDurationInSeconds * 1000,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
invalidateCache(renderingId) {
|
|
20
|
+
this.cache.delete(renderingId);
|
|
21
|
+
}
|
|
22
|
+
/** Checks that a charting query is in the list of allowed queries */
|
|
23
|
+
async canChart(context) {
|
|
24
|
+
// If the permissions level already allow the chart, no need to check further
|
|
25
|
+
if (['admin', 'editor', 'developer'].includes(context.state.user.permissionLevel)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const chart = { ...context.request.body };
|
|
29
|
+
// When the server sends the data of the allowed charts, the target column is not specified
|
|
30
|
+
// for relations => allow them all.
|
|
31
|
+
if (chart?.group_by_field?.includes(':'))
|
|
32
|
+
chart.group_by_field = chart.group_by_field.substring(0, chart.group_by_field.indexOf(':'));
|
|
33
|
+
const chartHash = (0, object_hash_1.default)(chart, {
|
|
34
|
+
respectType: false,
|
|
35
|
+
excludeKeys: key => chart[key] === null,
|
|
36
|
+
});
|
|
37
|
+
await this.can(context, `chart:${chartHash}`);
|
|
38
|
+
}
|
|
39
|
+
/** Check if a user is allowed to perform a specific action */
|
|
40
|
+
async can(context, action, allowRefetch = true) {
|
|
41
|
+
const { id: userId, renderingId } = context.state.user;
|
|
42
|
+
const perms = await this.getRenderingPermissions(renderingId);
|
|
43
|
+
const isAllowed = perms.actions.has(action) || perms.actionsByUser[action]?.has(userId);
|
|
44
|
+
if (!isAllowed && allowRefetch) {
|
|
45
|
+
this.invalidateCache(renderingId);
|
|
46
|
+
return this.can(context, action, false);
|
|
47
|
+
}
|
|
48
|
+
if (!isAllowed) {
|
|
49
|
+
context.throw(types_1.HttpCode.Forbidden, 'Forbidden');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async getScope(collection, context) {
|
|
53
|
+
const { user } = context.state;
|
|
54
|
+
const perms = await this.getRenderingPermissions(user.renderingId);
|
|
55
|
+
const scopes = perms.scopes[collection.name];
|
|
56
|
+
if (!scopes)
|
|
57
|
+
return null;
|
|
58
|
+
const conditionTree = condition_tree_parser_1.default.fromPlainObject(collection, scopes.conditionTree);
|
|
59
|
+
return conditionTree.replaceLeafs(leaf => {
|
|
60
|
+
const dynamicValues = scopes.dynamicScopeValues?.[user.id];
|
|
61
|
+
if (typeof leaf.value === 'string' && leaf.value.startsWith('$currentUser')) {
|
|
62
|
+
// Search replacement hash from forestadmin server
|
|
63
|
+
if (dynamicValues) {
|
|
64
|
+
return leaf.override({ value: dynamicValues[leaf.value] });
|
|
65
|
+
}
|
|
66
|
+
// Search JWT token (new user)
|
|
67
|
+
return leaf.override({
|
|
68
|
+
value: leaf.value.startsWith('$currentUser.tags.')
|
|
69
|
+
? user.tags[leaf.value.substring(18)]
|
|
70
|
+
: user[leaf.value.substring(13)],
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return leaf;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/** Get cached version of "rendering permissions" */
|
|
77
|
+
getRenderingPermissions(renderingId) {
|
|
78
|
+
if (!this.cache.has(renderingId))
|
|
79
|
+
this.cache.set(renderingId, forest_http_api_1.default.getPermissions(this.options, renderingId));
|
|
80
|
+
// We already checked the entry is up-to-date with the .has() call => allowStale
|
|
81
|
+
return this.cache.get(renderingId, { allowStale: true });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.default = PermissionService;
|
|
85
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVybWlzc2lvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvcGVybWlzc2lvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFFQSwwREFBaUM7QUFDakMsOERBQXFDO0FBRXJDLG9DQUE4RDtBQUM5RCwyRkFBaUU7QUFDakUsK0VBQStFO0FBTy9FLE1BQXFCLGlCQUFpQjtJQUlwQyxZQUFZLE9BQXFCO1FBQy9CLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxtQkFBUSxDQUFDO1lBQ3hCLEdBQUcsRUFBRSxHQUFHO1lBQ1IsR0FBRyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsaUNBQWlDLEdBQUcsSUFBSTtTQUMzRCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsZUFBZSxDQUFDLFdBQW1CO1FBQ2pDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRCxxRUFBcUU7SUFDckUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxPQUFnQjtRQUM3Qiw2RUFBNkU7UUFDN0UsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxFQUFFO1lBQ2pGLE9BQU87U0FDUjtRQUVELE1BQU0sS0FBSyxHQUFHLEVBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRTFDLDJGQUEyRjtRQUMzRixtQ0FBbUM7UUFDbkMsSUFBSSxLQUFLLEVBQUUsY0FBYyxFQUFFLFFBQVEsQ0FBQyxHQUFHLENBQUM7WUFDdEMsS0FBSyxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLGNBQWMsQ0FBQyxPQUFP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
|
package/dist/types.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export type AgentOptions = {
|
|
|
19
19
|
permissionsCacheDurationInSeconds?: number;
|
|
20
20
|
skipSchemaUpdate?: boolean;
|
|
21
21
|
forestAdminClient?: ForestAdminClient;
|
|
22
|
+
limitExportSize?: number;
|
|
22
23
|
experimental?: {
|
|
23
24
|
webhookCustomActions?: boolean;
|
|
24
25
|
updateRecordCustomActions?: boolean;
|
package/dist/types.js
CHANGED
|
@@ -20,4 +20,4 @@ var RouteType;
|
|
|
20
20
|
RouteType[RouteType["Authentication"] = 3] = "Authentication";
|
|
21
21
|
RouteType[RouteType["PrivateRoute"] = 4] = "PrivateRoute";
|
|
22
22
|
})(RouteType = exports.RouteType || (exports.RouteType = {}));
|
|
23
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBbURBLElBQVksUUFRWDtBQVJELFdBQVksUUFBUTtJQUNsQixxREFBZ0IsQ0FBQTtJQUNoQixtREFBZSxDQUFBO0lBQ2YsdUVBQXlCLENBQUE7SUFDekIsbURBQWUsQ0FBQTtJQUNmLGlEQUFjLENBQUE7SUFDZCxxQ0FBUSxDQUFBO0lBQ1IsMkRBQW1CLENBQUE7QUFDckIsQ0FBQyxFQVJXLFFBQVEsR0FBUixnQkFBUSxLQUFSLGdCQUFRLFFBUW5CO0FBRUQsSUFBWSxTQU9YO0FBUEQsV0FBWSxTQUFTO0lBQ25CLGlHQUFpRztJQUNqRywyREFBaUIsQ0FBQTtJQUNqQix5REFBZ0IsQ0FBQTtJQUNoQix1REFBZSxDQUFBO0lBQ2YsNkRBQWtCLENBQUE7SUFDbEIseURBQWdCLENBQUE7QUFDbEIsQ0FBQyxFQVBXLFNBQVMsR0FBVCxpQkFBUyxLQUFULGlCQUFTLFFBT3BCIn0=
|
|
@@ -6,7 +6,7 @@ export default class CsvGenerator {
|
|
|
6
6
|
* - backpressure is properly applied without needing to extend Readable (for slow clients)
|
|
7
7
|
* - we stop making queries to the database if the client closes the connection.
|
|
8
8
|
*/
|
|
9
|
-
static generate(caller: Caller, projection: Projection, header: string, filter: PaginatedFilter, collection: Collection, list: Collection['list']): AsyncGenerator<string>;
|
|
9
|
+
static generate(caller: Caller, projection: Projection, header: string, filter: PaginatedFilter, limitExportSize: number, collection: Collection, list: Collection['list']): AsyncGenerator<string>;
|
|
10
10
|
private static convert;
|
|
11
11
|
}
|
|
12
12
|
//# sourceMappingURL=csv-generator.d.ts.map
|
|
@@ -10,23 +10,30 @@ class CsvGenerator {
|
|
|
10
10
|
* - backpressure is properly applied without needing to extend Readable (for slow clients)
|
|
11
11
|
* - we stop making queries to the database if the client closes the connection.
|
|
12
12
|
*/
|
|
13
|
-
static async *generate(caller, projection, header, filter, collection, list) {
|
|
13
|
+
static async *generate(caller, projection, header, filter, limitExportSize, collection, list) {
|
|
14
14
|
yield (0, format_1.writeToString)([header.split(',')], { headers: true, includeEndRowDelimiter: true });
|
|
15
15
|
const copiedFilter = { ...filter };
|
|
16
16
|
if (!copiedFilter.sort || copiedFilter.sort.length === 0) {
|
|
17
17
|
copiedFilter.sort = datasource_toolkit_1.SortFactory.byPrimaryKeys(collection);
|
|
18
18
|
}
|
|
19
19
|
let currentIndex = 0;
|
|
20
|
+
let pageLimit = limitExportSize != null ? Math.min(limitExportSize, exports.CHUNK_SIZE) : exports.CHUNK_SIZE;
|
|
20
21
|
let areAllRecordsFetched = false;
|
|
21
22
|
while (!areAllRecordsFetched) {
|
|
22
23
|
// the first argument is included in the range, the second is excluded
|
|
23
|
-
copiedFilter.page = new datasource_toolkit_1.Page(currentIndex,
|
|
24
|
+
copiedFilter.page = new datasource_toolkit_1.Page(currentIndex, pageLimit);
|
|
24
25
|
// eslint-disable-next-line no-await-in-loop
|
|
25
26
|
const records = await list(caller, new datasource_toolkit_1.PaginatedFilter(copiedFilter), projection);
|
|
26
27
|
if (records.length !== 0)
|
|
27
28
|
yield CsvGenerator.convert(records, projection);
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
currentIndex += pageLimit;
|
|
30
|
+
areAllRecordsFetched = records.length < exports.CHUNK_SIZE || limitExportSize === currentIndex;
|
|
31
|
+
if (limitExportSize) {
|
|
32
|
+
pageLimit = Math.min(exports.CHUNK_SIZE, limitExportSize - currentIndex);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
pageLimit = exports.CHUNK_SIZE;
|
|
36
|
+
}
|
|
30
37
|
}
|
|
31
38
|
}
|
|
32
39
|
static convert(records, projection) {
|
|
@@ -40,4 +47,4 @@ class CsvGenerator {
|
|
|
40
47
|
}
|
|
41
48
|
}
|
|
42
49
|
exports.default = CsvGenerator;
|
|
43
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3N2LWdlbmVyYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9jc3YtZ2VuZXJhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZDQUFpRDtBQUNqRCx3RUFTeUM7QUFFNUIsUUFBQSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBRS9CLE1BQXFCLFlBQVk7SUFDL0I7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENBQ3BCLE1BQWMsRUFDZCxVQUFzQixFQUN0QixNQUFjLEVBQ2QsTUFBdUIsRUFDdkIsZUFBdUIsRUFDdkIsVUFBc0IsRUFDdEIsSUFBd0I7UUFFeEIsTUFBTSxJQUFBLHNCQUFhLEVBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLHNCQUFzQixFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFFMUYsTUFBTSxZQUFZLEdBQUcsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO1FBRW5DLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxJQUFJLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUN4RCxZQUFZLENBQUMsSUFBSSxHQUFHLGdDQUFXLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1NBQzNEO1FBRUQsSUFBSSxZQUFZLEdBQUcsQ0FBQyxDQUFDO1FBQ3JCLElBQUksU0FBUyxHQUFHLGVBQWUsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxFQUFFLGtCQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsa0JBQVUsQ0FBQztRQUM3RixJQUFJLG9CQUFvQixHQUFHLEtBQUssQ0FBQztRQUVqQyxPQUFPLENBQUMsb0JBQW9CLEVBQUU7WUFDNUIsc0VBQXNFO1lBQ3RFLFlBQVksQ0FBQyxJQUFJLEdBQUcsSUFBSSx5QkFBSSxDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsQ0FBQztZQUV0RCw0Q0FBNEM7WUFDNUMsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksb0NBQWUsQ0FBQyxZQUFZLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztZQUVsRixJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQztnQkFBRSxNQUFNLFlBQVksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBRTFFLFlBQVksSUFBSSxTQUFTLENBQUM7WUFDMUIsb0JBQW9CLEdBQUcsT0FBTyxDQUFDLE1BQU0sR0FBRyxrQkFBVSxJQUFJLGVBQWUsS0FBSyxZQUFZLENBQUM7WUFFdkYsSUFBSSxlQUFlLEVBQUU7Z0JBQ25CLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLGtCQUFVLEVBQUUsZUFBZSxHQUFHLFlBQVksQ0FBQyxDQUFDO2FBQ2xFO2lCQUFNO2dCQUNMLFNBQVMsR0FBRyxrQkFBVSxDQUFDO2FBQ3hCO1NBQ0Y7SUFDSCxDQUFDO0lBRU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFxQixFQUFFLFVBQXNCO1FBQ2xFLE9BQU8sSUFBQSxzQkFBYSxFQUNsQixPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQ25CLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDckIsTUFBTSxLQUFLLEdBQUcsZ0NBQVcsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBRXZELElBQUksS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLGlCQUFpQixFQUFFO2dCQUMzQyxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDOUI7WUFFRCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUMsQ0FBQyxDQUNILEVBQ0QsRUFBRSxzQkFBc0IsRUFBRSxJQUFJLEVBQUUsQ0FDakMsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQS9ERCwrQkErREMifQ==
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { JSONAPIDocument } from 'json-api-serializer';
|
|
2
|
+
import { IssuerMetadata } from 'openid-client';
|
|
3
|
+
import { AgentOptions } from '../types';
|
|
4
|
+
export declare type IpWhitelistConfiguration = {
|
|
5
|
+
isFeatureEnabled: boolean;
|
|
6
|
+
ipRules: Array<{
|
|
7
|
+
type: number;
|
|
8
|
+
ipMinimum?: string;
|
|
9
|
+
ipMaximum?: string;
|
|
10
|
+
ip?: string;
|
|
11
|
+
range?: string;
|
|
12
|
+
}>;
|
|
13
|
+
};
|
|
14
|
+
export declare type UserInfo = {
|
|
15
|
+
id: number;
|
|
16
|
+
email: string;
|
|
17
|
+
firstName: string;
|
|
18
|
+
lastName: string;
|
|
19
|
+
team: string;
|
|
20
|
+
renderingId: number;
|
|
21
|
+
role: string;
|
|
22
|
+
tags: {
|
|
23
|
+
[key: string]: string;
|
|
24
|
+
};
|
|
25
|
+
permissionLevel: string;
|
|
26
|
+
};
|
|
27
|
+
declare type HttpOptions = Pick<AgentOptions, 'envSecret' | 'forestServerUrl' | 'isProduction'>;
|
|
28
|
+
export default class ForestHttpApi {
|
|
29
|
+
static getIpWhitelistConfiguration(options: HttpOptions): Promise<IpWhitelistConfiguration>;
|
|
30
|
+
static getOpenIdIssuerMetadata(options: HttpOptions): Promise<IssuerMetadata>;
|
|
31
|
+
static getUserInformation(options: HttpOptions, renderingId: number, accessToken: string): Promise<UserInfo>;
|
|
32
|
+
static hasSchema(options: HttpOptions, hash: string): Promise<boolean>;
|
|
33
|
+
static uploadSchema(options: HttpOptions, apimap: JSONAPIDocument): Promise<void>;
|
|
34
|
+
private static handleResponseError;
|
|
35
|
+
}
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=forest-http-api.d.ts.map
|