Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ac7dfb677 | ||
|
|
683e939b0e |
No files matched your search
@@ -1,2 +0,0 @@
|
||||
# Anyone attached to this rule will always been assigned to a pull request
|
||||
* @hashicorp/boundary-ui
|
||||
@@ -1,6 +1,3 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
contact_links:
|
||||
- name: Ask a question
|
||||
url: https://discuss.hashicorp.com/c/boundary
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
addons:
|
||||
- addons/**/*
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
:tickets: [Jira ticket](https://hashicorp.atlassian.net/browse/JIRA_TICKET_NUMBER)
|
||||
|
||||
## Description
|
||||
|
||||
<!--
|
||||
Replace PATH_TO_FEATURE with Vercel link
|
||||
-->
|
||||
|
||||
:technologist: [Admin preview](PATH_TO_FEATURE)
|
||||
|
||||
:rose: [Rose preview](PATH_TO_FEATURE)
|
||||
|
||||
:desktop_computer: [Desktop preview](PATH_TO_FEATURE)
|
||||
|
||||
<!-- Add a brief description of changes here. Include any other necessary relevant links -->
|
||||
|
||||
### Screenshots (if appropriate):
|
||||
@@ -1,97 +0,0 @@
|
||||
name: Build Admin UI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
dependencies:
|
||||
name: Install dependencies
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn install
|
||||
build-admin-ui-oss:
|
||||
name: Build Admin UI OSS
|
||||
needs: [dependencies]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- name: Build
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn run build:ui:admin:oss
|
||||
- name: Upload artifact admin-ui
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
with:
|
||||
name: admin-ui
|
||||
path: ./ui/admin/dist/
|
||||
- name: Upload artifact OSS admin UI
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
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@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- name: Build
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn run build:ui:admin:enterprise
|
||||
- name: Upload artifact enterprise admin UI
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
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@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- name: Build
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn run build:ui:admin:hcp
|
||||
- name: Upload artifact HCP admin UI
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
with:
|
||||
name: admin-ui-hcp
|
||||
path: ./ui/admin/dist/
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@9a866ed4524fc3422c3af1e446dab8efa3503411 # codeql-bundle-20230418
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@9a866ed4524fc3422c3af1e446dab8efa3503411 # codeql-bundle-20230418
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -68,4 +68,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@9a866ed4524fc3422c3af1e446dab8efa3503411 # codeql-bundle-20230418
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.JIRA_SYNC_GITHUB_TOKEN }}
|
||||
|
||||
- name: Login
|
||||
uses: atlassian/gajira-login@45fd029b9f1d6d8926c6f04175aa80c0e42c9026 # v3.0.1
|
||||
uses: atlassian/gajira-login@v2.0.0
|
||||
env:
|
||||
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
|
||||
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
|
||||
- name: Create ticket
|
||||
if: github.event.action == 'opened' && !steps.boundary-team-role.outputs.role
|
||||
uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1
|
||||
uses: tomhjp/gh-action-jira-create@v0.1.0
|
||||
with:
|
||||
project: ICU
|
||||
issuetype: "GH Issue"
|
||||
@@ -61,28 +61,28 @@ jobs:
|
||||
- name: Search
|
||||
if: github.event.action != 'opened'
|
||||
id: search
|
||||
uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2
|
||||
uses: tomhjp/gh-action-jira-search@v0.2.1
|
||||
with:
|
||||
# cf[10089] is Issue Link custom field
|
||||
jql: 'issuetype = "GH Issue" and cf[10089]="${{ github.event.issue.html_url || github.event.pull_request.html_url }}"'
|
||||
|
||||
- name: Sync comment
|
||||
if: github.event.action == 'created' && steps.search.outputs.issue
|
||||
uses: atlassian/gajira-comment@v2.0.2 # TSCCR: no entry for repository "atlassian/gajira-comment"
|
||||
uses: atlassian/gajira-comment@v2.0.2
|
||||
with:
|
||||
issue: ${{ steps.search.outputs.issue }}
|
||||
comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}"
|
||||
|
||||
- name: Close ticket
|
||||
if: (github.event.action == 'closed' || github.event.action == 'deleted') && steps.search.outputs.issue
|
||||
uses: atlassian/gajira-transition@38fc9cd61b03d6a53dd35fcccda172fe04b36de3 # v3.0.1
|
||||
uses: atlassian/gajira-transition@v2.0.1
|
||||
with:
|
||||
issue: ${{ steps.search.outputs.issue }}
|
||||
transition: Done
|
||||
|
||||
- name: Reopen ticket
|
||||
if: github.event.action == 'reopened' && steps.search.outputs.issue
|
||||
uses: atlassian/gajira-transition@38fc9cd61b03d6a53dd35fcccda172fe04b36de3 # v3.0.1
|
||||
uses: atlassian/gajira-transition@v2.0.1
|
||||
with:
|
||||
issue: ${{ steps.search.outputs.issue }}
|
||||
transition: "To Do"
|
||||
@@ -6,6 +6,6 @@ jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@ba790c862c380240c6d5e7427be5ace9a05c754b # v4.0.3
|
||||
- uses: actions/labeler@main
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
@@ -6,17 +6,17 @@ jobs:
|
||||
name: Install dependencies
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: '16.x'
|
||||
- run: yarn install
|
||||
|
||||
compliance:
|
||||
@@ -24,51 +24,54 @@ jobs:
|
||||
needs: [dependencies]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: '16.x'
|
||||
if: steps.node-modules-cache.outputs.cache-hit != 'true'
|
||||
- run: yarn run compliance:licenses
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
needs: [dependencies, compliance]
|
||||
needs: [dependencies]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: '16.x'
|
||||
if: steps.node-modules-cache.outputs.cache-hit != 'true'
|
||||
- run: yarn lint
|
||||
|
||||
test:
|
||||
name: Test
|
||||
needs: [lint]
|
||||
needs: [dependencies]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
- uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: '16.x'
|
||||
if: steps.node-modules-cache.outputs.cache-hit != 'true'
|
||||
- run: yarn test
|
||||
@@ -1,25 +0,0 @@
|
||||
name: Trigger OSS to Enterprise Merge
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- closed
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
trigger-oss-merge:
|
||||
# Run this only on merge events in OSS repo
|
||||
if: ${{ github.event.pull_request.merged && github.repository == 'hashicorp/boundary-ui' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger Merge
|
||||
env:
|
||||
GIT_REF: ${{ github.ref_name }}
|
||||
GIT_SHA: ${{ github.sha }}
|
||||
GH_PAT: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
|
||||
GIT_ACTOR: ${{ github.actor }}
|
||||
run: |
|
||||
curl -H "Authorization: token $GH_PAT" \
|
||||
-H 'Accept: application/json' \
|
||||
-d "{\"event_type\": \"oss-merge\", \"client_payload\": {\"git-ref\": \"${GIT_REF}\", \"git-sha\": \"${GIT_SHA}\", \"git-actor\": \"${GIT_ACTOR}\" }}" \
|
||||
"https://api.github.com/repos/hashicorp/boundary-ui-enterprise/dispatches"
|
||||
@@ -1,5 +1,6 @@
|
||||
name: "Trigger Test Boundary UI release"
|
||||
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
@@ -8,18 +9,15 @@ on:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
trigger-gha-release:
|
||||
trigger-circleci-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Release description
|
||||
|
||||
- name: Trigger Release job
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: |
|
||||
echo "Triggering Test release using BRANCH and TEST_TAG ${{ github.event.inputs.branch }}"
|
||||
- name: Trigger Release workflow in boundary-ui-releases
|
||||
run: |
|
||||
export GITHUB_TOKEN="${{ secrets.ELEVATED_GITHUB_TOKEN }}"
|
||||
gh workflow run release.yml \
|
||||
--repo hashicorp/boundary-ui-releases \
|
||||
--ref main \
|
||||
-f TAG="${{ github.event.inputs.branch }}"
|
||||
|
||||
curl -u ${{ secrets.CIRCLE_TOKEN }}: -X POST --header "Content-Type: application/json" \
|
||||
-d '{ "branch": "main", "parameters": {"TAG": "'${{ github.event.inputs.branch }}'" }}' \
|
||||
https://circleci.com/api/v2/project/github/hashicorp/boundary-ui-releases/pipeline
|
||||
@@ -6,17 +6,14 @@ on:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
trigger-gha-release:
|
||||
trigger-circleci-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- name: Release description
|
||||
- uses: actions/checkout@v2
|
||||
- name: Trigger Release job
|
||||
run: |
|
||||
echo "Triggering release with a TAG ${GITHUB_REF#refs/tags/}"
|
||||
- name: Trigger Release workflow in boundary-ui-releases
|
||||
run: |
|
||||
export GITHUB_TOKEN="${{ secrets.ELEVATED_GITHUB_TOKEN }}"
|
||||
gh workflow run release.yml \
|
||||
--repo hashicorp/boundary-ui-releases \
|
||||
--ref main \
|
||||
-f TAG="${GITHUB_REF#refs/tags/}"
|
||||
|
||||
curl -u ${{ secrets.CIRCLE_TOKEN }}: -X POST --header "Content-Type: application/json" \
|
||||
-d '{ "branch": "main", "parameters": {"TAG": "'${GITHUB_REF#refs/tags/}'" }}' \
|
||||
https://circleci.com/api/v2/project/github/hashicorp/boundary-ui-releases/pipeline
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
yarn compliance:licenses
|
||||
npx lint-staged
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,6 +0,0 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
url_license = "https://github.com/hashicorp/boundary-ui/blob/main/LICENSE"
|
||||
url_project_website = "https://learn.hashicorp.com/tutorials/boundary/getting-started-desktop-app"
|
||||
url_source_repository = "https://github.com/hashicorp/boundary-ui"
|
||||
@@ -1,5 +1,3 @@
|
||||
Copyright (c) 2020 HashiCorp, Inc.
|
||||
|
||||
Mozilla Public License, version 2.0
|
||||
|
||||
1. Definitions
|
||||
|
||||
@@ -38,9 +38,9 @@ You will need the following things properly installed on your computer.
|
||||
|
||||
* [Git][git]
|
||||
* [Node.js][node]
|
||||
* Supported versions:`v12`, `v14` and `v16`.
|
||||
* v10–v15
|
||||
* **Apple Silicon Users**: if you experience problems building or running
|
||||
Boundary UIs, try Node v14.
|
||||
Boundary UIs, try Node v15.
|
||||
* [Yarn][yarn] installed globally
|
||||
* [Google Chrome][chrome]
|
||||
* [Firefox][firefox]
|
||||
@@ -66,6 +66,7 @@ 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. |
|
||||
@@ -159,16 +160,15 @@ 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 cluster URL of your Boundary dev instance, by default is: `http://localhost:9200`.
|
||||
Enter the origin of your Boundary dev instance, by default is: `http://localhost:9200`.
|
||||
|
||||
### Committing
|
||||
|
||||
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`.
|
||||
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.
|
||||
|
||||
#### License Checking
|
||||
|
||||
|
||||
@@ -14,6 +14,3 @@ indent_size = 2
|
||||
|
||||
[*.{diff,md}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.hbs]
|
||||
insert_final_newline = false
|
||||
@@ -5,11 +5,5 @@
|
||||
|
||||
Setting `disableAnalytics` to true will prevent any data from being sent.
|
||||
*/
|
||||
"disableAnalytics": false,
|
||||
|
||||
/**
|
||||
Setting `isTypeScriptProject` to true will force the blueprint generators to generate TypeScript
|
||||
rather than JavaScript by default, when a TypeScript version of a given blueprint is available.
|
||||
*/
|
||||
"isTypeScriptProject": false
|
||||
"disableAnalytics": false
|
||||
}
|
||||
@@ -13,13 +13,5 @@
|
||||
# misc
|
||||
/coverage/
|
||||
!.*
|
||||
.*/
|
||||
.eslintcache
|
||||
|
||||
# ember-try
|
||||
/.node_modules.ember-try/
|
||||
/bower.json.ember-try
|
||||
/npm-shrinkwrap.json.ember-try
|
||||
/package.json.ember-try
|
||||
/package-lock.json.ember-try
|
||||
/yarn.lock.ember-try
|
||||
+23
-21
@@ -1,25 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: '@babel/eslint-parser',
|
||||
parser: 'babel-eslint',
|
||||
parserOptions: {
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
// This is specific babel-config. If grows consider creating a babel config file
|
||||
requireConfigFile: false,
|
||||
babelOptions: {
|
||||
plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]],
|
||||
ecmaFeatures: {
|
||||
legacyDecorators: true,
|
||||
},
|
||||
// end of babel-config
|
||||
},
|
||||
plugins: ['ember'],
|
||||
extends: ['eslint:recommended', 'plugin:ember/recommended', 'prettier'],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:ember/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
@@ -34,15 +30,21 @@ module.exports = {
|
||||
// node files
|
||||
{
|
||||
files: [
|
||||
'./.eslintrc.js',
|
||||
'./.prettierrc.js',
|
||||
'./.template-lintrc.js',
|
||||
'./ember-cli-build.js',
|
||||
'./index.js',
|
||||
'./testem.js',
|
||||
'./blueprints/*/index.js',
|
||||
'./config/**/*.js',
|
||||
'./tests/dummy/config/**/*.js',
|
||||
'.eslintrc.js',
|
||||
'.prettierrc.js',
|
||||
'.template-lintrc.js',
|
||||
'ember-cli-build.js',
|
||||
'index.js',
|
||||
'testem.js',
|
||||
'blueprints/*/index.js',
|
||||
'config/**/*.js',
|
||||
'tests/dummy/config/**/*.js',
|
||||
],
|
||||
excludedFiles: [
|
||||
'addon/**',
|
||||
'addon-test-support/**',
|
||||
'app/**',
|
||||
'tests/dummy/app/**',
|
||||
],
|
||||
parserOptions: {
|
||||
sourceType: 'script',
|
||||
|
||||
@@ -14,27 +14,14 @@
|
||||
/.eslintignore
|
||||
/.eslintrc.js
|
||||
/.git/
|
||||
/.github/
|
||||
/.gitignore
|
||||
/.prettierignore
|
||||
/.prettierrc.js
|
||||
/.template-lintrc.js
|
||||
/.travis.yml
|
||||
/.watchmanconfig
|
||||
/bower.json
|
||||
/config/ember-try.js
|
||||
/CONTRIBUTING.md
|
||||
/ember-cli-build.js
|
||||
/testem.js
|
||||
/tests/
|
||||
/yarn-error.log
|
||||
/yarn.lock
|
||||
.gitkeep
|
||||
|
||||
# ember-try
|
||||
/.node_modules.ember-try/
|
||||
/bower.json.ember-try
|
||||
/npm-shrinkwrap.json.ember-try
|
||||
/package.json.ember-try
|
||||
/package-lock.json.ember-try
|
||||
/yarn.lock.ember-try
|
||||
@@ -14,12 +14,3 @@
|
||||
/coverage/
|
||||
!.*
|
||||
.eslintcache
|
||||
.lint-todo/
|
||||
|
||||
# ember-try
|
||||
/.node_modules.ember-try/
|
||||
/bower.json.ember-try
|
||||
/npm-shrinkwrap.json.ember-try
|
||||
/package.json.ember-try
|
||||
/package-lock.json.ember-try
|
||||
/yarn.lock.ember-try
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"printWidth": 80
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
singleQuote: true,
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
extends: ['recommended', 'stylistic'],
|
||||
extends: 'octane',
|
||||
};
|
||||
@@ -47,28 +47,21 @@ 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:ember-compatibility | Runs tests across multiple Ember versions with ember-try. |
|
||||
| precommit | Runs all lint and format. |
|
||||
| test:all | Runs tests across multiple Ember versions with ember-try. |
|
||||
| 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
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ModelAbility from './model';
|
||||
|
||||
/**
|
||||
@@ -11,30 +6,6 @@ import ModelAbility from './model';
|
||||
export default class AccountAbility extends ModelAbility {
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
* Only "known" account types may be read.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canRead() {
|
||||
return !this.model.isUnknown && this.hasAuthorizedAction('read');
|
||||
}
|
||||
|
||||
/**
|
||||
* Only "known" account types may be updated.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canUpdate() {
|
||||
return !this.model.isUnknown && this.hasAuthorizedAction('update');
|
||||
}
|
||||
|
||||
/**
|
||||
* Only "known" account types may be deleted.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canDelete() {
|
||||
return !this.model.isUnknown && this.hasAuthorizedAction('delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ModelAbility from './model';
|
||||
/**
|
||||
* Provides abilities for auth method.
|
||||
*/
|
||||
export default class AuthMethodAbility extends ModelAbility {
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
* Only "known" auth method types may be read.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canRead() {
|
||||
return !this.model.isUnknown && this.hasAuthorizedAction('read');
|
||||
}
|
||||
|
||||
/**
|
||||
* Only "known" auth method types may be updated.
|
||||
*/
|
||||
get canUpdate() {
|
||||
return !this.model.isUnknown && this.hasAuthorizedAction('update');
|
||||
}
|
||||
|
||||
/**
|
||||
* Only "known" auth method types may be deleted.
|
||||
*/
|
||||
get canDelete() {
|
||||
return !this.model.isUnknown && this.hasAuthorizedAction('delete');
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ModelAbility from './model';
|
||||
/**
|
||||
* Provides abilities for credential.
|
||||
*/
|
||||
export default class CredentialLibraryAbility extends ModelAbility {
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
* Only "known" credential library types may be read.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canRead() {
|
||||
return !this.model.isUnknown && this.hasAuthorizedAction('read');
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ModelAbility from './model';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ModelAbility from './model';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ModelAbility from './model';
|
||||
|
||||
/**
|
||||
* Provides abilities for host sets.
|
||||
*/
|
||||
export default class HostSetAbility extends ModelAbility {
|
||||
export default class UserAbility extends ModelAbility {
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
@@ -24,11 +19,4 @@ export default class HostSetAbility extends ModelAbility {
|
||||
get canRemoveHosts() {
|
||||
return this.hasAuthorizedAction('remove-hosts');
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canRead() {
|
||||
return !this.model.isUnknown && this.hasAuthorizedAction('read');
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ModelAbility from './model';
|
||||
|
||||
/**
|
||||
* Provides abilities for managed groups.
|
||||
*/
|
||||
export default class ManagedGroupAbility extends ModelAbility {
|
||||
// no op
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import { Ability } from 'ember-can';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,23 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ModelAbility from './model';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
class InvalidRolePrincipalTypeError extends Error {
|
||||
name = 'InvalidRolePrincipalTypeError';
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides abilities for roles.
|
||||
*/
|
||||
export default class RoleAbility extends ModelAbility {
|
||||
// =services
|
||||
|
||||
@service can;
|
||||
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
@@ -40,22 +26,4 @@ export default class RoleAbility extends ModelAbility {
|
||||
get canRemovePrincipals() {
|
||||
return this.hasAuthorizedAction('remove-principals');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ability check for a principal model instance.
|
||||
* Valid role principal models are: User, Group, and ManagedGroup.
|
||||
* Throws an error if the principal type is invalid.
|
||||
* @type {boolean}
|
||||
* @throws {InvalidRolePrincipalTypeError}
|
||||
*/
|
||||
get canReadPrincipal() {
|
||||
const type = this.model.constructor.modelName;
|
||||
const typeIsValid =
|
||||
type === 'user' || type === 'group' || type === 'managed-group';
|
||||
if (!typeIsValid)
|
||||
throw new InvalidRolePrincipalTypeError(
|
||||
`Expected a role principal of type 'user', 'group', or 'managed-group'. Got '${type}'.`
|
||||
);
|
||||
return this.can.can(`read ${type}`, this.model);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ModelAbility from './model';
|
||||
|
||||
/**
|
||||
@@ -35,18 +30,10 @@ export default class TargetAbility extends ModelAbility {
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canAddBrokeredCredentialSources() {
|
||||
get canAddCredentialSources() {
|
||||
return this.hasAuthorizedAction('add-credential-sources');
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canAddInjectedApplicationCredentialSources() {
|
||||
return (
|
||||
this.model.isSSH && this.hasAuthorizedAction('add-credential-sources')
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ModelAbility from './model';
|
||||
|
||||
/**
|
||||
@@ -24,20 +19,4 @@ export default class UserAbility extends ModelAbility {
|
||||
get canRemoveAccounts() {
|
||||
return this.hasAuthorizedAction('remove-accounts');
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canAddAccount() {
|
||||
const { account, canAddAccounts } = this;
|
||||
return canAddAccounts && !account.isUnknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canRemoveAccount() {
|
||||
const { account, canRemoveAccounts } = this;
|
||||
return canRemoveAccounts && !account.isUnknown;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import RESTAdapter from '@ember-data/adapter/rest';
|
||||
import { serializeIntoHash } from '@ember-data/adapter/-private';
|
||||
/* eslint-disable-next-line ember/no-mixins */
|
||||
@@ -268,17 +263,36 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
|
||||
source: { pointer: '/data' },
|
||||
};
|
||||
// Normalize field-specific errors, if any.
|
||||
const errors = fieldErrors.map((error) => ({
|
||||
detail: error.description,
|
||||
// Going forward, nested attributes will be hoisted. Thus "attributes."
|
||||
// must be stripped from the error name key. Until all models are
|
||||
// transitioned away from model fragments, however, both this and the
|
||||
// prior error key mappings are necessary.
|
||||
source: {
|
||||
pointer: `/data/attributes/${error.name.replace('attributes.', '')}`,
|
||||
},
|
||||
}));
|
||||
|
||||
const errors = fieldErrors.flatMap((error) => {
|
||||
const newValue = [
|
||||
{
|
||||
detail: error.description,
|
||||
// Ember Data cannot handle errors on nested attributes, so these are
|
||||
// flattened (e.g. `attributes.foobar` becomes `attributes_foobar`).
|
||||
// To capture these errors, add read-only fields on the model
|
||||
// corresponding to the underscored field name.
|
||||
source: {
|
||||
pointer: `/data/attributes/${error.name.replace('.', '_')}`,
|
||||
},
|
||||
},
|
||||
];
|
||||
if (error.name.includes('attributes.')) {
|
||||
newValue.push({
|
||||
detail: error.description,
|
||||
// Going forward, nested attributes will be hoisted. Thus "attributes."
|
||||
// must be stripped from the error name key. Until all models are
|
||||
// transitioned away from model fragments, however, both this and the
|
||||
// prior error key mappings are necessary.
|
||||
source: {
|
||||
pointer: `/data/attributes/${error.name.replace(
|
||||
'attributes.',
|
||||
''
|
||||
)}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
return newValue;
|
||||
});
|
||||
// Return a list of JSON API errors rooted under the `errors` key.
|
||||
return {
|
||||
errors: [baseError, ...errors],
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ApplicationAdapter from './application';
|
||||
|
||||
export default class HostCatalogAdapter extends ApplicationAdapter {
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
@@ -48,20 +43,4 @@ 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;
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
@@ -54,56 +49,4 @@ export default class GeneratedAuthMethodModel extends BaseModel {
|
||||
description: 'Current version number of this resource.',
|
||||
})
|
||||
version;
|
||||
|
||||
@attr('string', { readOnly: true, isNestedAttribute: true }) state;
|
||||
|
||||
@attr('string', { isNestedAttribute: true }) issuer;
|
||||
|
||||
@attr('string', { isNestedAttribute: true }) client_id;
|
||||
|
||||
@attr('string', { isNestedAttribute: true, isSecret: true }) client_secret;
|
||||
|
||||
@attr('string', { readOnly: true, isNestedAttribute: true })
|
||||
client_secret_hmac;
|
||||
|
||||
@attr('number', { isNestedAttribute: true }) max_age;
|
||||
|
||||
@attr('string', { isNestedAttribute: true }) api_url_prefix;
|
||||
|
||||
@attr('string', { readOnly: true, isNestedAttribute: true }) callback_url;
|
||||
|
||||
@attr('boolean', { isNestedAttribute: true })
|
||||
disable_discovered_config_validation;
|
||||
|
||||
@attr('boolean', { isNestedAttribute: true }) dry_run;
|
||||
|
||||
@attr('string-array', {
|
||||
emptyArrayIfMissing: true,
|
||||
isNestedAttribute: true,
|
||||
})
|
||||
claims_scopes;
|
||||
|
||||
@attr('string-array', {
|
||||
emptyArrayIfMissing: true,
|
||||
isNestedAttribute: true,
|
||||
})
|
||||
signing_algorithms;
|
||||
|
||||
@attr('string-array', {
|
||||
emptyArrayIfMissing: true,
|
||||
isNestedAttribute: true,
|
||||
})
|
||||
allowed_audiences;
|
||||
|
||||
@attr('string-array', {
|
||||
emptyArrayIfMissing: true,
|
||||
isNestedAttribute: true,
|
||||
})
|
||||
idp_ca_certs;
|
||||
|
||||
@attr('account-claim-map-array', {
|
||||
emptyArrayIfMissing: true,
|
||||
isNestedAttribute: true,
|
||||
})
|
||||
account_claim_maps;
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
@@ -49,82 +44,4 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
|
||||
description: 'Current version number of this resource.',
|
||||
})
|
||||
version;
|
||||
|
||||
//= attributes (vault)
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault-generic',
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'The HTTP method the library uses when requesting credentials from Vault.',
|
||||
defaultValue: () => 'GET',
|
||||
})
|
||||
http_method;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault-generic',
|
||||
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;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault-ssh-certificate',
|
||||
isNestedAttribute: true,
|
||||
description: 'The username to use when making an SSH connection.',
|
||||
})
|
||||
username;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault-ssh-certificate',
|
||||
isNestedAttribute: true,
|
||||
description: 'The desired key type to use when generating a private key.',
|
||||
})
|
||||
key_type;
|
||||
|
||||
@attr('number', {
|
||||
for: 'vault-ssh-certificate',
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'Specifies the number of bits used when generating the private key. Not used if key type is ed25519',
|
||||
})
|
||||
key_bits;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault-ssh-certificate',
|
||||
isNestedAttribute: true,
|
||||
description: 'Specifies the requested time to live for the certificate.',
|
||||
})
|
||||
ttl;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault-ssh-certificate',
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'Specifies the key id that the created certificate should have.',
|
||||
})
|
||||
key_id;
|
||||
|
||||
@attr('object-as-array', {
|
||||
for: 'vault-ssh-certificate',
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'Specifies a map of the critical options that the certificate should be signed for.',
|
||||
})
|
||||
critical_options;
|
||||
|
||||
@attr('object-as-array', {
|
||||
for: 'vault-ssh-certificate',
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'Specifies a map of the extensions that the certificate should be signed for.',
|
||||
})
|
||||
extensions;
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
@@ -44,91 +39,4 @@ 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,
|
||||
isSecret: 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;
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
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,
|
||||
isSecret: true,
|
||||
description: 'The password for credential.',
|
||||
})
|
||||
password;
|
||||
|
||||
// =attributes (ssh_private_key)
|
||||
@attr('string', {
|
||||
for: 'ssh_private_key',
|
||||
isNestedAttribute: true,
|
||||
isSecret: true,
|
||||
description: 'The private key for credential.',
|
||||
})
|
||||
private_key;
|
||||
|
||||
@attr('string', {
|
||||
for: 'ssh_private_key',
|
||||
isNestedAttribute: true,
|
||||
isSecret: true,
|
||||
description: 'The private key passphrase for credential.',
|
||||
})
|
||||
private_key_passphrase;
|
||||
|
||||
@attr('string', {
|
||||
for: 'json',
|
||||
isNestedAttribute: true,
|
||||
isSecret: true,
|
||||
description: 'The secret associated with credential.',
|
||||
})
|
||||
json_object;
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
@@ -68,32 +63,10 @@ export default class GeneratedHostSetModel extends BaseModel {
|
||||
})
|
||||
sync_interval_seconds;
|
||||
|
||||
/**
|
||||
* Host IDs are read-only under normal circumstances. But these can
|
||||
* be persisted via a dedicated call to `addHosts()`.
|
||||
*/
|
||||
@attr({
|
||||
readOnly: true,
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
host_ids;
|
||||
|
||||
@attr('string-array', {
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
preferred_endpoints;
|
||||
|
||||
// AWS specific
|
||||
@attr('string-array', {
|
||||
isNestedAttribute: true,
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
filters;
|
||||
|
||||
// Azure specific, comes in from API as "filter". This is to avoid collisions with filter
|
||||
// Azure specific
|
||||
@attr('string', {
|
||||
description: '',
|
||||
isNestedAttribute: true,
|
||||
})
|
||||
filter_string;
|
||||
filter;
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
@@ -49,13 +44,4 @@ 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. Comes in from API as "filter".',
|
||||
})
|
||||
filter_string;
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
@@ -35,27 +30,10 @@ export default class GeneratedTargetModel extends BaseModel {
|
||||
|
||||
@attr('number', {
|
||||
description: '',
|
||||
defaultValue: 1,
|
||||
})
|
||||
session_connection_limit;
|
||||
|
||||
@attr('string', {
|
||||
description:
|
||||
'Optional boolean expression to filter the workers that are allowed to satisfy this request.',
|
||||
})
|
||||
worker_filter;
|
||||
|
||||
@attr('string', {
|
||||
description:
|
||||
'Optional boolean expressions to filter the egress workers that are allowed to satisfy this request.',
|
||||
})
|
||||
egress_worker_filter;
|
||||
|
||||
@attr('string', {
|
||||
description:
|
||||
'Optional boolean expressions to filter the ingress workers that are allowed to satisfy this request.',
|
||||
})
|
||||
ingress_worker_filter;
|
||||
|
||||
@attr('date', {
|
||||
description: 'The time this resource was created\nOutput only.',
|
||||
readOnly: true,
|
||||
@@ -77,23 +55,4 @@ export default class GeneratedTargetModel extends BaseModel {
|
||||
description: 'Current version number of this resource.',
|
||||
})
|
||||
version;
|
||||
|
||||
@attr('string', {
|
||||
description:
|
||||
'An IP address or DNS name for the session to connect to. Cannot be used in conjunction with host sources.',
|
||||
})
|
||||
address;
|
||||
|
||||
@attr('number', {
|
||||
isNestedAttribute: true,
|
||||
description: 'The default port a target should use if present.',
|
||||
})
|
||||
default_port;
|
||||
|
||||
@attr('number', {
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
"The default port that will be listened on by the client's local proxy.",
|
||||
})
|
||||
default_client_port;
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// app/initializers/fragment-serializer.js
|
||||
import FragmentAuthMethodAttributesAccountClaimMapSerializer from '../serializers/fragment-auth-method-attributes-account-claim-map';
|
||||
|
||||
export function initialize(application) {
|
||||
application.register(
|
||||
'serializer:fragment-auth-method-attributes-account-claim-map',
|
||||
FragmentAuthMethodAttributesAccountClaimMapSerializer
|
||||
);
|
||||
}
|
||||
|
||||
// Fragment serializers must be manually registered
|
||||
export default {
|
||||
name: 'fragment-auth-method-attributes-account-claim-map',
|
||||
initialize: initialize,
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
// app/initializers/fragment-serializer.js
|
||||
import FragmentStringSerializer from '../serializers/fragment-string';
|
||||
|
||||
export function initialize(application) {
|
||||
application.register('serializer:fragment-string', FragmentStringSerializer);
|
||||
}
|
||||
|
||||
// Fragment serializers must be manually registered
|
||||
export default {
|
||||
name: 'fragment-string',
|
||||
initialize: initialize,
|
||||
};
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Mixin from '@ember/object/mixin';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,53 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedAccountModel from '../generated/models/account';
|
||||
import {
|
||||
TYPE_AUTH_METHOD_PASSWORD,
|
||||
TYPE_AUTH_METHOD_OIDC,
|
||||
TYPE_AUTH_METHOD_LDAP,
|
||||
TYPES_AUTH_METHOD,
|
||||
} from './auth-method';
|
||||
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
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* Attributes of this resource, if any, represented as a JSON fragment.
|
||||
* @type {FragmentAccountAttributesModel}
|
||||
*/
|
||||
get isPassword() {
|
||||
return this.type === TYPE_AUTH_METHOD_PASSWORD;
|
||||
}
|
||||
@fragment('fragment-account-attributes', { defaultValue: {} }) attributes;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isOIDC() {
|
||||
return this.type === TYPE_AUTH_METHOD_OIDC;
|
||||
}
|
||||
@equal('type', 'password') isPassword;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isLDAP() {
|
||||
return this.type === TYPE_AUTH_METHOD_LDAP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isUnknown() {
|
||||
return !TYPES_AUTH_METHOD.includes(this.type);
|
||||
}
|
||||
@equal('type', 'oidc') isOIDC;
|
||||
|
||||
/**
|
||||
* Convenience for getting username in account.
|
||||
* @type {string}
|
||||
*/
|
||||
@computed('attributes.{email,full_name,login_name}')
|
||||
get accountName() {
|
||||
const { email, full_name, login_name } = this;
|
||||
const { email, full_name, login_name } = this.attributes;
|
||||
return email || full_name || login_name;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedAuthMethodModel from '../generated/models/auth-method';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { fragment } from 'ember-data-model-fragments/attributes';
|
||||
import { equal } from '@ember/object/computed';
|
||||
|
||||
export const TYPE_AUTH_METHOD_PASSWORD = 'password';
|
||||
export const TYPE_AUTH_METHOD_OIDC = 'oidc';
|
||||
export const TYPE_AUTH_METHOD_LDAP = 'ldap';
|
||||
|
||||
export const TYPES_AUTH_METHOD = Object.freeze([
|
||||
TYPE_AUTH_METHOD_PASSWORD,
|
||||
TYPE_AUTH_METHOD_OIDC,
|
||||
TYPE_AUTH_METHOD_LDAP,
|
||||
]);
|
||||
|
||||
/**
|
||||
* Enum options per auth method type and field.
|
||||
*/
|
||||
@@ -41,8 +28,34 @@ export const options = {
|
||||
};
|
||||
|
||||
export default class AuthMethodModel extends GeneratedAuthMethodModel {
|
||||
// =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_state;
|
||||
@attr('string', { readOnly: true }) attributes_issuer;
|
||||
@attr('string', { readOnly: true }) attributes_client_id;
|
||||
@attr('string', { readOnly: true }) attributes_client_secret;
|
||||
@attr('string', { readOnly: true }) attributes_max_age;
|
||||
@attr('string', { readOnly: true }) attributes_api_url_prefix;
|
||||
@attr('string', { readOnly: true })
|
||||
attributes_disable_discovered_config_validation;
|
||||
@attr('string', { readOnly: true }) attributes_dry_run;
|
||||
@attr('string', { readOnly: true }) attributes_account_claim_maps;
|
||||
@attr('string', { readOnly: true }) attributes_claims_scopes;
|
||||
@attr('string', { readOnly: true }) attributes_signing_algorithms;
|
||||
@attr('string', { readOnly: true }) attributes_allowed_audiences;
|
||||
@attr('string', { readOnly: true }) attributes_idp_ca_certs;
|
||||
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
* Attributes of this resource, if any, represented as a JSON fragment.
|
||||
* @type {FragmentAuthMethodAttributesModel}
|
||||
*/
|
||||
@fragment('fragment-auth-method-attributes', { defaultValue: {} }) attributes;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@@ -54,49 +67,35 @@ export default class AuthMethodModel extends GeneratedAuthMethodModel {
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isPassword() {
|
||||
return this.type === TYPE_AUTH_METHOD_PASSWORD;
|
||||
return this.type === 'password';
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isOIDC() {
|
||||
return this.type === TYPE_AUTH_METHOD_OIDC;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isLDAP() {
|
||||
return this.type === TYPE_AUTH_METHOD_LDAP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isUnknown() {
|
||||
return !TYPES_AUTH_METHOD.includes(this.type);
|
||||
return this.type === 'oidc';
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isInactive() {
|
||||
return this.state === 'inactive';
|
||||
return this.attributes.state === 'inactive';
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isPrivate() {
|
||||
return this.state === 'active-private';
|
||||
return this.attributes.state === 'active-private';
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isPublic() {
|
||||
return this.state === 'active-public';
|
||||
return this.attributes.state === 'active-public';
|
||||
}
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedAuthTokenModel from '../generated/models/auth-token';
|
||||
|
||||
export default class AuthTokenModel extends GeneratedAuthTokenModel {}
|
||||
@@ -1,12 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
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';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
/**
|
||||
* Base model class provides common functionality for all models.
|
||||
@@ -31,16 +26,13 @@ import { inject as service } from '@ember/service';
|
||||
* 2) Or as an ID: `record.scopeID`.
|
||||
*/
|
||||
export default class BaseModel extends Model {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
|
||||
// =relationships
|
||||
|
||||
/**
|
||||
* Scope of this resource, if any, represented as a JSON fragment.
|
||||
* @type {FragmentScope}
|
||||
*/
|
||||
@attr() scope;
|
||||
@fragment('fragment-scope') scope;
|
||||
|
||||
// =attributes
|
||||
|
||||
@@ -59,18 +51,10 @@ export default class BaseModel extends Model {
|
||||
const id = this.scopeID;
|
||||
return this.store.peekRecord('scope', id);
|
||||
}
|
||||
|
||||
// Ember seems to have a bug with its internals and can't correctly set
|
||||
// the `scopeModel` when passed in as part of the `inputProperties`
|
||||
// of a `createRecord` call
|
||||
set scopeModel(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;
|
||||
}
|
||||
}
|
||||
@@ -101,6 +85,7 @@ export default class BaseModel extends Model {
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@computed('hasDirtyAttributes', 'isSaving')
|
||||
get canSave() {
|
||||
return this.hasDirtyAttributes && !this.isSaving;
|
||||
}
|
||||
@@ -108,6 +93,7 @@ export default class BaseModel extends Model {
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
@computed('canSave')
|
||||
get cannotSave() {
|
||||
return !this.canSave;
|
||||
}
|
||||
|
||||
@@ -1,65 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
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.
|
||||
*/
|
||||
export const options = {
|
||||
http_method: ['GET', 'POST'],
|
||||
key_type: ['ed25519', 'ecdsa', 'rsa'],
|
||||
};
|
||||
|
||||
export const TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC = 'vault-generic';
|
||||
export const TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE =
|
||||
'vault-ssh-certificate';
|
||||
|
||||
/**
|
||||
* Supported Credential Library types.
|
||||
*/
|
||||
export const TYPES_CREDENTIAL_LIBRARY = Object.freeze([
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
|
||||
]);
|
||||
|
||||
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
|
||||
|
||||
/**
|
||||
* True if credential is an unknown type.
|
||||
* @type {boolean}
|
||||
* Attributes of this resource, if any, represented as a JSON fragment.
|
||||
* @type {FragmentCredentialLibraryAttributesModel}
|
||||
*/
|
||||
get isUnknown() {
|
||||
return !TYPES_CREDENTIAL_LIBRARY.includes(this.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* True if credential is a vault type.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isVault() {
|
||||
return (
|
||||
this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC ||
|
||||
this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* True if credential is a generic vault type.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isVaultGeneric() {
|
||||
return this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if credential is a vault ssh cert type.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isVaultSSHCertificate() {
|
||||
return this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE;
|
||||
}
|
||||
@fragment('fragment-credential-library-attributes', { defaultValue: {} })
|
||||
attributes;
|
||||
}
|
||||
@@ -1,23 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
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 const types = ['static', 'vault'];
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedCredentialModel from '../generated/models/credential';
|
||||
|
||||
/**
|
||||
* Supported Credential types.
|
||||
*/
|
||||
export const types = ['username_password', 'ssh_private_key', 'json'];
|
||||
|
||||
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 type is `json`.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isJSON() {
|
||||
return this.type === 'json';
|
||||
}
|
||||
|
||||
/**
|
||||
* True if credential is an unknown type.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isUnknown() {
|
||||
return !types.includes(this.type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
export default class FragmentAuthMethodAttributesAccountClaimMapModel extends Fragment {
|
||||
// =attributes (OIDC)
|
||||
|
||||
@attr('string') from;
|
||||
@attr('string') to;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { fragmentArray } from 'ember-data-model-fragments/attributes';
|
||||
|
||||
export default class FragmentAuthMethodAttributesModel extends Fragment {
|
||||
// =attributes (OIDC)
|
||||
|
||||
@attr('string', { readOnly: true }) state;
|
||||
@attr('string') issuer;
|
||||
@attr('string') client_id;
|
||||
@attr('string') client_secret;
|
||||
@attr('string', { readOnly: true }) client_secret_hmac;
|
||||
@attr('number') max_age;
|
||||
@attr('string') api_url_prefix;
|
||||
@attr('string', { readOnly: true }) callback_url;
|
||||
@attr('boolean') disable_discovered_config_validation;
|
||||
@attr('boolean') dry_run;
|
||||
|
||||
@fragmentArray('fragment-auth-method-attributes-account-claim-map', {
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
account_claim_maps;
|
||||
|
||||
@fragmentArray('fragment-string', {
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
claims_scopes;
|
||||
|
||||
@fragmentArray('fragment-string', {
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
signing_algorithms;
|
||||
|
||||
@fragmentArray('fragment-string', {
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
allowed_audiences;
|
||||
|
||||
@fragmentArray('fragment-string', { emptyArrayIfMissing: true }) idp_ca_certs;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
/**
|
||||
* Represents an item in an array of strings.
|
||||
*/
|
||||
export default class FragmentStringModel extends Fragment {
|
||||
// =attributes
|
||||
|
||||
@attr('string', {
|
||||
description: 'The value of the string.',
|
||||
})
|
||||
value;
|
||||
}
|
||||
@@ -1,19 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedGroupModel from '../generated/models/group';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { computed } from '@ember/object';
|
||||
import { A } from '@ember/array';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class GroupModel extends GeneratedGroupModel {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedHostCatalogModel from '../generated/models/host-catalog';
|
||||
|
||||
export const types = ['static', 'plugin'];
|
||||
export const pluginTypes = ['aws', 'azure'];
|
||||
export const types = ['aws', 'azure'];
|
||||
|
||||
export default class HostCatalogModel extends GeneratedHostCatalogModel {
|
||||
// =attributes
|
||||
@@ -32,7 +26,7 @@ export default class HostCatalogModel extends GeneratedHostCatalogModel {
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isUnknown() {
|
||||
return this.isPlugin && !pluginTypes.includes(this.plugin?.name);
|
||||
return this.isPlugin && !types.includes(this.plugin?.name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedHostSetModel from '../generated/models/host-set';
|
||||
import { pluginTypes } from './host-catalog';
|
||||
import { fragmentArray } from 'ember-data-model-fragments/attributes';
|
||||
import { types } from './host-catalog';
|
||||
|
||||
export default class HostSetModel extends GeneratedHostSetModel {
|
||||
// =attributes
|
||||
@@ -30,7 +26,7 @@ export default class HostSetModel extends GeneratedHostSetModel {
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isUnknown() {
|
||||
return this.isPlugin && !pluginTypes.includes(this.plugin?.name);
|
||||
return this.isPlugin && !types.includes(this.plugin?.name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,6 +67,28 @@ export default class HostSetModel extends GeneratedHostSetModel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Host IDs are read-only under normal circumstances. But these can
|
||||
* be persisted via a dedicated call to `addHosts()`.
|
||||
*/
|
||||
@fragmentArray('fragment-string', {
|
||||
readOnly: true,
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
host_ids;
|
||||
|
||||
@fragmentArray('fragment-string', {
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
preferred_endpoints;
|
||||
|
||||
// AWS specific
|
||||
@fragmentArray('fragment-string', {
|
||||
emptyArrayIfMissing: true,
|
||||
isNestedAttribute: true,
|
||||
})
|
||||
filters;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedHostModel from '../generated/models/host';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
@@ -29,12 +24,6 @@ export default class HostModel extends GeneratedHostModel {
|
||||
})
|
||||
external_id;
|
||||
|
||||
@attr('string', {
|
||||
description: 'The external facing name for the plugin based host.',
|
||||
readOnly: true,
|
||||
})
|
||||
external_name;
|
||||
|
||||
// Aws specific
|
||||
@attr({
|
||||
readOnly: true,
|
||||
@@ -95,9 +84,4 @@ export default class HostModel extends GeneratedHostModel {
|
||||
this.plugin = { name: type };
|
||||
}
|
||||
}
|
||||
|
||||
// Plugin hosts can support an external name
|
||||
get displayName() {
|
||||
return this.name || this.external_name || this.id;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Members is read-only under normal circumstances. But members can
|
||||
* be persisted via calls to `addMembers()` or `removeMembers()`.
|
||||
@@ -20,4 +23,7 @@ export default class ManagedGroupModel extends GeneratedManagedGroupModel {
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
member_ids;
|
||||
|
||||
@fragment('fragment-managed-group-attributes', { defaultValue: {} })
|
||||
attributes;
|
||||
}
|
||||
@@ -1,20 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedRoleModel from '../generated/models/role';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { all, resolve } from 'rsvp';
|
||||
import { TYPE_AUTH_METHOD_OIDC } from 'api/models/auth-method';
|
||||
import { fragmentArray, array } from 'ember-data-model-fragments/attributes';
|
||||
|
||||
export default class RoleModel extends GeneratedRoleModel {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service resourceFilterStore;
|
||||
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
@@ -24,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.
|
||||
*/
|
||||
@attr('principal-array', {
|
||||
@fragmentArray('fragment-principal', {
|
||||
readOnly: true,
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
@@ -34,133 +21,8 @@ export default class RoleModel extends GeneratedRoleModel {
|
||||
* Grant strings are read-only. But grants can be persisted via a dedicated
|
||||
* call to `saveGrantStrings(grants)`.
|
||||
*/
|
||||
@attr({ readOnly: true, emptyArrayIfMissing: true }) grant_strings;
|
||||
@array('string', { readOnly: 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of IDs for principals of type `user`.
|
||||
* @type {string[]}
|
||||
*/
|
||||
get userIDs() {
|
||||
return this.principals
|
||||
.filter(({ type }) => type === 'user')
|
||||
.map(({ principal_id }) => principal_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of IDs for principals of type `group`.
|
||||
* @type {string[]}
|
||||
*/
|
||||
get groupIDs() {
|
||||
return this.principals
|
||||
.filter(({ type }) => type === 'group')
|
||||
.map(({ principal_id }) => principal_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of IDs for principals of type `managed group`.
|
||||
* @type {string[]}
|
||||
*/
|
||||
get managedGroupIDs() {
|
||||
return this.principals
|
||||
.filter(({ type }) => type === 'managed group')
|
||||
.map(({ principal_id }) => principal_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* A promise that resolves to an array of User instances.
|
||||
* When calling this getter, be sure to await resolution
|
||||
* before interacting with the results.
|
||||
* @type {Promise[UserModel]}
|
||||
*/
|
||||
get users() {
|
||||
const ids = this.userIDs;
|
||||
|
||||
// Role has prinicipal IDs,
|
||||
// return a promise which resolves model instances for those IDs
|
||||
if (ids?.length) {
|
||||
return this.resourceFilterStore
|
||||
.queryBy('user', { id: ids }, { scope_id: 'global', recursive: true })
|
||||
.then((models) => models.map((model) => model));
|
||||
}
|
||||
|
||||
// No principal IDs,
|
||||
// return a promise resolving to an empty array
|
||||
return resolve([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A promise that resolves to an array of Group instances.
|
||||
* When calling this getter, be sure to await resolution
|
||||
* before interacting with the results.
|
||||
* @type {Promise[GroupModel]}
|
||||
*/
|
||||
get groups() {
|
||||
const ids = this.groupIDs;
|
||||
|
||||
// Role has prinicipal IDs,
|
||||
// return a promise which resolves model instances for those IDs
|
||||
if (ids?.length) {
|
||||
return this.resourceFilterStore
|
||||
.queryBy('group', { id: ids }, { scope_id: 'global', recursive: true })
|
||||
.then((models) => models.map((model) => model));
|
||||
}
|
||||
|
||||
// No principal IDs,
|
||||
// return a promise resolving to an empty array
|
||||
return resolve([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A promise that resolves to an array of ManagedGroup instances.
|
||||
* When calling this getter, be sure to await resolution
|
||||
* before interacting with the results.
|
||||
* @type {Promise[ManagedGroupModel]}
|
||||
*/
|
||||
get managedGroups() {
|
||||
const ids = this.managedGroupIDs;
|
||||
|
||||
// Role has prinicipal IDs
|
||||
// return a promise which resolves model instances for those IDs
|
||||
if (ids?.length) {
|
||||
// Collect all auth methods.
|
||||
const authMethods = this.resourceFilterStore.queryBy(
|
||||
'auth-method',
|
||||
{ type: TYPE_AUTH_METHOD_OIDC },
|
||||
{ scope_id: 'global', recursive: true }
|
||||
);
|
||||
|
||||
// For each auth method, query all managed groups with IDs
|
||||
// that match the role's manage group principal IDs.
|
||||
const managedGroups = authMethods
|
||||
.then((methods) =>
|
||||
all(
|
||||
methods.map(({ id: auth_method_id }) =>
|
||||
this.resourceFilterStore
|
||||
.queryBy('managed-group', { id: ids }, { auth_method_id })
|
||||
.then((models) => models.map((model) => model))
|
||||
)
|
||||
)
|
||||
)
|
||||
// The result is an array of arrays of model instances (grouped by
|
||||
// auth methods), so these must be flattened.
|
||||
.then((grouped) => grouped.flat());
|
||||
|
||||
return managedGroups;
|
||||
}
|
||||
|
||||
// No principal IDs,
|
||||
// return a promise resolving to an empty array
|
||||
return resolve([]);
|
||||
}
|
||||
// =methods
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedScopeModel from '../generated/models/scope';
|
||||
import { computed } from '@ember/object';
|
||||
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedSessionModel from '../generated/models/session';
|
||||
import { computed } from '@ember/object';
|
||||
import { equal } from '@ember/object/computed';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { A } from '@ember/array';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export const statusTypes = ['active', 'pending', 'canceling', 'terminated'];
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -21,7 +13,7 @@ class SessionCredential {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static Source = class Source {
|
||||
static Library = class Library {
|
||||
id;
|
||||
name;
|
||||
description;
|
||||
@@ -50,7 +42,7 @@ class SessionCredential {
|
||||
|
||||
// =attributes
|
||||
rawCredential;
|
||||
source;
|
||||
library;
|
||||
#payloadSecret;
|
||||
|
||||
/**
|
||||
@@ -80,18 +72,14 @@ class SessionCredential {
|
||||
// =methods
|
||||
|
||||
constructor(cred) {
|
||||
const { id, name, description, type } = cred.credential_source;
|
||||
this.source = new SessionCredential.Source(id, name, description, type);
|
||||
const { id, name, description, type } = cred.credential_library;
|
||||
this.library = new SessionCredential.Library(id, name, description, type);
|
||||
this.#payloadSecret = cred.secret;
|
||||
this.rawCredential = cred;
|
||||
}
|
||||
}
|
||||
|
||||
export default class SessionModel extends GeneratedSessionModel {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
|
||||
// =attributes
|
||||
|
||||
// These transient attributes are used for values that come from the CLI
|
||||
@@ -106,14 +94,6 @@ export default class SessionModel extends GeneratedSessionModel {
|
||||
@equal('status', 'active') isActive;
|
||||
@equal('status', 'pending') isPending;
|
||||
|
||||
/**
|
||||
* True if status is an unknown string.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isUnknownStatus() {
|
||||
return !statusTypes.includes(this.status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
|
||||
@@ -1,51 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedTargetModel from '../generated/models/target';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export const TYPE_TARGET_TCP = 'tcp';
|
||||
export const TYPE_TARGET_SSH = 'ssh';
|
||||
export const TYPES_TARGET = Object.freeze([TYPE_TARGET_TCP, TYPE_TARGET_SSH]);
|
||||
import { fragmentArray } from 'ember-data-model-fragments/attributes';
|
||||
import { computed } from '@ember/object';
|
||||
|
||||
export default class TargetModel extends GeneratedTargetModel {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
|
||||
// =attributes
|
||||
|
||||
@attr('number', {
|
||||
isNestedAttribute: true,
|
||||
description: 'The default port a target should use if present.',
|
||||
})
|
||||
default_port;
|
||||
|
||||
/**
|
||||
* @type Array
|
||||
* @type {[FragmentHostSourceModel]}
|
||||
*/
|
||||
@attr('host-source-id-array', {
|
||||
@fragmentArray('fragment-host-source', {
|
||||
readOnly: true,
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
host_sources;
|
||||
|
||||
/**
|
||||
* Brokered Credential source ids are read only and can be
|
||||
* persisted via a dedicated call to `addBrokeredCredentialSources()`.
|
||||
* Credential source ids are read only and can be
|
||||
* persisted via a dedicated call to `addCredentialSources()`.
|
||||
*/
|
||||
@attr('string-array', {
|
||||
@fragmentArray('fragment-string', {
|
||||
readOnly: true,
|
||||
emptyArrayIfMissing: true,
|
||||
})
|
||||
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;
|
||||
application_credential_source_ids;
|
||||
|
||||
/**
|
||||
* An array of resolved host set and host catalog instances. Model instances
|
||||
@@ -53,6 +37,7 @@ 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 }) => ({
|
||||
@@ -63,38 +48,17 @@ export default class TargetModel extends GeneratedTargetModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of resolved credential library and credential instances. Model instances
|
||||
* An array of resolved credential library 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]}
|
||||
* @type {[CredentialLibraryModel]}
|
||||
*/
|
||||
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);
|
||||
}
|
||||
})
|
||||
@computed('application_credential_source_ids.[]', 'store')
|
||||
get credentialLibraries() {
|
||||
return this.application_credential_source_ids
|
||||
.map((source) =>
|
||||
this.store.peekRecord('credential-library', source.value)
|
||||
)
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
@@ -186,20 +150,17 @@ export default class TargetModel extends GeneratedTargetModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds credential sources via the `add-credential-sources` method.
|
||||
* Adds credential libraries via the `add-credential-sources` method.
|
||||
* See serializer and adapter for more information.
|
||||
* @param {[string]} brokeredCredentialSourceIDs
|
||||
* @param {[string]} credentialLibraryIDs
|
||||
* @param {object} options
|
||||
* @param {object} options.adapterOptions
|
||||
* @return {Promise}
|
||||
*/
|
||||
addBrokeredCredentialSources(
|
||||
brokeredCredentialSourceIDs,
|
||||
options = { adapterOptions: {} }
|
||||
) {
|
||||
addCredentialSources(credentialLibraryIDs, options = { adapterOptions: {} }) {
|
||||
const defaultAdapterOptions = {
|
||||
method: 'add-credential-sources',
|
||||
brokeredCredentialSourceIDs,
|
||||
credentialLibraryIDs,
|
||||
};
|
||||
// There is no "deep merge" in ES.
|
||||
return this.save({
|
||||
@@ -212,46 +173,20 @@ export default class TargetModel extends GeneratedTargetModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds credential sources via the `add-credential-sources` method.
|
||||
* Delete credential libraries via the `remove-credential-sources` method.
|
||||
* See serializer and adapter for more information.
|
||||
* @param {[string]} injectedApplicationCredentialSourceIDs
|
||||
* @param {[string]} credentialLibraryIDs
|
||||
* @param {object} options
|
||||
* @param {object} options.adapterOptions
|
||||
* @return {Promise}
|
||||
*/
|
||||
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,
|
||||
removeCredentialSources(
|
||||
credentialLibraryIDs,
|
||||
options = { adapterOptions: {} }
|
||||
) {
|
||||
const defaultAdapterOptions = {
|
||||
method: 'remove-credential-sources',
|
||||
brokeredCredentialSourceIDs,
|
||||
credentialLibraryIDs,
|
||||
};
|
||||
// There is no "deep merge" in ES.
|
||||
return this.save({
|
||||
@@ -264,65 +199,21 @@ export default class TargetModel extends GeneratedTargetModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a single credential library/credential set via the `remove-credential-sources` method.
|
||||
* @param {number} brokeredCredentialSourceID
|
||||
* Delete a single credential library set via the `remove-credential-sources` method.
|
||||
* @param {number} credentialLibraryID
|
||||
* @param {object} options
|
||||
* @return {Promise}
|
||||
*/
|
||||
removeBrokeredCredentialSource(brokeredCredentialSourceID, options) {
|
||||
return this.removeBrokeredCredentialSources(
|
||||
[brokeredCredentialSourceID],
|
||||
options
|
||||
);
|
||||
removeCredentialSource(credentialLibraryID, options) {
|
||||
return this.removeCredentialSources([credentialLibraryID], 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}
|
||||
*/
|
||||
get isTCP() {
|
||||
return this.type === TYPE_TARGET_TCP;
|
||||
return this.type === 'tcp';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -330,6 +221,6 @@ export default class TargetModel extends GeneratedTargetModel {
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isSSH() {
|
||||
return this.type === TYPE_TARGET_SSH;
|
||||
return this.type === 'ssh';
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedUserModel from '../generated/models/user';
|
||||
import { attr } from '@ember-data/model';
|
||||
import { computed } from '@ember/object';
|
||||
@@ -45,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')
|
||||
@computed('email,full_name,login_name,displayName')
|
||||
get accountName() {
|
||||
const { email, full_name, login_name } = this;
|
||||
return email || full_name || login_name;
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
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,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ApplicationSerializer from './application';
|
||||
|
||||
export default class AccountSerializer extends ApplicationSerializer {
|
||||
@@ -38,12 +33,12 @@ export default class AccountSerializer extends ApplicationSerializer {
|
||||
* `attributes` entirely on update.
|
||||
*/
|
||||
serializeOIDC(snapshot) {
|
||||
const { isNew } = snapshot?.record || {};
|
||||
const { isNew } = snapshot?.record;
|
||||
let serialized = super.serialize(...arguments);
|
||||
delete serialized.attributes;
|
||||
if (isNew) {
|
||||
serialized.attributes = {};
|
||||
const { issuer, subject } = snapshot.record;
|
||||
const { issuer, subject } = snapshot.attr('attributes').record;
|
||||
if (issuer) serialized.attributes.issuer = issuer;
|
||||
if (subject) serialized.attributes.subject = subject;
|
||||
}
|
||||
@@ -75,7 +70,7 @@ export default class AccountSerializer extends ApplicationSerializer {
|
||||
}
|
||||
// Change password custom method
|
||||
if (snapshot?.adapterOptions?.method === 'change-password') {
|
||||
const { currentPassword, newPassword } = snapshot?.adapterOptions || {};
|
||||
const { currentPassword, newPassword } = snapshot?.adapterOptions;
|
||||
serialized = this.serializeForChangePassword(
|
||||
snapshot,
|
||||
currentPassword,
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import RESTSerializer from '@ember-data/serializer/rest';
|
||||
import { underscore } from '@ember/string';
|
||||
import { get } from '@ember/object';
|
||||
import { copy } from 'ember-copy';
|
||||
|
||||
/**
|
||||
* Manages serialization/normalization of data to/from the API.
|
||||
@@ -43,10 +39,6 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
serializeAttribute(snapshot, json, key, attribute) {
|
||||
const { type, options } = attribute;
|
||||
let value = super.serializeAttribute(...arguments);
|
||||
// Remove secret attributes that are null or empty
|
||||
if (options.isSecret) {
|
||||
if (type === 'string' && !json[key]) delete json[key];
|
||||
}
|
||||
// Convert empty strings to null.
|
||||
if (type === 'string' && json[key] === '') json[key] = null;
|
||||
// Do not serialize read-only attributes.
|
||||
@@ -104,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')?.scope_id;
|
||||
const scope_id = snapshot?.attr('scope')?.attr('scope_id');
|
||||
if (scope_id) serialized.scope_id = scope_id;
|
||||
}
|
||||
return serialized;
|
||||
@@ -133,7 +125,7 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
);
|
||||
// Copy the data rooted under `items` in the existing payload into the new
|
||||
// payload under the expected root key name.
|
||||
transformedPayload[payloadKey] = structuredClone(payload.items);
|
||||
transformedPayload[payloadKey] = copy(payload.items, true);
|
||||
// Return the result of normalizing the transformed payload.
|
||||
return super.normalizeArrayResponse(
|
||||
store,
|
||||
@@ -145,7 +137,7 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
}
|
||||
|
||||
/**
|
||||
* In our API, singular resources are _unrooted_, whereas Ember Data expects
|
||||
* In our API, singluar 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.
|
||||
*
|
||||
@@ -160,7 +152,7 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
*/
|
||||
normalizeSingleResponse(store, primaryModelClass, payload, id, requestType) {
|
||||
// Copy payload (mostly to prevent mocking issues)
|
||||
payload = structuredClone(payload);
|
||||
payload = copy(payload, true);
|
||||
// Check for and normalize missing arrays
|
||||
payload = this.normalizeMissingArrays(store, primaryModelClass, payload);
|
||||
// Setup a new payload data structure.
|
||||
@@ -207,24 +199,19 @@ export default class ApplicationSerializer extends RESTSerializer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrates the incoming scope JSON with additional boolean fields and
|
||||
* delegates nested attributes and secrets normalization.
|
||||
* 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.
|
||||
* @override
|
||||
* @see FragmentScope
|
||||
* @param {Model} typeClass
|
||||
* @param {Object} hash
|
||||
* @return {Object}
|
||||
*/
|
||||
normalize(typeClass, hash) {
|
||||
let normalizedHash = structuredClone(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);
|
||||
@@ -281,48 +268,4 @@ 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 = structuredClone(payload);
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,5 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ApplicationSerializer from './application';
|
||||
import { TYPE_AUTH_METHOD_OIDC } from 'api/models/auth-method';
|
||||
import { copy } from 'ember-copy';
|
||||
|
||||
export default class AuthMethodSerializer extends ApplicationSerializer {
|
||||
// =methods
|
||||
@@ -17,7 +12,7 @@ export default class AuthMethodSerializer extends ApplicationSerializer {
|
||||
*/
|
||||
serialize(snapshot) {
|
||||
switch (snapshot.record.type) {
|
||||
case TYPE_AUTH_METHOD_OIDC:
|
||||
case 'oidc':
|
||||
return this.serializeOIDC(...arguments);
|
||||
default:
|
||||
return this.serializeDefault(...arguments);
|
||||
@@ -86,12 +81,13 @@ 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}
|
||||
*/
|
||||
normalize(typeClass, hash, ...rest) {
|
||||
let normalizedHash = structuredClone(hash);
|
||||
let normalizedHash = copy(hash, true);
|
||||
// switch (normalizedHash.type) {
|
||||
// case 'oidc':
|
||||
// normalizedHash = this.normalizeOIDC(normalizedHash);
|
||||
|
||||
@@ -1,63 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ApplicationSerializer from './application';
|
||||
import {
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
|
||||
} from '../models/credential-library';
|
||||
|
||||
export default class CredentialLibrarySerializer extends ApplicationSerializer {
|
||||
// =properties
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
serializeScopeID = false;
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @method serialize
|
||||
* @param {Snapshot} snapshot
|
||||
*/
|
||||
serialize(snapshot) {
|
||||
switch (snapshot.record.type) {
|
||||
case TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC:
|
||||
return this.serializeVaultGeneric(...arguments);
|
||||
case TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE:
|
||||
default:
|
||||
return super.serialize(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
serializeAttribute(snapshot, json, key, attribute) {
|
||||
super.serializeAttribute(...arguments);
|
||||
const { options } = attribute;
|
||||
const { type } = snapshot.record;
|
||||
|
||||
// If an attribute has a `for` option, it must match the
|
||||
// record's `type`, else the attribute is excluded
|
||||
// from serialization.
|
||||
if (options?.for && options.for !== type) {
|
||||
if (options.isNestedAttribute) {
|
||||
delete json.attributes[key];
|
||||
} else {
|
||||
delete json[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serializeVaultGeneric() {
|
||||
const serialized = super.serialize(...arguments);
|
||||
if (serialized.attributes) {
|
||||
// Set `http_request_body` only if `http_method` is POST
|
||||
// otherwise set to null to have the field removed
|
||||
if (!serialized.attributes?.http_method?.match(/post/i)) {
|
||||
serialized.attributes.http_request_body = null;
|
||||
}
|
||||
}
|
||||
return serialized;
|
||||
}
|
||||
}
|
||||
export default class CredentialLibrarySerializer extends ApplicationSerializer {}
|
||||
@@ -1,51 +1,3 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ApplicationSerializer from './application';
|
||||
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) {
|
||||
// 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 = structuredClone(hash);
|
||||
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;
|
||||
}
|
||||
}
|
||||
export default class CredentialStoreSerializer extends ApplicationSerializer {}
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import ApplicationSerializer from './application';
|
||||
export default class CredentialSerializer extends ApplicationSerializer {
|
||||
/**
|
||||
* @override
|
||||
* @method serialize
|
||||
* @param {Snapshot} snapshot
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
serializeScopeID = false;
|
||||
|
||||
serialize() {
|
||||
const serialized = super.serialize(...arguments);
|
||||
|
||||
if (serialized.type === 'json') {
|
||||
delete serialized.attributes.username;
|
||||
|
||||
if (serialized?.attributes?.json_object) {
|
||||
serialized.attributes.object = JSON.parse(
|
||||
serialized.attributes.json_object
|
||||
);
|
||||
delete serialized.attributes.json_object;
|
||||
}
|
||||
} else {
|
||||
delete serialized.attributes.json_object;
|
||||
}
|
||||
|
||||
return serialized;
|
||||
}
|
||||
|
||||
normalize(typeClass, hash, ...rest) {
|
||||
const normalizedHash = structuredClone(hash);
|
||||
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 = '';
|
||||
normalized.data.attributes.json_object = '';
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import JSONSerializer from '@ember-data/serializer/json';
|
||||
|
||||
export default class FragmentHostSourceSerializer extends JSONSerializer {
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Serializes an account claim to string.
|
||||
* @param {Snapshot} snapshot
|
||||
* @return {string}
|
||||
*/
|
||||
serialize(snapshot) {
|
||||
const from = snapshot.attr('from');
|
||||
const to = snapshot.attr('to');
|
||||
return `${from}=${to}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes account claim strings into JSON API objects.
|
||||
* @param {Model} typeClass
|
||||
* @param {string} value
|
||||
* @return {object}
|
||||
*/
|
||||
normalize(typeClass, value) {
|
||||
const normalizedHash = {
|
||||
from: value.split('=')[0],
|
||||
to: value.split('=')[1],
|
||||
};
|
||||
return super.normalize(typeClass, normalizedHash);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import JSONSerializer from '@ember-data/serializer/json';
|
||||
|
||||
export default class FragmentAuthMethodAttributesSerializer 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;
|
||||
}
|
||||
}
|
||||
Loaded 100 of 1925 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user