Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7dfaff1538 | ||
|
|
e09b4fffe7 | ||
|
|
3deec2ed50 | ||
|
|
3fc22b4aa3 | ||
|
|
0cba914045 | ||
|
|
4c4d4e2351 | ||
|
|
e2fff61416 | ||
|
|
82e531e836 | ||
|
|
e6d68c2e4a | ||
|
|
9e55f5f157 | ||
|
|
eb539b9c5b | ||
|
|
5224512da0 | ||
|
|
6aec408003 | ||
|
|
f937bbf282 | ||
|
|
7996d5439c | ||
|
|
3f2a17f59c | ||
|
|
24a99d0fb7 | ||
|
|
fdc4a13194 | ||
|
|
70bfd4c181 | ||
|
|
10a81f8590 | ||
|
|
c75abc11dc | ||
|
|
e17db2e0d6 | ||
|
|
d2b67fa76c | ||
|
|
3af439f1e6 | ||
|
|
f143ba3d58 | ||
|
|
82bbe798fd | ||
|
|
346e0d356a | ||
|
|
f603c405a7 | ||
|
|
8eeab7e87b | ||
|
|
3d32200cf3 | ||
|
|
29d41efade | ||
|
|
8efa3168c8 | ||
|
|
cd9d3e91e5 | ||
|
|
3c49dc1c48 | ||
|
|
e6767b1e14 | ||
|
|
3347668b41 | ||
|
|
34da192ef9 | ||
|
|
d930c3da3a | ||
|
|
0a2305bba9 | ||
|
|
86ab7331af | ||
|
|
c351452d71 | ||
|
|
8952541203 | ||
|
|
128b0ff492 | ||
|
|
ccf462019b | ||
|
|
a69d01c9fc | ||
|
|
a2e27b09c3 | ||
|
|
3ff89279e6 | ||
|
|
2614b311a1 | ||
|
|
bd0854b0f6 | ||
|
|
e019b825ac | ||
|
|
6fd0301635 | ||
|
|
96cf75bfdb | ||
|
|
4a6ed0b509 | ||
|
|
cde6abd445 | ||
|
|
83c7b76f48 | ||
|
|
cb3104a624 | ||
|
|
f1f7be4067 | ||
|
|
0ae2451b9c | ||
|
|
069a864cbb | ||
|
|
a3337b3771 | ||
|
|
9ee89585ec | ||
|
|
03b603be54 | ||
|
|
bc7ed3f0ed | ||
|
|
0dff900795 | ||
|
|
a3517e53a8 | ||
|
|
3130831ae0 | ||
|
|
dd0d37241c | ||
|
|
9a10b68bbe | ||
|
|
30b9f65251 | ||
|
|
fb981c02ea | ||
|
|
1ee83dd1e6 | ||
|
|
359614517e | ||
|
|
9a8665a314 | ||
|
|
f4f7c0e343 | ||
|
|
dae5174d2f | ||
|
|
53eef5caeb | ||
|
|
50038cdf85 | ||
|
|
7386b2c9ed | ||
|
|
e3324ad64a | ||
|
|
39c0835a99 | ||
|
|
29e3e8b843 | ||
|
|
72b7b85ad1 | ||
|
|
9a1d1225ca | ||
|
|
33728a6496 | ||
|
|
bf2a6aeb6a | ||
|
|
746426fc82 | ||
|
|
d8b5056094 | ||
|
|
bdc2238f17 | ||
|
|
1842631056 | ||
|
|
6f2a04d4c6 | ||
|
|
e0b59b7d8b | ||
|
|
fbf6b2c201 | ||
|
|
7b212efcf2 | ||
|
|
ecb34d7427 | ||
|
|
4ab7304411 | ||
|
|
62077d3c25 | ||
|
|
1f0baceb5e | ||
|
|
2cda4f639e | ||
|
|
9f09f01f36 | ||
|
|
c8a76078ec | ||
|
|
96b0ae3b06 | ||
|
|
bc6f849270 | ||
|
|
2fcfab7c1c | ||
|
|
210296f298 | ||
|
|
c675f790ef | ||
|
|
b722fa361b | ||
|
|
40184006cd | ||
|
|
ec56d2fbbe | ||
|
|
bfc433dc38 | ||
|
|
f6e1fb0e3b | ||
|
|
2b58e82d6d | ||
|
|
a84e8c693e | ||
|
|
dcf24478bd | ||
|
|
04d14005c0 | ||
|
|
4fcb005a1f | ||
|
|
40ba4286d3 | ||
|
|
409e68de1e | ||
|
|
32ba330889 | ||
|
|
f00da3d8d7 | ||
|
|
f51c56b4a1 | ||
|
|
d996d085a1 | ||
|
|
9274849622 | ||
|
|
ae0ce2bfad | ||
|
|
27a676774c | ||
|
|
379609217b | ||
|
|
b31a513ec1 | ||
|
|
821b9b56a7 | ||
|
|
c1e1b42672 | ||
|
|
bd0189cf10 | ||
|
|
ca1b2ce278 | ||
|
|
bc76d49729 | ||
|
|
94530cec9c | ||
|
|
31cf696902 | ||
|
|
c2083aefab | ||
|
|
817d2a44e1 | ||
|
|
bdabcc119e | ||
|
|
b6a811cbbd | ||
|
|
6c3e5ba4a8 | ||
|
|
b18f21e6f9 | ||
|
|
ed7e24b328 | ||
|
|
66d115ab06 | ||
|
|
9ad8eb93c7 | ||
|
|
970101d5dc | ||
|
|
985566d8eb | ||
|
|
7234a3841a | ||
|
|
28c9e600aa | ||
|
|
163bbc9fb8 | ||
|
|
b54e68cb86 | ||
|
|
78585d999b | ||
|
|
ef9513fea9 | ||
|
|
92fdacb635 | ||
|
|
d16c50e33f | ||
|
|
22e8971a5b | ||
|
|
f5c183a0bd | ||
|
|
49303469cb | ||
|
|
6f8afbb7af | ||
|
|
923526ad26 | ||
|
|
c21b8fdb64 | ||
|
|
60005f0233 | ||
|
|
da89e2f82e | ||
|
|
c9d6f37343 | ||
|
|
85e4b46821 | ||
|
|
d464419e47 | ||
|
|
021803942f | ||
|
|
eeba8dceb6 | ||
|
|
8764633111 | ||
|
|
9becadd3f1 | ||
|
|
9f45a9a955 | ||
|
|
51b94f7ac8 | ||
|
|
890cfe5168 | ||
|
|
fe225653ec | ||
|
|
dce7447880 | ||
|
|
330c3de256 | ||
|
|
2d15a62990 | ||
|
|
62af6e2f6e | ||
|
|
f50acc9913 | ||
|
|
2900692c6c | ||
|
|
193a7e9600 | ||
|
|
6b3091ea1b | ||
|
|
26baf8a80b | ||
|
|
4ef66fdd29 | ||
|
|
52904dc639 | ||
|
|
f3a5ef5b7c | ||
|
|
7d8012ef1f | ||
|
|
18434d4203 | ||
|
|
d7e458ab85 | ||
|
|
c5416e770a | ||
|
|
2bb1c9cfec | ||
|
|
8bdd4416fc | ||
|
|
a5da593f07 | ||
|
|
15dc735322 | ||
|
|
d69b0f90d8 | ||
|
|
0bb5989259 | ||
|
|
106999746f | ||
|
|
d60ae81bdc | ||
|
|
c7cb1fbbd8 | ||
|
|
8a05dbbc56 | ||
|
|
dc78fe9028 | ||
|
|
24f630f084 | ||
|
|
d4ac887f7a | ||
|
|
9fe8ce2c00 | ||
|
|
af3cfb7298 | ||
|
|
df609dcf2c | ||
|
|
1b9f774937 | ||
|
|
509215f787 | ||
|
|
698160d423 | ||
|
|
12b18510b9 | ||
|
|
aa52b6f9bc | ||
|
|
ee47f8e19e | ||
|
|
97196368cb | ||
|
|
7e792d3f76 | ||
|
|
f4df337761 | ||
|
|
de44863d02 | ||
|
|
e3f9feb474 | ||
|
|
57410b7bb6 | ||
|
|
5e2c6ca0fd |
No files matched your search
@@ -0,0 +1,2 @@
|
||||
# Anyone attached to this rule will always been assigned to a pull request
|
||||
* @hashicorp/boundary-ui
|
||||
@@ -21,8 +21,8 @@ jobs:
|
||||
with:
|
||||
node-version: '16.x'
|
||||
- run: yarn install
|
||||
build:
|
||||
name: Build Admin UI
|
||||
build-admin-ui-oss:
|
||||
name: Build Admin UI OSS
|
||||
needs: [dependencies]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -34,13 +34,67 @@ jobs:
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- uses: actions/setup-node@v3
|
||||
- name: Build
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
if: steps.node-modules-cache.outputs.cache-hit != 'true'
|
||||
- run: yarn run build:ui:admin
|
||||
- name: Upload artifact
|
||||
- run: yarn run build:ui:admin:oss
|
||||
- name: Upload artifact admin-ui
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: admin-ui
|
||||
path: ./ui/admin/dist/
|
||||
path: ./ui/admin/dist/
|
||||
- name: Upload artifact OSS admin UI
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: admin-ui-oss
|
||||
path: ./ui/admin/dist/
|
||||
build-admin-ui-enterprise:
|
||||
name: Build Admin UI Enterprise
|
||||
needs: [dependencies]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- name: Build
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
if: steps.node-modules-cache.outputs.cache-hit != 'true'
|
||||
- run: yarn run build:ui:admin:enterprise
|
||||
- name: Upload artifact enterprise admin UI
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: admin-ui-ent
|
||||
path: ./ui/admin/dist/
|
||||
build-admin-ui-hcp:
|
||||
name: Build Admin UI HCP
|
||||
needs: [dependencies]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- name: Build
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16.x'
|
||||
if: steps.node-modules-cache.outputs.cache-hit != 'true'
|
||||
- run: yarn run build:ui:admin:hcp
|
||||
- name: Upload artifact HCP admin UI
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: admin-ui-hcp
|
||||
path: ./ui/admin/dist/
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
needs: [dependencies]
|
||||
needs: [dependencies, compliance]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
|
||||
test:
|
||||
name: Test
|
||||
needs: [dependencies]
|
||||
needs: [lint]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
yarn compliance:licenses
|
||||
npx lint-staged
|
||||
yarn test
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
COMMIT_MSG_FILE=$1
|
||||
COMMIT_SOURCE=$2
|
||||
SHA1=$3
|
||||
|
||||
# Don't run commitizen for merge or squash commits
|
||||
if [ "${COMMIT_SOURCE}" = merge ] || [ "${COMMIT_SOURCE}" = squash ];then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# This is to allow interaction with the terminal for commitizen
|
||||
exec < /dev/tty && npx git-cz --hook || true
|
||||
@@ -66,7 +66,6 @@ List of available project commands. `yarn run <command-name>`
|
||||
|---------------------|---|
|
||||
| build | Builds Admin UI. |
|
||||
| test | Runs tests in CI mode. |
|
||||
| commit | Replaces `git commit`, ensures compliance, audit, lint, and test checks pass before commit is allowed and normalizes commit messages across authors. |
|
||||
| lint | Runs ember-template-lint on all of the hbs, js, and sass files. |
|
||||
| compliance:audit | Checks for issues using `yarn audit` with moderate and above criticality.|
|
||||
| compliance:licenses | Checks that all dependencies have OSS-compatible licenses. |
|
||||
@@ -160,15 +159,16 @@ You will need to turn `off` mirage and run it: `$ ENABLE_MIRAGE=false yarn start
|
||||
|
||||
In login screen, authenticate using generated admin login name and password.
|
||||
|
||||
Enter the origin of your Boundary dev instance, by default is: `http://localhost:9200`.
|
||||
Enter the cluster URL of your Boundary dev instance, by default is: `http://localhost:9200`.
|
||||
|
||||
### Committing
|
||||
|
||||
Instead of the default `git commit`, we prescribe a custom command that ensures
|
||||
linting and other checks pass before a commit may be completed. It also ensures
|
||||
that all contributors author consistent commit messages. To get started with a
|
||||
commit, stage your files as usual. Then run `yarn commit` and follow the
|
||||
on-screen instructions to author your message.
|
||||
We use `husky` and `lint-staged` to ensure linting and other checks pass before a
|
||||
commit is completed. Simply do a `yarn install` to make sure the hooks are installed.
|
||||
|
||||
Use a normal `git commit` to go through the checks, if you need to skip these checks,
|
||||
use `git commit --no-verify` to bypass them. However, a consistent commit message will
|
||||
still be enforced even if you use `--no-verify`.
|
||||
|
||||
#### License Checking
|
||||
|
||||
|
||||
@@ -14,11 +14,7 @@ module.exports = {
|
||||
// end of babel-config
|
||||
},
|
||||
plugins: ['ember'],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:ember/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
extends: ['eslint:recommended', 'plugin:ember/recommended', 'prettier'],
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
extends: 'octane',
|
||||
extends: ['recommended', 'stylistic'],
|
||||
};
|
||||
@@ -47,21 +47,28 @@ List of available project commands. `yarn run <command-name>`
|
||||
| build:development | Builds the dummy app in development mode. |
|
||||
| build | Builds the dummy app for production. |
|
||||
| lint | Runs all lint commands. |
|
||||
| lint:fix | Runs automatic lint fixes for all type of file. |
|
||||
| lint:hbs | Runs lint for `hbs` template files. |
|
||||
| lint:hbs:fix | Runs automatic lint fixes for `hbs` template files. |
|
||||
| lint:js | Lints `js` files. |
|
||||
| lint:js:fix | Runs automatic lint fixes for `js` files. |
|
||||
| format | Runs all auto-formatters. |
|
||||
| format:js | Auto-formats `js` files using Prettier. |
|
||||
| start | Runs the dummy app local server. |
|
||||
| test | Runs all tests. |
|
||||
| test:all | Runs tests across multiple Ember versions with ember-try. |
|
||||
| test:ember-compatibility | Runs tests across multiple Ember versions with ember-try. |
|
||||
| precommit | Runs all lint and format. |
|
||||
| doc:toc | Automatically generates a table of contents for this README file. |
|
||||
|
||||
Additional commands in the monorepo package may affect this projects.
|
||||
|
||||
## Linting
|
||||
|
||||
* `yarn lint:fix`
|
||||
* `yarn lint:hbs`
|
||||
* `yarn lint:hbs:fix`
|
||||
* `yarn lint:js`
|
||||
* `yarn lint:js --fix`
|
||||
* `yarn lint:js:fix`
|
||||
|
||||
## Formatting
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import ModelAbility from './model';
|
||||
/**
|
||||
* Provides abilities for credential.
|
||||
*/
|
||||
export default class CredentialLibaryAbility extends ModelAbility {
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
* Only "known" credential libary types may be read.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canRead() {
|
||||
return !this.model.isUnknown && this.hasAuthorizedAction('read');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import ModelAbility from './model';
|
||||
import { inject as service } from '@ember/service';
|
||||
/**
|
||||
* Provides abilities for credential store.
|
||||
*/
|
||||
export default class CredentialStoreAbility extends ModelAbility {
|
||||
// =services
|
||||
|
||||
@service features;
|
||||
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
* Only "known" credential store types may be read.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canRead() {
|
||||
return this.features.isEnabled('static-credentials')
|
||||
? this.hasAuthorizedAction('read')
|
||||
: !this.model.isStatic && this.hasAuthorizedAction('read');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import ModelAbility from "./model";
|
||||
/**
|
||||
* Provides abilities for credential.
|
||||
*/
|
||||
export default class CredentialAbility extends ModelAbility {
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
* Only "known" credential types may be read.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canRead() {
|
||||
return !this.model.isUnknown && this.hasAuthorizedAction('read');
|
||||
}
|
||||
}
|
||||
@@ -30,10 +30,18 @@ export default class TargetAbility extends ModelAbility {
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canAddCredentialSources() {
|
||||
get canAddBrokeredCredentialSources() {
|
||||
return this.hasAuthorizedAction('add-credential-sources');
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canAddInjectedApplicationCredentialSources() {
|
||||
return (
|
||||
this.model.isSSH && this.hasAuthorizedAction('add-credential-sources')
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import ModelAbility from './model';
|
||||
|
||||
/**
|
||||
* Provides abilities for workers.
|
||||
*/
|
||||
export default class WorkerAbility extends ModelAbility {
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canCreateWorkerLed() {
|
||||
return this.hasAuthorizedCollectionAction('create:worker-led');
|
||||
}
|
||||
}
|
||||
@@ -43,4 +43,20 @@ export default class GeneratedAccountModel extends BaseModel {
|
||||
description: 'Current version number of this resource.',
|
||||
})
|
||||
version;
|
||||
|
||||
// =attributes (password)
|
||||
@attr('string', {
|
||||
for: 'password',
|
||||
isNestedAttribute: true,
|
||||
description: 'The account login name',
|
||||
})
|
||||
login_name;
|
||||
|
||||
// =attributes (OIDC)
|
||||
@attr('string', { for: 'oidc', isNestedAttribute: true }) subject;
|
||||
@attr('string', { for: 'oidc', isNestedAttribute: true }) issuer;
|
||||
@attr('string', { for: 'oidc', isNestedAttribute: true, readOnly: true })
|
||||
email;
|
||||
@attr('string', { for: 'oidc', isNestedAttribute: true, readOnly: true })
|
||||
full_name;
|
||||
}
|
||||
@@ -44,4 +44,27 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
|
||||
description: 'Current version number of this resource.',
|
||||
})
|
||||
version;
|
||||
|
||||
//= attributes (vault)
|
||||
|
||||
@attr('string', {
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'The HTTP method the library uses when requesting credentials from Vault.',
|
||||
defaultValue: () => 'GET',
|
||||
})
|
||||
http_method;
|
||||
|
||||
@attr('string', {
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'The body of the HTTP request the library sends to Vault when requesting credentials. Only valid if `http_method` is set to `POST`.',
|
||||
})
|
||||
http_request_body;
|
||||
|
||||
@attr('string', {
|
||||
isNestedAttribute: true,
|
||||
description: 'The path in Vault to request credentials from.',
|
||||
})
|
||||
path;
|
||||
}
|
||||
@@ -39,4 +39,90 @@ export default class GeneratedCredentialStoreModel extends BaseModel {
|
||||
description: 'Current version number of this resource.',
|
||||
})
|
||||
version;
|
||||
|
||||
// =attributes (vault)
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
"The address to Vault server. This should be a complete URL such as 'https://127.0.0.1:8200'",
|
||||
})
|
||||
address;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
isNestedAttribute: true,
|
||||
description: 'The namespace within Vault to use.',
|
||||
})
|
||||
namespace;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
"A PEM-encoded CA certificate to verify the Vault server's TLS certificate.",
|
||||
})
|
||||
ca_cert;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'Name to use as the SNI host when connecting to Vault via TLS.',
|
||||
})
|
||||
tls_server_name;
|
||||
|
||||
@attr('boolean', {
|
||||
for: 'vault',
|
||||
isNestedAttribute: true,
|
||||
description: 'Whether or not to skip TLS verification.',
|
||||
})
|
||||
tls_skip_verify;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
isNestedAttribute: true,
|
||||
description: 'A token used for accessing Vault.',
|
||||
})
|
||||
token;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
isNestedAttribute: true,
|
||||
description: 'The Vault token hmac.',
|
||||
readOnly: true,
|
||||
})
|
||||
token_hmac;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'A PEM-encoded client certificate to use for TLS authentication to the Vault server.',
|
||||
})
|
||||
client_certificate;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
"A PEM-encoded private key matching the client certificate from 'client_certificate'.",
|
||||
})
|
||||
client_certificate_key;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
isNestedAttribute: true,
|
||||
description: 'The Vault client certificate key hmac.',
|
||||
readOnly: true,
|
||||
})
|
||||
client_certificate_key_hmac;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'Filters to the worker(s) who can handle Vault requests for this cred store.',
|
||||
})
|
||||
worker_filter;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
/**
|
||||
* A credential is a data structure containing one or more secrets that binds an
|
||||
* identity to a set of permissions or capabilities on a host for a session.
|
||||
*/
|
||||
export default class GeneratedCredentialModel extends BaseModel {
|
||||
// =attributes
|
||||
|
||||
@attr('string', {
|
||||
description:
|
||||
'The ID of the Credential Store of which this Credential is a part.',
|
||||
})
|
||||
credential_store_id;
|
||||
|
||||
@attr('string', {
|
||||
description: 'The type of the resource, to help differentiate schemas',
|
||||
})
|
||||
type;
|
||||
|
||||
@attr('string', {
|
||||
description: 'Optional name for identification purposes',
|
||||
})
|
||||
name;
|
||||
|
||||
@attr('string', {
|
||||
description: 'Optional user-set description for identification purposes',
|
||||
})
|
||||
description;
|
||||
|
||||
@attr('date', {
|
||||
description: 'The time this resource was created\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
created_time;
|
||||
|
||||
@attr('date', {
|
||||
description: 'The time this resource was last updated\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
updated_time;
|
||||
|
||||
@attr('number', {
|
||||
description: 'Current version number of this resource.',
|
||||
})
|
||||
version;
|
||||
|
||||
// =attributes (username_password, ssh_private_key)
|
||||
@attr('string', {
|
||||
for: ['username_password', 'ssh_private_key'],
|
||||
isNestedAttribute: true,
|
||||
description: 'The username for credential.',
|
||||
})
|
||||
username;
|
||||
|
||||
// =attributes (username_password)
|
||||
@attr('string', {
|
||||
for: 'username_password',
|
||||
isNestedAttribute: true,
|
||||
description: 'The password for credential.',
|
||||
})
|
||||
password;
|
||||
|
||||
// =attributes (ssh_private_key)
|
||||
@attr('string', {
|
||||
for: 'ssh_private_key',
|
||||
isNestedAttribute: true,
|
||||
description: 'The private key for credential.',
|
||||
})
|
||||
private_key;
|
||||
|
||||
@attr('string', {
|
||||
for: 'ssh_private_key',
|
||||
isNestedAttribute: true,
|
||||
description: 'The private key passphrase for credential.',
|
||||
})
|
||||
private_key_passphrase;
|
||||
}
|
||||
@@ -44,4 +44,13 @@ export default class GeneratedManagedGroupModel extends BaseModel {
|
||||
'The ID of the Auth Method that is associated with this ManagedGroup',
|
||||
})
|
||||
auth_method_id;
|
||||
|
||||
// =attributes (OIDC)
|
||||
|
||||
@attr('string', {
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'The boolean expression filter to use to determine membership.',
|
||||
})
|
||||
filter;
|
||||
}
|
||||
@@ -30,7 +30,6 @@ export default class GeneratedTargetModel extends BaseModel {
|
||||
|
||||
@attr('number', {
|
||||
description: '',
|
||||
defaultValue: 1,
|
||||
})
|
||||
session_connection_limit;
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
/**
|
||||
* Worker contains all fields related to a worker resource
|
||||
*/
|
||||
export default class GeneratedWorkerModel extends BaseModel {
|
||||
// =attributes
|
||||
|
||||
@attr('string', {
|
||||
description: 'Optional name for identification purposes.',
|
||||
})
|
||||
name;
|
||||
|
||||
@attr('string', {
|
||||
description: 'Optional user-set description for identification purposes.',
|
||||
})
|
||||
description;
|
||||
|
||||
@attr('date', {
|
||||
description: 'The time this resource was created\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
created_time;
|
||||
|
||||
@attr('date', {
|
||||
description: 'The time this resource was last updated\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
updated_time;
|
||||
|
||||
@attr('number', {
|
||||
description: 'Current version number of this resource.',
|
||||
})
|
||||
version;
|
||||
|
||||
@attr('string', {
|
||||
description: 'The address that this worker is reachable at.\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
address;
|
||||
|
||||
@attr('date', {
|
||||
description:
|
||||
'The time this worker was last reported its status.\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
last_status_time;
|
||||
|
||||
@attr('string', {
|
||||
description:
|
||||
'The version of the Boundary binary the worker is running.\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
release_version;
|
||||
|
||||
@attr('number', {
|
||||
description:
|
||||
'The number of connections that this worker is currently handling.\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
active_connection_count;
|
||||
|
||||
@attr('string', {
|
||||
description:
|
||||
'The type of the worker, denoted by how it authenticates: pki or kms.\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
type;
|
||||
}
|
||||
@@ -1,17 +1,10 @@
|
||||
import GeneratedAccountModel from '../generated/models/account';
|
||||
import { fragment } from 'ember-data-model-fragments/attributes';
|
||||
import { computed } from '@ember/object';
|
||||
import { equal } from '@ember/object/computed';
|
||||
|
||||
export default class AccountModel extends GeneratedAccountModel {
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
* Attributes of this resource, if any, represented as a JSON fragment.
|
||||
* @type {FragmentAccountAttributesModel}
|
||||
*/
|
||||
@fragment('fragment-account-attributes', { defaultValue: {} }) attributes;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@@ -26,9 +19,9 @@ export default class AccountModel extends GeneratedAccountModel {
|
||||
* Convenience for getting username in account.
|
||||
* @type {string}
|
||||
*/
|
||||
@computed('attributes.{email,full_name,login_name}')
|
||||
@computed('{email,full_name,login_name}')
|
||||
get accountName() {
|
||||
const { email, full_name, login_name } = this.attributes;
|
||||
const { email, full_name, login_name } = this;
|
||||
return email || full_name || login_name;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import Model from '@ember-data/model';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { fragment } from 'ember-data-model-fragments/attributes';
|
||||
import { computed } from '@ember/object';
|
||||
|
||||
/**
|
||||
@@ -30,9 +29,8 @@ export default class BaseModel extends Model {
|
||||
|
||||
/**
|
||||
* Scope of this resource, if any, represented as a JSON fragment.
|
||||
* @type {FragmentScope}
|
||||
*/
|
||||
@fragment('fragment-scope') scope;
|
||||
@attr() scope;
|
||||
|
||||
// =attributes
|
||||
|
||||
@@ -55,6 +53,10 @@ export default class BaseModel extends Model {
|
||||
if (model) {
|
||||
const json = model.serialize();
|
||||
json.scope_id = model.id;
|
||||
json.type = model.type;
|
||||
json.isGlobal = model.isGlobal;
|
||||
json.isOrg = model.isOrg;
|
||||
json.isProject = model.isProject;
|
||||
this.scope = json;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import GeneratedCredentialLibraryModel from '../generated/models/credential-library';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { fragment } from 'ember-data-model-fragments/attributes';
|
||||
|
||||
/**
|
||||
* Enum options for credential library.
|
||||
@@ -9,22 +7,27 @@ export const options = {
|
||||
http_method: ['GET', 'POST'],
|
||||
};
|
||||
|
||||
/**
|
||||
* Supported Credential Library types.
|
||||
*/
|
||||
export const types = ['vault'];
|
||||
|
||||
export default class CredentialLibraryModel extends GeneratedCredentialLibraryModel {
|
||||
// =error attributes
|
||||
// These attributes exist solely to capture errors on nested fields.
|
||||
// See the application adapter's error normalization method for
|
||||
// more information.
|
||||
|
||||
@attr('string', { readOnly: true }) attributes_http_method;
|
||||
@attr('string', { readOnly: true }) attributes_http_request_body;
|
||||
@attr('string', { readOnly: true }) attributes_path;
|
||||
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
* Attributes of this resource, if any, represented as a JSON fragment.
|
||||
* @type {FragmentCredentialLibraryAttributesModel}
|
||||
* True if credential is an unknown type.
|
||||
* @type {boolean}
|
||||
*/
|
||||
@fragment('fragment-credential-library-attributes', { defaultValue: {} })
|
||||
attributes;
|
||||
get isUnknown() {
|
||||
return !types.includes(this.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* True if credential is a vault type.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isVault() {
|
||||
return this.type === 'vault';
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,16 @@
|
||||
import GeneratedCredentialStoreModel from '../generated/models/credential-store';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { fragment } from 'ember-data-model-fragments/attributes';
|
||||
import { equal } from '@ember/object/computed';
|
||||
|
||||
export default class CredentialStoreModel extends GeneratedCredentialStoreModel {
|
||||
// =error attributes
|
||||
// These attributes exist solely to capture errors on nested fields.
|
||||
// See the application adapter's error normalization method for
|
||||
// more information.
|
||||
|
||||
@attr('string', { readOnly: true }) attributes_address;
|
||||
@attr('string', { readOnly: true }) attributes_namespace;
|
||||
@attr('string', { readOnly: true }) attributes_ca_cert;
|
||||
@attr('string', { readOnly: true }) attributes_tls_server_name;
|
||||
@attr('string', { readOnly: true }) attributes_tls_skip_verify;
|
||||
@attr('string', { readOnly: true }) attributes_token;
|
||||
@attr('string', { readOnly: true }) attributes_client_certificate;
|
||||
@attr('string', { readOnly: true }) attributes_client_certificate_key;
|
||||
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
* Attributes of this resource, if any, represented as a JSON fragment.
|
||||
* @type {FragmentAuthMethodAttributesModel}
|
||||
*/
|
||||
@fragment('fragment-credential-store-attributes', { defaultValue: {} })
|
||||
attributes;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@equal('type', 'vault') isVault;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@equal('type', 'static') isStatic;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import GeneratedCredentialModel from '../generated/models/credential';
|
||||
|
||||
/**
|
||||
* Supported Credential types.
|
||||
*/
|
||||
export const types = ['username_password', 'ssh_private_key'];
|
||||
|
||||
export default class CredentialModel extends GeneratedCredentialModel {
|
||||
// =attributes
|
||||
/**
|
||||
* All Credentials are prefixed with "cred" and are considered
|
||||
* static due to their relation with Static Credential Stores.
|
||||
*
|
||||
* True if credential starts with the "cred" prefix.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isStatic() {
|
||||
return this.id.startsWith('cred');
|
||||
}
|
||||
|
||||
/**
|
||||
* True if credential is an unknown type.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isUnknown() {
|
||||
return !types.includes(this.type);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
export default class FragmentAccountAttributesModel extends Fragment {
|
||||
// =attributes (password)
|
||||
@attr('string', {
|
||||
for: 'password',
|
||||
description: 'The account login name',
|
||||
})
|
||||
login_name;
|
||||
|
||||
// =attributes (OIDC)
|
||||
@attr('string', { for: 'oidc' }) subject;
|
||||
@attr('string', { for: 'oidc' }) issuer;
|
||||
@attr('string', { for: 'oidc', readOnly: true }) email;
|
||||
@attr('string', { for: 'oidc', readOnly: true }) full_name;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { options } from './credential-library';
|
||||
|
||||
export default class FragmentCredentialLibraryAttributesModel extends Fragment {
|
||||
//= attributes (vault)
|
||||
|
||||
@attr('string', {
|
||||
description:
|
||||
'The HTTP method the library uses when requesting credentials from Vault.',
|
||||
defaultValue: () => options.http_method[0],
|
||||
})
|
||||
http_method;
|
||||
|
||||
@attr('string', {
|
||||
description:
|
||||
'The body of the HTTP request the library sends to Vault when requesting credentials. Only valid if `http_method` is set to `POST`.',
|
||||
})
|
||||
http_request_body;
|
||||
|
||||
@attr('string', {
|
||||
description: 'The path in Vault to request credentials from.',
|
||||
})
|
||||
path;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
export default class FragmentCredentialStoreAttributesModel extends Fragment {
|
||||
// =attributes (vault)
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
description:
|
||||
"The address to Vault server. This should be a complete URL such as 'https://127.0.0.1:8200'",
|
||||
})
|
||||
address;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
description: 'The namespace within Vault to use.',
|
||||
})
|
||||
namespace;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
description:
|
||||
"A PEM-encoded CA certificate to verify the Vault server's TLS certificate.",
|
||||
})
|
||||
ca_cert;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
description:
|
||||
'Name to use as the SNI host when connecting to Vault via TLS.',
|
||||
})
|
||||
tls_server_name;
|
||||
|
||||
@attr('boolean', {
|
||||
for: 'vault',
|
||||
description: 'Whether or not to skip TLS verification.',
|
||||
})
|
||||
tls_skip_verify;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
description: 'A token used for accessing Vault.',
|
||||
})
|
||||
token;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
description: 'The Vault token hmac.',
|
||||
readOnly: true,
|
||||
})
|
||||
token_hmac;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
description:
|
||||
'A PEM-encoded client certificate to use for TLS authentication to the Vault server.',
|
||||
})
|
||||
client_certificate;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
description:
|
||||
"A PEM-encoded private key matching the client certificate from 'client_certificate'.",
|
||||
})
|
||||
client_certificate_key;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault',
|
||||
description: 'The Vault client certificate key hmac.',
|
||||
readOnly: true,
|
||||
})
|
||||
client_certificate_key_hmac;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
export default class FragmentHostSourceModel extends Fragment {
|
||||
// =attributes
|
||||
|
||||
@attr('string', {
|
||||
description: 'ID of the related host source',
|
||||
})
|
||||
host_source_id;
|
||||
|
||||
@attr('string', {
|
||||
description: 'ID of the catalog to which the host set belongs',
|
||||
})
|
||||
host_catalog_id;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
export default class FragmentManagedGroupAttributesModel extends Fragment {
|
||||
// =attributes (OIDC)
|
||||
|
||||
@attr('string', {
|
||||
description:
|
||||
'The boolean expression filter to use to determine membership.',
|
||||
})
|
||||
filter;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
export default class FragmentPrincipal extends Fragment {
|
||||
// =attributes
|
||||
|
||||
@attr('string', {
|
||||
description: 'ID of the related scope',
|
||||
})
|
||||
scope_id;
|
||||
|
||||
@attr('string', {
|
||||
description: 'ID of the related principal (user or group)',
|
||||
})
|
||||
principal_id;
|
||||
|
||||
@attr('string', {
|
||||
description: 'Type of the related principal (user or group)',
|
||||
})
|
||||
type;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
import { computed } from '@ember/object';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { scopeTypes } from './scope';
|
||||
|
||||
export default class FragmentScope extends Fragment {
|
||||
// =attributes
|
||||
|
||||
@attr('string', {
|
||||
description: 'ID of the related scope',
|
||||
})
|
||||
scope_id;
|
||||
|
||||
@attr('string', {
|
||||
description: 'The type of the resource',
|
||||
})
|
||||
type;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@computed('type')
|
||||
get isGlobal() {
|
||||
return this.type === scopeTypes.global;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@computed('type')
|
||||
get isOrg() {
|
||||
return this.type === scopeTypes.org;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@computed('type')
|
||||
get isProject() {
|
||||
return this.type === scopeTypes.project;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,10 @@
|
||||
import GeneratedManagedGroupModel from '../generated/models/managed-group';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { fragment } from 'ember-data-model-fragments/attributes';
|
||||
import { A } from '@ember/array';
|
||||
|
||||
export default class ManagedGroupModel extends GeneratedManagedGroupModel {
|
||||
// =attributes
|
||||
|
||||
// =error attributes
|
||||
// These attributes exist solely to capture errors on nested fields.
|
||||
// See the application adapter's error normalization method for
|
||||
// more information.
|
||||
|
||||
@attr('string', { readOnly: true }) attributes_filter;
|
||||
|
||||
/**
|
||||
@@ -23,7 +17,4 @@ export default class ManagedGroupModel extends GeneratedManagedGroupModel {
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
member_ids;
|
||||
|
||||
@fragment('fragment-managed-group-attributes', { defaultValue: {} })
|
||||
attributes;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import GeneratedRoleModel from '../generated/models/role';
|
||||
import { fragmentArray, array } from 'ember-data-model-fragments/attributes';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
export default class RoleModel extends GeneratedRoleModel {
|
||||
// =attributes
|
||||
@@ -11,7 +11,7 @@ export default class RoleModel extends GeneratedRoleModel {
|
||||
* see obvious. Instead, the application layer is expected to load referenced
|
||||
* users and groups as needed.
|
||||
*/
|
||||
@fragmentArray('fragment-principal', {
|
||||
@attr('principal-array', {
|
||||
readOnly: true,
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
@@ -21,7 +21,16 @@ export default class RoleModel extends GeneratedRoleModel {
|
||||
* Grant strings are read-only. But grants can be persisted via a dedicated
|
||||
* call to `saveGrantStrings(grants)`.
|
||||
*/
|
||||
@array('string', { readOnly: true }) grant_strings;
|
||||
@attr({ readOnly: true, emptyArrayIfMissing: true }) grant_strings;
|
||||
|
||||
/**
|
||||
* Convenience for looking up the grant scope, if loaded.
|
||||
*/
|
||||
get grantScope() {
|
||||
return this.grant_scope_id
|
||||
? this.store.peekRecord('scope', this.grant_scope_id)
|
||||
: null;
|
||||
}
|
||||
|
||||
// =methods
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class SessionCredential {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static Library = class Library {
|
||||
static Source = class Source {
|
||||
id;
|
||||
name;
|
||||
description;
|
||||
@@ -42,7 +42,7 @@ class SessionCredential {
|
||||
|
||||
// =attributes
|
||||
rawCredential;
|
||||
library;
|
||||
source;
|
||||
#payloadSecret;
|
||||
|
||||
/**
|
||||
@@ -72,8 +72,8 @@ class SessionCredential {
|
||||
// =methods
|
||||
|
||||
constructor(cred) {
|
||||
const { id, name, description, type } = cred.credential_library;
|
||||
this.library = new SessionCredential.Library(id, name, description, type);
|
||||
const { id, name, description, type } = cred.credential_source;
|
||||
this.source = new SessionCredential.Source(id, name, description, type);
|
||||
this.#payloadSecret = cred.secret;
|
||||
this.rawCredential = cred;
|
||||
}
|
||||
|
||||
@@ -1,35 +1,43 @@
|
||||
import GeneratedTargetModel from '../generated/models/target';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { fragmentArray } from 'ember-data-model-fragments/attributes';
|
||||
import { computed } from '@ember/object';
|
||||
|
||||
export default class TargetModel extends GeneratedTargetModel {
|
||||
// =attributes
|
||||
|
||||
@attr('number', {
|
||||
isNestedAttribute: true,
|
||||
description: 'The default port a target should use if present.',
|
||||
description: 'The default port a target should use if present.',
|
||||
})
|
||||
default_port;
|
||||
|
||||
/**
|
||||
* @type {[FragmentHostSourceModel]}
|
||||
* @type Array
|
||||
*/
|
||||
@fragmentArray('fragment-host-source', {
|
||||
@attr('host-source-id-array', {
|
||||
readOnly: true,
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
host_sources;
|
||||
|
||||
/**
|
||||
* Credential source ids are read only and can be
|
||||
* persisted via a dedicated call to `addCredentialSources()`.
|
||||
* Brokered Credential source ids are read only and can be
|
||||
* persisted via a dedicated call to `addBrokeredCredentialSources()`.
|
||||
*/
|
||||
@fragmentArray('fragment-string', {
|
||||
@attr('string-array', {
|
||||
readOnly: true,
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
application_credential_source_ids;
|
||||
brokered_credential_source_ids;
|
||||
|
||||
/**
|
||||
* Injected Application Credential source ids are read only and can be
|
||||
* persisted via a dedicated call to `addInjectedApplicationCredentialSources()`.
|
||||
*/
|
||||
@attr('string-array', {
|
||||
readOnly: true,
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
injected_application_credential_source_ids;
|
||||
|
||||
/**
|
||||
* An array of resolved host set and host catalog instances. Model instances
|
||||
@@ -37,7 +45,6 @@ export default class TargetModel extends GeneratedTargetModel {
|
||||
* instances). Unresolvable instances are excluded from the array.
|
||||
* @type {[{model: HostSetModel, hostCatalog: HostCatalogModel}]}
|
||||
*/
|
||||
@computed('host_sources.[]', 'store')
|
||||
get hostSets() {
|
||||
return this.host_sources
|
||||
.map(({ host_source_id, host_catalog_id }) => ({
|
||||
@@ -48,17 +55,38 @@ export default class TargetModel extends GeneratedTargetModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of resolved credential library instances. Model instances
|
||||
* An array of resolved credential library and credential instances. Model instances
|
||||
* must already be loaded into the store (this method will not load unloaded
|
||||
* instances). Unresolvable instances are excluded from the array.
|
||||
* @type {[CredentialLibraryModel]}
|
||||
* @type {[CredentialLibraryModel, CredentialModel]}
|
||||
*/
|
||||
@computed('application_credential_source_ids.[]', 'store')
|
||||
get credentialLibraries() {
|
||||
return this.application_credential_source_ids
|
||||
.map((source) =>
|
||||
this.store.peekRecord('credential-library', source.value)
|
||||
)
|
||||
get brokeredCredentialSources() {
|
||||
return this.brokered_credential_source_ids
|
||||
.map((source) => {
|
||||
if (source.value.startsWith('cred')) {
|
||||
return this.store.peekRecord('credential', source.value);
|
||||
} else {
|
||||
return this.store.peekRecord('credential-library', source.value);
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of resolved credential library and credential instances. Model instances
|
||||
* must already be loaded into the store (this method will not load unloaded
|
||||
* instances). Unresolvable instances are excluded from the array.
|
||||
* @type {[CredentialLibraryModel, CredentialModel]}
|
||||
*/
|
||||
get injectedApplicationCredentialSources() {
|
||||
return this.injected_application_credential_source_ids
|
||||
.map((source) => {
|
||||
if (source.value.startsWith('cred')) {
|
||||
return this.store.peekRecord('credential', source.value);
|
||||
} else {
|
||||
return this.store.peekRecord('credential-library', source.value);
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
@@ -150,17 +178,20 @@ export default class TargetModel extends GeneratedTargetModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds credential libraries via the `add-credential-sources` method.
|
||||
* Adds credential sources via the `add-credential-sources` method.
|
||||
* See serializer and adapter for more information.
|
||||
* @param {[string]} credentialLibraryIDs
|
||||
* @param {[string]} brokeredCredentialSourceIDs
|
||||
* @param {object} options
|
||||
* @param {object} options.adapterOptions
|
||||
* @return {Promise}
|
||||
*/
|
||||
addCredentialSources(credentialLibraryIDs, options = { adapterOptions: {} }) {
|
||||
addBrokeredCredentialSources(
|
||||
brokeredCredentialSourceIDs,
|
||||
options = { adapterOptions: {} }
|
||||
) {
|
||||
const defaultAdapterOptions = {
|
||||
method: 'add-credential-sources',
|
||||
credentialLibraryIDs,
|
||||
brokeredCredentialSourceIDs,
|
||||
};
|
||||
// There is no "deep merge" in ES.
|
||||
return this.save({
|
||||
@@ -173,20 +204,46 @@ export default class TargetModel extends GeneratedTargetModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete credential libraries via the `remove-credential-sources` method.
|
||||
* Adds credential sources via the `add-credential-sources` method.
|
||||
* See serializer and adapter for more information.
|
||||
* @param {[string]} credentialLibraryIDs
|
||||
* @param {[string]} injectedApplicationCredentialSourceIDs
|
||||
* @param {object} options
|
||||
* @param {object} options.adapterOptions
|
||||
* @return {Promise}
|
||||
*/
|
||||
removeCredentialSources(
|
||||
credentialLibraryIDs,
|
||||
addInjectedApplicationCredentialSources(
|
||||
injectedApplicationCredentialSourceIDs,
|
||||
options = { adapterOptions: {} }
|
||||
) {
|
||||
const defaultAdapterOptions = {
|
||||
method: 'add-credential-sources',
|
||||
injectedApplicationCredentialSourceIDs,
|
||||
};
|
||||
// There is no "deep merge" in ES.
|
||||
return this.save({
|
||||
...options,
|
||||
adapterOptions: {
|
||||
...defaultAdapterOptions,
|
||||
...options.adapterOptions,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete credential libraries and credentials via the `remove-credential-sources` method.
|
||||
* See serializer and adapter for more information.
|
||||
* @param {[string]} brokeredCredentialSourceIDs
|
||||
* @param {object} options
|
||||
* @param {object} options.adapterOptions
|
||||
* @return {Promise}
|
||||
*/
|
||||
removeBrokeredCredentialSources(
|
||||
brokeredCredentialSourceIDs,
|
||||
options = { adapterOptions: {} }
|
||||
) {
|
||||
const defaultAdapterOptions = {
|
||||
method: 'remove-credential-sources',
|
||||
credentialLibraryIDs,
|
||||
brokeredCredentialSourceIDs,
|
||||
};
|
||||
// There is no "deep merge" in ES.
|
||||
return this.save({
|
||||
@@ -199,15 +256,59 @@ export default class TargetModel extends GeneratedTargetModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a single credential library set via the `remove-credential-sources` method.
|
||||
* @param {number} credentialLibraryID
|
||||
* Delete a single credential library/credential set via the `remove-credential-sources` method.
|
||||
* @param {number} brokeredCredentialSourceID
|
||||
* @param {object} options
|
||||
* @return {Promise}
|
||||
*/
|
||||
removeCredentialSource(credentialLibraryID, options) {
|
||||
return this.removeCredentialSources([credentialLibraryID], options);
|
||||
removeBrokeredCredentialSource(brokeredCredentialSourceID, options) {
|
||||
return this.removeBrokeredCredentialSources(
|
||||
[brokeredCredentialSourceID],
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete credential libraries and credentials via the `remove-credential-sources` method.
|
||||
* See serializer and adapter for more information.
|
||||
* @param {[string]} injectedApplicationCredentialSourceIDs
|
||||
* @param {object} options
|
||||
* @param {object} options.adapterOptions
|
||||
* @return {Promise}
|
||||
*/
|
||||
removeInjectedApplicationCredentialSources(
|
||||
injectedApplicationCredentialSourceIDs,
|
||||
options = { adapterOptions: {} }
|
||||
) {
|
||||
const defaultAdapterOptions = {
|
||||
method: 'remove-credential-sources',
|
||||
injectedApplicationCredentialSourceIDs,
|
||||
};
|
||||
// There is no "deep merge" in ES.
|
||||
return this.save({
|
||||
...options,
|
||||
adapterOptions: {
|
||||
...defaultAdapterOptions,
|
||||
...options.adapterOptions,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a single credential library/credential set via the `remove-credential-sources` method.
|
||||
* @param {number} injectedApplicationCredentialSourceID
|
||||
* @param {object} options
|
||||
* @return {Promise}
|
||||
*/
|
||||
removeInjectedApplicationCredentialSource(
|
||||
injectedApplicationCredentialSourceID,
|
||||
options
|
||||
) {
|
||||
return this.removeInjectedApplicationCredentialSources(
|
||||
[injectedApplicationCredentialSourceID],
|
||||
options
|
||||
);
|
||||
}
|
||||
/**
|
||||
* True if the target type is tcp.
|
||||
* @type {boolean}
|
||||
|
||||
@@ -40,7 +40,7 @@ export default class UserModel extends GeneratedUserModel {
|
||||
* There are many options, so we fallback in order of precedence.
|
||||
* @type {string}
|
||||
*/
|
||||
@computed('email,full_name,login_name,displayName')
|
||||
@computed('email', 'full_name', 'login_name')
|
||||
get accountName() {
|
||||
const { email, full_name, login_name } = this;
|
||||
return email || full_name || login_name;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import GeneratedWorkerModel from '../generated/models/worker';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
export default class WorkerModel extends GeneratedWorkerModel {
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
* Names are optional on models in our API. Thus we need to fallback on ID
|
||||
* for display purposes.
|
||||
* @type {string}
|
||||
*/
|
||||
get displayName() {
|
||||
return this.name || this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the worker is a pki worker.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isPki() {
|
||||
return this.type === 'pki';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of config tags present on the worker.
|
||||
* @type {number}
|
||||
*/
|
||||
get tagCount() {
|
||||
if (!this.config_tags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Object.values(this.config_tags).reduce(
|
||||
(previousCount, currentTags) => previousCount + currentTags.length,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the config tags as an array of key/value pair objects.
|
||||
* @type {[object]}
|
||||
*/
|
||||
getConfigTagList() {
|
||||
if (!this.config_tags) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Object.entries(this.config_tags).flatMap(([key, value]) =>
|
||||
value.map((tag) => ({ key, value: tag }))
|
||||
);
|
||||
}
|
||||
|
||||
@attr({
|
||||
description:
|
||||
'The deduplicated union of the tags reported by the worker ' +
|
||||
'from its configuration and any tags added through other means.\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
canonical_tags;
|
||||
|
||||
@attr({
|
||||
description:
|
||||
"The tags set in the worker's configuration file.\nOutput only.",
|
||||
readOnly: true,
|
||||
})
|
||||
config_tags;
|
||||
|
||||
/**
|
||||
* Method to modify the adapter to handle custom POST route for creating worker.
|
||||
* @param {string} workerGeneratedAuthToken
|
||||
* @param {object} options
|
||||
* @param {object} options.adapterOptions
|
||||
* @return {Promise}
|
||||
*/
|
||||
createWorkerLed(workerGeneratedAuthToken, options = { adapterOptions: {} }) {
|
||||
const defaultAdapterOptions = {
|
||||
method: 'create:worker-led',
|
||||
workerGeneratedAuthToken,
|
||||
};
|
||||
return super.save({
|
||||
...options,
|
||||
adapterOptions: {
|
||||
...defaultAdapterOptions,
|
||||
...options.adapterOptions,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ export default class AccountSerializer extends ApplicationSerializer {
|
||||
delete serialized.attributes;
|
||||
if (isNew) {
|
||||
serialized.attributes = {};
|
||||
const { issuer, subject } = snapshot.attr('attributes').record;
|
||||
const { issuer, subject } = snapshot.record;
|
||||
if (issuer) serialized.attributes.issuer = issuer;
|
||||
if (subject) serialized.attributes.subject = subject;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
delete serialized.scope;
|
||||
// And serialize `scope_id`
|
||||
if (this.serializeScopeID) {
|
||||
const scope_id = snapshot?.attr('scope')?.attr('scope_id');
|
||||
const scope_id = snapshot?.attr('scope')?.scope_id;
|
||||
if (scope_id) serialized.scope_id = scope_id;
|
||||
}
|
||||
return serialized;
|
||||
@@ -137,7 +137,7 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
}
|
||||
|
||||
/**
|
||||
* In our API, singluar resources are _unrooted_, whereas Ember Data expects
|
||||
* In our API, singular resources are _unrooted_, whereas Ember Data expects
|
||||
* them to be rooted under their model name, e.g. `{modelName: {…}}`.
|
||||
* This method makes this transformation to accommodate Ember Data.
|
||||
*
|
||||
@@ -199,11 +199,9 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
}
|
||||
|
||||
/**
|
||||
* One consequence of using model fragments to represent the embedded scope
|
||||
* is that they cannot have `id` fields. We still need to know scope IDs,
|
||||
* so we copy the `scope.id` value into the `scope.scope_id` field.
|
||||
* Hydrates the incoming scope JSON with additional boolean fields and
|
||||
* delegates nested attributes and secrets normalization.
|
||||
* @override
|
||||
* @see FragmentScope
|
||||
* @param {Model} typeClass
|
||||
* @param {Object} hash
|
||||
* @return {Object}
|
||||
@@ -211,7 +209,14 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
normalize(typeClass, hash) {
|
||||
let normalizedHash = copy(hash, true);
|
||||
const scopeID = get(normalizedHash, 'scope.id');
|
||||
const scopeType = get(normalizedHash, 'scope.type');
|
||||
if (scopeID) normalizedHash.scope.scope_id = scopeID;
|
||||
if (scopeType) {
|
||||
normalizedHash.scope.type = scopeType;
|
||||
normalizedHash.scope.isGlobal = scopeType === 'global';
|
||||
normalizedHash.scope.isOrg = scopeType === 'org';
|
||||
normalizedHash.scope.isProject = scopeType === 'project';
|
||||
}
|
||||
normalizedHash = this.normalizeNestedAttributes(typeClass, normalizedHash);
|
||||
normalizedHash = this.normalizeNestedSecrets(typeClass, normalizedHash);
|
||||
return super.normalize(typeClass, normalizedHash);
|
||||
@@ -268,4 +273,48 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
});
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the API returns an updated response with removed fields, we need to
|
||||
* explicitly set any read only field that is on the model but wasn't
|
||||
* returned in the response to `null`.
|
||||
* This will let ember data know the field was removed, otherwise
|
||||
* it won't touch the removed field and will use the old value.
|
||||
*
|
||||
* @override
|
||||
* @param {object} store
|
||||
* @param {object} primaryModelClass
|
||||
* @param {object} payload
|
||||
* @param {?string} id
|
||||
* @param {string} requestType
|
||||
* @return {object}
|
||||
*/
|
||||
normalizeUpdateRecordResponse(
|
||||
store,
|
||||
primaryModelClass,
|
||||
payload,
|
||||
id,
|
||||
requestType
|
||||
) {
|
||||
const newPayload = copy(payload, true);
|
||||
|
||||
primaryModelClass.attributes.forEach((attribute) => {
|
||||
const {
|
||||
name,
|
||||
options: { readOnly },
|
||||
} = attribute;
|
||||
|
||||
if (readOnly && !Object.prototype.hasOwnProperty.call(newPayload, name)) {
|
||||
newPayload[name] = null;
|
||||
}
|
||||
});
|
||||
|
||||
return super.normalizeUpdateRecordResponse(
|
||||
store,
|
||||
primaryModelClass,
|
||||
newPayload,
|
||||
id,
|
||||
requestType
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,6 @@ export default class AuthMethodSerializer extends ApplicationSerializer {
|
||||
*
|
||||
* TODO: generalize this so that all zero values are reified.
|
||||
* @override
|
||||
* @see FragmentScope
|
||||
* @param {Model} typeClass
|
||||
* @param {Object} hash
|
||||
* @return {Object}
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
import ApplicationSerializer from './application';
|
||||
|
||||
export default class CredentialLibrarySerializer extends ApplicationSerializer {}
|
||||
export default class CredentialLibrarySerializer extends ApplicationSerializer {
|
||||
// =properties
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
serializeScopeID = false;
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @method serialize
|
||||
* @param {Snapshot} snapshot
|
||||
*/
|
||||
serialize() {
|
||||
const serialized = super.serialize(...arguments);
|
||||
if (serialized.attributes) {
|
||||
// Serialize `http_request_body` only if `http_method` is POST
|
||||
if (!serialized.attributes?.http_method?.match(/post/i))
|
||||
delete serialized.attributes.http_request_body;
|
||||
}
|
||||
return serialized;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,50 @@
|
||||
import ApplicationSerializer from './application';
|
||||
import { copy } from 'ember-copy';
|
||||
|
||||
export default class CredentialStoreSerializer extends ApplicationSerializer {}
|
||||
export default class CredentialStoreSerializer extends ApplicationSerializer {
|
||||
/**
|
||||
* @override
|
||||
* @method serialize
|
||||
* @param {Snapshot} snapshot
|
||||
*/
|
||||
serialize(snapshot) {
|
||||
switch (snapshot.record.type) {
|
||||
case 'vault':
|
||||
return this.serializeVault(...arguments);
|
||||
case 'static':
|
||||
default:
|
||||
return this.serializeStatic(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
serializeVault() {
|
||||
const serialized = super.serialize(...arguments);
|
||||
if (serialized.attributes) {
|
||||
// Token cannot be unset. If it's falsy, it must be removed.
|
||||
if (!serialized.attributes?.token) delete serialized.attributes.token;
|
||||
// Client certificate key cannot be unset when certificate is set.
|
||||
// If it's falsy, it must be removed.
|
||||
if (
|
||||
!serialized.attributes?.client_certificate_key &&
|
||||
serialized.attributes?.client_certificate
|
||||
)
|
||||
delete serialized.attributes.client_certificate_key;
|
||||
}
|
||||
return serialized;
|
||||
}
|
||||
|
||||
serializeStatic() {
|
||||
const serialized = super.serialize(...arguments);
|
||||
// Delete attributes for static cred store
|
||||
delete serialized.attributes;
|
||||
return serialized;
|
||||
}
|
||||
|
||||
normalize(typeClass, hash, ...rest) {
|
||||
const normalizedHash = copy(hash, true);
|
||||
const normalized = super.normalize(typeClass, normalizedHash, ...rest);
|
||||
// Remove secret fields as we don't track them after being created/updated
|
||||
normalized.data.attributes.token = '';
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import ApplicationSerializer from './application';
|
||||
import { copy } from 'ember-copy';
|
||||
|
||||
export default class CredentialSerializer extends ApplicationSerializer {
|
||||
/**
|
||||
* @override
|
||||
* @method serialize
|
||||
* @param {Snapshot} snapshot
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
serializeScopeID = false;
|
||||
|
||||
serialize(snapshot) {
|
||||
switch (snapshot.record.type) {
|
||||
case 'username_password':
|
||||
return this.serializeUsernamePassword(...arguments);
|
||||
case 'ssh_private_key':
|
||||
default:
|
||||
return this.serializeSSHPrivateKey(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
serializeUsernamePassword() {
|
||||
const serialized = super.serialize(...arguments);
|
||||
// Remove non-username_password type attributes
|
||||
delete serialized.attributes.private_key;
|
||||
delete serialized.attributes.private_key_passphrase;
|
||||
// Remove password from the payload if null
|
||||
// or empty string. This allows the user to only update
|
||||
// the username without providing the password again.
|
||||
// Users cannot unset the password, they would have
|
||||
// to delete the credential entirely.
|
||||
if (!serialized?.attributes?.password)
|
||||
delete serialized.attributes.password;
|
||||
return serialized;
|
||||
}
|
||||
|
||||
serializeSSHPrivateKey() {
|
||||
const serialized = super.serialize(...arguments);
|
||||
// Remove non-ssh_private_key type attributes
|
||||
delete serialized.attributes.password;
|
||||
// Remove private_key and/or private_key_passphrase from the payload
|
||||
// if null or empty string. This allows the user to only update
|
||||
// the username without providing the private key and passphrase again.
|
||||
// Users cannot unset the private key or passphrase, they would have
|
||||
// to delete the credential entirely.
|
||||
if (!serialized?.attributes?.private_key_passphrase)
|
||||
delete serialized.attributes.private_key_passphrase;
|
||||
if (!serialized?.attributes?.private_key)
|
||||
delete serialized.attributes.private_key;
|
||||
return serialized;
|
||||
}
|
||||
|
||||
normalize(typeClass, hash, ...rest) {
|
||||
const normalizedHash = copy(hash, true);
|
||||
const normalized = super.normalize(typeClass, normalizedHash, ...rest);
|
||||
// Remove secret fields as we don't track them after being created/updated
|
||||
normalized.data.attributes.password = '';
|
||||
normalized.data.attributes.private_key = '';
|
||||
normalized.data.attributes.private_key_passphrase = '';
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import JSONSerializer from '@ember-data/serializer/json';
|
||||
|
||||
export default class FragmentAccountAttributesSerializer extends JSONSerializer {
|
||||
/**
|
||||
* If an attribute is annotated as readOnly in the model, don't serialize it.
|
||||
* Otherwise delegate to default attribute serializer.
|
||||
*
|
||||
* @override
|
||||
* @method serializeAttribute
|
||||
* @param {Snapshot} snapshot
|
||||
* @param {Object} json
|
||||
* @param {String} key
|
||||
* @param {Object} attribute
|
||||
*/
|
||||
serializeAttribute(snapshot, json, key, attribute) {
|
||||
const { type, options } = attribute;
|
||||
let value = super.serializeAttribute(...arguments);
|
||||
// Convert empty strings to null.
|
||||
if (type === 'string' && json[key] === '') json[key] = null;
|
||||
// Do not serialize read-only attributes.
|
||||
if (options.readOnly) delete json[key];
|
||||
// Client secret cannot be unset. If it's falsy, it must be removed.
|
||||
if (key === 'client_secret' && !json[key]) delete json[key];
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import JSONSerializer from '@ember-data/serializer/json';
|
||||
|
||||
export default class FragmentCredentialLibraryAttributesSerializer extends JSONSerializer {
|
||||
/**
|
||||
* If an attribute is annotated as readOnly in the model, don't serialize it.
|
||||
* Otherwise delegate to default attribute serializer.
|
||||
* Only serialize http_request_body when `http_method` is set to `POST`.
|
||||
* @override
|
||||
* @method serializeAttribute
|
||||
* @param {Snapshot} snapshot
|
||||
* @param {Object} json
|
||||
* @param {String} key
|
||||
* @param {Object} attribute
|
||||
*/
|
||||
serializeAttribute(snapshot, json, key, attribute) {
|
||||
const { type, options } = attribute;
|
||||
let value = super.serializeAttribute(...arguments);
|
||||
// Convert empty strings to null.
|
||||
if (type === 'string' && json[key] === '') json[key] = null;
|
||||
// Do not serialize read-only attributes.
|
||||
if (options.readOnly) delete json[key];
|
||||
// Do not serialize http_request_body unless http_method is POST
|
||||
if (key === 'http_request_body' && !json['http_method']?.match(/post/i))
|
||||
delete json[key];
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import JSONSerializer from '@ember-data/serializer/json';
|
||||
|
||||
export default class FragmentCredentialStoreAttributesSerializer extends JSONSerializer {
|
||||
/**
|
||||
* If an attribute is annotated as readOnly in the model, don't serialize it.
|
||||
* Otherwise delegate to default attribute serializer.
|
||||
*
|
||||
* @override
|
||||
* @method serializeAttribute
|
||||
* @param {Snapshot} snapshot
|
||||
* @param {Object} json
|
||||
* @param {String} key
|
||||
* @param {Object} attribute
|
||||
*/
|
||||
serializeAttribute(snapshot, json, key, attribute) {
|
||||
const { type, options } = attribute;
|
||||
let value = super.serializeAttribute(...arguments);
|
||||
// Convert empty strings to null.
|
||||
if (type === 'string' && json[key] === '') json[key] = null;
|
||||
// Do not serialize read-only attributes.
|
||||
if (options.readOnly) delete json[key];
|
||||
// Token cannot be unset. If it's falsy, it must be removed.
|
||||
if (key === 'token' && !json[key]) delete json[key];
|
||||
// Client certificate key cannot be unset when certificate is set.
|
||||
// If it's falsy, it must be removed.
|
||||
if (
|
||||
key === 'client_certificate_key' &&
|
||||
!json[key] &&
|
||||
json['client_certificate']
|
||||
)
|
||||
delete json[key];
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import JSONSerializer from '@ember-data/serializer/json';
|
||||
|
||||
export default class FragmentHostSourceSerializer extends JSONSerializer {
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Renames `id` to `host_source_id` because fragments may not have IDs.
|
||||
* Otherwise normalizes as normal.
|
||||
* @param {ModelClass} typeClass
|
||||
* @param {object} resourceHash
|
||||
* @return {object}
|
||||
*/
|
||||
normalize(typeClass, { id: host_source_id, ...obj }) {
|
||||
return super.normalize(typeClass, { host_source_id, ...obj });
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import JSONSerializer from '@ember-data/serializer/json';
|
||||
|
||||
export default class FragmentManagedGroupAttributesSerializer extends JSONSerializer {
|
||||
/**
|
||||
* If an attribute is annotated as readOnly in the model, don't serialize it.
|
||||
* Otherwise delegate to default attribute serializer.
|
||||
* @override
|
||||
* @method serializeAttribute
|
||||
* @param {Snapshot} snapshot
|
||||
* @param {Object} json
|
||||
* @param {String} key
|
||||
* @param {Object} attribute
|
||||
*/
|
||||
serializeAttribute(snapshot, json, key, attribute) {
|
||||
const { type, options } = attribute;
|
||||
let value = super.serializeAttribute(...arguments);
|
||||
// Convert empty string to null.
|
||||
if (type === 'string' && json[key] === '') json[key] = null;
|
||||
// Do not serialize read-only attributes.
|
||||
if (options.readOnly) delete json[key];
|
||||
// Version is sent only if it has a non-nullish value
|
||||
if (key === 'version') {
|
||||
if (json[key] === null || json[key] === undefined) delete json[key];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import JSONSerializer from '@ember-data/serializer/json';
|
||||
|
||||
export default class FragmentPrincipalSerializer extends JSONSerializer {
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Renames `id` to `principal_id` because fragments may not have IDs.
|
||||
* Otherwise normalizes as normal.
|
||||
* @param {ModelClass} typeClass
|
||||
* @param {object} resourceHash
|
||||
* @return {object}
|
||||
*/
|
||||
normalize(typeClass, { id: principal_id, ...obj }) {
|
||||
return super.normalize(typeClass, { principal_id, ...obj });
|
||||
}
|
||||
}
|
||||
@@ -80,8 +80,8 @@ export default class HostSetSerializer extends ApplicationSerializer {
|
||||
*/
|
||||
normalize(typeClass, hash, ...rest) {
|
||||
const normalizedHash = copy(hash, true);
|
||||
if (typeof normalizedHash?.filters === 'string') {
|
||||
normalizedHash.filters = [normalizedHash.filters];
|
||||
if (typeof normalizedHash?.attributes?.filters === 'string') {
|
||||
normalizedHash.attributes.filters = [normalizedHash.attributes.filters];
|
||||
}
|
||||
const normalized = super.normalize(typeClass, normalizedHash, ...rest);
|
||||
return normalized;
|
||||
|
||||
@@ -7,10 +7,10 @@ export default class TargetSerializer extends ApplicationSerializer {
|
||||
* If `adapterOptions.hostSets` is set to an array of host set models,
|
||||
* the resulting target serialization should include **only host sets**
|
||||
* and the version.
|
||||
* If `adapterOptions.credentialLibraries` is set to an array of
|
||||
* credential library models, the resulting target serialization should
|
||||
* include **only credential libraries** and the version.
|
||||
* Normally, neither host sets or credential libraries are not serialized.
|
||||
* If `adapterOptions.credentialSources` is set to an array of
|
||||
* credential library and credential models, the resulting target serialization should
|
||||
* include **only credential libraries and crendentials** and the version.
|
||||
* Normally, neither host sets or credential libraries or credentials are not serialized.
|
||||
* @override
|
||||
* @param {Snapshot} snapshot
|
||||
* @return {object}
|
||||
@@ -21,11 +21,20 @@ export default class TargetSerializer extends ApplicationSerializer {
|
||||
if (hostSourceIDs) {
|
||||
serialized = this.serializeWithHostSources(snapshot, hostSourceIDs);
|
||||
}
|
||||
const credentialSourceIDs = snapshot?.adapterOptions?.credentialLibraryIDs;
|
||||
if (credentialSourceIDs)
|
||||
serialized = this.serializeWithCredentialSources(
|
||||
const brokeredCredentialSourceIDs =
|
||||
snapshot?.adapterOptions?.brokeredCredentialSourceIDs;
|
||||
const injectedApplicationCredentialSourceIDs =
|
||||
snapshot?.adapterOptions?.injectedApplicationCredentialSourceIDs;
|
||||
|
||||
if (brokeredCredentialSourceIDs)
|
||||
serialized = this.serializeWithBrokeredCredentialSources(
|
||||
snapshot,
|
||||
credentialSourceIDs
|
||||
brokeredCredentialSourceIDs
|
||||
);
|
||||
if (injectedApplicationCredentialSourceIDs)
|
||||
serialized = this.serializeWithInjectedApplicationCredentialSources(
|
||||
snapshot,
|
||||
injectedApplicationCredentialSourceIDs
|
||||
);
|
||||
return serialized;
|
||||
}
|
||||
@@ -48,13 +57,33 @@ export default class TargetSerializer extends ApplicationSerializer {
|
||||
* Returns a payload containing only version and an array of passed IDs,
|
||||
* rather than existing instances on the model.
|
||||
* @param {Snapshot} snapshot
|
||||
* @param {[string]} credentialSourceIDs
|
||||
* @param {[string]} brokered_credential_source_ids
|
||||
* @return {object}
|
||||
*/
|
||||
serializeWithCredentialSources(snapshot, credentialSourceIDs) {
|
||||
serializeWithBrokeredCredentialSources(
|
||||
snapshot,
|
||||
brokered_credential_source_ids
|
||||
) {
|
||||
return {
|
||||
version: snapshot.attr('version'),
|
||||
application_credential_source_ids: credentialSourceIDs,
|
||||
brokered_credential_source_ids,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a payload containing only version and an array of passed IDs,
|
||||
* rather than existing instances on the model.
|
||||
* @param {Snapshot} snapshot
|
||||
* @param {[string]} injected_application_credential_source_ids
|
||||
* @return {object}
|
||||
*/
|
||||
serializeWithInjectedApplicationCredentialSources(
|
||||
snapshot,
|
||||
injected_application_credential_source_ids
|
||||
) {
|
||||
return {
|
||||
version: snapshot.attr('version'),
|
||||
injected_application_credential_source_ids,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import ApplicationSerializer from './application';
|
||||
|
||||
export default class WorkerSerializer extends ApplicationSerializer {
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* If `adapterOptions.workerGeneratedAuthToken` is set,
|
||||
* then the payload is serialized via `serializedWithGeneratedToken`.
|
||||
* @override
|
||||
* @param {Snapshot} snapshot
|
||||
* @return {object}
|
||||
*/
|
||||
serialize(snapshot) {
|
||||
let serialized = super.serialize(...arguments);
|
||||
const workerGeneratedAuthToken =
|
||||
snapshot?.adapterOptions?.workerGeneratedAuthToken;
|
||||
if (workerGeneratedAuthToken)
|
||||
serialized = this.serializeWithGeneratedToken(
|
||||
snapshot,
|
||||
workerGeneratedAuthToken
|
||||
);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a payload with `worker_generated_auth_token` serialized.
|
||||
* @param {Snapshot} snapshot
|
||||
* @param {[string]} worker_generated_auth_token
|
||||
* @return {object}
|
||||
*/
|
||||
serializeWithGeneratedToken(snapshot, workerGeneratedAuthToken) {
|
||||
return {
|
||||
scope_id: snapshot.attr('scope').scope_id,
|
||||
worker_generated_auth_token: workerGeneratedAuthToken,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import Transform from '@ember-data/serializer/transform';
|
||||
|
||||
export default class HostSourceIdArrayTransform extends Transform {
|
||||
deserialize(serialized) {
|
||||
const stringValues = serialized || [];
|
||||
return stringValues.map(({ id: host_source_id, ...obj }) => ({
|
||||
host_source_id,
|
||||
...obj,
|
||||
}));
|
||||
}
|
||||
|
||||
serialize(deserialized) {
|
||||
const strings = deserialized || [];
|
||||
return strings.map(({ host_source_id: id, ...obj }) => ({ id, ...obj }));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import Transform from '@ember-data/serializer/transform';
|
||||
|
||||
export default class PrincipalArrayTransform extends Transform {
|
||||
deserialize(serialized) {
|
||||
const stringValues = serialized || [];
|
||||
return stringValues.map(({ id: principal_id, scope_id, type }) => ({
|
||||
principal_id,
|
||||
scope_id,
|
||||
type,
|
||||
}));
|
||||
}
|
||||
|
||||
serialize(deserialized) {
|
||||
const strings = deserialized || [];
|
||||
return strings.map(({ principal_id: id, scope_id, type }) => ({
|
||||
id,
|
||||
scope_id,
|
||||
type,
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import Transform from '@ember-data/serializer/transform';
|
||||
|
||||
export default class StringArrayTransform extends Transform {
|
||||
deserialize(serialized) {
|
||||
const stringValues = serialized || [];
|
||||
return stringValues.map((value) => ({ value }));
|
||||
}
|
||||
|
||||
serialize(deserialized) {
|
||||
const strings = deserialized || [];
|
||||
return strings.map(({ value }) => value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/abilities/credential-library';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/abilities/credential-store';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/abilities/credential';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/abilities/worker';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/models/credential';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/models/fragment-account-attributes';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/models/fragment-credential-library-attributes';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/models/fragment-credential-store-attributes';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/models/fragment-host-source';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/models/fragment-managed-group-attributes';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/models/fragment-principal';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/models/fragment-scope';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/models/worker';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/serializers/credential';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/serializers/fragment-account-attributes';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/serializers/fragment-credential-library-attributes';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/serializers/fragment-credential-store-attributes';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/serializers/fragment-host-source';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/serializers/fragment-managed-group-attributes';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/serializers/fragment-principal';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/serializers/worker';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/transforms/host-source-id-array';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/transforms/principal-array';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/transforms/string-array';
|
||||
+102
-55
@@ -1,5 +1,6 @@
|
||||
import config from '../config/environment';
|
||||
import { authHandler, deauthHandler } from './route-handlers/auth';
|
||||
import { targetHandler } from './route-handlers/target';
|
||||
import { pickRandomStatusString } from './factories/session';
|
||||
import { Response } from 'miragejs';
|
||||
import initializeMockIPC from './scenarios/ipc';
|
||||
@@ -57,8 +58,23 @@ export default function () {
|
||||
|
||||
this.get(
|
||||
'/auth-methods',
|
||||
({ authMethods }, { queryParams: { scope_id: scopeId, filter } }) => {
|
||||
const resultSet = authMethods.where({ scopeId });
|
||||
({ authMethods }, { queryParams: { scope_id, recursive, filter } }) => {
|
||||
let resultSet;
|
||||
if (recursive && scope_id === 'global') {
|
||||
resultSet = authMethods.all();
|
||||
} else if (recursive) {
|
||||
resultSet = authMethods.where((authMethod) => {
|
||||
const authMethodModel = authMethods.find(authMethod.id);
|
||||
return (
|
||||
authMethod.scopeId === scope_id ||
|
||||
authMethodModel?.scope?.scope?.id === scope_id
|
||||
);
|
||||
});
|
||||
} else {
|
||||
resultSet = authMethods.where(
|
||||
(authMethod) => authMethod.scopeId === scope_id
|
||||
);
|
||||
}
|
||||
return resultSet.filter(makeBooleanFilter(filter));
|
||||
}
|
||||
);
|
||||
@@ -123,12 +139,29 @@ export default function () {
|
||||
// Authenticate + auth methods custom routes
|
||||
this.post('/auth-methods/:id_method', authHandler);
|
||||
// Deauthenticate route
|
||||
this.post('/scopes/:id_method', deauthHandler);
|
||||
this.delete('/auth-tokens/:id', deauthHandler);
|
||||
|
||||
// IAM : Users
|
||||
this.get('/users', ({ users }, { queryParams: { scope_id: scopeId } }) => {
|
||||
return users.where({ scopeId });
|
||||
});
|
||||
this.get(
|
||||
'/users',
|
||||
({ users }, { queryParams: { scope_id, recursive, filter } }) => {
|
||||
let resultSet;
|
||||
if (recursive && scope_id === 'global') {
|
||||
resultSet = users.all();
|
||||
} else if (recursive) {
|
||||
resultSet = users.where((user) => {
|
||||
const userModel = users.find(user.id);
|
||||
return (
|
||||
user.scopeId === scope_id ||
|
||||
userModel?.scope?.scope?.id === scope_id
|
||||
);
|
||||
});
|
||||
} else {
|
||||
resultSet = users.where((user) => user.scopeId === scope_id);
|
||||
}
|
||||
return resultSet.filter(makeBooleanFilter(filter));
|
||||
}
|
||||
);
|
||||
this.post('/users');
|
||||
this.get('/users/:id');
|
||||
this.patch('/users/:id');
|
||||
@@ -160,9 +193,26 @@ export default function () {
|
||||
});
|
||||
|
||||
// IAM: Groups
|
||||
this.get('/groups', ({ groups }, { queryParams: { scope_id: scopeId } }) => {
|
||||
return groups.where({ scopeId });
|
||||
});
|
||||
this.get(
|
||||
'/groups',
|
||||
({ groups }, { queryParams: { scope_id, recursive, filter } }) => {
|
||||
let resultSet;
|
||||
if (recursive && scope_id === 'global') {
|
||||
resultSet = groups.all();
|
||||
} else if (recursive) {
|
||||
resultSet = groups.where((group) => {
|
||||
const groupModel = groups.find(group.id);
|
||||
return (
|
||||
group.scopeId === scope_id ||
|
||||
groupModel?.scope?.scope?.id === scope_id
|
||||
);
|
||||
});
|
||||
} else {
|
||||
resultSet = groups.where((group) => group.scopeId === scope_id);
|
||||
}
|
||||
return resultSet.filter(makeBooleanFilter(filter));
|
||||
}
|
||||
);
|
||||
this.post('/groups');
|
||||
this.get('/groups/:id');
|
||||
this.patch('/groups/:id');
|
||||
@@ -386,52 +436,7 @@ export default function () {
|
||||
this.get('/targets/:id');
|
||||
this.patch('/targets/:id');
|
||||
this.del('/targets/:id');
|
||||
this.post(
|
||||
'/targets/:idMethod',
|
||||
function ({ targets }, { params: { idMethod } }) {
|
||||
const attrs = this.normalizedRequestAttrs();
|
||||
const id = idMethod.split(':')[0];
|
||||
const method = idMethod.split(':')[1];
|
||||
const target = targets.find(id);
|
||||
const updatedAttrs = {
|
||||
version: attrs.version,
|
||||
};
|
||||
// If adding host sources, push them into the array
|
||||
if (method === 'add-host-sources') {
|
||||
updatedAttrs.hostSetIds = target.hostSetIds;
|
||||
attrs.hostSourceIds.forEach((id) => {
|
||||
if (!updatedAttrs.hostSetIds.includes(id)) {
|
||||
updatedAttrs.hostSetIds.push(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
// If deleting host sources, filter them out of the array
|
||||
if (method === 'remove-host-sources') {
|
||||
updatedAttrs.hostSetIds = target.hostSetIds;
|
||||
updatedAttrs.hostSetIds = updatedAttrs.hostSetIds.filter((id) => {
|
||||
return !attrs.hostSourceIds.includes(id);
|
||||
});
|
||||
}
|
||||
// If adding credential sources, push them into the array
|
||||
if (method === 'add-credential-sources') {
|
||||
updatedAttrs.credentialLibraryIds = target.credentialLibraryIds;
|
||||
attrs.applicationCredentialSourceIds.forEach((id) => {
|
||||
if (!updatedAttrs.credentialLibraryIds.includes(id)) {
|
||||
updatedAttrs.credentialLibraryIds.push(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
// If deleting credential sources, filter them out of the array
|
||||
if (method === 'remove-credential-sources') {
|
||||
updatedAttrs.credentialLibraryIds = target.credentialLibraryIds;
|
||||
updatedAttrs.credentialLibraryIds =
|
||||
updatedAttrs.credentialLibraryIds.filter((id) => {
|
||||
return !attrs.applicationCredentialSourceIds.includes(id);
|
||||
});
|
||||
}
|
||||
return target.update(updatedAttrs);
|
||||
}
|
||||
);
|
||||
this.post('/targets/:idMethod', targetHandler);
|
||||
|
||||
// session
|
||||
|
||||
@@ -541,6 +546,26 @@ export default function () {
|
||||
this.del('/credential-libraries/:id');
|
||||
this.patch('/credential-libraries/:id');
|
||||
|
||||
// credentials
|
||||
|
||||
this.get(
|
||||
'/credentials',
|
||||
(
|
||||
{ credentials },
|
||||
{ queryParams: { credential_store_id: credentialStoreId } }
|
||||
) => credentials.where({ credentialStoreId })
|
||||
);
|
||||
this.get('/credentials/:id');
|
||||
this.post('/credentials', function ({ credentialStores, credentials }) {
|
||||
const attrs = this.normalizedRequestAttrs();
|
||||
const credentialStore = credentialStores.find(attrs.credentialStoreId);
|
||||
attrs.scopeId = credentialStore.scope.id;
|
||||
return credentials.create(attrs);
|
||||
});
|
||||
|
||||
this.del('/credentials/:id');
|
||||
this.patch('/credentials/:id');
|
||||
|
||||
// managed-groups
|
||||
this.get(
|
||||
'/managed-groups',
|
||||
@@ -553,6 +578,28 @@ export default function () {
|
||||
this.patch('/managed-groups/:id');
|
||||
this.del('/managed-groups/:id');
|
||||
|
||||
// worker
|
||||
|
||||
this.get(
|
||||
'/workers',
|
||||
({ workers }, { queryParams: { scope_id: scopeId } }) => {
|
||||
return workers.where({ scopeId });
|
||||
}
|
||||
);
|
||||
this.get('/workers/:id');
|
||||
this.del('/workers/:id');
|
||||
this.patch('/workers/:id');
|
||||
this.post('/workers:create:worker-led', ({ workers, scopes }) => {
|
||||
const globalScope = scopes.find('global');
|
||||
|
||||
// This POST only takes in a token so we need to generate a random worker to return
|
||||
const newWorker = this.create('worker', {
|
||||
type: 'pki',
|
||||
scope: globalScope,
|
||||
});
|
||||
return workers.create(newWorker.attrs);
|
||||
});
|
||||
|
||||
/* Uncomment the following line and the Response import above
|
||||
* Then change the response code to simulate error responses.
|
||||
* this.get('/scopes', () => new Response(505));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import factory from '../generated/factories/account';
|
||||
import { random, internet } from 'faker';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
export default factory.extend({
|
||||
authorized_actions: () =>
|
||||
@@ -11,16 +12,19 @@ export default factory.extend({
|
||||
'delete',
|
||||
'set-password',
|
||||
],
|
||||
|
||||
id: () => generateId('acct_'),
|
||||
|
||||
attributes() {
|
||||
switch (this.type) {
|
||||
case 'password':
|
||||
return { login_name: random.words() };
|
||||
return { login_name: faker.random.words() };
|
||||
case 'oidc':
|
||||
return {
|
||||
issuer: internet.ip(),
|
||||
issuer: faker.internet.ip(),
|
||||
subject: 'sub',
|
||||
email: internet.email(),
|
||||
full_name: random.words(),
|
||||
email: faker.internet.email(),
|
||||
full_name: faker.random.words(),
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import factory from '../generated/factories/auth-method';
|
||||
import { trait } from 'ember-cli-mirage';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
const types = ['password', 'oidc'];
|
||||
|
||||
@@ -11,6 +12,7 @@ export default factory.extend({
|
||||
'read',
|
||||
'update',
|
||||
'delete',
|
||||
'authenticate',
|
||||
],
|
||||
authorized_collection_actions: () => {
|
||||
return {
|
||||
@@ -18,7 +20,8 @@ export default factory.extend({
|
||||
'managed-groups': ['create', 'list'],
|
||||
};
|
||||
},
|
||||
id: (i) => `auth-method-id-${i}`,
|
||||
|
||||
id: () => generateId('am_'),
|
||||
|
||||
// Cycle through available types
|
||||
type: (i) => types[i % types.length],
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import factory from '../generated/factories/credential-library';
|
||||
import { random, system } from 'faker';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
const types = ['vault'];
|
||||
|
||||
export default factory.extend({
|
||||
id: (i) => `credential-library-id-${i}`,
|
||||
id: () => generateId('cl_'),
|
||||
type: (i) => types[i % types.length],
|
||||
|
||||
authorized_actions: () =>
|
||||
@@ -21,8 +22,8 @@ export default factory.extend({
|
||||
case 'vault':
|
||||
return {
|
||||
http_method: 'GET',
|
||||
http_request_body: random.word(),
|
||||
path: system.directoryPath(),
|
||||
http_request_body: faker.random.word(),
|
||||
path: faker.system.directoryPath(),
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import factory from '../generated/factories/credential-store';
|
||||
import { random, internet, datatype } from 'faker';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { trait } from 'ember-cli-mirage';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
const types = ['vault'];
|
||||
const types = ['vault', 'static'];
|
||||
|
||||
export default factory.extend({
|
||||
authorized_actions: () =>
|
||||
@@ -13,37 +14,56 @@ export default factory.extend({
|
||||
'update',
|
||||
'delete',
|
||||
],
|
||||
authorized_collection_actions: () => {
|
||||
return {
|
||||
'credential-libraries': ['create', 'list'],
|
||||
};
|
||||
authorized_collection_actions() {
|
||||
switch (this.type) {
|
||||
case 'vault':
|
||||
return {
|
||||
'credential-libraries': ['create', 'list'],
|
||||
};
|
||||
case 'static':
|
||||
default:
|
||||
return {
|
||||
credentials: ['create', 'list'],
|
||||
};
|
||||
}
|
||||
},
|
||||
id: (i) => `credential-store-id-${i}`,
|
||||
id: () => generateId('cs_'),
|
||||
type: (i) => types[i % types.length],
|
||||
|
||||
attributes() {
|
||||
switch (this.type) {
|
||||
case 'vault':
|
||||
return {
|
||||
address: internet.ip(),
|
||||
namespace: random.word(),
|
||||
address: faker.internet.ip(),
|
||||
namespace: faker.random.word(),
|
||||
ca_cert: 'ca-cert-123',
|
||||
tls_server_name: internet.domainName(),
|
||||
tls_skip_verify: datatype.boolean(),
|
||||
tls_server_name: faker.internet.domainName(),
|
||||
tls_skip_verify: faker.datatype.boolean(),
|
||||
token_hmac: 'token-hmac-abcde0987654321',
|
||||
client_certificate: 'client-cert-123',
|
||||
client_certificate_key_hmac: 'client-cert-key-hmac-abcde0987654321',
|
||||
worker_filter: faker.random.words(),
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
withAssociations: trait({
|
||||
afterCreate(credentialStore, server) {
|
||||
const { scope } = credentialStore;
|
||||
server.createList('credential-library', 2, {
|
||||
scope,
|
||||
credentialStore,
|
||||
});
|
||||
const { scope, type } = credentialStore;
|
||||
switch (type) {
|
||||
case 'vault':
|
||||
server.createList('credential-library', 2, {
|
||||
scope,
|
||||
credentialStore,
|
||||
});
|
||||
break;
|
||||
case 'static':
|
||||
default:
|
||||
server.createList('credential', 3, {
|
||||
scope,
|
||||
credentialStore,
|
||||
});
|
||||
}
|
||||
},
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import factory from '../generated/factories/credential';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generatedId from '../helpers/id';
|
||||
|
||||
const types = ['username_password', 'ssh_private_key', 'json'];
|
||||
|
||||
export default factory.extend({
|
||||
type: (i) => types[i % types.length],
|
||||
id() {
|
||||
switch (this.type) {
|
||||
case 'ssh_private_key':
|
||||
return generatedId('credspk_');
|
||||
case 'username_password':
|
||||
return generatedId('credup_');
|
||||
case 'json':
|
||||
return generatedId('credjson_');
|
||||
}
|
||||
},
|
||||
authorized_actions: () =>
|
||||
permissions.authorizedActionsFor('credential') || [
|
||||
'no-op',
|
||||
'read',
|
||||
'update',
|
||||
'delete',
|
||||
],
|
||||
attributes() {
|
||||
return {
|
||||
username: faker.random.word(),
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
import factory from '../generated/factories/group';
|
||||
import { trait } from 'ember-cli-mirage';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
export default factory.extend({
|
||||
authorized_actions: () =>
|
||||
@@ -12,7 +13,8 @@ export default factory.extend({
|
||||
'add-members',
|
||||
'remove-members',
|
||||
],
|
||||
id: (i) => `group-${i}`,
|
||||
|
||||
id: () => generateId('g_'),
|
||||
|
||||
/**
|
||||
* Generates some users for the same scope and assigns them to the group
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import factory from '../generated/factories/host-catalog';
|
||||
import { trait } from 'ember-cli-mirage';
|
||||
import permissions from '../helpers/permissions';
|
||||
import { datatype, address, random } from 'faker';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
const types = ['static', 'plugin'];
|
||||
// Represents known plugin types, except "foobar" which models the possibility
|
||||
@@ -11,7 +12,7 @@ const pluginTypes = ['aws', 'azure', 'foobar'];
|
||||
let pluginTypeCounter = 1;
|
||||
|
||||
export default factory.extend({
|
||||
id: (i) => `host-catalog-id-${i}`,
|
||||
id: () => generateId('hc_'),
|
||||
|
||||
// Cycle through available types
|
||||
type: (i) => types[i % types.length],
|
||||
@@ -37,7 +38,7 @@ export default factory.extend({
|
||||
return {
|
||||
id: `plugin-id-${i}`,
|
||||
name: pluginTypes[pluginTypeCounter++ % pluginTypes.length],
|
||||
description: random.words(),
|
||||
description: faker.random.words(),
|
||||
};
|
||||
}
|
||||
},
|
||||
@@ -46,15 +47,15 @@ export default factory.extend({
|
||||
switch (this.plugin?.name) {
|
||||
case 'aws':
|
||||
return {
|
||||
disable_credential_rotation: datatype.boolean(),
|
||||
region: address.state(),
|
||||
disable_credential_rotation: faker.datatype.boolean(),
|
||||
region: faker.address.state(),
|
||||
};
|
||||
case 'azure':
|
||||
return {
|
||||
disable_credential_rotation: datatype.boolean(),
|
||||
tenant_id: datatype.hexaDecimal(6),
|
||||
client_id: datatype.hexaDecimal(6),
|
||||
subscription_id: datatype.hexaDecimal(8),
|
||||
disable_credential_rotation: faker.datatype.boolean(),
|
||||
tenant_id: faker.datatype.hexadecimal(6),
|
||||
client_id: faker.datatype.hexadecimal(6),
|
||||
subscription_id: faker.datatype.hexadecimal(8),
|
||||
};
|
||||
}
|
||||
},
|
||||
@@ -63,13 +64,13 @@ export default factory.extend({
|
||||
switch (this.plugin?.name) {
|
||||
case 'aws':
|
||||
return {
|
||||
access_key_id: datatype.hexaDecimal(8),
|
||||
secret_access_key: datatype.string(12),
|
||||
access_key_id: faker.datatype.hexadecimal(8),
|
||||
secret_access_key: faker.datatype.string(12),
|
||||
};
|
||||
case 'azure':
|
||||
return {
|
||||
secret_id: datatype.hexaDecimal(6),
|
||||
secret_value: datatype.string(12),
|
||||
secret_id: faker.datatype.hexadecimal(6),
|
||||
secret_value: faker.datatype.string(12),
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import factory from '../generated/factories/host-set';
|
||||
import permissions from '../helpers/permissions';
|
||||
import { datatype, internet, database } from 'faker';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
export default factory.extend({
|
||||
id: (i) => `host-set-id-${i}`,
|
||||
id: () => generateId('hs_'),
|
||||
type() {
|
||||
return this.hostCatalog?.type || factory.attrs.type;
|
||||
},
|
||||
@@ -21,34 +22,37 @@ export default factory.extend({
|
||||
},
|
||||
preferred_endpoints() {
|
||||
if (this.type === 'plugin') {
|
||||
const enpointsAmount = datatype.number({ min: 1, max: 5 });
|
||||
const enpointsAmount = faker.datatype.number({ min: 1, max: 5 });
|
||||
let result = [];
|
||||
for (let i = 0; i < enpointsAmount; ++i) {
|
||||
result.push(internet.ip());
|
||||
result.push(faker.internet.ip());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
},
|
||||
sync_interval_seconds() {
|
||||
if (this.type === 'plugin') {
|
||||
return datatype.number();
|
||||
return faker.datatype.number();
|
||||
}
|
||||
},
|
||||
// AWS specific
|
||||
filters() {
|
||||
|
||||
attributes() {
|
||||
// AWS specific
|
||||
if (this.plugin?.name === 'aws') {
|
||||
const filtersAmount = datatype.number({ min: 1, max: 5 });
|
||||
let result = [];
|
||||
const filtersAmount = faker.datatype.number({ min: 1, max: 5 });
|
||||
let filters = [];
|
||||
for (let i = 0; i < filtersAmount; ++i) {
|
||||
result.push(`${datatype.string(3)}=${datatype.string(8)}`);
|
||||
filters.push(`${faker.datatype.string(3)}=${faker.datatype.string(8)}`);
|
||||
}
|
||||
return result;
|
||||
return {
|
||||
filters,
|
||||
};
|
||||
}
|
||||
},
|
||||
// Azure specific
|
||||
filter() {
|
||||
// Azure specific
|
||||
if (this.plugin?.name === 'azure') {
|
||||
return `${database.column()}=${database.collation()}`;
|
||||
return {
|
||||
filter: `${faker.database.column()}=${faker.database.collation()}`,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1,9 +1,11 @@
|
||||
import factory from '../generated/factories/host';
|
||||
import permissions from '../helpers/permissions';
|
||||
import { internet, datatype } from 'faker';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
export default factory.extend({
|
||||
id: (i) => `host-id-${i}`,
|
||||
id: () => generateId('h_'),
|
||||
|
||||
type() {
|
||||
return this.hostCatalog?.type || factory.attrs.type;
|
||||
},
|
||||
@@ -23,12 +25,12 @@ export default factory.extend({
|
||||
const addressesAmount = Math.floor(Math.random() * 6) + 1;
|
||||
let result = [];
|
||||
for (let i = 0; i < addressesAmount; ++i) {
|
||||
result.push(internet.ip());
|
||||
result.push(faker.internet.ip());
|
||||
}
|
||||
return result;
|
||||
},
|
||||
external_id() {
|
||||
return datatype.uuid();
|
||||
return faker.datatype.uuid();
|
||||
},
|
||||
// Only aws plugins have dns_names
|
||||
dns_names() {
|
||||
@@ -36,7 +38,7 @@ export default factory.extend({
|
||||
const dnsNamesAmount = Math.floor(Math.random() * 6) + 1;
|
||||
let result = [];
|
||||
for (let i = 0; i < dnsNamesAmount; i++) {
|
||||
result.push(internet.domainName());
|
||||
result.push(faker.internet.domainName());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import factory from '../generated/factories/managed-group';
|
||||
import { random } from 'faker';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
const types = ['oidc'];
|
||||
|
||||
export default factory.extend({
|
||||
id: (i) => `managed-groups-id-${i}`,
|
||||
type: (i) => types[i % types.length],
|
||||
|
||||
authorized_actions: () =>
|
||||
@@ -16,11 +16,13 @@ export default factory.extend({
|
||||
'delete',
|
||||
],
|
||||
|
||||
id: () => generateId('mg_'),
|
||||
|
||||
attributes() {
|
||||
switch (this.type) {
|
||||
case 'oidc':
|
||||
return {
|
||||
filter: random.words(),
|
||||
filter: faker.random.words(),
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import factory from '../generated/factories/role';
|
||||
import { trait } from 'ember-cli-mirage';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
export default factory.extend({
|
||||
authorized_actions: () =>
|
||||
@@ -19,6 +20,8 @@ export default factory.extend({
|
||||
'id=*;type=host-catalog;actions=create,read',
|
||||
],
|
||||
|
||||
id: () => generateId('r_'),
|
||||
|
||||
/**
|
||||
* Adds principals to the role.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import factory from '../generated/factories/scope';
|
||||
import { trait } from 'ember-cli-mirage';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
export default factory.extend({
|
||||
type: 'global',
|
||||
@@ -13,8 +14,8 @@ export default factory.extend({
|
||||
'delete',
|
||||
],
|
||||
|
||||
authorized_collection_actions: () => {
|
||||
return {
|
||||
authorized_collection_actions() {
|
||||
const collectionActions = {
|
||||
scopes: ['create', 'list'],
|
||||
users: ['create', 'list'],
|
||||
sessions: ['list'],
|
||||
@@ -25,17 +26,16 @@ export default factory.extend({
|
||||
'auth-methods': ['create', 'list'],
|
||||
'host-catalogs': ['create', 'list'],
|
||||
};
|
||||
|
||||
// Worker permissions only available on the global scope
|
||||
if (this.type === 'global') {
|
||||
collectionActions.workers = ['create:worker-led', 'list'];
|
||||
}
|
||||
|
||||
return collectionActions;
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates realistic-ish IDs while still being deterministic.
|
||||
*/
|
||||
id(i) {
|
||||
let id = 'tv6fv3yz8p';
|
||||
if (i % 3) id = 'xk1i4dk50v';
|
||||
if (i % 2) id = 's9n819zgko';
|
||||
return `s_${id}${i}`;
|
||||
},
|
||||
id: () => generateId('s_'),
|
||||
|
||||
withChildren: trait({
|
||||
afterCreate(record, server) {
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import factory from '../generated/factories/session';
|
||||
import { trait } from 'ember-cli-mirage';
|
||||
import { random } from 'faker';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
const statusStrings = ['pending', 'active', 'canceling', 'terminated'];
|
||||
|
||||
export const pickRandomStatusString = () => random.arrayElement(statusStrings);
|
||||
export const pickRandomStatusString = () =>
|
||||
faker.helpers.arrayElement(statusStrings);
|
||||
|
||||
export default factory.extend({
|
||||
id: (i) => `session-id-${i}`,
|
||||
id: () => generateId('ss_'),
|
||||
|
||||
status: pickRandomStatusString,
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import factory from '../generated/factories/target';
|
||||
import { trait } from 'ember-cli-mirage';
|
||||
import { random, datatype } from 'faker';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
const randomBoolean = (chance = 0.5) => Math.random() < chance;
|
||||
const hostSetChance = 0.3;
|
||||
@@ -21,11 +22,14 @@ export default factory.extend({
|
||||
'remove-credential-sources',
|
||||
],
|
||||
|
||||
id: () => generateId('t_'),
|
||||
|
||||
/**
|
||||
* -1 means "unlimited" and we want to generate these on occasion.
|
||||
*/
|
||||
session_connection_limit: () => random.arrayElement([-1, datatype.number()]),
|
||||
worker_filter: (i) => (i % 2 === 0 ? random.words() : null),
|
||||
session_connection_limit: () =>
|
||||
faker.helpers.arrayElement([-1, faker.datatype.number()]),
|
||||
worker_filter: (i) => (i % 2 === 0 ? faker.random.words() : null),
|
||||
type: (i) => types[i % types.length],
|
||||
/**
|
||||
* Generates attributes fields by type.
|
||||
@@ -34,7 +38,7 @@ export default factory.extend({
|
||||
if (target.type === 'tcp' || target.type === 'ssh') {
|
||||
target.update({
|
||||
attributes: {
|
||||
default_port: datatype.number(),
|
||||
default_port: faker.datatype.number(),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -45,7 +49,9 @@ export default factory.extend({
|
||||
*/
|
||||
withAssociations: trait({
|
||||
afterCreate(target, server) {
|
||||
let randomlySelectedHostSets, randomlySelectedCredentialLibraries;
|
||||
let randomlySelectedHostSets,
|
||||
randomlySelectedCredentialLibraries,
|
||||
randomlySelectedCredentials;
|
||||
randomlySelectedHostSets = server.schema.hostSets
|
||||
// BLERG: fun fact, for no reason at all, the element passed
|
||||
// into a where function is not a full model instance, as you might
|
||||
@@ -59,11 +65,22 @@ export default factory.extend({
|
||||
.where(
|
||||
(credentialLibrary) => credentialLibrary.scopeId === target.scope.id
|
||||
)
|
||||
.models.filter(() => randomBoolean());
|
||||
|
||||
.models.filter(() => randomBoolean())
|
||||
.map((cred) => cred.id);
|
||||
randomlySelectedCredentials = server.schema.credentials
|
||||
.where((credential) => credential.scopeId === target.scope.id)
|
||||
.models.filter(() => randomBoolean())
|
||||
.map((cred) => cred.id);
|
||||
target.update({
|
||||
hostSets: randomlySelectedHostSets,
|
||||
credentialLibraries: randomlySelectedCredentialLibraries,
|
||||
brokeredCredentialSourceIds: [
|
||||
...randomlySelectedCredentialLibraries,
|
||||
...randomlySelectedCredentials,
|
||||
],
|
||||
injectedApplicationCredentialSourceIds: [
|
||||
...randomlySelectedCredentialLibraries,
|
||||
...randomlySelectedCredentials,
|
||||
],
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import factory from '../generated/factories/user';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
export default factory.extend({
|
||||
authorized_actions: () =>
|
||||
@@ -11,5 +12,5 @@ export default factory.extend({
|
||||
'add-accounts',
|
||||
'remove-accounts',
|
||||
],
|
||||
id: (i) => `user-${i}`,
|
||||
id: () => generateId('u_'),
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import factory from '../generated/factories/worker';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
const types = ['pki', 'kms'];
|
||||
|
||||
export default factory.extend({
|
||||
id: () => generateId('w_'),
|
||||
authorized_actions: () =>
|
||||
permissions.authorizedActionsFor('worker') || [
|
||||
'no-op',
|
||||
'read',
|
||||
'update',
|
||||
'delete',
|
||||
],
|
||||
type: (i) => types[i % types.length],
|
||||
canonical_tags: (i) => {
|
||||
if (i % 3 === 0) {
|
||||
return { os: ['ubuntu'] };
|
||||
}
|
||||
if (i % 2 === 0) {
|
||||
return {
|
||||
type: [faker.random.word(), faker.random.word()],
|
||||
os: ['ubuntu'],
|
||||
env: ['dev', 'local'],
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
config_tags: (i) => {
|
||||
if (i % 3 === 0) {
|
||||
return { os: ['ubuntu'] };
|
||||
}
|
||||
if (i % 2 === 0) {
|
||||
return {
|
||||
type: [faker.random.word(), faker.random.word()],
|
||||
os: ['ubuntu'],
|
||||
env: ['dev', 'local'],
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
@@ -1,14 +1,12 @@
|
||||
import { Factory } from 'ember-cli-mirage';
|
||||
import { date, datatype } from 'faker';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
/**
|
||||
* GeneratedAccountFactory
|
||||
*/
|
||||
export default Factory.extend({
|
||||
type: 'password',
|
||||
// name: () => random.words(),
|
||||
// description: () => random.words(),
|
||||
created_time: () => date.recent(),
|
||||
updated_time: () => date.recent(),
|
||||
version: () => datatype.number(),
|
||||
created_time: () => faker.date.recent(),
|
||||
updated_time: () => faker.date.recent(),
|
||||
version: () => faker.datatype.number(),
|
||||
});
|
||||
@@ -1,16 +1,16 @@
|
||||
import { Factory } from 'ember-cli-mirage';
|
||||
import { random, date, datatype } from 'faker';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
/**
|
||||
* GeneratedAuthMethodModelFactory
|
||||
*/
|
||||
export default Factory.extend({
|
||||
type: 'password',
|
||||
name: () => random.words(),
|
||||
description: () => random.words(),
|
||||
created_time: () => date.recent(),
|
||||
updated_time: () => date.recent(),
|
||||
disabled: () => datatype.boolean(),
|
||||
name: () => faker.random.words(),
|
||||
description: () => faker.random.words(),
|
||||
created_time: () => faker.date.recent(),
|
||||
updated_time: () => faker.date.recent(),
|
||||
disabled: () => faker.datatype.boolean(),
|
||||
|
||||
attributes: function () {
|
||||
let attrs;
|
||||
|
||||
Loaded 100 of 864 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user