Compare commits

..
2 Commits
2151 changed files with 27909 additions and 64390 deletions

No files matched your search

-19
View File
@@ -1,19 +0,0 @@
schema_version = 1
project {
license = "MPL-2.0"
copyright_year = 2020
# (OPTIONAL) A list of globs that should not have copyright/license headers.
# Supports doublestar glob patterns for more flexibility in defining which
# files or folders should be ignored
header_ignore = [
".github/**",
".husky/**",
"**/node_modules/**",
"**/dist/**",
"**/coverage/**",
"ui/desktop/electron-app/out/**",
"ui/desktop/electron-app/ember-dist/**",
]
}
-2
View File
@@ -1,2 +0,0 @@
# Anyone attached to this rule will always been assigned to a pull request
* @hashicorp/boundary-ui
-3
View File
@@ -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
-3
View File
@@ -1,6 +1,3 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0
addons:
- addons/**/*
-29
View File
@@ -1,29 +0,0 @@
:tickets: [Jira ticket](https://hashicorp.atlassian.net/browse/JIRA_TICKET_NUMBER)
## Description
<!-- Add a brief description of changes here -->
## Screenshots (if appropriate):
## How to Test
<!-- Add steps to test this change. Include any other necessary relevant links -->
<!--
Replace PATH_TO_FEATURE with Vercel link
-->
:technologist: [Admin preview](PATH_TO_FEATURE)
:desktop_computer: [Desktop preview](PATH_TO_FEATURE)
## Checklist:
<!-- strikethrough the checklist item that is not relevant to your change -->
- [ ] I have added before and after screenshots for UI changes
- [ ] I have added JSON response output for API changes
- [ ] I have added steps to reproduce and test for bug fixes in the description
- [ ] I have commented on my code, particularly in hard-to-understand areas
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
-94
View File
@@ -1,94 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0
set -euo pipefail
# Configure Git
git config --global user.email "hc-github-team-secure-boundary@hashicorp.com"
git config --global user.name "github-team-secure-boundary"
# Fetch branches from ENT
git fetch origin
BRANCH=${1}
echo "BRANCH to merge is $BRANCH"
git checkout "${BRANCH}"
# Checkout OSS repo
git remote add oss-remote https://github.com/hashicorp/boundary-ui.git
git fetch oss-remote
# Merge oss/${BRANCH} into ent/${BRANCH}
git_merge_branch="${2}"
git checkout -b "${git_merge_branch}"
latest_oss_commit="$(git rev-parse --short oss-remote/${BRANCH})"
echo "Trying to merge the latest oss commit - ${latest_oss_commit} from oss/${BRANCH} into ent/${BRANCH}"
if ! errors=$(git merge -m "Merge Boundary UI OSS branch '${BRANCH}' at commit ${latest_oss_commit}" "${latest_oss_commit}"); then
# Here we can try to auto resolve conflicts
# This logic will vary from project to project. The below is just an example.
# We'll try to resolve package.json and yarn.lock conflicts by taking the OSS changes
conflicts=$(git diff --name-only --diff-filter=U)
printf "Found conflicts:\n${conflicts}\n"
# Resolve package.json conflicts by taking oss
if echo "$conflicts" | grep -q package.json; then
echo "Checking out oss package.json..."
git checkout --theirs package.json
git add package.json
fi
# Resolve yarn.lock conflicts by taking oss
if echo "$conflicts" | grep -q yarn.lock; then
echo "Checking out oss yarn.lock..."
git checkout --theirs yarn.lock
git add yarn.lock
fi
# If we can commit all the changes without conflict, we have resolved everything automatically
if ! git commit --no-edit; then
echo "Auto Merge failed, creating a draft PR"
git merge --abort
git clean -xfd
git fetch oss-remote
git checkout "${OSS_BRANCH}"
git checkout -b "${OSS_LOCAL_BRANCH}"
git push -f --set-upstream origin "${OSS_LOCAL_BRANCH}"
gh pr create \
--draft \
--fill-first \
--label "oss-merge" \
-B "${BASE_BRANCH}" \
-H "${OSS_LOCAL_BRANCH}" \
-a "${ACTOR}" \
-t "[${BASE_BRANCH/oss\/release\//}] OSS to ENT merge of (${SHA::7})" \
-b "${BASE_BRANCH/oss\//} upstream merge of (${SHA::7})
Merge failed, Please fix the conflicts using github UI or using the following commands:
\`\`\`bash
git checkout ${BASE_BRANCH}
git pull
git checkout ${OSS_LOCAL_BRANCH}
git merge ${BASE_BRANCH}
# fix conflicts and commit
git push origin ${OSS_LOCAL_BRANCH}
\`\`\`"
exit 0
fi
fi
# Check that there are actually changes to merge by comparing the
# merge branch to the current checked out branch
if (git diff ${BRANCH} --exit-code > /dev/null); then
echo "there are no changes to merge"
exit 0
fi
git push origin "${git_merge_branch}"
gh pr create \
--fill-first \
--label "oss-merge" \
-B "${BASE_BRANCH}" \
-H "${MERGE_BRANCH}" \
-a ${ACTOR} \
-t "[${BASE_BRANCH/oss\/release\//}] OSS to ENT merge of (${SHA::7})" \
-b "${BASE_BRANCH/oss\//} upstream merge of (${SHA::7})"
gh pr merge --auto --merge
# This PR will be need to be approved manually
-97
View File
@@ -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@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
id: node-modules-cache
with:
path: '**/node_modules'
key: node-modules-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
node-modules-
- uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
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@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
id: node-modules-cache
with:
path: '**/node_modules'
key: node-modules-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
node-modules-
- name: Build
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
with:
node-version: 16
- run: yarn run build:ui:admin:oss
- name: Upload artifact admin-ui
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: admin-ui
path: ./ui/admin/dist/
- name: Upload artifact OSS admin UI
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
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@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
id: node-modules-cache
with:
path: '**/node_modules'
key: node-modules-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
node-modules-
- name: Build
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
with:
node-version: 16
- run: yarn run build:ui:admin:enterprise
- name: Upload artifact enterprise admin UI
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
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@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
id: node-modules-cache
with:
path: '**/node_modules'
key: node-modules-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
node-modules-
- name: Build
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
with:
node-version: 16
- run: yarn run build:ui:admin:hcp
- name: Upload artifact HCP admin UI
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: admin-ui-hcp
path: ./ui/admin/dist/
+19 -5
View File
@@ -7,7 +7,7 @@ name: "CodeQL"
on:
push:
branches: [main]
branches: [main, release-v0.1.0]
pull_request:
# The branches below must be a subset of the branches above
branches: [main]
@@ -27,14 +27,23 @@ jobs:
language: ['javascript']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
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.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@8e0b1c74b1d5a0077b04d064c76ee714d3da7637 # codeql-bundle-v2.14.6
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.
@@ -42,6 +51,11 @@ jobs:
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# 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@v1
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -54,4 +68,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@8e0b1c74b1d5a0077b04d064c76ee714d3da7637 # codeql-bundle-v2.14.6
uses: github/codeql-action/analyze@v1
+10 -10
View File
@@ -19,18 +19,18 @@ jobs:
id: boundary-team-role
run: |
TEAM=boundary
ROLE="$(gh api orgs/hashicorp/teams/${TEAM}/memberships/${{ github.actor }} | jq -r '.role | select(.!=null)')"
ROLE="$(hub api orgs/hashicorp/teams/${TEAM}/memberships/${{ github.actor }} | jq -r '.role | select(.!=null)')"
if [[ -n ${ROLE} ]]; then
echo "Actor ${{ github.actor }} is a ${TEAM} team member, skipping ticket creation"
else
echo "Actor ${{ github.actor }} is not a ${TEAM} team member"
fi
echo "role=${ROLE}" >> $GITHUB_OUTPUT
echo "::set-output name=role::${ROLE}"
env:
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 }}
@@ -41,14 +41,14 @@ jobs:
id: set-ticket-type
run: |
if [[ "${{ github.event_name }}" == "pull_request_target" ]]; then
echo "type=PR" >> $GITHUB_OUTPUT
echo "::set-output name=type::PR"
else
echo "type=ISS" >> $GITHUB_OUTPUT
echo "::set-output name=type::ISS"
fi
- 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@164913891625fe50e9836957902e0bf7d9ef99a8 # v3.0.1
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"
+1 -1
View File
@@ -6,6 +6,6 @@ jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0
- uses: actions/labeler@main
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
+21 -18
View File
@@ -6,17 +6,17 @@ jobs:
name: Install dependencies
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
- 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@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
- 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@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
- 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@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
- 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@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
- 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@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
- 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@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
- 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@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
- 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"
-24
View File
@@ -1,24 +0,0 @@
name: OSS → ENT Merge
on:
repository_dispatch:
types: [ oss-merge ]
jobs:
oss-merge:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
with:
token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
- run: |
git fetch --prune --unshallow
./.github/scripts/merge.sh "${BASE_BRANCH}" "${MERGE_BRANCH}"
env:
BASE_BRANCH: ${{ github.event.client_payload.git-ref }}
OSS_BRANCH: oss-remote/${{ github.event.client_payload.git-ref }}
OSS_LOCAL_BRANCH: oss/${{ github.event.client_payload.git-ref }}-${{ github.event.client_payload.git-sha }}
MERGE_BRANCH: oss/merge-${{ github.event.client_payload.git-ref }}-${{github.event.client_payload.git-sha}}
GITHUB_TOKEN: ${{secrets.ELEVATED_GITHUB_TOKEN }}
MERGE_APPROVE_TOKEN: ${{secrets.ELEVATED_GITHUB_TOKEN }}
ACTOR: ${{ github.event.client_payload.git-actor }}
SHA: ${{github.event.client_payload.git-sha}}
+7 -9
View File
@@ -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
+7 -10
View File
@@ -6,17 +6,14 @@ on:
- '*'
jobs:
trigger-gha-release:
trigger-circleci-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- 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
+2
View File
@@ -20,4 +20,6 @@ libpeerconnection.log
npm-debug.log*
testem.log
yarn-error.log
storybook-static
**/.storybook/*.html
.watchman-cookie*
-5
View File
@@ -1,5 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
yarn compliance:licenses
npx lint-staged
-16
View File
@@ -1,16 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
SHA1=$3
# Gets the current branch name but if we're in a detached head state, return "HEAD"
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
# Don't run commitizen for merge or squash commits, as well as when rebasing
if [ "${COMMIT_SOURCE}" = merge ] || [ "${COMMIT_SOURCE}" = squash ] || [ "${COMMIT_SOURCE}" = "message" -a "${BRANCH_NAME}" = "HEAD" ];then
exit 0
fi
# This is to allow interaction with the terminal for commitizen
exec < /dev/tty && npx git-cz --hook || true
-6
View File
@@ -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"
-2
View File
@@ -1,5 +1,3 @@
Copyright (c) 2020 HashiCorp, Inc.
Mozilla Public License, version 2.0
1. Definitions
+32 -78
View File
@@ -13,78 +13,44 @@ subproject, e.g. running or testing.
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Boundary UI Monorepo](#boundary-ui-monorepo)
- [Projects](#projects)
- [Core (addons/core):](#core-addonscore)
- [API (addons/api):](#api-addonsapi)
- [Auth (addons/auth):](#auth-addonsauth)
- [Rose (addons/rose)](#rose-addonsrose)
- [Admin (ui/admin)](#admin-uiadmin)
- [Desktop Client (ui/desktop)](#desktop-client-uidesktop)
- [Prerequisites](#prerequisites)
- [Optional Tooling](#optional-tooling)
- [Installation](#installation)
- [Yarn Commands](#yarn-commands)
- [Contributing](#contributing)
- [Branching](#branching)
- [Building ToC](#building-toc)
- [Building Admin UI for Production](#building-admin-ui-for-production)
- [Building with a Container](#building-with-a-container)
- [Building Desktop UI for Production](#building-desktop-ui-for-production)
- [Connect Boundary UI to Boundary local instance](#connect-boundary-ui-to-boundary-local-instance)
- [For admin](#for-admin)
- [For desktop](#for-desktop)
- [Committing](#committing)
- [License Checking](#license-checking)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Yarn Commands](#yarn-commands)
- [Contributing](#contributing)
- [Branching](#branching)
- [Building ToC](#building-toc)
- [Building Admin UI for Production](#building-admin-ui-for-production)
- [Building with a Container](#building-with-a-container)
- [Building Desktop UI for Production](#building-desktop-ui-for-production)
- [Connect Boundary UI to Boundary local instance](#connect-boundary-ui-to-boundary-local-instance)
- [For admin](#for-admin)
- [For desktop](#for-desktop)
- [Committing](#committing)
- [License Checking](#license-checking)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Projects
This monorepo contains multiple projects.
### Core (addons/core):
Core features use by Boundary UI's, i.e i18n, helpers or components. [Project Readme](addons/core).
### API (addons/api):
The API data access layer for Boundary and all the related mocks. [Project Readme](addons/api).
### Auth (addons/auth):
Authentication layer for Boundary. [Project Readme](addons/auth).
### Rose (addons/rose)
Common styles and components shared by Boundary UIs. [Project Readme](addons/rose).
### Admin (ui/admin)
The Admin UI for Boundary. [Project Readme](ui/admin).
### Desktop Client (ui/desktop)
The desktop client UI for Boundary. [Project Readme](ui/desktop).
## Prerequisites
You will need the following things properly installed on your computer.
* [Git][git]
* [Node.js][node]
* Supported versions: `v16` and `v18`.
* v10–v15
* **Apple Silicon Users**: if you experience problems building or running
Boundary UIs, try Node v15.
* [Yarn][yarn] installed globally
* [Google Chrome][chrome]
* [Firefox][firefox]
## Optional Tooling
Our team finds the following applications useful in day-to-day development
workflows. These are merely recommendations. We encourage you to use the tools
that best suit you and your personal style.
* [VS Code][vscode]: Code editor for building and debugging web applications
* [Warp][warp]: Terminal application for macOS
* [Homebrew][homebrew]: The missing package manager for macOS and Linux
* [Ember Inspector][ember-inspector]: Understand and debug Ember applications
* [Postman][postman]: Test and inspect APIs
[git]: https://git-scm.com/
[node]: https://nodejs.org/
[yarn]: https://classic.yarnpkg.com/lang/en/
[chrome]: https://google.com/chrome/
[firefox]: https://firefox.com/
[yarn-workspaces]: https://classic.yarnpkg.com/en/docs/workspaces/
## Installation
@@ -100,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,7 +126,7 @@ In windows, UI is generated using docker to provide a stable UI across platforms
```cmd
yarn install
docker-compose -f docker-compose-embedding.yml run build-desktop-production
docker-compose -f docker-compose-embedding.yml run build-desktop-production
yarn build:ui:desktop:app
```
@@ -193,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
@@ -214,15 +180,3 @@ The change will be verified upon PR. GPL variants and UNLICENSED dependencies
will not be accepted.
[github-flow]: https://guides.github.com/introduction/flow/
[git]: https://git-scm.com/
[node]: https://nodejs.org/
[yarn]: https://classic.yarnpkg.com/lang/en/
[chrome]: https://google.com/chrome/
[firefox]: https://firefox.com/
[yarn-workspaces]: https://classic.yarnpkg.com/en/docs/workspaces/
[homebrew]: https://brew.sh
[warp]: https://www.warp.dev
[vscode]: https://code.visualstudio.com/
[ember-inspector]: https://guides.emberjs.com/release/ember-inspector/
[postman]: https://www.postman.com/downloads/
-3
View File
@@ -14,6 +14,3 @@ indent_size = 2
[*.{diff,md}]
trim_trailing_whitespace = false
[*.hbs]
insert_final_newline = false
+1 -7
View File
@@ -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
}
-8
View File
@@ -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
+26 -26
View File
@@ -1,27 +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: 'latest',
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', { decoratorsBeforeExport: 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,
},
@@ -36,16 +30,21 @@ module.exports = {
// node files
{
files: [
'./.eslintrc.js',
'./.prettierrc.js',
'./.stylelintrc.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',
@@ -54,7 +53,8 @@ module.exports = {
browser: false,
node: true,
},
extends: ['plugin:n/recommended'],
plugins: ['node'],
extends: ['plugin:node/recommended'],
},
{
// Test files:
-12
View File
@@ -14,10 +14,7 @@
/.eslintignore
/.eslintrc.js
/.git/
/.github/
/.gitignore
/.prettierignore
/.prettierrc.js
/.template-lintrc.js
/.travis.yml
/.watchmanconfig
@@ -26,14 +23,5 @@
/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
-9
View File
@@ -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
+4
View File
@@ -0,0 +1,4 @@
{
"singleQuote": true,
"printWidth": 80
}
+2 -12
View File
@@ -1,15 +1,5 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
'use strict';
module.exports = {
overrides: [
{
files: '*.{js,ts}',
options: {
singleQuote: true,
},
},
],
singleQuote: true,
};
+1 -6
View File
@@ -1,10 +1,5 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
'use strict';
module.exports = {
extends: ['recommended', 'stylistic'],
extends: 'octane',
};
+2 -9
View File
@@ -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
-29
View File
@@ -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}
*/
-34
View File
@@ -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,26 +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 channel recordings.
*/
export default class ChannelRecordingAbility extends ModelAbility {
// =services
@service abilities;
// =permissions
get canGetAsciicast() {
const sessionRecording = this.model.connection_recording.session_recording;
const sessionRecordingAbility = this.abilities.abilityFor(
'session-recording',
sessionRecording
);
return this.model.isAsciicast && sessionRecordingAbility.canDownload;
}
}
@@ -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');
}
}
-20
View File
@@ -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');
}
}
-5
View File
@@ -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 -13
View File
@@ -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
}
-5
View File
@@ -1,8 +1,3 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import { Ability } from 'ember-can';
/**
-32
View File
@@ -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,27 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import ModelAbility from './model';
/**
* Provides abilities for session recordings.
*/
export default class SessionRecordingAbility extends ModelAbility {
// =services
// =permissions
/**
* Only "known" session recording types may be read.
* @type {boolean}
*/
get canRead() {
return !this.model.isUnknown && super.canRead;
}
get canDownload() {
return this.hasAuthorizedAction('download');
}
}
-23
View File
@@ -1,23 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import ModelAbility from './model';
/**
* Provides abilities for sessions.
*/
export default class SessionAbility extends ModelAbility {
// =services
// =permissions
/**
* Only "active" or "pending" sessions may be read.
* @type {boolean}
*/
get canRead() {
return (this.model.isActive || this.model.isPending) && super.canRead;
}
}
@@ -1,39 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import ModelAbility from './model';
/**
* Provides abilities for storage buckets.
*/
export default class StorageBucketAbility extends ModelAbility {
// =services
// =permissions
/**
* Only "known" storage bucket types may be read.
* @type {boolean}
*/
get canRead() {
return !this.model.isUnknown && super.canRead;
}
/**
* Only "known" storage bucket types may be updated.
* @type {boolean}
*/
get canUpdate() {
return !this.model.isUnknown && super.canUpdate;
}
/**
* Only "known" storage bucket types may be deleted.
* @type {boolean}
*/
get canDelete() {
return !this.model.isUnknown && super.canDelete;
}
}
+1 -14
View File
@@ -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}
*/
-21
View File
@@ -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;
}
}
-20
View File
@@ -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');
}
}
+30 -16
View File
@@ -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],
+2 -11
View File
@@ -1,8 +1,3 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import ApplicationAdapter from './application';
export default class HostCatalogAdapter extends ApplicationAdapter {
@@ -20,12 +15,8 @@ export default class HostCatalogAdapter extends ApplicationAdapter {
buildURL(modelName, id, snapshot, requestType) {
let url = super.buildURL(...arguments);
if (requestType === 'createRecord') {
try {
const pluginName = snapshot.attr('plugin')?.name;
if (pluginName) url = `${url}?plugin_name=${pluginName}`;
} catch (e) {
// Ignore any adapter errors here
}
const pluginName = snapshot.attr('plugin')?.name;
if (pluginName) url = `${url}?plugin_name=${pluginName}`;
}
return url;
}
@@ -1,74 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import ApplicationAdapter from './application';
import { MIME_TYPE_ASCIICAST } from 'api/models/channel-recording';
export default class SessionRecordingAdapter extends ApplicationAdapter {
/**
* Overrides the default `buildURL` such that for custom download methods,
* URLs will get the query parameters. All other request types behave as normal.
*
* @param modelName {string}
* @param id {string}
* @param snapshot {object}
* @param requestType {string}
* @param query {object}
* @returns {string}
*/
buildURL(modelName, id, snapshot, requestType, query) {
let url = super.buildURL(...arguments);
let method;
try {
method = snapshot?.adapterOptions?.method;
} catch (e) {
// Ignore any adapter errors here
}
if (method === 'download') {
const queryParams = new URLSearchParams(query).toString();
if (queryParams) url = `${url}?${queryParams}`;
}
return url;
}
/**
* Handles the download recording for recordings. Takes in a mime type for the
* type or recording to return.
* The ID can be the session ID, session recording ID,
* connection recording ID, or the channel recording ID.
* @param id {string}
* @param mimeType {string}
* @returns {Promise<string>}
*/
async getRecordingDownload({ id, mimeType }) {
const options = { adapterOptions: { method: 'download' } };
const url = this.buildURL('session-recording', id, options, 'findRecord', {
mime_type: mimeType,
});
const response = await fetch(url, { headers: this.headers });
if (response?.ok) {
return response.text();
} else {
throw this.handleResponse(
response.status,
response.headers,
await response.text()
);
}
}
/**
* Returns an ascii cast recording.
* @param id
* @returns {Promise<string>}
*/
getAsciicast(id) {
return this.getRecordingDownload({
id,
mimeType: MIME_TYPE_ASCIICAST,
});
}
}
@@ -1,33 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import ApplicationAdapter from './application';
export default class StorageBucketAdapter extends ApplicationAdapter {
/**
* Overrides the default `buildURL` such that on _create_, URLs for records of
* type `plugin` get an extra query parameter `?plugin_name`. All other
* request types behave as normal.
*
* @override
* @param {string} modelName
* @param {string} id
* @return {string} url
* @return {string} requestType
*/
buildURL(modelName, id, snapshot, requestType) {
let url = super.buildURL(...arguments);
let pluginName;
try {
pluginName = snapshot?.attr('plugin')?.name;
} catch (e) {
// Ignore any adapter errors here
}
if (requestType === 'createRecord' && pluginName) {
url = `${url}?plugin_name=${pluginName}`;
}
return url;
}
}
@@ -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,39 +43,4 @@ export default class GeneratedAccountModel extends BaseModel {
description: 'Current version number of this resource.',
})
version;
// =attributes (password and LDAP)
@attr('string', {
for: ['password', 'ldap'],
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;
// =attributes (OIDC and LDAP)
@attr('string', {
for: ['oidc', 'ldap'],
isNestedAttribute: true,
readOnly: true,
})
email;
@attr('string', {
for: ['oidc', 'ldap'],
isNestedAttribute: true,
readOnly: true,
})
full_name;
// =attributes (LDAP)
@attr('string', { for: 'ldap', isNestedAttribute: true, readOnly: true }) dn;
@attr('string-array', {
for: 'ldap',
isNestedAttribute: true,
readOnly: true,
})
member_of_groups;
}
@@ -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,260 +49,4 @@ export default class GeneratedAuthMethodModel extends BaseModel {
description: 'Current version number of this resource.',
})
version;
// =attributes(oidc, ldap)
@attr('string', {
for: ['oidc', 'ldap'],
readOnly: true,
isNestedAttribute: true,
})
state;
// =attributes(oidc)
@attr('string', {
for: 'oidc',
isNestedAttribute: true,
})
issuer;
@attr('string', {
for: 'oidc',
isNestedAttribute: true,
})
client_id;
@attr('string', {
for: 'oidc',
isNestedAttribute: true,
isSecret: true,
})
client_secret;
@attr('string', {
for: 'oidc',
readOnly: true,
isNestedAttribute: true,
})
client_secret_hmac;
@attr('number', {
for: 'oidc',
isNestedAttribute: true,
})
max_age;
@attr('string', {
for: 'oidc',
isNestedAttribute: true,
})
api_url_prefix;
@attr('string', {
for: 'oidc',
readOnly: true,
isNestedAttribute: true,
})
callback_url;
@attr('boolean', {
for: 'oidc',
isNestedAttribute: true,
})
disable_discovered_config_validation;
@attr('boolean', {
for: 'oidc',
isNestedAttribute: true,
})
dry_run;
@attr('string-array', {
for: 'oidc',
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
claims_scopes;
@attr('string-array', {
for: 'oidc',
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
signing_algorithms;
@attr('string-array', {
for: 'oidc',
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
allowed_audiences;
@attr('string-array', {
for: 'oidc',
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
idp_ca_certs;
@attr('account-value-map-array', {
for: 'oidc',
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
account_claim_maps;
// =attributes(ldap)
@attr('boolean', {
for: 'ldap',
isNestedAttribute: true,
})
start_tls;
@attr('boolean', {
for: 'ldap',
isNestedAttribute: true,
})
insecure_tls;
@attr('boolean', {
for: 'ldap',
isNestedAttribute: true,
})
discover_dn;
@attr('boolean', {
for: 'ldap',
isNestedAttribute: true,
})
anon_group_search;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
})
upn_domain;
@attr('string-array', {
for: 'ldap',
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
urls;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
})
user_dn;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
})
user_attr;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
})
user_filter;
@attr('boolean', {
for: 'ldap',
isNestedAttribute: true,
})
enable_groups;
@attr('boolean', {
for: 'ldap',
isNestedAttribute: true,
})
use_token_groups;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
})
group_dn;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
})
group_attr;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
})
group_filter;
@attr('string-array', {
for: 'ldap',
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
certificates;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
})
client_certificate;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
isSecret: true,
})
client_certificate_key;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
readOnly: true,
})
client_certificate_key_hmac;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
})
bind_dn;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
isSecret: true,
})
bind_password;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
readOnly: true,
})
bind_password_hmac;
@attr('account-value-map-array', {
for: 'ldap',
emptyArrayIfMissing: true,
isNestedAttribute: true,
})
account_attribute_maps;
@attr('number', {
for: 'ldap',
isNestedAttribute: true,
})
maximum_page_size;
@attr('string', {
for: 'ldap',
isNestedAttribute: true,
})
dereference_aliases;
}
@@ -1,8 +1,3 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import BaseModel from '../../models/base';
/**
@@ -1,59 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import BaseModel from '../../models/base';
import { attr } from '@ember-data/model';
/**
* A channel contains data for a single channel within a connection.
*/
export default class GeneratedChannelRecordingModel extends BaseModel {
// =attributes
@attr('string', {
description:
'The total number of bytes uploaded from the client in this Channel.',
readOnly: true,
})
bytes_up;
@attr('string', {
description:
'The total number of bytes downloaded to the client in this Channel.',
readOnly: true,
})
bytes_down;
@attr('number', {
description:
'The total number of errors that occurred during the use of this Channel.',
readOnly: true,
})
errors;
@attr('date', {
description: 'The time the Channel started.',
readOnly: true,
})
start_time;
@attr('date', {
description: 'The time the Channel finished.',
readOnly: true,
})
end_time;
@attr({
description: 'The array of mime types that this recording will support.',
readOnly: true,
})
mime_types;
@attr('duration', {
description: 'The duration of this channel recording in ms.',
readOnly: true,
})
duration;
}
@@ -1,66 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import BaseModel from '../../models/base';
import { attr } from '@ember-data/model';
/**
* A connection contains data for a boundary connection within a session.
*/
export default class GeneratedConnectionRecordingModel extends BaseModel {
// =attributes
@attr('string', {
description:
'The ID of the Connection which this Connection Recording recorded.',
readOnly: true,
})
connection_id;
@attr('string', {
description:
'The total number of bytes uploaded from the client in this Connection.',
readOnly: true,
})
bytes_up;
@attr('string', {
description:
'The total number of bytes downloaded to the client in this Connection.',
readOnly: true,
})
bytes_down;
@attr('number', {
description:
'The total number of errors that occurred during the use of this Connection.',
readOnly: true,
})
errors;
@attr('date', {
description: 'The time the Connection started.',
readOnly: true,
})
start_time;
@attr('date', {
description: 'The time the Connection finished.',
readOnly: true,
})
end_time;
@attr({
description: 'The array of mime types that this recording will support.',
readOnly: true,
})
mime_types;
@attr('duration', {
description: 'The duration of this connection recording in ms.',
readOnly: true,
})
duration;
}
@@ -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';
+2 -29
View File
@@ -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,23 +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', {
for: 'oidc',
isNestedAttribute: true,
description:
'The boolean expression filter to use to determine membership. Comes in from API as "filter".',
})
filter_string;
// =attributes (LDAP)
@attr('string-array', {
for: 'ldap',
isNestedAttribute: true,
description: 'The list of groups that make up the ManagedGroup',
})
group_names;
}
@@ -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,112 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import BaseModel from '../../models/base';
import { attr } from '@ember-data/model';
/**
* A session recording contains all data related to session recordings
*/
export default class GeneratedSessionRecordingModel extends BaseModel {
// =attributes
@attr('string', {
description: 'The type of the resource, to help differentiate schemas.',
readOnly: true,
})
type;
@attr('date', {
description:
'The time the Session Recording was created in the controller.',
readOnly: true,
})
created_time;
@attr('date', {
description: 'The time of the most recent update to the Session Recording.',
readOnly: true,
})
updated_time;
@attr({
description:
'Contains the values of related fields at the time this Session Recording was created',
readOnly: true,
})
create_time_values;
@attr('string', {
description: 'The ID of the Session which this Session Recording recorded.',
readOnly: true,
})
session_id;
@attr('string', {
description:
'The ID of the Storage Bucket for the Target of this Session Recording',
readOnly: true,
})
storage_bucket_id;
@attr('string', {
description:
'The total number of bytes uploaded from the client in the Session.',
readOnly: true,
})
bytes_up;
@attr('string', {
description:
'The total number of bytes downloaded to the client in the Session.',
readOnly: true,
})
bytes_down;
@attr('number', {
description:
'The total number of errors that occurred during the use of the Session.',
readOnly: true,
})
errors;
@attr('date', {
description: 'The time the Session started.',
readOnly: true,
})
start_time;
@attr('date', {
description: 'The time the Session finished.',
readOnly: true,
})
end_time;
@attr({
description: 'The array of mime types that this recording will support.',
readOnly: true,
})
mime_types;
@attr('duration', {
description: 'The duration of this session recording in ms.',
readOnly: true,
})
duration;
@attr('string', {
description:
'The current state of the session recording. One of "started", "available" and "unknown".',
readOnly: true,
})
state;
@attr('string', {
description:
'Any error seen during the closing of the session recording. Currently only set if state is "unknown".',
readOnly: true,
})
error_details;
}
@@ -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,126 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import BaseModel from '../../models/base';
import { attr } from '@ember-data/model';
/**
* A storage bucket is a resource that that represents a bucket in an external object store.
*/
export default class GeneratedStorageBucketModel extends BaseModel {
// =attributes
@attr('string', {
description: 'The type of the resource, to help differentiate schemas',
})
type;
@attr({
description: 'Plugin information for this resource.',
readOnly: true,
})
plugin;
@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 name of the bucket in the external object store.',
})
bucket_name;
@attr('string', {
description:
'The base path where session recordings will be stored in the external object store.',
})
bucket_prefix;
@attr('string', {
description:
'An expression used to filter the workers that have network access to a service that is hosting the external object store.',
})
worker_filter;
@attr('string', {
isNestedAttribute: true,
description: 'The AWS region to use.',
})
region;
//this field is not used in the UI, but this is kept here to replicate the API
@attr('string', {
readOnly: true,
isNestedAttribute: true,
})
secrets_hmac;
@attr('boolean', {
isNestedAttribute: true,
description: 'If set to `true`, credential rotation is not performed.',
})
disable_credential_rotation;
// =attributes (static credentials)
@attr('string', {
isNestedSecret: true,
description: 'The AWS access key ID to use.',
})
access_key_id;
@attr('string', {
isNestedSecret: true,
description: 'The secret access key to use.',
})
secret_access_key;
// =attributes (dynamic credentials)
@attr('string', {
isNestedAttribute: true,
description: 'The role ARN to use.',
})
role_arn;
@attr('string', {
isNestedAttribute: true,
description: 'The role external ID to use.',
})
role_external_id;
@attr('string', {
isNestedAttribute: true,
description: 'The role session to use.',
})
role_session_name;
@attr('object-as-array', {
isNestedAttribute: true,
description: 'The role tags to use.',
})
role_tags;
}
+1 -54
View File
@@ -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,35 +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;
@attr('string', {
description: 'The storage bucket associated with this target.',
isNestedAttribute: true,
})
storage_bucket_id;
@attr('boolean', {
description: 'Whether session recording is enabled on the target.',
isNestedAttribute: true,
})
enable_session_recording;
}
@@ -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;
}
@@ -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';
/**
+10 -29
View File
@@ -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;
}
+37 -51
View File
@@ -1,26 +1,12 @@
/**
* 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.
*/
export const options = {
state: ['inactive', 'active-private', 'active-public'],
oidc: {
signing_algorithms: [
'RS256',
@@ -34,26 +20,42 @@ export const options = {
'PS512',
'EdDSA',
],
state: ['inactive', 'active-private', 'active-public'],
account_claim_maps: {
to: ['sub', 'name', 'email'],
},
},
ldap: {
account_attribute_maps: {
to: ['fullName', 'email'],
},
dereference_aliases: {
NeverDerefAliases: 'never',
DerefInSearching: 'searching',
DerefFindingBaseObj: 'finding',
DerefAlways: 'always',
},
},
};
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}
*/
@@ -65,57 +67,43 @@ 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
/**
* Change the active and visibility state of an OIDC and LDAP auth method
* Change the active and visibility state of an OIDC auth method
* given its ID.
* For OIDC and LDAP auth methods only.
* For OIDC auth methods only.
* @param {[string]} state
* @param {object} options
* @param {object} options.adapterOptions
@@ -123,11 +111,9 @@ export default class AuthMethodModel extends GeneratedAuthMethodModel {
*/
changeState(state, options = { adapterOptions: {} }) {
const defaultAdapterOptions = {
method: 'change-state',
state,
};
if (this.isOIDC) {
defaultAdapterOptions.method = 'change-state';
}
return this.save({
...options,
adapterOptions: {
-5
View File
@@ -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 {}
+6 -20
View File
@@ -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
@@ -57,20 +49,12 @@ export default class BaseModel extends Model {
get scopeModel() {
const id = this.scopeID;
return id ? this.store.peekRecord('scope', id) : null;
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,34 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import GeneratedChannelRecordingModel from '../generated/models/channel-recording';
import { belongsTo } from '@ember-data/model';
export const MIME_TYPE_ASCIICAST = 'application/x-asciicast';
export default class ChannelRecordingModel extends GeneratedChannelRecordingModel {
@belongsTo('connection-recording', {
async: false,
inverse: 'channel_recordings',
})
connection_recording;
/**
* True if the channel supports asciicast.
* @type {boolean}
*/
get isAsciicast() {
return this.mime_types?.includes(MIME_TYPE_ASCIICAST) ?? false;
}
/**
* Download the ascii cast recording for this channel.
* @returns {Promise<string>}
*/
getAsciicast() {
const adapter = this.store.adapterFor('session-recording');
return adapter.getAsciicast(this.id);
}
}
@@ -1,20 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import GeneratedConnectionRecordingModel from '../generated/models/connection-recording';
import { belongsTo, hasMany } from '@ember-data/model';
export default class ConnectionRecordingModel extends GeneratedConnectionRecordingModel {
@belongsTo('session-recording', {
async: false,
inverse: 'connection_recordings',
})
session_recording;
@hasMany('channel-recording', {
async: false,
inverse: 'connection_recording',
})
channel_recordings;
}
+15 -50
View File
@@ -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;
}
+23 -12
View File
@@ -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;
}
-41
View File
@@ -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;
}
+42
View File
@@ -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;
}
-10
View File
@@ -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
/**
+2 -8
View File
@@ -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);
}
/**
+25 -7
View File
@@ -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
/**
-25
View File
@@ -1,11 +1,5 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/
import GeneratedHostModel from '../generated/models/host';
import { attr } from '@ember-data/model';
import { pluginTypes } from './host-catalog';
export default class HostModel extends GeneratedHostModel {
// =attributes
@@ -30,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,
@@ -59,14 +47,6 @@ export default class HostModel extends GeneratedHostModel {
return this.type === 'plugin';
}
/**
* True if the host catalog is an unknown type.
* @type {boolean}
*/
get isUnknown() {
return this.isPlugin && !pluginTypes.includes(this.plugin?.name);
}
/**
* True if the host plugin type is AWS.
* @type {boolean}
@@ -104,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;
}
}
Loaded 100 of 2151 files, more files were not shown because too many files have changed in this diff. Show more