@fleetbase/ember-core 0.2.14 → 0.2.15

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.
@@ -0,0 +1,39 @@
1
+ import { Ability } from 'ember-can';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { singularize } from 'ember-inflector';
5
+
6
+ export default class extends Ability {
7
+ @service currentUser;
8
+ @tracked service;
9
+ @tracked resource;
10
+ @tracked ability;
11
+ @tracked permissions = new Set();
12
+
13
+ constructor() {
14
+ super(...arguments);
15
+ this.permissions = new Set(this.currentUser.permissions.map((permission) => permission.name));
16
+ }
17
+
18
+ parseProperty(str) {
19
+ let [service, ability, resource] = str.split(' ');
20
+
21
+ this.service = service;
22
+ this.ability = ability;
23
+ this.resource = singularize(resource);
24
+
25
+ return 'can';
26
+ }
27
+
28
+ get can() {
29
+ if (this.currentUser.isAdmin) {
30
+ return true;
31
+ }
32
+
33
+ const permission = [this.service, this.ability, this.resource].join(' ');
34
+ const wilcardPermission = [this.service, '*', this.resource].join(' ');
35
+ const wildcardServicePermission = [this.service, '*'].join(' ');
36
+
37
+ return this.permissions.has(permission) || this.permissions.has(wilcardPermission) || this.permissions.has(wildcardServicePermission);
38
+ }
39
+ }
@@ -15,6 +15,7 @@ const hostServices = [
15
15
  'fileQueue',
16
16
  'universe',
17
17
  'intl',
18
+ 'abilities',
18
19
  { hostRouter: 'router' },
19
20
  ];
20
21
 
@@ -16,6 +16,7 @@ const services = [
16
16
  'fileQueue',
17
17
  'universe',
18
18
  'intl',
19
+ 'abilities',
19
20
  ];
20
21
 
21
22
  export default services;
@@ -0,0 +1,7 @@
1
+ import Service from 'ember-can/services/abilities';
2
+
3
+ export default class AbilitiesService extends Service {
4
+ parse(propertyName) {
5
+ return { propertyName, abilityName: 'dynamic' };
6
+ }
7
+ }
@@ -54,6 +54,13 @@ export default class CurrentUserService extends Service.extend(Evented) {
54
54
  id: 'anon',
55
55
  };
56
56
 
57
+ /**
58
+ * The current users permissions.
59
+ *
60
+ * @memberof CurrentUserService
61
+ */
62
+ @tracked permissions = [];
63
+
57
64
  /**
58
65
  * User options in localStorage
59
66
  *
@@ -96,36 +103,82 @@ export default class CurrentUserService extends Service.extend(Evented) {
96
103
  */
97
104
  @alias('user.company_uuid') companyId;
98
105
 
106
+ /**
107
+ * Alias for if user is admin.
108
+ *
109
+ * @var {Boolean}
110
+ * @memberof CurrentUserService
111
+ */
112
+ @alias('user.is_admin') isAdmin;
113
+
114
+ /**
115
+ * The prefix for this user options
116
+ *
117
+ * @var {String}
118
+ */
119
+ @computed('id') get optionsPrefix() {
120
+ return `${this.id}:`;
121
+ }
122
+
123
+ get latitude() {
124
+ return this.whois('latitude');
125
+ }
126
+
127
+ get longitude() {
128
+ return this.whois('longitude');
129
+ }
130
+
131
+ get currency() {
132
+ return this.whois('currency.code');
133
+ }
134
+
135
+ get city() {
136
+ return this.whois('city');
137
+ }
138
+
139
+ get country() {
140
+ return this.whois('country_code');
141
+ }
142
+
99
143
  /**
100
144
  * Loads the current authenticated user
101
145
  *
102
- * @void
146
+ * @return Promise<UserModel>|null
103
147
  */
104
148
  async load() {
105
149
  if (this.session.isAuthenticated) {
106
150
  let user = await this.store.findRecord('user', 'me');
107
151
  this.set('user', user);
108
152
  this.trigger('user.loaded', user);
153
+
154
+ // Set permissions
155
+ this.permissions = this.getUserPermissions(user);
156
+
157
+ return user;
109
158
  }
159
+
160
+ return null;
110
161
  }
111
162
 
112
163
  /**
113
164
  * Resolves a user model.
114
165
  *
115
- * @return {Promise}
166
+ * @return {Promise<User>}
116
167
  */
117
168
  @action promiseUser(options = {}) {
118
169
  const NoUserAuthenticatedError = new Error('Failed to authenticate user.');
119
170
 
120
171
  return new Promise((resolve, reject) => {
121
172
  if (this.session.isAuthenticated) {
122
- return this.store
123
- .queryRecord('user', { me: true })
124
- .then((user) => {
173
+ try {
174
+ this.store.queryRecord('user', { me: true }).then((user) => {
125
175
  // set the `current user`
126
176
  this.set('user', user);
127
177
  this.trigger('user.loaded', user);
128
178
 
179
+ // Set permissions
180
+ this.permissions = this.getUserPermissions(user);
181
+
129
182
  // set environment from user option
130
183
  this.theme.setEnvironment();
131
184
 
@@ -135,10 +188,10 @@ export default class CurrentUserService extends Service.extend(Evented) {
135
188
  }
136
189
 
137
190
  resolve(user);
138
- })
139
- .catch(() => {
140
- reject(NoUserAuthenticatedError);
141
191
  });
192
+ } catch (error) {
193
+ reject(NoUserAuthenticatedError);
194
+ }
142
195
  } else {
143
196
  reject(NoUserAuthenticatedError);
144
197
  }
@@ -146,60 +199,56 @@ export default class CurrentUserService extends Service.extend(Evented) {
146
199
  }
147
200
 
148
201
  /**
149
- * Loads and resolved all current users installed order configurations.
202
+ * Gets all user permissions.
150
203
  *
151
- * @return {Promise}
204
+ * @param {UserModel} user
205
+ * @return {Array}
206
+ * @memberof CurrentUserService
152
207
  */
153
- @action getInstalledOrderConfigs(params = {}) {
154
- return new Promise((resolve, reject) => {
155
- this.fetch
156
- .get('fleet-ops/order-configs/get-installed', params)
157
- .then((configs) => {
158
- const serialized = [];
208
+ getUserPermissions(user) {
209
+ const permissions = [];
159
210
 
160
- for (let i = 0; i < configs.length; i++) {
161
- const config = configs.objectAt(i);
162
- const normalizedConfig = this.store.normalize('order-config', config);
163
- const serializedConfig = this.store.push(normalizedConfig);
211
+ // get direct applied permissions
212
+ if (user.get('permissions')) {
213
+ permissions.pushObjects(user.get('permissions').toArray());
214
+ }
215
+
216
+ // get role permissions and role policies permissions
217
+ if (user.get('role')) {
218
+ if (user.get('role.permissions')) {
219
+ permissions.pushObjects(user.get('role.permissions').toArray());
220
+ }
164
221
 
165
- serialized.pushObject(serializedConfig);
222
+ if (user.get('role.policies')) {
223
+ for (let i = 0; i < user.get('role.policies').length; i++) {
224
+ const policy = user.get('role.policies').objectAt(i);
225
+ if (policy.get('permissions')) {
226
+ permissions.pushObjects(policy.get('permissions').toArray());
166
227
  }
228
+ }
229
+ }
230
+ }
167
231
 
168
- resolve(serialized);
169
- })
170
- .catch(reject);
171
- });
232
+ // get direct applied policy permissions
233
+ if (user.get('policies')) {
234
+ for (let i = 0; i < user.get('policies').length; i++) {
235
+ const policy = user.get('policies').objectAt(i);
236
+ if (policy.get('permissions')) {
237
+ permissions.pushObjects(policy.get('permissions').toArray());
238
+ }
239
+ }
240
+ }
241
+
242
+ return permissions;
172
243
  }
173
244
 
174
245
  /**
175
- * The prefix for this user options
246
+ * Alias to get a user's whois property
176
247
  *
177
- * @var {String}
248
+ * @param {String} key
249
+ * @return {Mixed}
250
+ * @memberof CurrentUserService
178
251
  */
179
- @computed('id') get optionsPrefix() {
180
- return `${this.id}:`;
181
- }
182
-
183
- get latitude() {
184
- return this.whois('latitude');
185
- }
186
-
187
- get longitude() {
188
- return this.whois('longitude');
189
- }
190
-
191
- get currency() {
192
- return this.whois('currency.code');
193
- }
194
-
195
- get city() {
196
- return this.whois('city');
197
- }
198
-
199
- get country() {
200
- return this.whois('country_code');
201
- }
202
-
203
252
  @action whois(key) {
204
253
  return this.getWhoisProperty(key);
205
254
  }
@@ -847,7 +847,7 @@ export default class UniverseService extends Service.extend(Evented) {
847
847
  // If component is a definition register to host application
848
848
  if (typeof component === 'function') {
849
849
  const owner = getOwner(this);
850
- const widgetId = component.widgetId || widgetId || this._createUniqueWidgetHashFromDefinition(component);
850
+ widgetId = component.widgetId || widgetId || this._createUniqueWidgetHashFromDefinition(component);
851
851
 
852
852
  if (owner) {
853
853
  owner.register(`component:${widgetId}`, component);
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/ember-core/abilities/dynamic';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/ember-core/services/abilities';
package/index.js CHANGED
@@ -41,6 +41,7 @@ module.exports = {
41
41
  new Funnel(path.dirname(require.resolve('socketcluster-client')), {
42
42
  files: ['socketcluster-client.min.js'],
43
43
  destDir: '/assets',
44
+ allowEmpty: true,
44
45
  })
45
46
  );
46
47
 
package/package.json CHANGED
@@ -1,128 +1,126 @@
1
1
  {
2
- "name": "@fleetbase/ember-core",
3
- "version": "0.2.14",
4
- "description": "Provides all the core services, decorators and utilities for building a Fleetbase extension for the Console.",
5
- "keywords": [
6
- "fleetbase-core",
7
- "fleetbase-services",
8
- "fleetbase",
9
- "ember-addon"
10
- ],
11
- "repository": "https://github.com/fleetbase/ember-core",
12
- "license": "AGPL-3.0-or-later",
13
- "author": "Fleetbase Pte Ltd <hello@fleetbase.io>",
14
- "directories": {
15
- "app": "app",
16
- "addon": "addon",
17
- "tests": "tests"
18
- },
19
- "scripts": {
20
- "build": "ember build --environment=production",
21
- "lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\"",
22
- "lint:css": "stylelint \"**/*.css\"",
23
- "lint:css:fix": "concurrently \"npm:lint:css -- --fix\"",
24
- "lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\"",
25
- "lint:hbs": "ember-template-lint .",
26
- "lint:hbs:fix": "ember-template-lint . --fix",
27
- "lint:js": "eslint . --cache",
28
- "lint:js:fix": "eslint . --fix",
29
- "start": "ember serve",
30
- "test": "concurrently \"npm:lint\" \"npm:test:*\" --names \"lint,test:\"",
31
- "test:ember": "ember test",
32
- "test:ember-compatibility": "ember try:each",
33
- "publish:npm": "npm config set registry https://registry.npmjs.org/ && npm publish",
34
- "publish:github": "npm config set '@fleetbase:registry' https://npm.pkg.github.com/ && npm publish"
35
- },
36
- "dependencies": {
37
- "@babel/core": "^7.23.2",
38
- "compress-json": "^3.0.0",
39
- "date-fns": "^2.30.0",
40
- "ember-auto-import": "^2.6.3",
41
- "ember-cli-babel": "^8.2.0",
42
- "ember-cli-htmlbars": "^6.3.0",
43
- "ember-cli-notifications": "^9.0.0",
44
- "ember-concurrency": "^3.1.1",
45
- "ember-concurrency-decorators": "^2.0.3",
46
- "ember-decorators": "^6.1.1",
47
- "ember-get-config": "^2.1.1",
48
- "ember-inflector": "^4.0.2",
49
- "ember-intl": "6.3.2",
50
- "ember-loading": "^2.0.0",
51
- "ember-local-storage": "^2.0.4",
52
- "ember-simple-auth": "^6.0.0",
53
- "ember-wormhole": "^0.6.0",
54
- "socketcluster-client": "^17.1.1"
55
- },
56
- "devDependencies": {
57
- "@babel/eslint-parser": "^7.22.15",
58
- "@babel/plugin-proposal-decorators": "^7.23.2",
59
- "@ember/optional-features": "^2.0.0",
60
- "@ember/test-helpers": "^3.2.0",
61
- "@embroider/test-setup": "^3.0.2",
62
- "@glimmer/component": "^1.1.2",
63
- "@glimmer/tracking": "^1.1.2",
64
- "broccoli-asset-rev": "^3.0.0",
65
- "broccoli-funnel": "^3.0.8",
66
- "broccoli-merge-trees": "^4.2.0",
67
- "broccoli-persistent-filter": "^3.1.3",
68
- "concurrently": "^8.2.2",
69
- "ember-cli": "~5.4.1",
70
- "ember-cli-clean-css": "^3.0.0",
71
- "ember-cli-dependency-checker": "^3.3.2",
72
- "ember-cli-inject-live-reload": "^2.1.0",
73
- "ember-cli-sri": "^2.1.1",
74
- "ember-cli-terser": "^4.0.2",
75
- "ember-data": "^4.12.5",
76
- "ember-file-upload": "8.4.0",
77
- "ember-load-initializers": "^2.1.2",
78
- "ember-page-title": "^8.0.0",
79
- "ember-qunit": "^8.0.1",
80
- "ember-resolver": "^11.0.1",
81
- "ember-source": "~5.4.0",
82
- "ember-source-channel-url": "^3.0.0",
83
- "ember-template-lint": "^5.11.2",
84
- "ember-try": "^3.0.0",
85
- "eslint": "^8.52.0",
86
- "eslint-config-prettier": "^9.0.0",
87
- "eslint-plugin-ember": "^11.11.1",
88
- "eslint-plugin-n": "^16.2.0",
89
- "eslint-plugin-prettier": "^5.0.1",
90
- "eslint-plugin-qunit": "^8.0.1",
91
- "loader.js": "^4.7.0",
92
- "prettier": "^3.0.3",
93
- "qunit": "^2.20.0",
94
- "qunit-dom": "^2.0.0",
95
- "resolve": "^1.22.2",
96
- "stylelint": "^15.11.0",
97
- "stylelint-config-standard": "^34.0.0",
98
- "stylelint-prettier": "^4.0.2",
99
- "webpack": "^5.89.0"
100
- },
101
- "overrides": {
102
- "broccoli-persistent-filter": "^3.1.3"
103
- },
104
- "engines": {
105
- "node": ">= 18"
106
- },
107
- "ember": {
108
- "edition": "octane"
109
- },
110
- "ember-addon": {
111
- "configPath": "tests/dummy/config"
112
- },
113
- "prettier": {
114
- "trailingComma": "es5",
115
- "tabWidth": 4,
116
- "semi": true,
117
- "singleQuote": true,
118
- "printWidth": 190,
119
- "overrides": [
120
- {
121
- "files": "*.hbs",
122
- "options": {
123
- "singleQuote": false
124
- }
125
- }
126
- ]
127
- }
2
+ "name": "@fleetbase/ember-core",
3
+ "version": "0.2.15",
4
+ "description": "Provides all the core services, decorators and utilities for building a Fleetbase extension for the Console.",
5
+ "keywords": [
6
+ "fleetbase-core",
7
+ "fleetbase-services",
8
+ "fleetbase",
9
+ "ember-addon"
10
+ ],
11
+ "repository": "https://github.com/fleetbase/ember-core",
12
+ "license": "AGPL-3.0-or-later",
13
+ "author": "Fleetbase Pte Ltd <hello@fleetbase.io>",
14
+ "directories": {
15
+ "app": "app",
16
+ "addon": "addon",
17
+ "tests": "tests"
18
+ },
19
+ "scripts": {
20
+ "build": "ember build --environment=production",
21
+ "lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\"",
22
+ "lint:css": "stylelint \"**/*.css\"",
23
+ "lint:css:fix": "concurrently \"npm:lint:css -- --fix\"",
24
+ "lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\"",
25
+ "lint:hbs": "ember-template-lint .",
26
+ "lint:hbs:fix": "ember-template-lint . --fix",
27
+ "lint:js": "eslint . --cache",
28
+ "lint:js:fix": "eslint . --fix",
29
+ "start": "ember serve",
30
+ "test": "concurrently \"npm:lint\" \"npm:test:*\" --names \"lint,test:\"",
31
+ "test:ember": "ember test",
32
+ "test:ember-compatibility": "ember try:each",
33
+ "publish:npm": "npm config set registry https://registry.npmjs.org/ && npm publish",
34
+ "publish:github": "npm config set '@fleetbase:registry' https://npm.pkg.github.com/ && npm publish"
35
+ },
36
+ "dependencies": {
37
+ "@babel/core": "^7.23.2",
38
+ "compress-json": "^3.0.0",
39
+ "date-fns": "^2.30.0",
40
+ "ember-auto-import": "^2.7.4",
41
+ "ember-can": "^6.0.0",
42
+ "ember-cli-babel": "^8.2.0",
43
+ "ember-cli-htmlbars": "^6.3.0",
44
+ "ember-cli-notifications": "^9.0.0",
45
+ "ember-concurrency": "^3.1.1",
46
+ "ember-concurrency-decorators": "^2.0.3",
47
+ "ember-decorators": "^6.1.1",
48
+ "ember-get-config": "^2.1.1",
49
+ "ember-inflector": "^4.0.2",
50
+ "ember-intl": "6.3.2",
51
+ "ember-loading": "^2.0.0",
52
+ "ember-local-storage": "^2.0.4",
53
+ "ember-simple-auth": "^6.0.0",
54
+ "ember-wormhole": "^0.6.0",
55
+ "socketcluster-client": "^17.1.1"
56
+ },
57
+ "devDependencies": {
58
+ "@babel/eslint-parser": "^7.22.15",
59
+ "@babel/plugin-proposal-decorators": "^7.23.2",
60
+ "@ember/optional-features": "^2.0.0",
61
+ "@ember/test-helpers": "^3.2.0",
62
+ "@embroider/test-setup": "^3.0.2",
63
+ "@glimmer/component": "^1.1.2",
64
+ "@glimmer/tracking": "^1.1.2",
65
+ "broccoli-asset-rev": "^3.0.0",
66
+ "broccoli-funnel": "^3.0.8",
67
+ "broccoli-merge-trees": "^4.2.0",
68
+ "broccoli-persistent-filter": "^3.1.3",
69
+ "concurrently": "^8.2.2",
70
+ "ember-cli": "~5.4.1",
71
+ "ember-cli-clean-css": "^3.0.0",
72
+ "ember-cli-dependency-checker": "^3.3.2",
73
+ "ember-cli-inject-live-reload": "^2.1.0",
74
+ "ember-cli-sri": "^2.1.1",
75
+ "ember-cli-terser": "^4.0.2",
76
+ "ember-data": "^4.12.5",
77
+ "ember-file-upload": "8.4.0",
78
+ "ember-load-initializers": "^2.1.2",
79
+ "ember-page-title": "^8.0.0",
80
+ "ember-qunit": "^8.0.1",
81
+ "ember-resolver": "^11.0.1",
82
+ "ember-source": "~5.4.0",
83
+ "ember-source-channel-url": "^3.0.0",
84
+ "ember-template-lint": "^5.11.2",
85
+ "ember-try": "^3.0.0",
86
+ "eslint": "^8.52.0",
87
+ "eslint-config-prettier": "^9.0.0",
88
+ "eslint-plugin-ember": "^11.11.1",
89
+ "eslint-plugin-n": "^16.2.0",
90
+ "eslint-plugin-prettier": "^5.0.1",
91
+ "eslint-plugin-qunit": "^8.0.1",
92
+ "loader.js": "^4.7.0",
93
+ "prettier": "^3.0.3",
94
+ "qunit": "^2.20.0",
95
+ "qunit-dom": "^2.0.0",
96
+ "resolve": "^1.22.2",
97
+ "stylelint": "^15.11.0",
98
+ "stylelint-config-standard": "^34.0.0",
99
+ "stylelint-prettier": "^4.0.2",
100
+ "webpack": "^5.89.0"
101
+ },
102
+ "engines": {
103
+ "node": ">= 18"
104
+ },
105
+ "ember": {
106
+ "edition": "octane"
107
+ },
108
+ "ember-addon": {
109
+ "configPath": "tests/dummy/config"
110
+ },
111
+ "prettier": {
112
+ "trailingComma": "es5",
113
+ "tabWidth": 4,
114
+ "semi": true,
115
+ "singleQuote": true,
116
+ "printWidth": 190,
117
+ "overrides": [
118
+ {
119
+ "files": "*.hbs",
120
+ "options": {
121
+ "singleQuote": false
122
+ }
123
+ }
124
+ ]
125
+ }
128
126
  }