@steedos/standard-ui 2.2.55-beta.16
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/main/default/applications/.gitkeep +0 -0
- package/main/default/client/apps.client.js +37 -0
- package/main/default/client/tabs.client.js +55 -0
- package/main/default/objectTranslations/apps.en/apps.en.objectTranslation.yml +171 -0
- package/main/default/objectTranslations/apps.zh-CN/apps.zh-CN.objectTranslation.yml +186 -0
- package/main/default/objectTranslations/tabs.en/tabs.en.objectTranslation.yml +63 -0
- package/main/default/objectTranslations/tabs.zh-CN/tabs.zh-CN.objectTranslation.yml +63 -0
- package/main/default/objects/apps.action.js +79 -0
- package/main/default/objects/apps.object.js +94 -0
- package/main/default/objects/apps.object.yml +328 -0
- package/main/default/objects/tabs.object.yml +149 -0
- package/main/default/permissionsets/.gitkeep +0 -0
- package/main/default/profiles/.gitkeep +0 -0
- package/main/default/tabs/.gitkeep +0 -0
- package/main/default/triggers/.gitkeep +0 -0
- package/main/default/triggers/apps.oauth.trigger.remove.js +134 -0
- package/main/default/triggers/apps.trigger.js +135 -0
- package/main/default/triggers/tabs.trigger.js +35 -0
- package/main/default/triggers/tabs_api_name.trigger.js +24 -0
- package/main/default/triggers/tabs_metadata.trigger.js +85 -0
- package/package.json +16 -0
- package/package.service.js +75 -0
- package/public/.md +3 -0
- package/src/.md +3 -0
- package/webapp/.md +1 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const core = require('@steedos/core');
|
|
2
|
+
db.apps = Creator.Collections.apps ? Creator.Collections.apps : core.newCollection('apps')
|
|
3
|
+
|
|
4
|
+
db.apps.isInternalApp = function (url) {
|
|
5
|
+
var app_url, i, len, ref;
|
|
6
|
+
if (url && db.apps.INTERNAL_APPS) {
|
|
7
|
+
ref = db.apps.INTERNAL_APPS;
|
|
8
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
|
9
|
+
app_url = ref[i];
|
|
10
|
+
if (url.startsWith(app_url)) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
if (Meteor.isServer) {
|
|
19
|
+
db.apps.allow({
|
|
20
|
+
insert: function (userId, doc) {
|
|
21
|
+
if (!Steedos.isSpaceAdmin(doc.space, userId)) {
|
|
22
|
+
return false;
|
|
23
|
+
} else {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
update: function (userId, doc) {
|
|
28
|
+
if (!Steedos.isSpaceAdmin(doc.space, userId)) {
|
|
29
|
+
return false;
|
|
30
|
+
} else {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
remove: function (userId, doc) {
|
|
35
|
+
if (!Steedos.isSpaceAdmin(doc.space, userId)) {
|
|
36
|
+
return false;
|
|
37
|
+
} else {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (Meteor.isServer) {
|
|
45
|
+
// db.apps.before.insert (userId, doc) ->
|
|
46
|
+
// doc.internal = db.apps.isInternalApp(doc.url)
|
|
47
|
+
// return
|
|
48
|
+
db.apps.before.update(function (userId, doc, fieldNames, modifier, options) {
|
|
49
|
+
return modifier.$set = modifier.$set || {};
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
Fiber = require('fibers')
|
|
54
|
+
|
|
55
|
+
var getUserOrganizations = function(userId, spaceId){
|
|
56
|
+
var space_user = db.space_users.findOne({user:userId,space:spaceId}, {fields:{organizations:1}})
|
|
57
|
+
if(!space_user){
|
|
58
|
+
return []
|
|
59
|
+
}
|
|
60
|
+
var organizations = space_user.organizations
|
|
61
|
+
if(!organizations){
|
|
62
|
+
return []
|
|
63
|
+
}
|
|
64
|
+
var userOrgs = db.organizations.find({_id:{$in:organizations}}).fetch()
|
|
65
|
+
var parents = _.flatten(_.pluck(userOrgs, 'parents'))
|
|
66
|
+
return _.union(organizations,parents)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
var getUserApps = function (userId, spaceId) {
|
|
70
|
+
var userOrgs = getUserOrganizations(userId, spaceId);
|
|
71
|
+
var selector = {
|
|
72
|
+
$or: [
|
|
73
|
+
{$or: [{space: {$exists: false}}, {space: spaceId}]},
|
|
74
|
+
{ 'members.organizations': {$in: userOrgs} },
|
|
75
|
+
{ 'members.users': {$in: [ userId ]} }
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
return db.apps.find(selector, {sort: {sort: 1}}).fetch();
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// Creator.Objects['apps'].methods = {
|
|
82
|
+
// safe_apps: function (req, res) {
|
|
83
|
+
// return Fiber(function () {
|
|
84
|
+
// var userSession = req.user
|
|
85
|
+
// var userId = userSession.userId
|
|
86
|
+
// var spaceId = userSession.spaceId
|
|
87
|
+
// var apps = getUserApps(userId, spaceId);
|
|
88
|
+
// return res.send({
|
|
89
|
+
// "@odata.count": apps.length,
|
|
90
|
+
// value: apps
|
|
91
|
+
// });
|
|
92
|
+
// }).run();
|
|
93
|
+
// }
|
|
94
|
+
// }
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
name: apps
|
|
2
|
+
label: App
|
|
3
|
+
icon: apps
|
|
4
|
+
hidden: true
|
|
5
|
+
version: 2
|
|
6
|
+
fields:
|
|
7
|
+
name:
|
|
8
|
+
label: Name
|
|
9
|
+
type: text
|
|
10
|
+
defaultValue: ''
|
|
11
|
+
description: ''
|
|
12
|
+
inlineHelpText: ''
|
|
13
|
+
required: true
|
|
14
|
+
searchable: true
|
|
15
|
+
index: true
|
|
16
|
+
code:
|
|
17
|
+
label: API Name
|
|
18
|
+
type: text
|
|
19
|
+
required: true
|
|
20
|
+
searchable: true
|
|
21
|
+
icon_slds:
|
|
22
|
+
label: SLDS Icon
|
|
23
|
+
type: lookup
|
|
24
|
+
required: true
|
|
25
|
+
optionsFunction: !!js/function |
|
|
26
|
+
function () {
|
|
27
|
+
var options;
|
|
28
|
+
options = [];
|
|
29
|
+
|
|
30
|
+
_.forEach(Creator.resources.sldsIcons.standard, function (svg) {
|
|
31
|
+
return options.push({
|
|
32
|
+
value: svg,
|
|
33
|
+
label: svg,
|
|
34
|
+
icon: svg
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return options;
|
|
39
|
+
}
|
|
40
|
+
filterable: true
|
|
41
|
+
visible:
|
|
42
|
+
label: Visible
|
|
43
|
+
type: boolean
|
|
44
|
+
defaultValue: true
|
|
45
|
+
description:
|
|
46
|
+
label: Description
|
|
47
|
+
type: textarea
|
|
48
|
+
is_wide: true
|
|
49
|
+
tabs:
|
|
50
|
+
label: Tabs
|
|
51
|
+
type: lookup
|
|
52
|
+
multiple: true
|
|
53
|
+
group: Business object
|
|
54
|
+
is_wide: true
|
|
55
|
+
reference_to: tabs
|
|
56
|
+
reference_to_field: name
|
|
57
|
+
objects:
|
|
58
|
+
label: Objects
|
|
59
|
+
type: lookup
|
|
60
|
+
multiple: true
|
|
61
|
+
group: Business object
|
|
62
|
+
optionsFunction: !!js/function |
|
|
63
|
+
function () {
|
|
64
|
+
return Steedos.getObjectsOptions()
|
|
65
|
+
}
|
|
66
|
+
filterable: true
|
|
67
|
+
mobile_objects:
|
|
68
|
+
label: Mobile Objects
|
|
69
|
+
type: lookup
|
|
70
|
+
multiple: true
|
|
71
|
+
group: Business object
|
|
72
|
+
optionsFunction: !!js/function |
|
|
73
|
+
function () {
|
|
74
|
+
return Steedos.getObjectsOptions()
|
|
75
|
+
}
|
|
76
|
+
filterable: true
|
|
77
|
+
is_creator:
|
|
78
|
+
type: boolean
|
|
79
|
+
label: Item of Menu
|
|
80
|
+
defaultValue: true
|
|
81
|
+
group: Business object
|
|
82
|
+
mobile:
|
|
83
|
+
type: boolean
|
|
84
|
+
label: Mobile App
|
|
85
|
+
defaultValue: true
|
|
86
|
+
group: Business object
|
|
87
|
+
icon:
|
|
88
|
+
label: Icon
|
|
89
|
+
type: text
|
|
90
|
+
hidden: true
|
|
91
|
+
sort:
|
|
92
|
+
label: Sort Number
|
|
93
|
+
type: number
|
|
94
|
+
defaultValue: 9100
|
|
95
|
+
sortable: true
|
|
96
|
+
|
|
97
|
+
# members:
|
|
98
|
+
# type: object
|
|
99
|
+
# label: Members
|
|
100
|
+
# is_wide: true
|
|
101
|
+
# members.users:
|
|
102
|
+
# type: lookup
|
|
103
|
+
# label: User Members
|
|
104
|
+
# reference_to: users
|
|
105
|
+
# multiple: true
|
|
106
|
+
# filterable: true
|
|
107
|
+
# members.organizations:
|
|
108
|
+
# type: lookup
|
|
109
|
+
# label: Department Members
|
|
110
|
+
# reference_to: organizations
|
|
111
|
+
# multiple: true
|
|
112
|
+
# filterable: true
|
|
113
|
+
|
|
114
|
+
url:
|
|
115
|
+
label: URL
|
|
116
|
+
type: url
|
|
117
|
+
group: External Application
|
|
118
|
+
is_use_ie:
|
|
119
|
+
type: boolean
|
|
120
|
+
label: Open in IE (Using Steedos Desktop)
|
|
121
|
+
defaultValue: false
|
|
122
|
+
group: External Application
|
|
123
|
+
is_use_iframe:
|
|
124
|
+
type: boolean
|
|
125
|
+
label: Open with iframe
|
|
126
|
+
defaultValue: false
|
|
127
|
+
group: External Application
|
|
128
|
+
is_new_window:
|
|
129
|
+
type: boolean
|
|
130
|
+
label: Open in New Window
|
|
131
|
+
defaultValue: false
|
|
132
|
+
group: External Application
|
|
133
|
+
on_click:
|
|
134
|
+
type: textarea
|
|
135
|
+
label: onClick
|
|
136
|
+
rows: 2
|
|
137
|
+
is_wide: true
|
|
138
|
+
group: External Application
|
|
139
|
+
|
|
140
|
+
auth_name:
|
|
141
|
+
label: Auth Name
|
|
142
|
+
type: text
|
|
143
|
+
group: External Application
|
|
144
|
+
secret:
|
|
145
|
+
label: API Secret Key
|
|
146
|
+
type: text
|
|
147
|
+
max: 16
|
|
148
|
+
min: 16
|
|
149
|
+
group: External Application
|
|
150
|
+
|
|
151
|
+
oauth2_enabled:
|
|
152
|
+
group: OAuth2
|
|
153
|
+
label: OAuth2 Enabled
|
|
154
|
+
type: boolean
|
|
155
|
+
hidden: true
|
|
156
|
+
oauth2_callback_url:
|
|
157
|
+
group: OAuth2
|
|
158
|
+
label: Callback URL
|
|
159
|
+
type: text
|
|
160
|
+
required: "{{formData.oauth2_enabled}}"
|
|
161
|
+
hidden: true
|
|
162
|
+
oauth2_scopes:
|
|
163
|
+
group: OAuth2
|
|
164
|
+
label: Scopes
|
|
165
|
+
type: select
|
|
166
|
+
hidden: true
|
|
167
|
+
multiple: true
|
|
168
|
+
required: "{{formData.oauth2_enabled}}"
|
|
169
|
+
options:
|
|
170
|
+
- label: Access to Your Unique Identifier (openid)
|
|
171
|
+
value: openid
|
|
172
|
+
- label: Access Basic Information (id, email, address, phone, locale)
|
|
173
|
+
value: profile
|
|
174
|
+
- label: Access Fully (full)
|
|
175
|
+
value: full
|
|
176
|
+
oauth2_logout_enabled:
|
|
177
|
+
group: OAuth2
|
|
178
|
+
label: OAuth2 Logout Enabled
|
|
179
|
+
type: boolean
|
|
180
|
+
hidden: true
|
|
181
|
+
oauth2_logout_url:
|
|
182
|
+
group: OAuth2
|
|
183
|
+
label: OAuth2 Logout URL
|
|
184
|
+
type: url
|
|
185
|
+
hidden: true
|
|
186
|
+
oauth2_home_url:
|
|
187
|
+
group: OAuth2
|
|
188
|
+
label: Homepage URL
|
|
189
|
+
type: url
|
|
190
|
+
required: "{{formData.oauth2_enabled}}"
|
|
191
|
+
hidden: true
|
|
192
|
+
oauth2_logo:
|
|
193
|
+
group: OAuth2
|
|
194
|
+
label: OAuth2 Logo
|
|
195
|
+
type: image
|
|
196
|
+
required: "{{formData.oauth2_enabled}}"
|
|
197
|
+
hidden: true
|
|
198
|
+
oauth2_client_secret:
|
|
199
|
+
group: OAuth2
|
|
200
|
+
label: OAuth2 Client secret
|
|
201
|
+
type: text
|
|
202
|
+
omit: true
|
|
203
|
+
hidden: true
|
|
204
|
+
saml_enabled:
|
|
205
|
+
hidden: true
|
|
206
|
+
group: SAML
|
|
207
|
+
label: SAML Enabled
|
|
208
|
+
type: boolean
|
|
209
|
+
saml_entity_id:
|
|
210
|
+
hidden: true
|
|
211
|
+
group: SAML
|
|
212
|
+
label: Entity Id
|
|
213
|
+
type: text
|
|
214
|
+
saml_issuer:
|
|
215
|
+
hidden: true
|
|
216
|
+
group: SAML
|
|
217
|
+
label: Issuer
|
|
218
|
+
type: text
|
|
219
|
+
saml_idp_cert:
|
|
220
|
+
hidden: true
|
|
221
|
+
group: SAML
|
|
222
|
+
label: IDP Cert
|
|
223
|
+
type: text
|
|
224
|
+
saml_acs_url:
|
|
225
|
+
hidden: true
|
|
226
|
+
group: SAML
|
|
227
|
+
label: ACS URL
|
|
228
|
+
type: url
|
|
229
|
+
saml_name_id_format:
|
|
230
|
+
hidden: true
|
|
231
|
+
group: SAML
|
|
232
|
+
label: Name
|
|
233
|
+
type: text
|
|
234
|
+
saml_logout_enabled:
|
|
235
|
+
hidden: true
|
|
236
|
+
group: SAML
|
|
237
|
+
label: SAML Logout Enabled
|
|
238
|
+
type: boolean
|
|
239
|
+
saml_logout_url:
|
|
240
|
+
hidden: true
|
|
241
|
+
group: SAML
|
|
242
|
+
label: SAML Logout URL
|
|
243
|
+
type: url
|
|
244
|
+
saml_logout_block:
|
|
245
|
+
hidden: true
|
|
246
|
+
group: SAML
|
|
247
|
+
label: SAML Logout Block
|
|
248
|
+
type: select
|
|
249
|
+
options:
|
|
250
|
+
- label: HTTP Redirect
|
|
251
|
+
value: redirect
|
|
252
|
+
- label: HTTP Post
|
|
253
|
+
value: post
|
|
254
|
+
is_system:
|
|
255
|
+
type: boolean
|
|
256
|
+
label: System
|
|
257
|
+
# omit: true
|
|
258
|
+
readonly: true
|
|
259
|
+
visible_on: "{{global.mode ==='read' ? true : false}}"
|
|
260
|
+
disabled: true
|
|
261
|
+
from_code_id:
|
|
262
|
+
type: text
|
|
263
|
+
visible_on: "{{false}}"
|
|
264
|
+
disabled: true
|
|
265
|
+
paging:
|
|
266
|
+
enabled: false
|
|
267
|
+
actions:
|
|
268
|
+
customize:
|
|
269
|
+
label: Customize
|
|
270
|
+
on: record_only
|
|
271
|
+
reset:
|
|
272
|
+
label: Reset
|
|
273
|
+
on: record_only
|
|
274
|
+
createOAuth2App:
|
|
275
|
+
label: 创建 OAuth 应用
|
|
276
|
+
on: list
|
|
277
|
+
sort: 180
|
|
278
|
+
list_views:
|
|
279
|
+
all:
|
|
280
|
+
label: All Apps
|
|
281
|
+
filter_scope: space
|
|
282
|
+
columns:
|
|
283
|
+
- name
|
|
284
|
+
- code
|
|
285
|
+
- description
|
|
286
|
+
- visible
|
|
287
|
+
- sort
|
|
288
|
+
- is_system
|
|
289
|
+
permission_set:
|
|
290
|
+
user:
|
|
291
|
+
allowCreate: false
|
|
292
|
+
allowDelete: false
|
|
293
|
+
allowEdit: false
|
|
294
|
+
allowRead: true
|
|
295
|
+
modifyAllRecords: false
|
|
296
|
+
viewAllRecords: true
|
|
297
|
+
admin:
|
|
298
|
+
allowCreate: true
|
|
299
|
+
allowDelete: true
|
|
300
|
+
allowEdit: true
|
|
301
|
+
allowRead: true
|
|
302
|
+
modifyAllRecords: true
|
|
303
|
+
viewAllRecords: true
|
|
304
|
+
# triggers:
|
|
305
|
+
# before.insert.server.apps:
|
|
306
|
+
# 'on': server
|
|
307
|
+
# when: before.insert
|
|
308
|
+
# todo: !!js/function |
|
|
309
|
+
# function (userId, doc) {
|
|
310
|
+
# return doc.icon = doc.icon_slds;
|
|
311
|
+
# }
|
|
312
|
+
# after.update.server.apps:
|
|
313
|
+
# 'on': server
|
|
314
|
+
# when: after.update
|
|
315
|
+
# todo: !!js/function |
|
|
316
|
+
# function (userId, doc, fieldNames, modifier, options) {
|
|
317
|
+
# var ref;
|
|
318
|
+
|
|
319
|
+
# if (modifier != null ? (ref = modifier.$set) != null ? ref.icon_slds : void 0 : void 0) {
|
|
320
|
+
# return Creator.getCollection("apps").direct.update({
|
|
321
|
+
# _id: doc._id
|
|
322
|
+
# }, {
|
|
323
|
+
# $set: {
|
|
324
|
+
# icon: modifier.$set.icon_slds
|
|
325
|
+
# }
|
|
326
|
+
# });
|
|
327
|
+
# }
|
|
328
|
+
# }
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
name: tabs
|
|
2
|
+
label: Tabs
|
|
3
|
+
icon: apps
|
|
4
|
+
hidden: true
|
|
5
|
+
version: 2.0
|
|
6
|
+
fields:
|
|
7
|
+
label:
|
|
8
|
+
inlineHelpText: This is the label of the tab, for web tabs only.
|
|
9
|
+
type: text
|
|
10
|
+
is_name: true
|
|
11
|
+
required: true
|
|
12
|
+
name:
|
|
13
|
+
label: Api Name
|
|
14
|
+
type: text
|
|
15
|
+
required: true
|
|
16
|
+
icon:
|
|
17
|
+
label: Icon
|
|
18
|
+
type: lookup
|
|
19
|
+
required: true
|
|
20
|
+
optionsFunction: !<tag:yaml.org,2002:js/function> |-
|
|
21
|
+
function () {
|
|
22
|
+
var options;
|
|
23
|
+
options = [];
|
|
24
|
+
|
|
25
|
+
_.forEach(Creator.resources.sldsIcons.standard, function (svg) {
|
|
26
|
+
return options.push({
|
|
27
|
+
value: svg,
|
|
28
|
+
label: svg,
|
|
29
|
+
icon: svg
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return options;
|
|
34
|
+
}
|
|
35
|
+
parent:
|
|
36
|
+
label: Parent
|
|
37
|
+
type: lookup
|
|
38
|
+
reference_to: tabs
|
|
39
|
+
omit: true
|
|
40
|
+
hidden: true
|
|
41
|
+
type:
|
|
42
|
+
type: select
|
|
43
|
+
options:
|
|
44
|
+
- label: Object
|
|
45
|
+
value: object
|
|
46
|
+
- label: Url
|
|
47
|
+
value: url
|
|
48
|
+
- label: Page
|
|
49
|
+
value: page
|
|
50
|
+
mobile:
|
|
51
|
+
label: Display on the Mobile
|
|
52
|
+
type: boolean
|
|
53
|
+
defaultValue: true
|
|
54
|
+
desktop:
|
|
55
|
+
label: Display on the Desktop
|
|
56
|
+
type: boolean
|
|
57
|
+
defaultValue: true
|
|
58
|
+
frame_height:
|
|
59
|
+
hidden: true
|
|
60
|
+
inlineHelpText: The height, in pixels of the tab frame. Required for frame and page tabs.
|
|
61
|
+
label: Height
|
|
62
|
+
type: number
|
|
63
|
+
has_sidebar:
|
|
64
|
+
hidden: true
|
|
65
|
+
inlineHelpText: Indicates if the tab displays the sidebar panel.
|
|
66
|
+
type: boolean
|
|
67
|
+
object:
|
|
68
|
+
label: Object
|
|
69
|
+
type: lookup
|
|
70
|
+
reference_to: objects
|
|
71
|
+
reference_to_field: name
|
|
72
|
+
optionsFunction: !!js/function |
|
|
73
|
+
function () {
|
|
74
|
+
return Steedos.getObjectsOptions()
|
|
75
|
+
}
|
|
76
|
+
filterable: true
|
|
77
|
+
required: "{{'object' === formData.type ? true: false}}"
|
|
78
|
+
visible_on: "{{'object' === formData.type ? true: false}}"
|
|
79
|
+
url:
|
|
80
|
+
type: url
|
|
81
|
+
label: Url
|
|
82
|
+
required: "{{'url' === formData.type ? true: false}}"
|
|
83
|
+
visible_on: "{{'url' === formData.type ? true: false}}"
|
|
84
|
+
is_new_window:
|
|
85
|
+
type: boolean
|
|
86
|
+
visible_on: "{{'url' === formData.type ? true: false}}"
|
|
87
|
+
page:
|
|
88
|
+
type: lookup
|
|
89
|
+
label: 页面
|
|
90
|
+
required: "{{'page' === formData.type ? true: false}}"
|
|
91
|
+
visible_on: "{{'page' === formData.type ? true: false}}"
|
|
92
|
+
reference_to: pages
|
|
93
|
+
reference_to_field: name
|
|
94
|
+
filters:
|
|
95
|
+
- ['type','notin', ['record','list','form']]
|
|
96
|
+
action_overrides:
|
|
97
|
+
type: text
|
|
98
|
+
hidden: true
|
|
99
|
+
inlineHelpText: A list of the action overrides that are assigned to the tab. Only one override is allowed per formFactor for a given tab.
|
|
100
|
+
description:
|
|
101
|
+
type: textarea
|
|
102
|
+
is_wide: true
|
|
103
|
+
is_system:
|
|
104
|
+
type: boolean
|
|
105
|
+
label: System
|
|
106
|
+
# omit: true
|
|
107
|
+
readonly: true
|
|
108
|
+
visible_on: "{{global.mode ==='read' ? true : false}}"
|
|
109
|
+
disabled: true
|
|
110
|
+
list_views:
|
|
111
|
+
all:
|
|
112
|
+
label: All Apps
|
|
113
|
+
filter_scope: space
|
|
114
|
+
columns:
|
|
115
|
+
- label
|
|
116
|
+
- name
|
|
117
|
+
# - parent
|
|
118
|
+
- desktop
|
|
119
|
+
- mobile
|
|
120
|
+
- type
|
|
121
|
+
- is_system
|
|
122
|
+
permission_set:
|
|
123
|
+
user:
|
|
124
|
+
allowCreate: false
|
|
125
|
+
allowDelete: false
|
|
126
|
+
allowEdit: false
|
|
127
|
+
allowRead: true
|
|
128
|
+
modifyAllRecords: false
|
|
129
|
+
viewAllRecords: true
|
|
130
|
+
admin:
|
|
131
|
+
allowCreate: true
|
|
132
|
+
allowDelete: true
|
|
133
|
+
allowEdit: true
|
|
134
|
+
allowRead: true
|
|
135
|
+
modifyAllRecords: true
|
|
136
|
+
viewAllRecords: true
|
|
137
|
+
# form:
|
|
138
|
+
# beforeEdit: !!js/function |
|
|
139
|
+
# function(){
|
|
140
|
+
# return Steedos.TabsManager.changeSchema(this.doc, this.schema, 'edit');
|
|
141
|
+
# }
|
|
142
|
+
# afterEdit: !!js/function |
|
|
143
|
+
# function(){
|
|
144
|
+
# return Steedos.TabsManager.changeSchema(this.doc, this.schema, 'edit');
|
|
145
|
+
# }
|
|
146
|
+
# beforeView: !!js/function |
|
|
147
|
+
# function(){
|
|
148
|
+
# Steedos.TabsManager.changeSchema(this.doc, this.schema, 'view');
|
|
149
|
+
# }
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
const _ = require('underscore');
|
|
2
|
+
const randomString = require("crypto-random-string");
|
|
3
|
+
const accounts = require('@steedos/accounts');
|
|
4
|
+
const objectql = require('@steedos/objectql')
|
|
5
|
+
|
|
6
|
+
const GrantTypes = ['authorization_code', 'refresh_token']
|
|
7
|
+
|
|
8
|
+
const getOAuth2ClientBody = (clientId, clientName, clientSecret, clientUri, logoUri, responseTypes, scope, callbacks) => {
|
|
9
|
+
return {
|
|
10
|
+
client_id: clientId,
|
|
11
|
+
client_name: clientName,
|
|
12
|
+
client_secret: clientSecret,
|
|
13
|
+
client_uri: clientUri,
|
|
14
|
+
logo_uri: logoUri,
|
|
15
|
+
response_types: responseTypes,
|
|
16
|
+
scope: scope,
|
|
17
|
+
callbacks: callbacks,
|
|
18
|
+
redirect_uris: [callbacks],
|
|
19
|
+
grant_types: GrantTypes,
|
|
20
|
+
token_endpoint_auth_method: 'client_secret_post'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//grant-types authorization_code,refresh_token
|
|
25
|
+
//token-endpoint-auth-method client_secret_post
|
|
26
|
+
const createOAuth2Client = async (clientId, clientName, clientSecret, clientUri, logoUri, responseTypes, scope, callbacks) => {
|
|
27
|
+
console.log(`createOAuth2Client`, clientId);
|
|
28
|
+
return await accounts.hydraAdmin.createOAuth2Client(getOAuth2ClientBody(clientId, clientName, clientSecret, clientUri, logoUri, responseTypes, scope, callbacks))
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const deleteOAuth2Client = async (clientId) => {
|
|
32
|
+
console.log(`deleteOAuth2Client`, clientId);
|
|
33
|
+
return await accounts.hydraAdmin.deleteOAuth2Client(clientId);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const updateOAuth2Client = async (clientId, clientName, clientSecret, clientUri, logoUri, responseTypes, scope, callbacks) => {
|
|
37
|
+
return await accounts.hydraAdmin.updateOAuth2Client(clientId, getOAuth2ClientBody(clientId, clientName, clientSecret, clientUri, logoUri, responseTypes, scope, callbacks))
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const upsetOAuth2Client = async (clientId, clientName, clientSecret, clientUri, logoUri, responseTypes, scope, callbacks) => {
|
|
41
|
+
const client = await accounts.hydraAdmin.getOAuth2Client(clientId);
|
|
42
|
+
if (client) {
|
|
43
|
+
return await updateOAuth2Client(clientId, clientName, clientSecret, clientUri, logoUri, responseTypes, scope, callbacks)
|
|
44
|
+
} else {
|
|
45
|
+
return await createOAuth2Client(clientId, clientName, clientSecret, clientUri, logoUri, responseTypes, scope, callbacks)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const getResponseTypes = (oauth2_scopes) => {
|
|
50
|
+
const scopes = ['code', 'id_token'];
|
|
51
|
+
_.each(oauth2_scopes, (oauth2_scope) => {
|
|
52
|
+
if (oauth2_scope === 'profile') {
|
|
53
|
+
scopes.push('steedos_id')
|
|
54
|
+
scopes.push('name')
|
|
55
|
+
scopes.push('username')
|
|
56
|
+
scopes.push('mobile')
|
|
57
|
+
scopes.push('email')
|
|
58
|
+
// scopes.push('job_number')
|
|
59
|
+
scopes.push('locale')
|
|
60
|
+
scopes.push('space')
|
|
61
|
+
// scopes.push('profile')
|
|
62
|
+
scopes.push('userId')
|
|
63
|
+
scopes.push('mobile_verified')
|
|
64
|
+
scopes.push('email_verified')
|
|
65
|
+
scopes.push('utcOffset')
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
return scopes;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = {
|
|
72
|
+
listenTo: 'apps',
|
|
73
|
+
beforeInsert: async function () {
|
|
74
|
+
const { doc } = this;
|
|
75
|
+
if (doc.oauth2_enabled) {
|
|
76
|
+
doc.oauth2_client_secret = randomString(40);
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
afterInsert: async function () {
|
|
80
|
+
const { doc } = this;
|
|
81
|
+
|
|
82
|
+
if (doc.oauth2_enabled) {
|
|
83
|
+
const responseTypes = getResponseTypes(doc.oauth2_scopes)
|
|
84
|
+
const result = await createOAuth2Client(
|
|
85
|
+
doc.code,
|
|
86
|
+
doc.name,
|
|
87
|
+
doc.oauth2_client_secret,
|
|
88
|
+
doc.oauth2_home_url,
|
|
89
|
+
Meteor.absoluteUrl(`/api/files/images/${doc.oauth2_logo}`),
|
|
90
|
+
responseTypes,
|
|
91
|
+
doc.oauth2_scopes.join(','),
|
|
92
|
+
doc.oauth2_callback_url
|
|
93
|
+
)
|
|
94
|
+
console.log(`result`, result);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
},
|
|
98
|
+
beforeUpdate: async function () {
|
|
99
|
+
const { doc, id } = this
|
|
100
|
+
if (doc.oauth2_enabled) {
|
|
101
|
+
const record = await objectql.getObject('apps').findOne(id);
|
|
102
|
+
if (!record.oauth2_client_secret) {
|
|
103
|
+
doc.oauth2_client_secret = randomString(40);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
afterUpdate: async function () {
|
|
108
|
+
const { previousDoc, id, doc } = this;
|
|
109
|
+
const newDoc = await objectql.getObject('apps').findOne(id)
|
|
110
|
+
|
|
111
|
+
if ((_.has(doc, 'oauth2_enabled') && previousDoc.oauth2_enabled && newDoc.oauth2_enabled != true) || (_.has(doc, 'code') && previousDoc.code != newDoc.code)) {
|
|
112
|
+
await deleteOAuth2Client(newDoc.code)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (newDoc.oauth2_enabled) {
|
|
116
|
+
const responseTypes = getResponseTypes(newDoc.oauth2_scopes)
|
|
117
|
+
await upsetOAuth2Client(
|
|
118
|
+
newDoc.code,
|
|
119
|
+
newDoc.name,
|
|
120
|
+
newDoc.oauth2_client_secret,
|
|
121
|
+
newDoc.oauth2_home_url,
|
|
122
|
+
Meteor.absoluteUrl(`/api/files/images/${newDoc.oauth2_logo}`),
|
|
123
|
+
responseTypes,
|
|
124
|
+
newDoc.oauth2_scopes.join(','),
|
|
125
|
+
newDoc.oauth2_callback_url)
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
afterDelete: async function () {
|
|
129
|
+
const { previousDoc } = this;
|
|
130
|
+
if (previousDoc.oauth2_enabled) {
|
|
131
|
+
await deleteOAuth2Client(doc.code)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|