You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by is...@apache.org on 2020/10/05 13:57:41 UTC
[airavata-custos-portal] branch custos-tenant-portal updated
(add7925 -> 337802a)
This is an automated email from the ASF dual-hosted git repository.
isjarana pushed a change to branch custos-tenant-portal
in repository https://gitbox.apache.org/repos/asf/airavata-custos-portal.git.
from add7925 Merge pull request #15 from isururanawaka/custos-tenant-portal
new 853bb8f tag local version
new 50ce1ad tag local version
new 337802a Merge pull request #19 from isururanawaka/custos-tenant-portal
The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
custos-demo-gateway/docker-compose.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
[airavata-custos-portal] 09/09: Merge pull request #19 from
isururanawaka/custos-tenant-portal
Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
isjarana pushed a commit to branch custos-tenant-portal
in repository https://gitbox.apache.org/repos/asf/airavata-custos-portal.git
commit 337802ac56f17c5e47b8d8ffc77edc25c4627327
Merge: add7925 50ce1ad
Author: Isuru Ranawaka <ir...@gmail.com>
AuthorDate: Mon Oct 5 09:57:36 2020 -0400
Merge pull request #19 from isururanawaka/custos-tenant-portal
Custos tenant portal
custos-demo-gateway/docker-compose.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
[airavata-custos-portal] 05/09: Initial code of custos-tenant-portal
Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
isjarana pushed a commit to branch custos-tenant-portal
in repository https://gitbox.apache.org/repos/asf/airavata-custos-portal.git
commit c42eda965330e4e595fbbde0aa47adaf9aeb87fc
Author: Isuru Ranawaka <ir...@gmail.com>
AuthorDate: Sun Oct 4 15:22:34 2020 -0400
Initial code of custos-tenant-portal
---
.gitignore | 3 +
custos-demo-gateway/.dockerignore | 13 +
custos-demo-gateway/.env | 3 +
custos-demo-gateway/.idea/custos-demo-gateway.iml | 8 +
.../.idea/inspectionProfiles/Project_Default.xml | 6 +
custos-demo-gateway/.idea/misc.xml | 9 +
custos-demo-gateway/.idea/modules.xml | 8 +
custos-demo-gateway/.idea/vcs.xml | 6 +
custos-demo-gateway/.idea/workspace.xml | 141 +
custos-demo-gateway/Dockerfile | 19 +
custos-demo-gateway/README.md | 24 +
custos-demo-gateway/babel.config.js | 5 +
custos-demo-gateway/docker-compose.yml | 11 +
custos-demo-gateway/entrypoint.sh | 18 +
custos-demo-gateway/fullchain.pem | 59 +
custos-demo-gateway/nginx.conf | 35 +
custos-demo-gateway/package.json | 50 +
custos-demo-gateway/public/favicon.ico | Bin 0 -> 4286 bytes
custos-demo-gateway/public/index.html | 17 +
custos-demo-gateway/src/App.vue | 29 +
custos-demo-gateway/src/assets/bots.png | Bin 0 -> 5228 bytes
custos-demo-gateway/src/assets/credentials.png | Bin 0 -> 3332 bytes
custos-demo-gateway/src/assets/custos_home.png | Bin 0 -> 44021 bytes
custos-demo-gateway/src/assets/dblogs.png | Bin 0 -> 19538 bytes
custos-demo-gateway/src/assets/groups_web.png | Bin 0 -> 2934 bytes
custos-demo-gateway/src/assets/logo.png | Bin 0 -> 6849 bytes
custos-demo-gateway/src/assets/sharings.png | Bin 0 -> 2417 bytes
custos-demo-gateway/src/assets/users.png | Bin 0 -> 4824 bytes
custos-demo-gateway/src/components/Callback.vue | 86 +
.../src/components/TheNavigator.vue | 24 +
.../src/components/landing/Landing.vue | 229 +
.../src/components/registration/CreateAccount.vue | 206 +
.../src/components/workspace/Agents.vue | 295 +
.../src/components/workspace/Groups.vue | 653 ++
.../src/components/workspace/Logs.vue | 223 +
.../src/components/workspace/Secrets.vue | 355 +
.../src/components/workspace/Sharing.vue | 892 ++
.../src/components/workspace/Users.vue | 609 ++
.../src/components/workspace/Workspace.vue | 141 +
custos-demo-gateway/src/config.js | 41 +
custos-demo-gateway/src/main.js | 23 +
custos-demo-gateway/src/router.js | 159 +
.../src/service/agent_management.js | 116 +
custos-demo-gateway/src/service/api.js | 12 +
custos-demo-gateway/src/service/auth.js | 96 +
.../src/service/group_management.js | 157 +
.../src/service/identity_management.js | 55 +
custos-demo-gateway/src/service/log_management.js | 36 +
.../src/service/secret_management.js | 98 +
.../src/service/sharing_management.js | 198 +
custos-demo-gateway/src/service/user_management.js | 161 +
custos-demo-gateway/src/store/index.js | 29 +
.../src/store/modules/agent.store.js | 155 +
.../src/store/modules/group.store.js | 153 +
.../src/store/modules/identity.store.js | 134 +
custos-demo-gateway/src/store/modules/log.store.js | 46 +
.../src/store/modules/secret.store.js | 116 +
.../src/store/modules/sharing.store.js | 227 +
.../src/store/modules/user.store.js | 149 +
custos-demo-gateway/yarn-error.log | 8587 ++++++++++++++++++++
custos-demo-gateway/yarn.lock | 8534 +++++++++++++++++++
61 files changed, 23459 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5707668
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+
+node_modules
+.idea*
diff --git a/custos-demo-gateway/.dockerignore b/custos-demo-gateway/.dockerignore
new file mode 100644
index 0000000..e3b21df
--- /dev/null
+++ b/custos-demo-gateway/.dockerignore
@@ -0,0 +1,13 @@
+# Items that don't need to be in a Docker image.
+# Anything not used by the build system should go here.
+.git
+.dockerignore
+.gitignore
+.github/*
+README.md
+Dockerfile
+
+# Artifacts that will be built during image creation.
+# This should contain all files created during `yarn build`.
+dist
+node_modules
\ No newline at end of file
diff --git a/custos-demo-gateway/.env b/custos-demo-gateway/.env
new file mode 100644
index 0000000..e84f702
--- /dev/null
+++ b/custos-demo-gateway/.env
@@ -0,0 +1,3 @@
+VUE_APP_CLIENT_ID=""
+VUE_APP_CLIENT_SEC=""
+VUE_APP_REDIRECT_URI="http://localhost:8080/callback"
\ No newline at end of file
diff --git a/custos-demo-gateway/.idea/custos-demo-gateway.iml b/custos-demo-gateway/.idea/custos-demo-gateway.iml
new file mode 100644
index 0000000..c956989
--- /dev/null
+++ b/custos-demo-gateway/.idea/custos-demo-gateway.iml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+ <component name="NewModuleRootManager">
+ <content url="file://$MODULE_DIR$" />
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
\ No newline at end of file
diff --git a/custos-demo-gateway/.idea/inspectionProfiles/Project_Default.xml b/custos-demo-gateway/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..03d9549
--- /dev/null
+++ b/custos-demo-gateway/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+ <profile version="1.0">
+ <option name="myName" value="Project Default" />
+ <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
+ </profile>
+</component>
\ No newline at end of file
diff --git a/custos-demo-gateway/.idea/misc.xml b/custos-demo-gateway/.idea/misc.xml
new file mode 100644
index 0000000..5b9db6f
--- /dev/null
+++ b/custos-demo-gateway/.idea/misc.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="JavaScriptSettings">
+ <option name="languageLevel" value="ES6" />
+ </component>
+ <component name="WebPackConfiguration">
+ <option name="path" value="$PROJECT_DIR$/node_modules/@vue/cli-service/webpack.config.js" />
+ </component>
+</project>
\ No newline at end of file
diff --git a/custos-demo-gateway/.idea/modules.xml b/custos-demo-gateway/.idea/modules.xml
new file mode 100644
index 0000000..bdb36b1
--- /dev/null
+++ b/custos-demo-gateway/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/custos-demo-gateway.iml" filepath="$PROJECT_DIR$/.idea/custos-demo-gateway.iml" />
+ </modules>
+ </component>
+</project>
\ No newline at end of file
diff --git a/custos-demo-gateway/.idea/vcs.xml b/custos-demo-gateway/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/custos-demo-gateway/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
+ </component>
+</project>
\ No newline at end of file
diff --git a/custos-demo-gateway/.idea/workspace.xml b/custos-demo-gateway/.idea/workspace.xml
new file mode 100644
index 0000000..1db002d
--- /dev/null
+++ b/custos-demo-gateway/.idea/workspace.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ChangeListManager">
+ <list default="true" id="c2cd5109-1431-412f-85ad-eb6f68d4ed8d" name="Default Changelist" comment="">
+ <change afterPath="$PROJECT_DIR$/src/assets/sharings.png" afterDir="false" />
+ <change afterPath="$PROJECT_DIR$/src/components/landing/Landing.vue" afterDir="false" />
+ <change afterPath="$PROJECT_DIR$/src/components/workspace/Workspace.vue" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/src/App.vue" beforeDir="false" afterPath="$PROJECT_DIR$/src/App.vue" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/src/components/HelloWorld.vue" beforeDir="false" />
+ <change beforePath="$PROJECT_DIR$/src/main.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/main.js" afterDir="false" />
+ <change beforePath="$PROJECT_DIR$/yarn.lock" beforeDir="false" afterPath="$PROJECT_DIR$/yarn.lock" afterDir="false" />
+ </list>
+ <option name="SHOW_DIALOG" value="false" />
+ <option name="HIGHLIGHT_CONFLICTS" value="true" />
+ <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+ <option name="LAST_RESOLUTION" value="IGNORE" />
+ </component>
+ <component name="FileTemplateManagerImpl">
+ <option name="RECENT_TEMPLATES">
+ <list>
+ <option value="CSS File" />
+ <option value="Vue Single File Component" />
+ <option value="JavaScript File" />
+ </list>
+ </option>
+ </component>
+ <component name="Git.Settings">
+ <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
+ </component>
+ <component name="ProjectId" id="1hBYpJOvyxvD4Py2dSNM3iRhs0V" />
+ <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
+ <component name="ProjectViewState">
+ <option name="hideEmptyMiddlePackages" value="true" />
+ <option name="showExcludedFiles" value="true" />
+ <option name="showLibraryContents" value="true" />
+ </component>
+ <component name="PropertiesComponent">
+ <property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
+ <property name="WebServerToolWindowFactoryState" value="false" />
+ <property name="last_opened_file_path" value="$PROJECT_DIR$/src/assets" />
+ <property name="list.type.of.created.stylesheet" value="CSS" />
+ <property name="node.js.detected.package.eslint" value="true" />
+ <property name="node.js.detected.package.standard" value="true" />
+ <property name="node.js.path.for.package.eslint" value="project" />
+ <property name="node.js.path.for.package.standard" value="project" />
+ <property name="node.js.selected.package.eslint" value="(autodetect)" />
+ <property name="node.js.selected.package.standard" value="" />
+ <property name="nodejs_interpreter_path" value="node" />
+ <property name="nodejs_package_manager_path" value="yarn" />
+ <property name="ts.external.directory.path" value="$APPLICATION_HOME_DIR$/plugins/JavaScriptLanguage/jsLanguageServicesImpl/external" />
+ </component>
+ <component name="RecentsManager">
+ <key name="CopyFile.RECENT_KEYS">
+ <recent name="$PROJECT_DIR$/src/assets" />
+ </key>
+ <key name="MoveFile.RECENT_KEYS">
+ <recent name="$PROJECT_DIR$/src/store/modules" />
+ <recent name="$PROJECT_DIR$/src/components/landing" />
+ <recent name="$PROJECT_DIR$/src/components" />
+ </key>
+ </component>
+ <component name="RunManager" selected="npm.npm serve">
+ <configuration name="Debug Application" type="JavascriptDebugType" uri="http://localhost:8080">
+ <method v="2" />
+ </configuration>
+ <configuration name="npm serve" type="js.build_tools.npm">
+ <package-json value="$PROJECT_DIR$/package.json" />
+ <command value="run" />
+ <scripts>
+ <script value="serve" />
+ </scripts>
+ <node-interpreter value="project" />
+ <envs />
+ <method v="2" />
+ </configuration>
+ </component>
+ <component name="ServiceViewManager">
+ <option name="viewStates">
+ <list>
+ <serviceView>
+ <treeState>
+ <expand />
+ <select />
+ </treeState>
+ </serviceView>
+ </list>
+ </option>
+ </component>
+ <component name="SvnConfiguration">
+ <configuration />
+ </component>
+ <component name="TaskManager">
+ <task active="true" id="Default" summary="Default task">
+ <changelist id="c2cd5109-1431-412f-85ad-eb6f68d4ed8d" name="Default Changelist" comment="" />
+ <created>1599486133223</created>
+ <option name="number" value="Default" />
+ <option name="presentableId" value="Default" />
+ <updated>1599486133223</updated>
+ <workItem from="1599486134588" duration="217546000" />
+ <workItem from="1601038400517" duration="39716000" />
+ </task>
+ <servers />
+ </component>
+ <component name="TypeScriptGeneratedFilesManager">
+ <option name="version" value="1" />
+ </component>
+ <component name="WindowStateProjectService">
+ <state x="2240" y="205" key="#ESLint" timestamp="1600964289041">
+ <screen x="1680" y="0" width="1920" height="1080" />
+ </state>
+ <state x="2240" y="205" key="#ESLint/1680.0.1920.1080/0.0.1680.1050@1680.0.1920.1080" timestamp="1600964289041" />
+ <state x="2363" y="350" key="#com.intellij.fileTypes.FileTypeChooser" timestamp="1601165959137">
+ <screen x="1680" y="0" width="1920" height="1080" />
+ </state>
+ <state x="2363" y="350" key="#com.intellij.fileTypes.FileTypeChooser/1680.0.1920.1080/0.0.1680.1050@1680.0.1920.1080" timestamp="1601165959137" />
+ <state x="2378" y="294" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog" timestamp="1601162305471">
+ <screen x="1680" y="0" width="1920" height="1080" />
+ </state>
+ <state x="2378" y="294" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog/1680.0.1920.1080/0.0.1680.1050@1680.0.1920.1080" timestamp="1601162305471" />
+ <state x="2305" y="183" width="667" height="729" key="find.popup" timestamp="1601404607112">
+ <screen x="1680" y="0" width="1920" height="1080" />
+ </state>
+ <state x="2305" y="183" width="667" height="729" key="find.popup/1680.0.1920.1080/0.0.1680.1050@1680.0.1920.1080" timestamp="1601404607112" />
+ <state x="2305" y="241" width="670" height="676" key="search.everywhere.popup" timestamp="1600705258945">
+ <screen x="1680" y="0" width="1920" height="1080" />
+ </state>
+ <state x="2305" y="241" width="670" height="676" key="search.everywhere.popup/1680.0.1920.1080/0.0.1680.1050@1680.0.1920.1080" timestamp="1600705258945" />
+ </component>
+ <component name="XDebuggerManager">
+ <breakpoint-manager>
+ <breakpoints>
+ <line-breakpoint enabled="true" type="javascript">
+ <url>file://$PROJECT_DIR$/src/components/workspace/Users.vue</url>
+ <line>320</line>
+ <option name="timeStamp" value="1" />
+ </line-breakpoint>
+ </breakpoints>
+ </breakpoint-manager>
+ </component>
+</project>
\ No newline at end of file
diff --git a/custos-demo-gateway/Dockerfile b/custos-demo-gateway/Dockerfile
new file mode 100644
index 0000000..879cb74
--- /dev/null
+++ b/custos-demo-gateway/Dockerfile
@@ -0,0 +1,19 @@
+# build stage
+FROM node:lts-alpine as build-stage
+WORKDIR /app
+COPY package*.json ./
+RUN npm install
+COPY . .
+RUN npm run build
+
+# production stage
+FROM nginx:stable-alpine as production-stage
+COPY --from=build-stage /app/dist /usr/share/nginx/html
+COPY nginx.conf /etc/nginx/conf.d/default.conf
+COPY privkey.pem /etc/nginx/privkey.pem
+COPY fullchain.pem /etc/nginx/fullchain.pem
+COPY entrypoint.sh /
+RUN chmod +x /entrypoint.sh
+EXPOSE 443
+ENTRYPOINT [ "/entrypoint.sh" ]
+#CMD ["nginx", "-g", "daemon off;"]
\ No newline at end of file
diff --git a/custos-demo-gateway/README.md b/custos-demo-gateway/README.md
new file mode 100644
index 0000000..dd39c19
--- /dev/null
+++ b/custos-demo-gateway/README.md
@@ -0,0 +1,24 @@
+# custos-demo-gateway
+
+## Project setup
+```
+yarn install
+```
+
+### Compiles and hot-reloads for development
+```
+yarn serve
+```
+
+### Compiles and minifies for production
+```
+yarn build
+```
+
+### Lints and fixes files
+```
+yarn lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).
diff --git a/custos-demo-gateway/babel.config.js b/custos-demo-gateway/babel.config.js
new file mode 100644
index 0000000..e955840
--- /dev/null
+++ b/custos-demo-gateway/babel.config.js
@@ -0,0 +1,5 @@
+module.exports = {
+ presets: [
+ '@vue/cli-plugin-babel/preset'
+ ]
+}
diff --git a/custos-demo-gateway/docker-compose.yml b/custos-demo-gateway/docker-compose.yml
new file mode 100644
index 0000000..c774049
--- /dev/null
+++ b/custos-demo-gateway/docker-compose.yml
@@ -0,0 +1,11 @@
+version: "3.3"
+services:
+ web:
+ image : "apachecustos/custos-demo-gateway:latest"
+ ports:
+ - "8080:8080"
+ environment:
+ VUE_APP_CLIENT_ID: ''
+ VUE_APP_CLIENT_SEC: ''
+ VUE_APP_REDIRECT_URI: 'http://localhost:8080/callback'
+ VUE_APP_CUSTOS_TOKEN_ENDPOINT: 'https://custos.scigap.org/apiserver/identity-management/v1.0.0/token'
\ No newline at end of file
diff --git a/custos-demo-gateway/entrypoint.sh b/custos-demo-gateway/entrypoint.sh
new file mode 100644
index 0000000..9b9b603
--- /dev/null
+++ b/custos-demo-gateway/entrypoint.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Replace env vars in JavaScript files
+echo "Replacing env vars in JS"
+for file in /usr/share/nginx/html/js/app.*.js;
+do
+ echo "Processing $file ...";
+
+ # Use the existing JS file as template
+ if [ ! -f $file.tmpl.js ]; then
+ cp $file $file.tmpl.js
+ fi
+
+ envsubst '$VUE_APP_CLIENT_ID,$VUE_APP_CLIENT_SEC,$VUE_APP_REDIRECT_URI' < $file.tmpl.js > $file
+done
+
+echo "Starting Nginx"
+nginx -g 'daemon off;'
\ No newline at end of file
diff --git a/custos-demo-gateway/fullchain.pem b/custos-demo-gateway/fullchain.pem
new file mode 100644
index 0000000..e6199f0
--- /dev/null
+++ b/custos-demo-gateway/fullchain.pem
@@ -0,0 +1,59 @@
+-----BEGIN CERTIFICATE-----
+MIIFdTCCBF2gAwIBAgISA4dFxqSZr9p+QksSmAdoLUZfMA0GCSqGSIb3DQEBCwUA
+MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
+ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0yMDA5MjgyMzIzMTNaFw0y
+MDEyMjcyMzIzMTNaMCkxJzAlBgNVBAMTHmRlbW8uZ2F0ZXdheS5jdXN0b3Muc2Np
+Z2FwLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMhSqh9FXvM0
+xo8t0oQJ9OGCE9loLbMm2/knZ1ITsRbKTHMczvKkiRBxwgU7kitLDrwolNf5vqQy
+lZrCOjEqda5pi1KwFLNLlYJmV1g+oF5+o0yTTMKUPOnN2+hI9Sjuwwi+/fRMqKsw
+l8SfAum2nDBP9BUuB9MZFThcCm+Cxl55Qz0VXVgzYE+jnNY+BvX4EDaov9mmHkwn
+uXFO6W61k4F/IiD2qhxWmTX8ElwyG8Y6wgNCA/qn5kEPDFCuEXypaVIimDoJyKwD
+VJ84nXlQLrJVLu8Ai6MFKQE6uGOW4tM4zwD9r3zUb8noPJqfwKeE5MEDhQtCA/lh
+PG4UBniquBUCAwEAAaOCAnQwggJwMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAU
+BggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUUrmz
+/B8YDBArAIE6loWileymPe0wHwYDVR0jBBgwFoAUqEpqYwR93brm0Tm3pkVl7/Oo
+7KEwbwYIKwYBBQUHAQEEYzBhMC4GCCsGAQUFBzABhiJodHRwOi8vb2NzcC5pbnQt
+eDMubGV0c2VuY3J5cHQub3JnMC8GCCsGAQUFBzAChiNodHRwOi8vY2VydC5pbnQt
+eDMubGV0c2VuY3J5cHQub3JnLzApBgNVHREEIjAggh5kZW1vLmdhdGV3YXkuY3Vz
+dG9zLnNjaWdhcC5vcmcwTAYDVR0gBEUwQzAIBgZngQwBAgEwNwYLKwYBBAGC3xMB
+AQEwKDAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwggEF
+BgorBgEEAdZ5AgQCBIH2BIHzAPEAdwBep3P531bA57U2SH3QSeAyepGaDIShEhKE
+GHWWgXFFWAAAAXTXPeyUAAAEAwBIMEYCIQCOpzkBmQCq4YljG/+IYPhuiTyBTBB6
+lyx25017CC3ZmAIhAKaYWDLX/QCeWOVbWzxqXdcAwwPqSA5SL2mDL3SDePzMAHYA
+B7dcG+V9aP/xsMYdIxXHuuZXfFeUt2ruvGE6GmnTohwAAAF01z3s9gAABAMARzBF
+AiAKxZt6ENgjLqtnzkR0mbEUivqEjqtPcNlC4GN+H1EQlAIhAO1oygawEpMs2TAa
+eMhw3J+bJ4P63IRQEdGerqChRs/HMA0GCSqGSIb3DQEBCwUAA4IBAQA3vvDU3ULX
+VbHWFHug54FkWfhVK49V6eGVRImQOiyTdOoQS6MHKvsedg3aBhj3FwRXQzx7VZ61
+xPthZeNooKNUB184eg+R9L2v1HDT1PyGQgXq9MIVJJzXGw9A9W22o68vbMOp5Pw/
+WC5b+ozYbNz38527XE9KBVoETwrsjIg3q/U/beV9MaLt8EfVobOJXb7JvpTvc3me
+ZI6+y2t9Buj4ebIjHA/Ve1SrWEfGVQNjgz86J8JIg7jPV3lv5Gn49JwILSC53bCK
+GSgYLjGPp8Lwtew8NJDTVzRjwquvxky9smVci2GwGUYAv55l07vvv5dHRYKKFF/z
+gUoZxG3CR60/
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
+MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
+SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
+GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
+q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
+SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
+Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
+a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
+/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
+AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
+CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
+bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
+c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
+VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
+ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
+MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
+Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
+AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
+uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
+wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
+X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
+PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
+KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
+-----END CERTIFICATE-----
diff --git a/custos-demo-gateway/nginx.conf b/custos-demo-gateway/nginx.conf
new file mode 100644
index 0000000..de44403
--- /dev/null
+++ b/custos-demo-gateway/nginx.conf
@@ -0,0 +1,35 @@
+gzip on;
+gzip_disable "msie6";
+gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
+
+server {
+ listen 80;
+ server_name demo.gateway.custos.scigap.org www.demo.gateway.custos.scigap.org;
+ return 301 https://demo.gateway.custos.scigap.org$request_uri;
+}
+
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+
+ ssl_certificate /etc/nginx/fullchain.pem;
+ ssl_certificate_key /etc/nginx/privkey.pem;
+
+ root /usr/share/nginx/html;
+
+ index index.html;
+
+ location ~ ^/(css|js)/ {
+ # These assets include a digest in the filename, so they will never change
+ expires max;
+ }
+
+ location ~* ^.+\.(html|htm)$ {
+ # Very short caching time to ensure changes are immediately recognized
+ expires 5m;
+ }
+
+ location / {
+ try_files $uri $uri/ /index.html;
+ }
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/package.json b/custos-demo-gateway/package.json
new file mode 100644
index 0000000..2fe7f96
--- /dev/null
+++ b/custos-demo-gateway/package.json
@@ -0,0 +1,50 @@
+{
+ "name": "custos-demo-gateway",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "serve": "vue-cli-service serve",
+ "build": "vue-cli-service build",
+ "lint": "vue-cli-service lint"
+ },
+ "dependencies": {
+ "core-js": "^3.6.5",
+ "vue": "^2.6.11",
+ "vue-router": "^3.4.3",
+ "bootstrap-vue": "^2.16.0",
+ "axios": "0.20.0",
+ "vuex": "^3.5.1",
+ "jwt-decode": "^3.0.0-beta.2",
+ "qs": "^6.9.4",
+ "dotenv": "^8.2.0"
+ },
+ "devDependencies": {
+ "@vue/cli-plugin-babel": "~4.5.0",
+ "@vue/cli-plugin-eslint": "~4.5.0",
+ "@vue/cli-service": "~4.5.0",
+ "babel-eslint": "^10.1.0",
+ "eslint": "^6.7.2",
+ "eslint-plugin-vue": "^6.2.2",
+ "vue-template-compiler": "^2.6.11"
+
+ },
+ "eslintConfig": {
+ "root": true,
+ "env": {
+ "node": true
+ },
+ "extends": [
+ "plugin:vue/essential",
+ "eslint:recommended"
+ ],
+ "parserOptions": {
+ "parser": "babel-eslint"
+ },
+ "rules": {}
+ },
+ "browserslist": [
+ "> 1%",
+ "last 2 versions",
+ "not dead"
+ ]
+}
diff --git a/custos-demo-gateway/public/favicon.ico b/custos-demo-gateway/public/favicon.ico
new file mode 100644
index 0000000..df36fcf
Binary files /dev/null and b/custos-demo-gateway/public/favicon.ico differ
diff --git a/custos-demo-gateway/public/index.html b/custos-demo-gateway/public/index.html
new file mode 100644
index 0000000..4123528
--- /dev/null
+++ b/custos-demo-gateway/public/index.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
+ <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+ <title><%= htmlWebpackPlugin.options.title %></title>
+ </head>
+ <body>
+ <noscript>
+ <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+ </noscript>
+ <div id="app"></div>
+ <!-- built files will be auto injected -->
+ </body>
+</html>
diff --git a/custos-demo-gateway/src/App.vue b/custos-demo-gateway/src/App.vue
new file mode 100644
index 0000000..3cb051c
--- /dev/null
+++ b/custos-demo-gateway/src/App.vue
@@ -0,0 +1,29 @@
+<template>
+ <div id="app">
+ <div id="nav">
+ <router-view/>
+ </div>
+ </div>
+</template>
+
+<script>
+ import TheNavigator from "./components/TheNavigator.vue";
+
+ export default {
+ name: 'App',
+ components: [
+ TheNavigator
+ ]
+ }
+</script>
+
+<style>
+ #app {
+ font-family: Avenir, Helvetica, Arial, sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ text-align: center;
+ color: #2c3e50;
+ margin-top: 60px;
+ }
+</style>
diff --git a/custos-demo-gateway/src/assets/bots.png b/custos-demo-gateway/src/assets/bots.png
new file mode 100644
index 0000000..902d442
Binary files /dev/null and b/custos-demo-gateway/src/assets/bots.png differ
diff --git a/custos-demo-gateway/src/assets/credentials.png b/custos-demo-gateway/src/assets/credentials.png
new file mode 100644
index 0000000..ac9a60c
Binary files /dev/null and b/custos-demo-gateway/src/assets/credentials.png differ
diff --git a/custos-demo-gateway/src/assets/custos_home.png b/custos-demo-gateway/src/assets/custos_home.png
new file mode 100644
index 0000000..e89d50a
Binary files /dev/null and b/custos-demo-gateway/src/assets/custos_home.png differ
diff --git a/custos-demo-gateway/src/assets/dblogs.png b/custos-demo-gateway/src/assets/dblogs.png
new file mode 100644
index 0000000..0cc6502
Binary files /dev/null and b/custos-demo-gateway/src/assets/dblogs.png differ
diff --git a/custos-demo-gateway/src/assets/groups_web.png b/custos-demo-gateway/src/assets/groups_web.png
new file mode 100644
index 0000000..1d9ee5b
Binary files /dev/null and b/custos-demo-gateway/src/assets/groups_web.png differ
diff --git a/custos-demo-gateway/src/assets/logo.png b/custos-demo-gateway/src/assets/logo.png
new file mode 100644
index 0000000..f3d2503
Binary files /dev/null and b/custos-demo-gateway/src/assets/logo.png differ
diff --git a/custos-demo-gateway/src/assets/sharings.png b/custos-demo-gateway/src/assets/sharings.png
new file mode 100644
index 0000000..14e7bb1
Binary files /dev/null and b/custos-demo-gateway/src/assets/sharings.png differ
diff --git a/custos-demo-gateway/src/assets/users.png b/custos-demo-gateway/src/assets/users.png
new file mode 100644
index 0000000..274ccdc
Binary files /dev/null and b/custos-demo-gateway/src/assets/users.png differ
diff --git a/custos-demo-gateway/src/components/Callback.vue b/custos-demo-gateway/src/components/Callback.vue
new file mode 100644
index 0000000..ba63380
--- /dev/null
+++ b/custos-demo-gateway/src/components/Callback.vue
@@ -0,0 +1,86 @@
+<template>
+ <p></p>
+</template>
+
+<script>
+
+ import config from "@/config";
+
+ export default {
+ name: "Callback",
+ data: function () {
+ return {
+ username: "",
+ password: "",
+ custosId: null,
+ custosSec: null,
+ redirectURI: null,
+ tokenEndpoint: null
+ }
+ },
+
+ methods: {
+ async authenticate() {
+ let code = this.$route.query.code
+ let params = {
+ client_id: this.custosId, client_sec: this.custosSec, code: code,
+ redirect_uri: this.redirectURI, token_endpoint: this.tokenEndpoint
+ };
+ await this.$store.dispatch('identity/authenticateUsingCode', params)
+
+ }
+ },
+
+ computed: {
+ isAuthenticated: function () {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec
+ }
+ return this.$store.dispatch('identity/isAuthenticated', data)
+ }
+ },
+
+ async mounted() {
+ this.custosId = config.value('clientId')
+ this.custosSec = config.value('clientSec')
+ this.redirectURI = config.value('redirectURI')
+ this.tokenEndpoint = "https://custos.scigap.org/apiserver/identity-management/v1.0.0/token"
+ await this.authenticate()
+ console.log("calling authenticate")
+ if (this.isAuthenticated) {
+ console.log("calling authenticated")
+ let username = await this.$store.dispatch('identity/getCurrentUserName')
+ await this.$router.push('workspace')
+ let data = {
+ offset: 0, limit: 1, client_id: this.custosId, client_sec: this.custosSec,
+ username: username
+ }
+ let resp = await this.$store.dispatch('user/users', data)
+ console.log(resp)
+ if (Array.isArray(resp) && resp.length > 0) {
+ resp.forEach(user => {
+ let dat = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ username: user.username,
+ first_name: user.first_name,
+ last_name: user.last_name,
+ email: user.email,
+ }
+ }
+ console.log(dat)
+ this.$store.dispatch('user/updateUserProfile', dat)
+ })
+ }
+ } else {
+ await this.$router.push('home')
+ }
+ }
+ }
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/custos-demo-gateway/src/components/TheNavigator.vue b/custos-demo-gateway/src/components/TheNavigator.vue
new file mode 100644
index 0000000..ed9e715
--- /dev/null
+++ b/custos-demo-gateway/src/components/TheNavigator.vue
@@ -0,0 +1,24 @@
+<template>
+ <nav id ="nav">
+ <router-link to="/">Landing Page</router-link>
+ <router-link to="/register">User Account Creation</router-link>
+ <router-link to="/workspace">Work Space</router-link>
+ <router-link to="/workspace/groups">Work Space</router-link>
+ <router-link to="/workspace/users">Work Space</router-link>
+ <router-link to="/workspace/logs">Work Space</router-link>
+ <router-link to="/workspace/secrets">Work Space</router-link>
+ <router-link to="/workspace/sharings">Work Space</router-link>
+ <router-link to="/callback">Work Space</router-link>
+ </nav>
+
+</template>
+
+<script>
+ export default {
+ name: "TheNavigator"
+ }
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/custos-demo-gateway/src/components/landing/Landing.vue b/custos-demo-gateway/src/components/landing/Landing.vue
new file mode 100644
index 0000000..0def2cd
--- /dev/null
+++ b/custos-demo-gateway/src/components/landing/Landing.vue
@@ -0,0 +1,229 @@
+<template>
+ <div class="landing">
+
+ <div class="row">
+
+ <div class="column">
+ <h2>Welcome to Custos Explorer</h2>
+ <p>SignUp and explore capabilities</p>
+ <img src="./../../assets/custos_home.png">
+ </div>
+ <div class="column">
+ <div class="login">
+ <div class="exlogin">
+ <p>Login with your existing organization</p>
+ <b-button variant="primary" v-on:click="this.loadAuthURL">Login with Institution</b-button>
+ </div>
+ <div class="locallogin">
+ <p>Login with Custos Explorer (Not registered ?
+ <router-link to="/register">Create Account</router-link>
+ )
+ </p>
+
+ <div class="logininput">
+ <b-form-input v-model="username" placeholder="Username"></b-form-input>
+
+ </div>
+ <div class="logininput">
+ <b-form-input type="password" v-model="password" placeholder="Password"></b-form-input>
+ </div>
+ <div class="logininput">
+ <b-button variant="primary" v-on:click="this.login" :disabled="this.loginDisabled">
+ <div v-if="this.loginDisabled">
+ <b-spinner small></b-spinner>
+ </div>
+ Login
+ </b-button>
+ </div>
+ </div>
+ <div>
+ <b-alert v-model="this.loginError" variant="danger" dismissible @dismissed="this.callDismissed">
+ Invalid Username or Password
+ </b-alert>
+ </div>
+
+
+ </div>
+
+ </div>
+ </div>
+
+ </div>
+</template>
+
+<script>
+
+ import config from "@/config";
+
+ export default {
+ name: 'Landing',
+ props: {
+ msg: String,
+ seen: Boolean,
+ todos: Array
+ },
+ data: function () {
+ return {
+ username: "",
+ password: "",
+ custosId: null,
+ custosSec: null,
+ loginDisabled: false,
+ redirectURI: null,
+ loginError: false
+ }
+ },
+ methods: {
+
+ async login() {
+ this.loginDisabled = true
+ if (this.username != null && this.username != '' && this.password != null && this.password != '') {
+ let params = {
+ client_id: this.custosId, client_sec: this.custosSec, username: this.username,
+ password: this.password, token_endpoint: this.tokenEndpoint
+ };
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec
+ }
+ await this.$store.dispatch('identity/authenticateLocally', params)
+ let resp = await this.$store.dispatch('identity/isAuthenticated', data)
+ if (resp) {
+ await this.$router.push('workspace')
+ let data = {
+ offset: 0, limit: 1, client_id: this.custosId, client_sec: this.custosSec,
+ username: this.username
+ }
+ let resp = await this.$store.dispatch('user/users', data)
+ if (Array.isArray(resp) && resp.length > 0) {
+ resp.forEach(user => {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ username: user.username,
+ first_name: user.first_name,
+ last_name: user.last_name,
+ email: user.email,
+ }
+ }
+ this.$store.dispatch('user/updateUserProfile', data)
+
+ })
+ }
+
+ } else {
+ this.loginError = true
+ }
+ } else {
+ this.loginError = true
+ }
+ this.loginDisabled = false
+ },
+
+
+ async callDismissed() {
+ this.loginError = false
+ },
+ async loadAuthURL() {
+ let params = {client_id: this.custosId, redirect_uri: this.redirectURI};
+ await this.$store.dispatch('identity/fetchAuthorizationEndpoint', params)
+ window.location.href = this.$store.getters['identity/getAuthorizationEndpoint']
+ }
+ },
+
+ mounted() {
+ this.custosId = config.value('clientId')
+ this.custosSec = config.value('clientSec')
+ this.redirectURI = config.value('redirectURI')
+ this.tokenEndpoint = "https://custos.scigap.org/apiserver/identity-management/v1.0.0/token"
+
+ },
+
+ computed: {
+ // ...mapGetters({
+ //
+ // })
+ }
+
+
+ }
+</script>
+
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+ h2 {
+ margin: 40px 0 0;
+ font-size: xx-large;
+ font-family: "Arial";;
+ }
+
+ p {
+ font-size: medium;
+ font-family: "Arial";
+ }
+
+ ul {
+ list-style-type: none;
+ padding: 0;
+ }
+
+ li {
+ display: inline-block;
+ margin: 0 10px;
+ }
+
+ a {
+ color: #42b983;
+ }
+
+ * {
+ box-sizing: border-box;
+ }
+
+ /* Create two equal columns that floats next to each other */
+ .column {
+ float: left;
+ width: 50%;
+ padding: 10px;
+ height: 300px; /* Should be removed. Only for demonstration */
+ }
+
+ /* Clear floats after the columns */
+ .row:after {
+ content: "";
+ display: table;
+ clear: both;
+ }
+
+ .login {
+ height: 10%;
+ position: relative;
+ top: 50%;
+ z-index: 2;
+ width: 60%;
+ left: 20%;
+ }
+
+ .exlogin {
+ background-color: whitesmoke;
+ box-sizing: border-box;
+ margin-top: 20%;
+ }
+
+ .locallogin {
+ background-color: whitesmoke;
+ box-sizing: border-box;
+ position: relative;
+ margin-top: 7%;
+ }
+
+ .logininput {
+ width: 60%;
+ position: relative;
+ left: 20%;
+ margin-top: 4%;
+ }
+
+</style>
diff --git a/custos-demo-gateway/src/components/registration/CreateAccount.vue b/custos-demo-gateway/src/components/registration/CreateAccount.vue
new file mode 100644
index 0000000..798f3d7
--- /dev/null
+++ b/custos-demo-gateway/src/components/registration/CreateAccount.vue
@@ -0,0 +1,206 @@
+<template>
+ <div class="account">
+ <div class="row">
+ <div class="column">
+ <div class="login">
+ <div class="locallogin">
+ <h2> Create account </h2>
+
+ <div class="logininput">
+ <p>Username</p>
+ </div>
+ <div class="logininput">
+ <b-form-input v-model="username" placeholder="Username"></b-form-input>
+ </div>
+ <div class="logininput">
+ <p>Password</p>
+ </div>
+ <div class="logininput">
+ <b-form-input type="password" v-model="password" placeholder="Password"></b-form-input>
+ </div>
+ <div class="logininput">
+ <p>Password</p>
+ </div>
+ <div class="logininput">
+ <b-form-input type="password" v-model="confirmedPassword"
+ placeholder="Confirm Password"></b-form-input>
+ </div>
+ <div class="logininput">
+ <p>Email</p>
+ </div>
+ <div class="logininput">
+ <b-form-input type="email" v-model="email" placeholder="Email"></b-form-input>
+ </div>
+ <div class="logininput">
+ <p>First Name</p>
+ </div>
+ <div class="logininput">
+ <b-form-input type="email" v-model="firstName" placeholder="First Name"></b-form-input>
+ </div>
+ <div class="logininput">
+ <p>Last Name</p>
+ </div>
+ <div class="logininput">
+ <b-form-input type="email" v-model="lastName" placeholder="Last Name"></b-form-input>
+ </div>
+ <div class="logininput">
+ <b-button variant="primary" v-on:click="this.registerUser" :disabled="this.isButtonDisabled">
+ <div v-if="this.isButtonDisabled">
+ <b-spinner small></b-spinner>
+ </div>
+ Create Account</b-button>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ </div>
+
+
+ </div>
+</template>
+
+<script>
+ import config from "@/config";
+
+ export default {
+ name: "CreateAccount",
+ data: function () {
+ return {
+ username: "",
+ password: "",
+ confirmedPassword: null,
+ email: null,
+ firstName: null,
+ lastName: null,
+ custosId: null,
+ custosSec: null,
+ isButtonDisabled:false
+ }
+ },
+
+ methods: {
+
+ async registerUser() {
+ this.isButtonDisabled = true
+ if (this.password != null && this.confirmedPassword != null && this.password === this.confirmedPassword) {
+
+ if (this.username != null && this.firstName != null && this.lastName != null) {
+ let body = {
+ 'client_id': this.custosId,
+ 'client_sec': this.custosSec,
+ 'username': this.username,
+ 'first_name': this.firstName,
+ 'last_name': this.lastName,
+ 'password': this.password,
+ 'temporary_password': false,
+ 'email': this.email
+ }
+ let avilable = await this.$store.dispatch('user/checkUsernameIsValid', body)
+ if (avilable) {
+ let status = await this.$store.dispatch('user/registerUser', body)
+ if (status) {
+ await this.$router.push("/")
+ } else {
+ alert("Some error occurred")
+ }
+
+ } else {
+ alert("Username is not valid")
+ }
+ } else {
+ alert("fill all fields")
+ }
+
+ } else {
+ alert("password mismatch")
+ }
+ this.isButtonDisabled = true
+ },
+
+ },
+
+ mounted() {
+ this.custosId = config.value('clientId')
+ this.custosSec = config.value('clientSec')
+ }
+ }
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+ h2 {
+ margin: 40px 0 0;
+ font-size: xx-large;
+ font-family: "Arial";;
+ }
+
+ p {
+ font-size: medium;
+ font-family: "Arial";
+ text-align: left;
+ }
+
+ ul {
+ list-style-type: none;
+ padding: 0;
+ }
+
+ li {
+ display: inline-block;
+ margin: 0 10px;
+ }
+
+ a {
+ color: #42b983;
+ }
+
+ * {
+ box-sizing: border-box;
+ }
+
+ /* Create two equal columns that floats next to each other */
+ .column {
+ float: left;
+ width: 50%;
+ padding: 10px;
+ height: 300px; /* Should be removed. Only for demonstration */
+ }
+
+ /* Clear floats after the columns */
+ .row:after {
+ content: "";
+ display: table;
+ clear: both;
+ }
+
+ .login {
+ height: 10%;
+ position: relative;
+ margin-top: 5%;
+ z-index: 2;
+ width: 60%;
+ left: 20%;
+ }
+
+ .exlogin {
+ background-color: whitesmoke;
+ box-sizing: border-box;
+ margin-top: 20%;
+ }
+
+ .locallogin {
+ background-color: whitesmoke;
+ box-sizing: border-box;
+ position: relative;
+ margin-top: 7%;
+ }
+
+ .logininput {
+ width: 60%;
+ position: relative;
+ left: 20%;
+ margin-top: 2%;
+ }
+
+</style>
\ No newline at end of file
diff --git a/custos-demo-gateway/src/components/workspace/Agents.vue b/custos-demo-gateway/src/components/workspace/Agents.vue
new file mode 100644
index 0000000..7dee536
--- /dev/null
+++ b/custos-demo-gateway/src/components/workspace/Agents.vue
@@ -0,0 +1,295 @@
+<template>
+ <div class="accounttable">
+<!-- <div class="enableComAcc">-->
+<!-- <b-form-checkbox v-model="checked" :disabled=isCheckedBtnDisabled v-on:change="enableAgents"-->
+<!-- name="check-button" switch>-->
+<!-- Enable Community Accounts-->
+<!-- </b-form-checkbox>-->
+<!-- </div>-->
+ <div v-if="this.loadingAgents" class="d-flex justify-content-center mb-3">
+ <b-spinner variant="primary" label="Text Centered"></b-spinner>
+ </div>
+ <b-table striped hover responsive :items="communityAccounts" :fields="community_fields" selectable
+ ref="selectableTable"
+ select-mode="single"
+ @row-selected="onCommunityAcSelected" caption-top>
+ <template v-slot:table-caption>Community Accounts</template>
+ </b-table>
+ <div class="addAccItem">
+ <b-button variant="outline-primary" v-on:click="this.addAccount">Add Account</b-button>
+ </div>
+
+ <b-modal ref="newAcc" scrollable title="New Account" ok-title="Ok" @ok="registerAgent">
+ <div class="userform">
+ <div class="userformItem">
+ <p>Id</p>
+ <b-form-input v-model="newAccountName"></b-form-input>
+ </div>
+ </div>
+ </b-modal>
+ <b-modal ref="exAcc" scrollable title=" Account" ok-title="Ok" hide-footer>
+ <div class="userform">
+ <div class="userformItem">
+ <p>Id</p>
+ <b-form-input v-model="exAccountId" disabled></b-form-input>
+ </div>
+ <div class="userform">
+ <p>Status</p>
+ <b-form-select v-model="selectedStatus" v-on:change="changeAccountStatus">
+ <option v-for="(selectOption, indexOpt) in statusOptions"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+ <div class="userformItem">
+ <p>Attributes</p>
+ <b-table striped hover responsive :items="accSelectedAttributes" selectable select-mode="single"
+ @row-selected="onAccAtrSelected">
+ </b-table>
+ <dev class="addAtrCls">
+ <b-button variant="outline-primary" v-on:click="addActAttribute">Add Attributes</b-button>
+ </dev>
+ </div>
+ </div>
+ </b-modal>
+ <b-modal ref="accAtrModel" scrollable title="Add Attribute" ok-title="Add" @ok="addAtrOkPressed">
+ <div class="userform">
+ <div class="userformItem">
+ <p>Key</p>
+ <b-form-input v-model="newAcAtrKey"></b-form-input>
+ </div>
+ <div class="userformItem">
+ <p>Value</p>
+ <b-form-input v-model="newAcAtrValue"></b-form-input>
+ </div>
+ </div>
+ </b-modal>
+ <b-modal ref="AccAtrModelSelected" scrollable title="Attribute" ok-title="Delete" @ok="deleteAtrOkPressed">
+ <div class="userform">
+ <div class="userformItem">
+ <p>Key</p>
+ <b-form-input v-model="exAccountAtrKey" disabled></b-form-input>
+ </div>
+ <div class="userformItem">
+ <p>Value</p>
+ <b-form-input v-model="exAccountAtrValue" disabled></b-form-input>
+ </div>
+ </div>
+ </b-modal>
+ <b-modal ref="enablePopOver" scrollable title="Agent Credentials" cancel-disabled>
+ <div class="userform">
+ <div class="userformItem">
+ <p>Id</p>
+ <b-form-input v-model="agentId" disabled></b-form-input>
+ </div>
+ <div class="userformItem">
+ <p>Secret</p>
+ <b-form-input v-model="agentSec" disabled></b-form-input>
+ </div>
+ </div>
+ </b-modal>
+
+ </div>
+</template>
+
+<script>
+ import config from "@/config";
+
+ export default {
+ name: "Agents",
+ data: function () {
+ return {
+ community_fields: ["id", "status"],
+ communityAccounts: [],
+ statusOptions: ['ACTIVE', 'DISABLED'],
+ scopes: ['TENANT', 'CLIENT'],
+ checked: true,
+ newAccountName: null,
+ exAccountId: null,
+ exAccount: null,
+ accSelectedAttributes: [],
+ accSelectedRoles: [],
+ exAccountAtr: null,
+ exAccountRole: null,
+ exAccountAtrKey: null,
+ exAccountAtrValue: null,
+ exAccountRoleKey: null,
+ exAccountRoleValue: null,
+ custosId: null,
+ custosSec: null,
+ isAdminUser: false,
+ tenantroles: [],
+ clientroles: [],
+ newAcAtrKey: null,
+ newAcAtrValue: null,
+ agentId: null,
+ agentSec: null,
+ selectedStatus: null,
+ loadingAgents:false
+
+
+ }
+ },
+
+ methods: {
+ async onCommunityAcSelected(items) {
+ if (items != null && items.length > 0) {
+ this.exAccount = items
+ this.exAccountId = this.exAccount[0].id
+ let act = await this.$store.getters['identity/getAccessToken']
+ let dt = {
+ user_token: act,
+ agent_id: this.exAccountId
+ }
+ let agent = await this.$store.dispatch('agent/getAgent', dt)
+ let atrs = []
+ agent.attributes.forEach(at => {
+ atrs.push({key: at.key, value: at.values.join("")})
+ })
+ this.accSelectedAttributes = atrs
+ this.selectedStatus = this.exAccount[0].status
+ this.$refs.exAcc.show()
+ }
+ },
+ addAccount: function () {
+ this.newAccountName = null
+ this.$refs.newAcc.show()
+ },
+
+ onAccAtrSelected: function (items) {
+ this.exAccountAtr = items
+ this.exAccountAtrKey = this.exAccountAtr[0].key
+ this.exAccountAtrValue = this.exAccountAtr[0].value
+ this.$refs.AccAtrModelSelected.show()
+ },
+
+ onAccRoleSelected: function (items) {
+ this.exAccountRole = items
+ this.exAccountRoleKey = this.exAccountRole[0].name
+ this.exAccountRoleValue = this.exAccountRole[0].scope
+ this.$refs.accRoleModelSelected.show()
+ },
+
+ addActAttribute: function () {
+ this.$refs.accAtrModel.show()
+ },
+ addActRole: function () {
+ this.$refs.accRoleModel.show()
+ },
+ async enableAgents() {
+ let accessToken = await this.$store.getters['identity/getAccessToken']
+ let data = {
+ user_token: accessToken,
+ }
+ await this.$store.dispatch('agent/enableAgents', data)
+ },
+
+ async registerAgent() {
+ let accessToken = await this.$store.getters['identity/getAccessToken']
+ let data = {
+ user_token: accessToken,
+ body: {
+ id: this.newAccountName
+ }
+ }
+ let response = await this.$store.dispatch('agent/registerAgent', data)
+ let agents = await this.$store.getters['agent/getAgents']
+ this.communityAccounts = agents
+ this.agentId = response.id
+ this.agentSec = response.secret
+ this.$refs.enablePopOver.show()
+ },
+
+ async addAtrOkPressed() {
+ let accessToken = await this.$store.getters['identity/getAccessToken']
+ let data = {
+ user_token: accessToken,
+ body: {
+ agents: [this.exAccountId],
+ attributes: [{
+ key: this.newAcAtrKey,
+ values: [this.newAcAtrValue]
+ }]
+ }
+ }
+ let atr = {key: this.newAcAtrKey, value: this.newAcAtrValue}
+ this.accSelectedAttributes.push(atr)
+ await this.$store.dispatch('agent/addAttributeToAgent', data)
+ this.newAcAtrKey = null
+ this.newAcAtrValue = null
+ },
+
+ async deleteAtrOkPressed() {
+ let accessToken = await this.$store.getters['identity/getAccessToken']
+ let data = {
+ user_token: accessToken,
+ body: {
+ agents: [this.exAccountId],
+ attributes: [{
+ key: this.exAccountAtrKey,
+ values: [this.exAccountAtrValue]
+ }]
+ }
+ }
+
+ let acSelAtrs = []
+ this.accSelectedAttributes.forEach(atr => {
+ if (atr.key != this.exAccountAtrKey) {
+ acSelAtrs.push(atr)
+ }
+ })
+ this.accSelectedAttributes = acSelAtrs
+ await this.$store.dispatch('agent/deleteAttributeFromAgent', data)
+ this.exAccountAtrKey = null
+ this.exAccountAtrValue = null
+ },
+ async changeAccountStatus() {
+ let accessToken = await this.$store.getters['identity/getAccessToken']
+ let data = {
+ user_token: accessToken,
+ agent_id: this.exAccountId
+ }
+ if (this.selectedStatus == 'ACTIVE') {
+ await this.$store.dispatch('agent/activateAgent', data)
+ } else {
+ await this.$store.dispatch('agent/deactivateAgent', data)
+ }
+ }
+
+ },
+
+ async mounted() {
+ this.custosId = config.value('clientId')
+ this.custosSec = config.value('clientSec')
+ this.isAdminUser = await this.$store.dispatch('identity/isLoggedUserHasAdminAccess')
+
+ let accessToken = await this.$store.getters['identity/getAccessToken']
+ let data = {
+ user_token: accessToken
+ }
+ this.loadingAgents = true
+ await this.enableAgents()
+ this.communityAccounts = await this.$store.dispatch('agent/get_all_agents', data)
+ this.loadingAgents = false
+ }
+ }
+</script>
+
+<style scoped>
+ .enableComAcc {
+ width: 70%;
+ }
+
+ .addAccItem {
+ margin-left: 70%;
+ }
+
+ .accounttable {
+ width: 30%;
+ margin-left: 30%;
+ margin-top: 3%;
+ }
+</style>
\ No newline at end of file
diff --git a/custos-demo-gateway/src/components/workspace/Groups.vue b/custos-demo-gateway/src/components/workspace/Groups.vue
new file mode 100644
index 0000000..2cce24f
--- /dev/null
+++ b/custos-demo-gateway/src/components/workspace/Groups.vue
@@ -0,0 +1,653 @@
+<template>
+ <div>
+ <div class="grouptable">
+ <div v-if="this.groupsLoading" class="d-flex justify-content-center mb-3">
+ <b-spinner variant="primary" label="Text Centered"></b-spinner>
+ </div>
+ <b-table striped hover responsive :items="groupItems" :fields="fields" selectable
+ ref="selectableTable"
+ select-mode="single"
+ @row-selected="onRowSelected" caption-top>
+ <template v-slot:table-caption>Groups</template>
+ </b-table>
+ <div class="addGr">
+ <b-button variant="outline-primary" v-on:click="addGr">Add Group</b-button>
+ </div>
+ </div>
+
+ <div>
+ <b-modal ref="groupmodel" scrollable title="Group Profile" ok-title="Update">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Id</p>
+ <b-form-input v-model="selectedId" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Name</p>
+ <b-form-input v-model="selectedName" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Description</p>
+ <b-form-input v-model="selectedDescription"></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>OwnerId</p>
+ <b-form-input v-model="selectedOwnerId" disabled></b-form-input>
+ </div>
+ <div v-if="!this.operationCompleted" class="d-flex justify-content-center mb-3">
+ <b-spinner variant="primary" label="Text Centered"></b-spinner>
+ </div>
+ <div class="groupformItem">
+ <p>Members</p>
+ <b-table striped hover responsive :items="members" selectable select-mode="single"
+ @row-selected="onMemberShipSelected">
+ </b-table>
+ </div>
+
+ <div class="w-100">
+ <b-button class="addmemberbtn" variant="outline-primary" v-on:click="addMemberShip">Add Member
+ </b-button>
+ </div>
+ <div class="groupformItem">
+ <p>Child Groups</p>
+ <b-table striped hover responsive :items="childGroupMembers" :fields="memberGroupsFields"
+ selectable select-mode="single"
+ @row-selected="onGroupMemberShipSelected">
+ </b-table>
+ </div>
+ <div class="w-100">
+ <b-button class="addmemberbtn" variant="outline-primary" v-on:click="addChildGroup">Add Child
+ Group
+ </b-button>
+ </div>
+
+ </div>
+ <template v-slot:modal-footer>
+ <div class="w-100">
+ <b-button
+ variant="primary"
+ size="sm"
+ class="grBtnDel"
+ v-on:click="removeGroupProfile"
+ @click="show=false"
+ >
+ Delete
+ </b-button>
+ <b-button
+ variant="primary"
+ size="sm"
+ class="grBtnCl"
+ v-on:click="closeGroupProfile"
+ @click="show=false"
+
+ >
+ Close
+ </b-button>
+ <b-button
+ variant="primary"
+ size="sm"
+ class="grBtnUp"
+ v-on:click="updateGroupProfile"
+ @click="show=false"
+
+ >
+ Update
+ </b-button>
+ </div>
+ </template>
+ </b-modal>
+ </div>
+ <div>
+ <div>
+ <b-modal ref="membershipModel" title="Update Membership" ok-title="Update">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Owner Id</p>
+ <b-form-input v-model="selectedMembershipUsername" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Type</p>
+ <b-form-select v-model="selectedMembershipType">
+ <option v-for="(selectOption, indexOpt) in memberTypes"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+
+ </div>
+ <template v-slot:modal-footer>
+ <div class="w-100">
+ <b-button
+ variant="primary"
+ size="sm"
+ class="memBtnDel"
+ v-on:click="removeMembership"
+ @click="show=false"
+ >
+ Remove Membership
+ </b-button>
+ <b-button
+ variant="primary"
+ size="sm"
+ class="memBtnCl"
+ v-on:click="closeMembershipModel"
+ @click="show=false"
+
+ >
+ Close
+ </b-button>
+ <b-button
+ variant="primary"
+ size="sm"
+ class="memBtnUp"
+ v-on:click="updateMembership"
+ @click="show=false"
+
+ >
+ Update
+ </b-button>
+ </div>
+ </template>
+ </b-modal>
+ </div>
+ <div>
+ <b-modal ref="addMembershipModel" title="Add Membership" ok-title="Add" @ok="addMembershipOKPressed">
+ <div class="groupform">
+ <div v-if="selectedChildType==='User'" class="groupformItem">
+ <p>Username</p>
+ <b-form-select v-model="selectedNewUsername">
+ <option v-for="(selectOption, indexOpt) in usernames"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+ <div v-if="selectedChildType==='User'" class="groupformItem">
+ <p>Type</p>
+ <b-form-select v-model="selectedNewMemType">
+ <option v-for="(selectOption, indexOpt) in memberTypes"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+
+ </div>
+ </b-modal>
+ </div>
+ <div>
+ <b-modal ref="addGrModel" title="Add Group" ok-title="Add" @ok="addGroupOKPressed">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Name</p>
+ <b-form-input v-model="selectedNewGrName"></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Description</p>
+ <b-form-input v-model="selectedNewGrDesc"></b-form-input>
+ </div>
+
+ </div>
+ </b-modal>
+ <b-modal ref="viewGrMembership" title="Group" cancel-title="Delete" @cancel="removeGroupMembership">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Name</p>
+ <b-form-input v-model="selectedGrName"></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Id</p>
+ <b-form-input v-model="selectedGrId"></b-form-input>
+ </div>
+
+ </div>
+ </b-modal>
+ <b-modal ref="addGrMembershipModel" title="Add Group Membership" ok-title="Add"
+ @ok="addChildGroupOkPressed">
+ <div class="groupform">
+ <p>Select Group Id</p>
+ <b-form-select v-model="addingGr">
+ <option v-for="(selectOption, indexOpt) in feasibleGroupMembers"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption.id }}
+ </option>
+ </b-form-select>
+ </div>
+ </b-modal>
+ </div>
+ </div>
+ </div>
+
+</template>
+
+<script>
+
+ import config from "@/config";
+
+ export default {
+ name: "Groups",
+ data: function () {
+ return {
+ fields: ['id', 'name', 'description', 'ownerId'],
+ groupItems: [],
+ members: [],
+ childGroupMembers: [],
+ feasibleGroupMembers: [],
+ usernames: [],
+ exGroups: [
+ '1234-edrfg-567-rfgbn', '1234-ed-5634-rfn'
+ ],
+ memberTypes: [
+ 'ADMIN', 'MEMBER'],
+ memberGroupsFields: ['id', 'name'],
+ selectedId: null,
+ selectedName: null,
+ selectedDescription: null,
+ selectedOwnerId: null,
+ selectedMembershipItem: null,
+ selectedMembershipUsername: null,
+ selectedMembershipType: null,
+ selectedNewMemType: 'Member',
+ selectedNewUsername: null,
+ selectedNewGrName: null,
+ selectedNewGrDesc: null,
+ selectedChildType: 'User',
+ selectedExGr: null,
+ selectedGrName: null,
+ selectedGrId: null,
+ selectedGr: null,
+ addingGr: null,
+ groupsLoading: false,
+ operationCompleted: true,
+
+ }
+ },
+ methods: {
+ async onRowSelected(items) {
+ if (items != null && items.length > 0) {
+ this.selectedItem = items
+ this.selectedId = this.selectedItem[0].id
+ this.selectedName = this.selectedItem[0].name
+ this.selectedDescription = this.selectedItem[0].description
+ this.selectedOwnerId = this.selectedItem[0].ownerId
+
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ group_id: this.selectedId
+ }
+
+ let users = await this.$store.dispatch('group/getAllChildUsers', data)
+
+ this.members = []
+ users.profiles.forEach(user => {
+
+ let usr = {user_id: user.username, type: user.membership_type}
+ this.members.push(usr)
+ })
+
+ let response = await this.$store.dispatch('group/getAllChildGroups', data)
+ this.childGroupMembers = response.groups
+
+ this.$refs.groupmodel.show()
+ }
+ },
+ onMemberShipSelected: function (items) {
+ this.selectedMembershipItem = items
+
+ this.selectedMembershipUsername = this.selectedMembershipItem[0].user_id
+ this.selectedMembershipType = this.selectedMembershipItem[0].type
+ if (this.selectedMembershipType !== 'OWNER') {
+ this.$refs.membershipModel.show()
+ }
+ },
+
+ onGroupMemberShipSelected: function (items) {
+ if (items != null && items.length > 0) {
+ this.selectedGr = items
+ this.selectedGrId = this.selectedGr[0].id
+ this.selectedGrName = this.selectedGr[0].name
+ this.$refs.viewGrMembership.show()
+ }
+ },
+
+ addChildGroup: function () {
+ let grs = []
+ this.groupItems.forEach(gr => {
+ let addToGroup = true
+ this.childGroupMembers.forEach(lx => {
+ if (gr.id === lx.id) {
+ addToGroup = false
+ }
+ })
+ if (gr.id === this.selectedId) {
+ addToGroup = false
+ }
+ if (addToGroup) {
+ grs.push(gr)
+ }
+ })
+ this.feasibleGroupMembers = grs
+ this.$refs.addGrMembershipModel.show()
+ },
+
+ async addChildGroupOkPressed() {
+ this.operationCompleted = false
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ child_id: this.addingGr.id,
+ parent_id: this.selectedId
+ }
+ }
+
+ let status = await this.$store.dispatch('group/addChildGroup', data)
+ if (status) {
+ this.childGroupMembers.push(this.addingGr)
+ }
+ this.operationCompleted = true
+ },
+
+ async addMemberShip() {
+ let users = []
+ this.usernames.forEach(user => {
+ if (user != this.selectedOwnerId) {
+ let add = true
+ this.members.forEach(mem => {
+ if (mem.user_id === user) {
+ add = false
+ }
+ })
+ if (add) {
+ users.push(user)
+ }
+ }
+ })
+ this.usernames = users
+ this.$refs.addMembershipModel.show()
+ },
+
+ addGr: function () {
+ this.$refs.addGrModel.show()
+ },
+
+ async addGroupOKPressed() {
+ this.groupsLoading = true
+ let username = await this.$store.dispatch('identity/getCurrentUserName')
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ groups: [{
+ name: this.selectedNewGrName,
+ description: this.selectedNewGrDesc,
+ ownerId: username,
+ realm_roles: [],
+ client_roles: [],
+ attributes: [],
+ sub_groups: []
+ }]
+ }
+ }
+ await this.$store.dispatch('group/createGroup', data)
+ this.groupItems = await this.$store.dispatch('group/loadAllGroups', data)
+ this.groupsLoading = false
+ this.this.selectedNewGrName = null
+ this.selectedNewGrDesc = null
+ },
+
+ async loadUsers() {
+ let data = {offset: 0, limit: 50, client_id: this.custosId, client_sec: this.custosSec}
+ await this.$store.dispatch('user/users', data)
+ let resp = await this.$store.getters['user/getUsers']
+ this.usernames = []
+ if (Array.isArray(resp) && resp.length > 0) {
+ resp.forEach(obj => {
+ this.usernames.push(obj.username)
+ });
+
+ }
+ },
+
+ async addMembershipOKPressed() {
+ this.operationCompleted = false
+ let data = {
+ client_id: this.custosId, client_sec: this.custosSec, body: {
+ group_id: this.selectedId,
+ username: this.selectedNewUsername,
+ membership_type: this.selectedNewMemType
+ }
+ }
+ let response = await this.$store.dispatch('group/addUserToGroup', data)
+
+ if (response.status) {
+ let obj = {user_id: this.selectedNewUsername, type: this.selectedNewMemType}
+ this.members.push(obj)
+ }
+ this.operationCompleted = true
+ },
+
+ async updateMembership() {
+ this.operationCompleted = false
+ let data = {
+ client_id: this.custosId, client_sec: this.custosSec, body: {
+ group_id: this.selectedId,
+ username: this.selectedMembershipUsername,
+ type: this.selectedMembershipType
+ }
+ }
+ let response = await this.$store.dispatch('group/changeGroupMembership', data)
+
+ if (response.status) {
+ let obj = {user_id: this.selectedMembershipUsername, type: this.selectedMembershipType}
+ let newMems = []
+ this.members.forEach(mem => {
+ if (mem.user_id !== this.selectedMembershipUsername) {
+ newMems.push(mem)
+ }
+ })
+
+ newMems.push(obj)
+ this.members = newMems
+ }
+ this.operationCompleted = true
+ this.$refs.membershipModel.hide()
+ },
+
+ async removeMembership() {
+ this.operationCompleted = false
+ let data = {
+ client_id: this.custosId, client_sec: this.custosSec, body: {
+ group_id: this.selectedId,
+ username: this.selectedMembershipUsername
+ }
+ }
+ let response = await this.$store.dispatch('group/removeUserFromGroup', data)
+
+ if (response.status) {
+ let newMems = []
+ this.members.forEach(mem => {
+ if (mem.user_id !== this.selectedMembershipUsername) {
+ newMems.push(mem)
+ }
+ })
+ this.members = newMems
+ }
+ this.operationCompleted = true
+ this.$refs.membershipModel.hide()
+ },
+
+
+ async updateGroupProfile() {
+ this.operationCompleted = false
+ let data = {
+ client_id: this.custosId, client_sec: this.custosSec, group_id: this.selectedId, body: {
+ group: {
+ name: this.selectedName,
+ ownerId: this.selectedOwnerId,
+ description: this.selectedDescription,
+ realm_roles: [],
+ client_roles: [],
+ attributes: [],
+ sub_groups: []
+ }
+ }
+ }
+ await this.$store.dispatch('group/updateGroup', data)
+ this.$refs.groupmodel.hide()
+ let dat = {
+ client_id: this.custosId,
+ client_sec: this.custosSec
+ }
+ this.groupItems = await this.$store.dispatch('group/loadAllGroups', dat)
+ this.operationCompleted = true
+ },
+
+
+ async removeGroupProfile() {
+ this.operationCompleted = false
+ let data = {
+ client_id: this.custosId, client_sec: this.custosSec, group_id: this.selectedId, body: {
+ group: {
+ name: this.selectedName,
+ ownerId: this.selectedOwnerId,
+ description: this.selectedDescription,
+ realm_roles: [],
+ client_roles: [],
+ attributes: [],
+ sub_groups: []
+ }
+ }
+ }
+ await this.$store.dispatch('group/deleteGroup', data)
+ this.$refs.groupmodel.hide()
+ let dat = {
+ client_id: this.custosId,
+ client_sec: this.custosSec
+ }
+ this.groupItems = await this.$store.dispatch('group/loadAllGroups', dat)
+ this.operationCompleted = true
+ },
+
+
+ async closeGroupProfile() {
+ this.$refs.groupmodel.hide()
+ },
+
+ async closeMembershipModel() {
+ this.$refs.membershipModel.hide()
+ },
+
+ async removeGroupMembership() {
+ this.operationCompleted = false
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ child_id: this.selectedGrId,
+ parent_id: this.selectedId
+ }
+ }
+
+ let status = await this.$store.dispatch('group/removeChildGroup', data)
+ if (status) {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ group_id: this.selectedId
+ }
+
+ let response = await this.$store.dispatch('group/getAllChildGroups', data)
+ this.childGroupMembers = response.groups
+ }
+ this.operationCompleted = true
+ }
+
+ },
+ async mounted() {
+ this.groupsLoading = true
+ this.custosId = config.value('clientId')
+ this.custosSec = config.value('clientSec')
+ this.isAdminUser = await this.$store.dispatch('identity/isLoggedUserHasAdminAccess')
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec
+ }
+ this.groupItems = await this.$store.dispatch('group/loadAllGroups', data)
+ this.groupsLoading = false
+ this.loadUsers()
+ }
+ }
+</script>
+
+<style scoped>
+ .grouptable {
+ width: 50%;
+ margin-left: 10%;
+ margin-top: 3%;
+ }
+
+ .groupformItem {
+ margin-top: 3%;
+ }
+
+ .grBtnDel {
+ margin-left: 30%;
+ position: relative;
+ background-color: red;
+ }
+
+ .grBtnCl {
+ margin-left: 10%;
+ position: relative;
+ background-color: darkgrey;
+ }
+
+ .grBtnUp {
+ margin-left: 10%;
+ position: relative;
+ }
+
+ .addmemberbtn {
+ position: relative;
+ margin-left: 50%;
+ }
+
+ .removememberbtn {
+ position: relative;
+ margin-left: 20%;
+
+ }
+
+ .memBtnDel {
+ margin-left: 10%;
+ position: relative;
+ background-color: red;
+ }
+
+ .memBtnCl {
+ margin-left: 10%;
+ position: relative;
+ background-color: darkgrey;
+ }
+
+ .memBtnUp {
+ margin-left: 10%;
+ position: relative;
+ }
+
+ .addGr {
+ margin-right: 0;
+ position: relative;
+ }
+</style>
\ No newline at end of file
diff --git a/custos-demo-gateway/src/components/workspace/Logs.vue b/custos-demo-gateway/src/components/workspace/Logs.vue
new file mode 100644
index 0000000..fb1fae8
--- /dev/null
+++ b/custos-demo-gateway/src/components/workspace/Logs.vue
@@ -0,0 +1,223 @@
+<template>
+ <div>
+ <div v-if="activateLogEnabling">
+ <b-form-checkbox v-model="checked" :disabled=isCheckedBtnDisabled v-on:change="enableLogging"
+ name="check-button" switch>
+ Enable Logging
+ </b-form-checkbox>
+ </div>
+ <div v-if="isLoggingEnabled">
+ <div class="logSearchBar">
+ <b-input-group>
+ <template v-slot:prepend>
+ <b-form-input disabled v-model="defaultSearchText">Search By</b-form-input>
+ <b-dropdown :text="selectedService" variant="info" v-model="selectedService">
+ <b-dropdown-item v-for="option in options"
+ :key="option.value"
+ :value="option.value"
+ @click=searchLogsWithFilter(option)>
+ {{option.text}}
+ </b-dropdown-item>
+
+ </b-dropdown>
+
+ </template>
+ </b-input-group>
+ </div>
+
+ <div class="grouptable">
+ <b-table striped hover responsive :items="logItems" :fields="fields" selectable
+ ref="selectableTable"
+ select-mode="single"
+ :per-page="perPage"
+ :current-page="currentPage"
+ caption-top>
+ <template v-slot:table-caption>Access Logs</template>
+ </b-table>
+ <div class="pgClass">
+ <b-pagination
+ v-model="currentPage"
+ :total-rows="rows"
+ :per-page="perPage"
+ aria-controls="my-table"
+
+ ></b-pagination>
+ </div>
+ </div>
+ </div>
+
+ </div>
+</template>
+
+<script>
+ import config from "@/config";
+
+ export default {
+ name: "Logs",
+ data: function () {
+ return {
+ defaultSearchText: 'Search By',
+ fields: ['service_name', 'event_type', 'accessed_time', 'external_ip'],
+ logItems: [],
+ options: [
+ {
+ value: 0,
+ text: "UserManagementService",
+ service_name: "org.apache.custos.user.management.service.UserManagementService"
+ },
+ {
+ value: 1,
+ text: "TenantManagementService",
+ service_name: "org.apache.custos.tenant.management.service.TenantManagementService"
+ },
+ {
+ value: 2,
+ text: "SharingManagementService",
+ service_name: "org.apache.custos.sharing.management.service.SharingManagementService"
+ },
+ {
+ value: 3,
+ text: "ResourceSecretManagementService",
+ service_name: "org.apache.custos.resource.secret.management.service.ResourceSecretManagementService"
+ },
+ {
+ value: 4,
+ text: "IdentityManagementService",
+ service_name: "org.apache.custos.identity.management.service.IdentityManagementService"
+ },
+ {
+ value: 5,
+ text: "GroupManagementService",
+ service_name: "org.apache.custos.group.management.service.GroupManagementService"
+ },
+ {
+ value: 6,
+ text: "AgentManagementService",
+ service_name: "org.apache.custos.agent.management.service.AgentManagementService"
+ },
+ {
+ value: 7,
+ text: "All"
+ }
+ ],
+ perPage: 10,
+ currentPage: 0,
+ selectedService: null,
+ custosSec: null,
+ custosId: null,
+ isLoggingEnabled: false,
+ activateLogEnabling: false,
+ checked: false,
+ isCheckedBtnDisabled: false
+ }
+ },
+
+ methods: {
+ async searchLogsWithFilter(data) {
+ this.selectedService = data.text
+ let dat = {}
+ if (data.text === "All") {
+ dat = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ params: {
+ offset: 0,
+ limit: 200,
+ }
+ }
+ } else {
+ dat = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ params: {
+ offset: 0,
+ limit: 200,
+ service_name: data.service_name
+ }
+ }
+ }
+ let response = await this.$store.dispatch('log/getLogEvents', dat)
+
+ response.forEach(res => {
+ let date = new Date(res.created_time * 1000)
+ res.accessed_time = date.toString()
+ })
+ this.logItems = response
+
+
+ },
+
+
+ async enableLogging() {
+ let accessToken = await this.$store.getters['identity/getAccessToken']
+ let data = {
+ user_token: accessToken
+ }
+
+ let response = await this.$store.dispatch('log/enableLogging', data)
+ if (response) {
+ this.checked = true
+ this.isCheckedBtnDisabled = true
+ this.isLoggingEnabled = true
+ }
+ }
+ },
+ computed: {
+ rows() {
+ return this.logItems.length
+ }
+ },
+
+ async mounted() {
+ this.custosId = config.value('clientId')
+ this.custosSec = config.value('clientSec')
+ this.isAdminUser = await this.$store.dispatch('identity/isLoggedUserHasAdminAccess')
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec
+ }
+
+ this.isLoggingEnabled = await this.$store.dispatch('log/isLoggingEnabled', data)
+ this.activateLogEnabling = this.isAdminUser && !this.isLoggingEnabled
+ this.isCheckedBtnDisabled = this.isLoggingEnabled
+ this.checked = this.isLoggingEnabled
+
+ if (this.isLoggingEnabled) {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ params: {
+ offset: 0,
+ limit: 200
+ }
+ }
+ let response = await this.$store.dispatch('log/getLogEvents', data)
+
+ response.forEach(res => {
+ let date = new Date(res.created_time * 1000)
+ res.accessed_time = date.toString()
+ })
+ this.logItems = response
+
+ }
+
+ }
+ }
+</script>
+
+<style scoped>
+ .logSearchBar {
+ margin-left: 35%;
+ }
+
+ .grouptable {
+ width: 80%;
+ margin-left: 10%;
+ margin-top: 3%;
+ }
+
+ .pgClass {
+ margin-left: 70%;
+ }
+
+</style>
\ No newline at end of file
diff --git a/custos-demo-gateway/src/components/workspace/Secrets.vue b/custos-demo-gateway/src/components/workspace/Secrets.vue
new file mode 100644
index 0000000..f218663
--- /dev/null
+++ b/custos-demo-gateway/src/components/workspace/Secrets.vue
@@ -0,0 +1,355 @@
+<template>
+ <div>
+ <div class="secrettable">
+ <div v-if="this.secretsLoading" class="d-flex justify-content-center mb-3">
+ <b-spinner variant="primary" label="Text Centered"></b-spinner>
+ </div>
+ <b-table striped hover responsive :items="secItems" :fields="fields" selectable
+ select-mode="single"
+ @row-selected="onRowSelected" caption-top>
+ <template v-slot:table-caption>Secrets</template>
+ </b-table>
+ <div class="addSec">
+ <b-button variant="outline-primary" v-on:click="addSec">Add Secret</b-button>
+ </div>
+ </div>
+ <div>
+ <b-modal ref="addSecmodel" scrollable title="Add Secret" ok-title="Add" @ok="addSecOKButtonPressed">
+ <div class="secform">
+ <div class="secFormItem">
+ <p>Type</p>
+ <b-form-select v-model="defaultMemType">
+ <option v-for="(selectOption, indexOpt) in secretTypes"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+ <div class="secformItem">
+ <p>Description</p>
+ <b-form-input v-model="selectedDescription"></b-form-input>
+ </div>
+ <div v-if="defaultMemType==='Password'" class="secformItem">
+ <p>Password</p>
+ <b-form-input v-model="selectedPassword"></b-form-input>
+ </div>
+ </div>
+
+ </b-modal>
+ </div>
+ <div>
+ <b-modal ref="updateSecmodel" scrollable title="View Secret" cancel-title="Delete"
+ @cancel="secDeleteButtonPressed" cancel-variant="outline-primary">
+ <div class="secform">
+ <div class="secformItem">
+ <p>Token</p>
+ <b-form-input v-model="selectedExId" disabled></b-form-input>
+ </div>
+ <div class="secFormItem">
+ <p>Type</p>
+ <b-form-input v-model="selectedExType" disabled></b-form-input>
+ </div>
+ <div class="secformItem">
+ <p>Description</p>
+ <b-form-input v-model="selectedExDescription" disabled></b-form-input>
+ </div>
+ <div class="secformItem">
+ <p>Owner Id</p>
+ <b-form-input v-model="selectedExOwnerId" disabled></b-form-input>
+ </div>
+ <div v-if="selectedExType ==='PASSWORD'" class="secformItem">
+ <p>Password</p>
+ <b-form-input v-model="selectedExPassword" disabled></b-form-input>
+ </div>
+ <div v-if="selectedExType ==='SSH'" class="secformItem">
+ <p>Publick Key</p>
+ <b-textarea v-model="selectedExPubKey" disabled></b-textarea>
+ </div>
+ <div v-if="selectedExType ==='SSH'" class="secformItem">
+ <p>Private Key</p>
+ <b-textarea v-model="selectedExPrivKey" disabled></b-textarea>
+ </div>
+
+ </div>
+
+ </b-modal>
+ </div>
+ </div>
+</template>
+
+<script>
+ import config from "@/config";
+
+ export default {
+ name: "Secrets",
+ data: function () {
+ return {
+ fields: ['token', 'description', 'type', 'owner_id'],
+ secItems: [],
+ selectedSecret: null,
+ secretTypes: ['SSH', 'Password'],
+ defaultMemType: 'SSH',
+ selectedDescription: null,
+ selectedPassword: null,
+ selectedExType: null,
+ selectedExId: null,
+ selectedExDescription: null,
+ selectedExPassword: null,
+ selectedExPubKey: null,
+ selectedExPrivKey: null,
+ selectedExOwnerId: null,
+ currentUserName: null,
+ secretsLoading: false
+
+ }
+ },
+ methods: {
+ async onRowSelected(items) {
+ if (items != null && items.length > 0) {
+ this.selectedSecret = items
+
+ this.selectedExDescription = this.selectedSecret[0].description
+ this.selectedExType = this.selectedSecret[0].type
+ this.selectedExId = this.selectedSecret[0].token
+ this.selectedExOwnerId = this.selectedSecret[0].owner_id
+
+ if (this.selectedExType === "SSH") {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ token: this.selectedExId
+ }
+ let response = await this.$store.dispatch('secret/getSSHCredential', data)
+ this.selectedExPubKey = response.public_key
+ this.selectedExPrivKey = response.private_key
+ } else {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ token: this.selectedExId
+ }
+ let response = await this.$store.dispatch('secret/getPasswordCredential', data)
+ this.selectedExPassword = response.password
+ }
+ this.$refs.updateSecmodel.show()
+ }
+ },
+
+ addSec: function () {
+ this.selectedDescription = null
+ this.selectedPassword = null
+ this.defaultMemType = 'SSH'
+ this.$refs.addSecmodel.show()
+ },
+
+ async addSecOKButtonPressed() {
+ this.secretsLoading = true
+ if (this.defaultMemType === 'SSH') {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ metadata: {
+ client_id: this.custosId,
+ description: this.selectedDescription,
+ owner_id: this.currentUserName
+ }
+ }
+ }
+ let response = await this.$store.dispatch('secret/addSSHCredential', data)
+ let dataEn = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ entity: {
+ id: response.token,
+ name: 'SSH token',
+ description: 'SSH credential created for ' + this.selectedDescription,
+ type: 'SECRET',
+ owner_id: this.currentUserName
+ }
+ }
+ }
+
+ await this.$store.dispatch('sharing/createEntity', dataEn)
+
+ } else {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ metadata: {
+ client_id: this.custosId,
+ description: this.selectedDescription,
+ owner_id: this.currentUserName
+ },
+ password: this.selectedPassword
+ }
+ }
+ let response = await this.$store.dispatch('secret/addPasswordCredential', data)
+ let dataEN = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ entity: {
+ id: response.token,
+ name: 'Password token',
+ description: 'Password credential created for ' + this.selectedDescription,
+ type: 'SECRET',
+ owner_id: this.currentUserName
+ }
+ }
+ }
+ await this.$store.dispatch('sharing/createEntity', dataEN)
+ }
+ this.secItems = await this.getAllCredentials()
+ this.secretsLoading = false
+ },
+
+ async secDeleteButtonPressed() {
+ this.secretsLoading = true
+ if (this.defaultMemType === 'SSH') {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ token: this.selectedExId
+ }
+ let response = await this.$store.dispatch('secret/deleteSSHCredential', data)
+ if (response) {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ entity: {
+ id: this.selectedExId,
+ owner_id: this.currentUserName
+ }
+ }
+ }
+ await this.$store.dispatch('sharing/deleteEntity', data)
+ }
+
+ } else {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ token: this.selectedExId
+ }
+ let response = await this.$store.dispatch('secret/deletePassswordCredential', data)
+ if (response) {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ entity: {
+ id: this.selectedExId,
+ owner_id: this.currentUserName
+ }
+ }
+ }
+ await this.$store.dispatch('sharing/deleteEntity', data)
+ }
+
+ }
+ this.secItems = await this.getAllCredentials()
+ this.secretsLoading = false
+ this.secretsLoading = false
+ },
+
+
+ async getAllCredentials() {
+ let searchEntitiesData = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ owner_id: this.currentUserName,
+ search_criteria: [
+ {
+ search_field: "ENTITY_TYPE_ID",
+ value: 'SECRET',
+ condition: "EQUAL"
+ }
+ ]
+ }
+ }
+
+ let response = await this.$store.dispatch('sharing/getEntities', searchEntitiesData)
+ let accessible_token = []
+ if (response != null && response.length > 0) {
+ response.forEach(a => {
+ accessible_token.push(a.id)
+ })
+
+ }
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ accessible_tokens: accessible_token
+ }
+ return await this.$store.dispatch('secret/getAllCredentials', data)
+ }
+ },
+
+
+ async mounted() {
+ this.secretsLoading = true
+ this.custosId = config.value('clientId')
+ this.custosSec = config.value('clientSec')
+ this.currentUserName = await this.$store.dispatch('identity/getCurrentUserName')
+
+ this.secItems = await this.getAllCredentials()
+ this.secretsLoading = false
+
+ let permTypesData = {
+ client_id: this.custosId,
+ client_sec: this.custosSec
+ }
+
+ let entityTypes = await this.$store.dispatch('sharing/getEntityTypes', permTypesData)
+
+ let created = false
+
+ entityTypes.forEach(ent => {
+ if (ent.id === 'SECRET') {
+ created = true
+ }
+ })
+
+ if (!created) {
+ let dat = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ entity_type: {
+ id: 'SECRET',
+ name: 'SECRET',
+ description: 'This is secret entity type of demo gateway'
+ }
+ }
+ }
+ this.entityTypes = await this.$store.dispatch('sharing/createEntityType', dat)
+ }
+ }
+ }
+</script>
+
+<style scoped>
+ .secrettable {
+ width: 50%;
+ margin-left: 10%;
+ margin-top: 3%;
+ }
+
+ .secformItem {
+ margin-top: 3%;
+ }
+
+</style>
\ No newline at end of file
diff --git a/custos-demo-gateway/src/components/workspace/Sharing.vue b/custos-demo-gateway/src/components/workspace/Sharing.vue
new file mode 100644
index 0000000..4c383cf
--- /dev/null
+++ b/custos-demo-gateway/src/components/workspace/Sharing.vue
@@ -0,0 +1,892 @@
+<template>
+ <div>
+ <div class="row">
+ <div class="column">
+ <div class="sharingtable">
+ <div v-if="this.permissionTypesLoading" class="d-flex justify-content-center mb-3">
+ <b-spinner variant="primary" label="Text Centered"></b-spinner>
+ </div>
+ <b-table striped hover responsive :items="permissionTypes" :fields="fields" selectable
+ ref="selectableTable"
+ select-mode="single"
+ @row-selected="onPrTySelected" caption-top>
+ <template v-slot:table-caption>Permissions</template>
+ </b-table>
+ <div class="addGr">
+ <b-button variant="outline-primary" v-on:click="onNewPrTyAdd">Add Permission Type</b-button>
+ </div>
+ </div>
+ <div v-if="this.entityTypesLoading" class="d-flex justify-content-center mb-3">
+ <b-spinner variant="primary" label="Text Centered"></b-spinner>
+ </div>
+ <div class="sharingtable">
+ <b-table striped hover responsive :items="entityTypes" :fields="fields" selectable
+ ref="selectableTable"
+ select-mode="single"
+ @row-selected="onEnTySelected" caption-top>
+ <template v-slot:table-caption>Entity Types</template>
+ </b-table>
+ <div class="addGr">
+ <b-button variant="outline-primary" v-on:click="onNewEnTyAdd">Add Entity Type</b-button>
+ </div>
+ </div>
+ <div v-if="this.entitiesLoading" class="d-flex justify-content-center mb-3">
+ <b-spinner variant="primary" label="Text Centered"></b-spinner>
+ </div>
+ <div class="sharingtable">
+ <b-table striped hover responsive :items="entities" :fields="entityFields" selectable
+ ref="selectableTable"
+ select-mode="single"
+ @row-selected="onEntitySelected" caption-top>
+ <template v-slot:table-caption>Entities</template>
+ </b-table>
+ <div class="addGr">
+ <b-button variant="outline-primary" v-on:click="onNewEnAdd">Add Entity</b-button>
+ </div>
+ </div>
+ <div v-if="this.sharingsLoading" class="d-flex justify-content-center mb-3">
+ <b-spinner variant="primary" label="Text Centered"></b-spinner>
+ </div>
+ <div class="sharingtable">
+ <b-table striped hover responsive :items="sharings" :fields="sharingFields" selectable
+ ref="selectableTable"
+ select-mode="single"
+ @row-selected="onSharingSelected" caption-top>
+ <template v-slot:table-caption>Sharings</template>
+ </b-table>
+ <div class="addGr">
+ <b-button variant="outline-primary" v-on:click="onSharingAdd">Share Entities</b-button>
+ </div>
+ </div>
+ <div>
+ <b-modal ref="prtypemodel" scrollable title="Add Permission Type " ok-title="Add" @ok="addPrType">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Id</p>
+ <b-form-input v-model="prId"></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Name</p>
+ <b-form-input v-model="prName"></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Description</p>
+ <b-form-input v-model="prDesc"></b-form-input>
+ </div>
+
+ </div>
+ </b-modal>
+ </div>
+ <div>
+ <b-modal ref="entypemodel" scrollable title="Add Entity Type " ok-title="Add" @ok="addNewEnType">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Id</p>
+ <b-form-input v-model="enTyId"></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Name</p>
+ <b-form-input v-model="enTyName"></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Description</p>
+ <b-form-input v-model="enTyDesc"></b-form-input>
+ </div>
+
+ </div>
+ </b-modal>
+ </div>
+ <div>
+ <b-modal ref="enModel" scrollable title="Add Entity " ok-title="Add" @ok="addNewEntity">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Id</p>
+ <b-form-input v-model="enId"></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Name</p>
+ <b-form-input v-model="enName"></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Type</p>
+ <b-form-select v-model="selectedEntityType">
+ <option v-for="(selectOption, indexOpt) in entityTypes"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption.id }}
+ </option>
+ </b-form-select>
+ </div>
+ <div class="groupformItem">
+ <p>Description</p>
+ <b-form-input v-model="enDesc"></b-form-input>
+ </div>
+
+ </div>
+ </b-modal>
+ <b-modal ref="selectedPrTyModel" scrollable title="Permission Type " ok-title="Delete"
+ @ok="deletePRType">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Id</p>
+ <b-form-input v-model="selectedPrTyId" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Name</p>
+ <b-form-input v-model="selectedPrTyName" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Description</p>
+ <b-form-input v-model="selectedPrTyDesc" disabled></b-form-input>
+ </div>
+
+ </div>
+ </b-modal>
+ <b-modal ref="selectedEnTyModel" scrollable title="Entity Type " ok-title="Delete"
+ @ok="deleteEnType">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Id</p>
+ <b-form-input v-model="selectedEnTyId" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Name</p>
+ <b-form-input v-model="selectedEnTyName" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Description</p>
+ <b-form-input v-model="selectedEnTyDesc" disabled></b-form-input>
+ </div>
+
+ </div>
+ </b-modal>
+ <b-modal ref="selectedEnModel" scrollable title="Entity " ok-title="Delete" @ok="deleteEntity">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Id</p>
+ <b-form-input v-model="selectedEnId" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Name</p>
+ <b-form-input v-model="selectedEnName" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Type</p>
+ <b-form-input v-model="selectedEntityType" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Description</p>
+ <b-form-input v-model="selectedEnDesc" disabled></b-form-input>
+ </div>
+
+ </div>
+ </b-modal>
+ <b-modal ref="selectedShraingModel" scrollable title="Sharing " ok-title="Delete"
+ @ok="removeSharing">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Entity Id</p>
+ <b-form-input v-model="selectedShEnId" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Permission Type Id</p>
+ <b-form-input v-model="selectedShPrId" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Owner Id</p>
+ <b-form-input v-model="selectedShOwId" disabled></b-form-input>
+ </div>
+ <div class="groupformItem">
+ <p>Type</p>
+ <b-form-input v-model="selectedShOwType" disabled></b-form-input>
+ </div>
+
+ </div>
+ </b-modal>
+ </div>
+ <div>
+ <b-modal ref="sharingModel" scrollable title="Share Entities " ok-title="Add" @ok="addNewSharing">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Entity Id</p>
+ <b-form-select v-model="defaultEntityId">
+ <option v-for="(selectOption, indexOpt) in entities"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption.id }}
+ </option>
+ </b-form-select>
+ </div>
+ <div class="groupformItem">
+ <p>Permission Type</p>
+ <b-form-select v-model="defaultPermissionType">
+ <option v-for="(selectOption, indexOpt) in permissionTypes"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption.id }}
+ </option>
+ </b-form-select>
+ </div>
+
+ <div class="groupformItem">
+ <p>Sharing Type</p>
+ <b-form-select v-model="defaultSharingType">
+ <option v-for="(selectOption, indexOpt) in sharingTypeIds"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+ <div v-if="defaultSharingType == 'USERS'" class="groupformItem">
+ <p>User Id</p>
+ <b-form-select v-model="defaultOwner">
+ <option v-for="(selectOption, indexOpt) in users"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+
+ <div v-if="defaultSharingType == 'GROUPS'" class="groupformItem">
+ <p>Group Id</p>
+ <b-form-select v-model="defaultOwner">
+ <option v-for="(selectOption, indexOpt) in groups"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+ </div>
+ </b-modal>
+ </div>
+ </div>
+ <div class="column">
+ <div class="permissionChecker">
+ <div class="addGr">
+ <b-button variant="outline-primary" v-on:click="checkPermissions">Evaluate Permissions</b-button>
+ </div>
+ </div>
+ </div>
+ <b-modal ref="permissionChecker" scrollable title="Check Permissions" ok-title="Evaluate"
+ @ok="evaluatePermission">
+ <div class="groupform">
+ <div class="groupformItem">
+ <p>Entity Id</p>
+ <b-form-select v-model="defaultEntityId">
+ <option v-for="(selectOption, indexOpt) in entities"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption.id }}
+ </option>
+ </b-form-select>
+ </div>
+ <div class="groupformItem">
+ <p>User</p>
+ <b-form-select v-model="defaultOwner">
+ <option v-for="(selectOption, indexOpt) in users"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+ <div class="groupformItem">
+ <p>Permission</p>
+ <b-form-select v-model="defaultPermissionType">
+ <option v-for="(selectOption, indexOpt) in permissionTypes"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption.id }}
+ </option>
+ </b-form-select>
+ </div>
+
+ </div>
+ </b-modal>
+ <b-modal ref="evalutionResultPopup" hide-footer>
+ <div v-if="this.evaluating">
+ <b-button variant="primary" size="large" class="evaluater" disabled>
+ <b-spinner small type="grow"></b-spinner>
+ Evaluating...
+ </b-button>
+ </div>
+ <div v-if="!this.evaluating">
+ <div v-if="evalutionResult" class="groupform">
+ <p class="textCls"> Evalution Status: True </p>
+ <p>User has permission</p>
+
+ </div>
+ <div v-if="!evalutionResult" class="groupform">
+ <p class="textClsWrng"> Evalution Status: False </p>
+ <p>User does not have permission</p>
+
+ </div>
+ </div>
+ </b-modal>
+ </div>
+ </div>
+</template>
+
+<script>
+ import config from "@/config";
+
+ export default {
+ name: "Sharing",
+ data: function () {
+ return {
+ fields: ['id', 'name', 'description'],
+ sharingFields: ['entity_id', 'permission_type_id', 'owner_id', 'type'],
+ entityFields: ['id', 'name', 'type', 'description'],
+ permissionTypes: [],
+ entityTypes: [],
+ entities: [],
+
+ sharings: [],
+ users: [],
+ groups: [],
+ sharingTypeIds: ['USERS', 'GROUPS'],
+ prId: null,
+ prName: null,
+ prDesc: null,
+ enTyId: null,
+ enTyName: null,
+ enTyDesc: null,
+ enId: null,
+ enName: null,
+ enDesc: null,
+ defaultEntityId: null,
+ defaultPermissionType: null,
+ defaultOwner: null,
+ selectedPrTyId: null,
+ selectedPrTyName: null,
+ selectedPrTyDesc: null,
+ selectedEnTyId: null,
+ selectedEnTyName: null,
+ selectedEnTyDesc: null,
+ selectedEnId: null,
+ selectedEnName: null,
+ selectedEnDesc: null,
+ selectedPrType: null,
+ selectedEnType: null,
+ selectedEn: null,
+ selectedSh: null,
+ selectedShEnId: null,
+ selectedShPrId: null,
+ selectedShOwId: null,
+ currentUserName: null,
+ selectedEntityType: null,
+ defaultSharingType: null,
+ defaultGroup: null,
+ selectedShOwType: null,
+ evalutionResult: false,
+ permissionTypesLoading: false,
+ entityTypesLoading:false,
+ entitiesLoading:false,
+ sharingsLoading:false,
+ evaluating: false,
+
+
+ }
+ },
+
+ methods: {
+ async addPrType() {
+ this.permissionTypesLoading =true
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ permission_type: {
+ id: this.prId,
+ name: this.prName,
+ description: this.prDesc
+
+ }
+ }
+ }
+
+ this.permissionTypes = await this.$store.dispatch('sharing/createPermissionType', data)
+ this.permissionTypesLoading = false
+ this.prId = null
+ this.prName = null
+ this.prDesc = null
+
+ },
+
+ async deletePRType() {
+ this.permissionTypesLoading =true
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ permission_type: {
+ id: this.selectedPrTyId,
+ name: this.selectedPrTyName,
+ description: this.selectedPrTyDesc
+
+ }
+ }
+ }
+
+ this.permissionTypes = await this.$store.dispatch('sharing/deletePermissionType', data)
+ this.permissionTypesLoading = false
+ this.prId = null
+ this.prName = null
+ this.prDesc = null
+ },
+ async addNewEnType() {
+ this.entityTypesLoading = true
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ entity_type: {
+ id: this.enTyId,
+ name: this.enTyName,
+ description: this.enTyDesc
+ }
+ }
+ }
+
+ this.entityTypes = await this.$store.dispatch('sharing/createEntityType', data)
+ this.entityTypesLoading = false
+ this.enTyId = null
+ this.enTyName = null
+ this.enTyDesc = null
+
+ },
+
+ async deleteEnType() {
+ this.entityTypesLoading = true
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ entity_type: {
+ id: this.selectedEnTyId,
+ name: this.selectedEnTyName,
+ description: this.selectedEnTyDesc
+
+ }
+ }
+ }
+
+ this.entityTypes = await this.$store.dispatch('sharing/deleteEntityType', data)
+ this.entityTypesLoading = false
+ this.prId = null
+ this.prName = null
+ this.prDesc = null
+ },
+
+
+ async addNewEntity() {
+ this.entitiesLoading = true
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ entity: {
+ id: this.enId,
+ name: this.enName,
+ description: this.enDesc,
+ type: this.selectedEntityType.id,
+ owner_id: this.currentUserName
+ }
+ }
+ }
+
+ this.entities = await this.$store.dispatch('sharing/createEntity', data)
+ this.entitiesLoading = false
+ this.enId = null
+ this.enName = null
+ this.enDesc = null
+ this.selectedEntityType = null
+ this.sharings = await this.loadSharings()
+
+ },
+
+ async deleteEntity() {
+ this.entitiesLoading = true
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ entity: {
+ id: this.selectedEnId,
+ name: this.selectedEnName,
+ description: this.selectedEnDesc,
+ type: this.selectedEntityType.id,
+ owner_id: this.currentUserName
+ }
+ }
+ }
+
+ this.entities = await this.$store.dispatch('sharing/deleteEntity', data)
+ this.entitiesLoading = false
+ this.selectedEnId = null
+ this.selectedEnName = null
+ this.selectedEnDesc = null
+ this.selectedEntityType = null
+ this.sharings = await this.loadSharings()
+ },
+
+ async addNewSharing() {
+ this.sharingsLoading = true
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+
+ client_id: this.custosId,
+ entity: {
+ id: this.defaultEntityId.id
+ },
+ permission_type: {
+ id: this.defaultPermissionType.id
+ },
+ owner_id: [this.defaultOwner],
+ cascade: true
+
+ }
+ }
+
+ if (this.defaultSharingType === 'USERS') {
+ let response = await this.$store.dispatch('sharing/shareEntityWithUsers', data)
+
+ if (response) {
+ this.sharings = await this.loadSharings()
+ }
+ } else {
+ let response = await this.$store.dispatch('sharing/shareEntityWithGroups', data)
+ if (response) {
+ this.sharings = await this.loadSharings()
+ }
+ }
+ this.sharingsLoading = false
+ },
+
+ async removeSharing() {
+ this.sharingsLoading = true
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+
+ client_id: this.custosId,
+ entity: {
+ id: this.selectedShEnId
+ },
+ permission_type: {
+ id: this.selectedShPrId
+ },
+ owner_id: [this.selectedShOwId],
+ cascade: true
+
+ }
+ }
+
+ if (this.selectedShOwType === 'USER') {
+ let response = await this.$store.dispatch('sharing/revokeEntitySharingFromUsers', data)
+ if (response) {
+ this.sharings = await this.loadSharings()
+ }
+ } else {
+ let response = await this.$store.dispatch('sharing/revokeEntitySharingFromGroups', data)
+ if (response) {
+ this.sharings = await this.loadSharings()
+ }
+ }
+ this.sharingsLoading = false
+ },
+
+ onPrTySelected: function (items) {
+ if (items != null && items.length > 0) {
+ this.selectedPrType = items
+ this.selectedPrTyId = this.selectedPrType[0].id
+ this.selectedPrTyName = this.selectedPrType[0].name
+ this.selectedPrTyDesc = this.selectedPrType[0].description
+ if (this.selectedPrTyId != "OWNER") {
+ this.$refs.selectedPrTyModel.show()
+ }
+ }
+ },
+
+ onEnTySelected: function (items) {
+ if (items != null && items.length > 0) {
+ this.selectedEnType = items
+ this.selectedEnTyId = this.selectedEnType[0].id
+ this.selectedEnTyName = this.selectedEnType[0].name
+ this.selectedEnTyDesc = this.selectedEnType[0].description
+ this.$refs.selectedEnTyModel.show()
+ }
+ },
+
+ onEntitySelected: function (items) {
+ if (items != null && items.length > 0) {
+ this.selectedEn = items
+ this.selectedEnId = this.selectedEn[0].id
+ this.selectedEnName = this.selectedEn[0].name
+ this.selectedEnDesc = this.selectedEn[0].description
+ this.selectedEntityType = this.selectedEn[0].type
+ this.$refs.selectedEnModel.show()
+ }
+ },
+
+ onSharingSelected: function (items) {
+ if (items != null && items.length > 0) {
+ this.selectedSh = items
+ this.selectedShEnId = this.selectedSh[0].entity_id
+ this.selectedShPrId = this.selectedSh[0].permission_type_id
+ this.selectedShOwId = this.selectedSh[0].owner_id
+ this.selectedShOwType = this.selectedSh[0].type
+ this.$refs.selectedShraingModel.show()
+ }
+ },
+ onNewPrTyAdd: function () {
+ this.$refs.prtypemodel.show()
+ },
+ onNewEnTyAdd: function () {
+ this.$refs.entypemodel.show()
+ },
+ onNewEnAdd: function () {
+ this.$refs.enModel.show()
+ },
+ onSharingAdd: function () {
+ this.$refs.sharingModel.show()
+ },
+
+ checkPermissions: function () {
+ this.$refs.permissionChecker.show()
+ },
+
+ async loadUsers() {
+ let data = {offset: 0, limit: 50, client_id: this.custosId, client_sec: this.custosSec}
+ let response = await this.$store.dispatch('user/users', data)
+
+ let usrs = [];
+ if (Array.isArray(response) && response.length > 0) {
+ response.forEach(obj => {
+ usrs.push(obj.username)
+ })
+ }
+ return usrs
+ },
+
+ async loadGroups() {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec
+ }
+ let response = await this.$store.dispatch('group/loadAllGroups', data)
+
+ let grs = [];
+ if (Array.isArray(response) && response.length > 0) {
+ response.forEach(obj => {
+ grs.push(obj.id)
+ })
+ }
+ return grs
+ },
+
+
+ async evaluatePermission() {
+ this.evaluating = true
+ this.$refs.evalutionResultPopup.show()
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ params: {
+ client_id: this.custosId,
+ 'entity.id': this.defaultEntityId.id,
+ 'permission_type.id': this.defaultPermissionType.id,
+ owner_id: this.defaultOwner
+ }
+ }
+ let response = await this.$store.dispatch('sharing/userHasAccess', data)
+ this.evalutionResult = response
+ this.evaluating = false
+
+ },
+
+ async loadSharings() {
+ let shars = []
+ for (const en of this.entities) {
+ for (const pr of this.permissionTypes) {
+ let pars = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ params: {
+ 'entity.id': en.id,
+ 'permission_type.id': pr.id
+ }
+ }
+ let userIds = await this.$store.dispatch('sharing/getListOfSharedUsers', pars)
+
+ if (userIds != null && userIds.length > 0) {
+ userIds.forEach(uId => {
+ let shItem = {
+ entity_id: en.id,
+ permission_type_id: pr.id,
+ owner_id: uId,
+ type: 'USER'
+ }
+ shars.push(shItem)
+ })
+ }
+
+ let groupIds = await this.$store.dispatch('sharing/getListOfSharedGroups', pars)
+
+ if (groupIds != null && groupIds.length > 0) {
+ groupIds.forEach(uId => {
+ let shItem = {
+ entity_id: en.id,
+ permission_type_id: pr.id,
+ owner_id: uId,
+ type: 'GROUP'
+ }
+ shars.push(shItem)
+ })
+ }
+ }
+ }
+ return shars
+ }
+ },
+
+ async mounted() {
+ this.custosId = config.value('clientId')
+ this.custosSec = config.value('clientSec')
+ this.isAdminUser = await this.$store.dispatch('identity/isLoggedUserHasAdminAccess')
+ this.currentUserName = await this.$store.dispatch('identity/getCurrentUserName')
+
+
+ let permTypesData = {
+ client_id: this.custosId,
+ client_sec: this.custosSec
+ }
+
+ this.permissionTypes = await this.$store.dispatch('sharing/getPermissionTypes', permTypesData)
+
+ if (this.permissionTypes.length == 0) {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ permission_type: {
+ id: "OWNER",
+ name: "Owner",
+ description: "This is owner permission type"
+ }
+ }
+ }
+
+ this.permissionTypes = await this.$store.dispatch('sharing/createPermissionType', data)
+ }
+
+
+ this.entityTypes = await this.$store.dispatch('sharing/getEntityTypes', permTypesData)
+
+ let searchEntitiesData = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ client_id: this.custosId,
+ owner_id: this.currentUserName,
+ search_criteria: [
+ {
+ search_field: "OWNER_ID",
+ value: this.currentUserName,
+ condition: "EQUAL"
+ }
+ ]
+ }
+ }
+
+ this.entities = await this.$store.dispatch('sharing/getEntities', searchEntitiesData)
+
+ this.sharings = await this.loadSharings()
+
+ this.users = await this.loadUsers()
+ this.groups = await this.loadGroups()
+
+ }
+ }
+
+
+</script>
+
+<style scoped>
+ .sharingtable {
+ margin-left: 20%;
+ width: 100%;
+ }
+
+ .addGr {
+ margin-left: 60%;
+ }
+
+ .column {
+ float: left;
+ width: 50%;
+ padding: 10px;
+ height: 300px; /* Should be removed. Only for demonstration */
+ }
+
+ /* Clear floats after the columns */
+ .row:after {
+ content: "";
+ display: table;
+ clear: both;
+ }
+
+ .permissionChecker {
+ width: 60%;
+ position: relative;
+ margin-left: 10%;
+ margin-top: 10%;
+ }
+
+ .groupformItem {
+ margin-top: 3%;
+ }
+
+ .textCls {
+ color: blue;
+ font-family: Arial;
+ font-size: x-large;
+ margin-left: 10%;
+ }
+
+ .textClsWrng {
+ color: red;
+ font-family: Arial;
+ font-size: x-large;
+ margin-left: 10%;
+ }
+
+ .evaluater {
+ margin-left: 40%;
+ color: #42b983;
+ }
+
+
+</style>
\ No newline at end of file
diff --git a/custos-demo-gateway/src/components/workspace/Users.vue b/custos-demo-gateway/src/components/workspace/Users.vue
new file mode 100644
index 0000000..1f6c63d
--- /dev/null
+++ b/custos-demo-gateway/src/components/workspace/Users.vue
@@ -0,0 +1,609 @@
+<template>
+ <div>
+ <div class="userSearchBar">
+ <b-input-group prepend="Username" class="mt-3">
+ <b-form-input v-model="searchUsername"></b-form-input>
+ <b-input-group-append>
+ <b-button variant="outline-success" v-on:click="this.searchResult">
+ <div v-if="!this.searchUsers">
+ <b-spinner small></b-spinner>
+ </div>
+ Search
+ </b-button>
+ </b-input-group-append>
+ </b-input-group>
+ </div>
+ <div v-if="this.userloading" class="d-flex justify-content-center mb-3">
+ <b-spinner variant="primary" label="Text Centered"></b-spinner>
+ </div>
+ <div class="usertable">
+ <b-table striped hover responsive :items="items" :fields="fields" selectable
+ ref="selectableTable"
+ select-mode="single"
+ :per-page="perPage"
+ :current-page="currentPage"
+ @row-selected="onRowSelected" caption-top>
+ <template v-slot:table-caption>Users</template>
+ </b-table>
+ <div class="pgClass">
+ <b-pagination
+ v-model="currentPage"
+ :total-rows="rows"
+ :per-page="perPage"
+ aria-controls="my-table"
+
+ ></b-pagination>
+ </div>
+ </div>
+
+ <div>
+ <b-modal ref="usermodel" scrollable title="User Profile" ok-title="Update" @ok="this.updateUserProfile">
+ <div class="userform">
+ <div class="userformItem">
+ <p>Username</p>
+ <b-form-input v-model="selectedUsername" disabled></b-form-input>
+ </div>
+ <div class="userformItem">
+ <p>First Name</p>
+ <b-form-input v-model="selectedFirstName"></b-form-input>
+ </div>
+ <div class="userformItem">
+ <p>Last Name</p>
+ <b-form-input v-model="selectedLastName"></b-form-input>
+ </div>
+ <div class="userformItem">
+ <p>Email</p>
+ <b-form-input v-model="selectedEmail"></b-form-input>
+ </div>
+ <div class="userformItem">
+ <p>Status</p>
+ <b-form-select v-model="selectedStatus">
+ <option v-for="(selectOption, indexOpt) in statusOptions"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+ <div v-if="!this.operationCompleted" class="d-flex justify-content-center mb-3">
+ <b-spinner variant="primary" label="Text Centered"></b-spinner>
+ </div>
+ <div class="userformItem">
+ <p>Attributes</p>
+ <b-table striped hover responsive :items="selectedAttributes" selectable select-mode="single"
+ @row-selected="onAtrSelected">
+ </b-table>
+ <dev class="addAtrCls">
+ <b-button variant="outline-primary" v-on:click="addAttribute">Add Attributes</b-button>
+ </dev>
+ </div>
+ <div class="userformItem">
+ <p>Roles</p>
+ <b-table striped hover responsive :items="selectedRoles" selectable select-mode="single"
+ @row-selected="onRoleSelected">
+ </b-table>
+ <dev class="addAtrCls">
+ <b-button variant="outline-primary" v-on:click="addRole"
+ :disabled="this.isAdminUser==false">Add Role
+ </b-button>
+ </dev>
+ </div>
+
+ </div>
+ </b-modal>
+ <b-modal ref="atrModel" scrollable title="Add Attribute" ok-title="Add" @ok="addAtrOkPressed">
+ <div class="userform">
+ <div class="userformItem">
+ <p>Key</p>
+ <b-form-input v-model="newKey"></b-form-input>
+ </div>
+ <div class="userformItem">
+ <p>Value</p>
+ <b-form-input v-model="newValue"></b-form-input>
+ </div>
+ </div>
+ </b-modal>
+ <b-modal ref="atrModelSelected" scrollable title="Attribute" ok-title="Delete" @ok="addAtrDeletePressed">
+ <div class="userform">
+ <div class="userformItem">
+ <p>Key</p>
+ <b-form-input v-model="selectedKey" disabled></b-form-input>
+ </div>
+ <div class="userformItem">
+ <p>Value</p>
+ <b-form-input v-model="selectedValue" disabled></b-form-input>
+ </div>
+ </div>
+ </b-modal>
+ <b-modal ref="roleModel" scrollable title="Add Role" ok-title="Add" @ok="addRoleOkPressed">
+ <div class="userform">
+ <div class="userformItem">
+ <p>Scope</p>
+ <b-form-select v-model="selectedScope">
+ <option v-for="(selectOption, indexOpt) in scopes"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+ <div class="userformItem">
+ <p>Role</p>
+ <div v-if="selectedScope==='TENANT'">
+ <b-form-select v-model="selectedRole">
+ <option v-for="(selectOption, indexOpt) in tenantroles"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+ <div v-if="selectedScope==='CLIENT'">
+ <b-form-select v-model="selectedRole">
+ <option v-for="(selectOption, indexOpt) in clientroles"
+ :key="indexOpt"
+ :value="selectOption"
+ >
+ {{ selectOption }}
+ </option>
+ </b-form-select>
+ </div>
+ </div>
+ </div>
+ </b-modal>
+ <b-modal ref="roleModelSelected" scrollable title="Role" ok-title="Delete" @ok="deleteRoleOkPressed">
+ <div class="userform">
+ <div class="userformItem">
+ <p>Role</p>
+ <b-form-input v-model="rowSelectedRole" disabled></b-form-input>
+ </div>
+ <div class="userformItem">
+ <p>Scope</p>
+ <b-form-input v-model="rowSelectedScope" disabled></b-form-input>
+ </div>
+ </div>
+ </b-modal>
+ </div>
+ </div>
+</template>
+
+<script>
+ import config from "@/config";
+
+ export default {
+ name: "Users",
+ data: function () {
+ return {
+ fields: ['username', 'first_name', 'last_name', 'email', 'status'],
+ community_fields: ['id'],
+ items: [],
+ communityAccounts: [{
+ id: 'asdfcvrfg',
+ attributes: [{key: "work", vaule: 8123456789}, {key: "phone", vaule: 8123456789}],
+ roles: [{name: 'agentAdmin', scope: 'TENANT'}]
+ },
+ {
+ id: 'zxsdcfvtghy',
+ attributes: [{key: "work", vaule: 8123456789}, {key: "phone", vaule: 8123456789}],
+ roles: [{name: 'user', scope: 'TENANT'}]
+ }
+
+ ],
+ statusOptions: ['ACTIVE', 'DISABLE'],
+ scopes: ['TENANT', 'CLIENT'],
+ tenantroles: [],
+ clientroles: [],
+ selectedItem: null,
+ searchUsername: null,
+ selectedUsername: null,
+ selectedFirstName: null,
+ selectedLastName: null,
+ selectedEmail: null,
+ selectedStatus: null,
+ selectedAttributes: [],
+ selectedRoles: [],
+ selectedKey: null,
+ selectedValue: null,
+ newKey: null,
+ newValue: null,
+ selectedAtr: null,
+ selectedRoleItem: null,
+ selectedRole: null,
+ selectedScope: null,
+ rowSelectedRole: null,
+ rowSelectedScope: null,
+ newScope: null,
+ newRole: null,
+ checked: false,
+ newAccountName: null,
+ exAccountId: null,
+ exAccount: null,
+ accSelectedAttributes: [],
+ accSelectedRoles: [],
+ exAccountAtr: null,
+ exAccountRole: null,
+ exAccountAtrKey: null,
+ exAccountAtrValue: null,
+ exAccountRoleKey: null,
+ exAccountRoleValue: null,
+ custosId: null,
+ custosSec: null,
+ isAdminUser: false,
+ perPage: 5,
+ currentPage: 0,
+ userloading: true,
+ operationCompleted: true,
+ searchUsers: true,
+ currentUserName: null
+
+ }
+ },
+ methods: {
+ onRowSelected: function (items) {
+ if (items != null && items.length > 0) {
+ this.selectedItem = items
+ this.selectedUsername = this.selectedItem[0].username
+ this.selectedFirstName = this.selectedItem[0].first_name
+ this.selectedLastName = this.selectedItem[0].last_name
+ this.selectedEmail = this.selectedItem[0].email
+ this.selectedStatus = this.selectedItem[0].status
+ this.selectedAttributes = this.selectedItem[0].attributes
+ this.selectedRoles = this.selectedItem[0].roles
+ if (this.selectedUsername === this.currentUserName || this.isAdminUser) {
+ this.$refs.usermodel.show()
+ }
+ }
+
+ },
+ clearSelected: function () {
+ this.$refs.selectableTable.clearSelected()
+ },
+ async searchResult() {
+ this.searchUsers = false
+ if (this.searchUsername == null || this.searchUsername == "") {
+ await this.loadUsers()
+ } else {
+ let data = {
+ offset: 0, limit: 1, client_id: this.custosId, client_sec: this.custosSec,
+ username: this.searchUsername
+ }
+ await this.$store.dispatch('user/users', data)
+ let resp = await this.$store.getters['user/getUsers']
+ this.items = []
+ if (Array.isArray(resp) && resp.length > 0) {
+ resp.forEach(obj => {
+ let user = {
+ username: obj.username,
+ first_name: obj.first_name,
+ last_name: obj.last_name,
+ email: obj.email,
+ status: obj.state,
+ attributes: [],
+ roles: []
+ }
+ let rr = obj.realm_roles
+ let cr = obj.client_roles
+
+ let attribs = obj.attributes
+
+ attribs.forEach(r => {
+ let newAt = {
+ key: r.key,
+ value: r.values.join(",")
+ }
+ user.attributes.push(newAt)
+ })
+
+
+ rr.forEach(r => {
+ let rel_role = {
+ name: r,
+ scope: 'TENANT'
+ }
+ user.roles.push(rel_role)
+ })
+
+ cr.forEach(r => {
+ let cl_role = {
+ name: r,
+ scope: 'CLIENT'
+ }
+ user.roles.push(cl_role)
+ })
+
+ this.items.push(user)
+
+ });
+ }
+ }
+ this.searchUsers = true
+ },
+ async addAttribute() {
+ this.$refs.atrModel.show()
+ },
+ onAtrSelected: function (items) {
+ if (items != null && items.length > 0) {
+ this.selectedAtr = items
+ this.selectedKey = this.selectedAtr[0].key
+ this.selectedValue = this.selectedAtr[0].value
+ this.$refs.atrModelSelected.show()
+ }
+ },
+ addRole: function () {
+ this.$refs.roleModel.show()
+ },
+ onRoleSelected: function (items) {
+ if (items != null && items.length > 0) {
+ this.selectedRoleItem = items
+ if (this.isAdminUser) {
+ this.rowSelectedScope = this.selectedRoleItem[0].scope
+ this.rowSelectedRole = this.selectedRoleItem[0].name
+ this.$refs.roleModelSelected.show()
+ }
+ }
+ },
+
+ async addAtrOkPressed() {
+ this.operationCompleted = false
+ let accessToken = await this.$store.getters['identity/getAccessToken']
+ let bd = {
+ user_token: accessToken, body: {
+ attributes: [{
+ key: this.newKey,
+ values: [this.newValue]
+ }],
+ users: [this.selectedUsername]
+ }
+ }
+ let userAtr = await this.$store.dispatch('user/addUserAttributes', bd)
+ if (userAtr) {
+ let atr = {key: this.newKey, value: this.newValue}
+ this.selectedAttributes.push(atr)
+ }
+ this.operationCompleted = true
+ this.newKey = null
+ this.newValue = null
+ this.loadUsers()
+ },
+ async addAtrDeletePressed() {
+ this.operationCompleted = false
+ let accessToken = await this.$store.getters['identity/getAccessToken']
+ let bd = {
+ user_token: accessToken, body: {
+ attributes: [{
+ key: this.selectedKey,
+ values: [this.selectedValue]
+ }],
+ users: [this.selectedUsername]
+ }
+ }
+ let userAtr = await this.$store.dispatch('user/deleteUserAttributes', bd)
+ if (userAtr) {
+ let newAtr = []
+ this.selectedAttributes.forEach(atr => {
+
+ if (atr.key != this.selectedKey) {
+ newAtr.push(atr)
+ }
+ this.selectedAttributes = newAtr
+ })
+ }
+ this.operationCompleted = true
+ this.selectedKey = null
+ this.selectedValue = null
+ this.loadUsers()
+ },
+ async addRoleOkPressed() {
+ this.operationCompleted = false
+ let accessToken = await this.$store.getters['identity/getAccessToken']
+ let bd = {
+ user_token: accessToken,
+ body: {
+ roles: [this.selectedRole],
+ usernames: [this.selectedUsername],
+ client_level: (this.selectedScope === 'CLIENT')
+ }
+ }
+ let userAtr = await this.$store.dispatch('user/addRoleToUser', bd)
+ if (userAtr) {
+ if (this.selectedScope === 'CLIENT') {
+ let role = {name: this.selectedRole, scope: "CLIENT"}
+ this.selectedRoles.push(role)
+ } else {
+ let role = {name: this.selectedRole, scope: "TENANT"}
+ this.selectedRoles.push(role)
+ }
+
+ }
+ this.operationCompleted = true
+ this.selectedRole = null
+ this.selectedScope = null
+ this.loadUsers()
+ },
+ async deleteRoleOkPressed() {
+ this.operationCompleted = false
+ let accessToken = await this.$store.getters['identity/getAccessToken']
+ let bd = {};
+ if (this.rowSelectedScope === 'TENANT') {
+ bd = {
+ user_token: accessToken,
+ body: {
+ roles: [this.rowSelectedRole],
+ username: this.selectedUsername
+ }
+ }
+ } else {
+ bd = {
+ user_token: accessToken,
+ body: {
+ client_roles: [this.rowSelectedRole],
+ username: this.selectedUsername
+ }
+ }
+ }
+
+ let deleted = await this.$store.dispatch('user/deleteRoleFromUser', bd)
+ if (deleted) {
+
+ let newRoles = []
+ this.selectedRoles.forEach(atr => {
+
+ if (atr.name != this.rowSelectedRole) {
+ newRoles.push(atr)
+ }
+ this.selectedRoles = newRoles
+ })
+ }
+ this.operationCompleted = true
+ this.loadUsers()
+ },
+
+ async loadUsers() {
+ let data = {offset: 0, limit: 5, client_id: this.custosId, client_sec: this.custosSec}
+ let resp = await this.$store.dispatch('user/users', data)
+ this.userloading = false
+ this.items = []
+ let newUsersCount = this.parseUsers(this.items, resp)
+ if (newUsersCount == 5) {
+ let offset = 5
+ while (newUsersCount >= 5) {
+ newUsersCount = await this.loadUsersR(offset, this.items)
+ offset = offset + 5
+ }
+ }
+ },
+
+ async loadUsersR(offset, items) {
+ let data = {offset: offset, limit: 5, client_id: this.custosId, client_sec: this.custosSec}
+ let resp = await this.$store.dispatch('user/users', data)
+ return this.parseUsers(items, resp)
+ },
+
+ parseUsers(items, resp) {
+ if (Array.isArray(resp) && resp.length > 0) {
+ resp.forEach(obj => {
+ let user = {
+ username: obj.username,
+ first_name: obj.first_name,
+ last_name: obj.last_name,
+ email: obj.email,
+ status: obj.state,
+ attributes: [],
+ roles: []
+ }
+ let rr = obj.realm_roles
+ let cr = obj.client_roles
+
+ let attribs = obj.attributes
+
+ attribs.forEach(r => {
+ let newAt = {
+ key: r.key,
+ value: r.values.join(",")
+ }
+ user.attributes.push(newAt)
+ })
+
+ rr.forEach(r => {
+ let rel_role = {
+ name: r,
+ scope: 'TENANT'
+ }
+ user.roles.push(rel_role)
+ })
+
+ cr.forEach(r => {
+ let cl_role = {
+ name: r,
+ scope: 'CLIENT'
+ }
+ user.roles.push(cl_role)
+ })
+
+ items.push(user)
+
+ });
+
+ }
+ return resp.length
+ },
+
+ async updateUserProfile() {
+ this.operationCompleted = false
+ let params = {client_id: this.custosId, client_sec: this.custosSec, username: this.selectedUsername}
+ if (this.selectedStatus === 'ACTIVE') {
+ await this.$store.dispatch('user/enableUser', params)
+
+ } else {
+ await this.$store.dispatch('user/disableUser', params)
+ }
+
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec,
+ body: {
+ username: this.selectedUsername,
+ first_name: this.selectedFirstName,
+ last_name: this.selectedLastName,
+ email: this.selectedEmail
+ }
+ }
+ await this.$store.dispatch('user/updateUserProfile', data)
+ this.operationCompleted = true
+ this.loadUsers()
+
+ },
+ }
+ ,
+
+ async mounted() {
+ this.custosId = config.value('clientId')
+ this.custosSec = config.value('clientSec')
+ this.isAdminUser = await this.$store.dispatch('identity/isLoggedUserHasAdminAccess')
+ this.currentUserName = await this.$store.dispatch('identity/getCurrentUserName')
+ await this.loadUsers()
+
+ let params = {client_id: this.custosId, client_sec: this.custosSec}
+ this.tenantroles = await this.$store.dispatch('user/getTenantLevelRoles', params)
+ this.clientroles = await this.$store.dispatch('user/getClientLevelRoles', params)
+ }
+ ,
+ computed: {
+ rows() {
+ return this.items.length
+ }
+ }
+ }
+
+</script>
+
+<style scoped>
+ .usertable {
+ width: 50%;
+ margin-left: 10%;
+ margin-top: 3%;
+ }
+
+ .userSearchBar {
+ width: 50%;
+ margin-left: 10%;
+ }
+
+ .userformItem {
+ margin-top: 3%;
+ }
+
+ .addAtrCls {
+ margin-left: 70%;
+ }
+
+ .pgClass {
+ margin-left: 70%;
+ position: relative;
+ }
+
+
+</style>
\ No newline at end of file
diff --git a/custos-demo-gateway/src/components/workspace/Workspace.vue b/custos-demo-gateway/src/components/workspace/Workspace.vue
new file mode 100644
index 0000000..a7929e5
--- /dev/null
+++ b/custos-demo-gateway/src/components/workspace/Workspace.vue
@@ -0,0 +1,141 @@
+<template>
+ <dev>
+ <div class="logout">
+ <b-button href="#" v-on:click="logout">Logout</b-button>
+ </div>
+ <div class="grouping">
+ <b-card-group deck>
+ <b-card :img-src="require('../../assets/users.png')"
+ img-height="50%"
+ style="max-width: 20rem;"
+ class="mb-2"
+ body-class="bcbody"
+ >
+ <b-button href="#" variant="outline-primary" v-on:click="loadRoute($event, '/workspace/users')">
+ Manage Users
+ </b-button>
+ </b-card>
+ <b-card :img-src="require('../../assets/groups_web.png')"
+ img-height="50%"
+ style="max-width: 20rem;"
+ class="mb-2"
+ body-class="bcbody"
+ >
+ <b-button href="#" variant="outline-primary" v-on:click="loadRoute($event, '/workspace/groups')">
+ Manage Groups
+ </b-button>
+ </b-card>
+ <b-card :img-src="require('../../assets/credentials.png')"
+ img-height="50%"
+ style="max-width: 20rem;"
+ class="mb-2"
+ body-class="bcbody"
+ >
+ <b-button href="#" variant="outline-primary" v-on:click="loadRoute($event, '/workspace/secrets')">
+ Manage Secrets
+ </b-button>
+ </b-card>
+ </b-card-group>
+ </div>
+ <div class="groupingbt">
+ <b-card-group deck>
+ <b-card :img-src="require('../../assets/sharings.png')"
+ img-height="50%"
+ style="max-width: 20rem;"
+ class="mb-2"
+ body-class="bcbody"
+ >
+ <b-button href="#" variant="outline-primary" v-on:click="loadRoute($event, '/workspace/sharings')">
+ Sharing
+ </b-button>
+ </b-card>
+ <b-card :img-src="require('../../assets/bots.png')"
+ img-height="50%"
+ style="max-width: 20rem;"
+ class="mb-2"
+ body-class="bcbody"
+ >
+ <b-button href="#" variant="outline-primary" :disabled="!isAdmin"
+ v-on:click="loadRoute($event, '/workspace/agents')">
+ Community Accounts
+ </b-button>
+ </b-card>
+ <b-card :img-src="require('../../assets/dblogs.png')"
+ img-height="50%"
+ style="max-width: 20rem;"
+ class="mb-2"
+ body-class="bcbody"
+ >
+ <b-button href="#" variant="outline-primary" :disabled="!isAdmin" v-on:click="loadRoute($event, '/workspace/logs')">
+ Logs
+ </b-button>
+ </b-card>
+ </b-card-group>
+ </div>
+ </dev>
+</template>
+
+<script>
+ import config from "@/config";
+
+ export default {
+ name: "Workspace",
+ data: function () {
+ return {
+ custosId: null,
+ custosSec: null,
+ isAdmin: false
+ }
+ },
+ methods: {
+ loadRoute: function (event, route) {
+ this.$router.push(route)
+ },
+ async logout() {
+ let data = {
+ client_id: this.custosId,
+ client_sec: this.custosSec
+ }
+ await this.$store.dispatch('identity/logout', data)
+ await this.$router.push("/")
+ await this.$store.dispatch('agent/reset')
+ await this.$store.dispatch('group/reset')
+ await this.$store.dispatch('secret/reset')
+ await this.$store.dispatch('sharing/reset')
+ await this.$store.dispatch('user/reset')
+ }
+ },
+
+ async mounted() {
+ this.custosId = config.value('clientId')
+ this.custosSec = config.value('clientSec')
+ this.isAdmin = await this.$store.dispatch('identity/isLoggedUserHasAdminAccess')
+ }
+ }
+</script>
+
+<style scoped>
+ .grouping {
+ position: relative;
+ margin-left: 30%;
+ width: 40%;
+ margin-top: 5%;
+ }
+
+ .groupingbt {
+ position: relative;
+ margin-left: 30%;
+ width: 40%;
+ margin-top: 5%;
+ }
+
+ .bcbody {
+ background-color: lightgray;
+ height: 30%;
+ }
+
+ .logout {
+ margin-left: 70%;
+ }
+
+</style>
\ No newline at end of file
diff --git a/custos-demo-gateway/src/config.js b/custos-demo-gateway/src/config.js
new file mode 100644
index 0000000..0ba2735
--- /dev/null
+++ b/custos-demo-gateway/src/config.js
@@ -0,0 +1,41 @@
+import dotenv from 'dotenv'
+dotenv.config()
+
+export default class Configuration {
+ static get CONFIG () {
+ return {
+ clientId: '$VUE_APP_CLIENT_ID',
+ clientSec: '$VUE_APP_CLIENT_SEC',
+ redirectURI: '$VUE_APP_REDIRECT_URI'
+ }
+ }
+
+ static value (name) {
+ if (!(name in this.CONFIG)) {
+ console.log(`Configuration: There is no key named "${name}"`)
+ return
+ }
+
+ const value = this.CONFIG[name]
+
+ if (!value) {
+ console.log(`Configuration: Value for "${name}" is not defined`)
+ return
+ }
+
+ if (value.startsWith('$VUE_APP_')) {
+ // value was not replaced, it seems we are in development.
+ // Remove $ and get current value from process.env
+ const envName = value.substr(1)
+ const envValue = process.env[envName]
+ if (envValue) {
+ return envValue
+ } else {
+ console.log(`Configuration: Environment variable "${envName}" is not defined`)
+ }
+ } else {
+ // value was already replaced, it seems we are in production.
+ return value
+ }
+ }
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/main.js b/custos-demo-gateway/src/main.js
new file mode 100644
index 0000000..218a0ce
--- /dev/null
+++ b/custos-demo-gateway/src/main.js
@@ -0,0 +1,23 @@
+import Vue from 'vue'
+import App from './App.vue'
+import router from "./router.js";
+import store from './store/index.js'
+import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
+
+
+import 'bootstrap/dist/css/bootstrap.css';
+import 'bootstrap-vue/dist/bootstrap-vue.css';
+
+Vue.use(BootstrapVue)
+// Optionally install the BootstrapVue icon components plugin
+Vue.use(IconsPlugin)
+
+Vue.config.productionTip = false
+
+new Vue({
+ router,
+ store,
+ render: h => h(App),
+}).$mount('#app')
+
+
diff --git a/custos-demo-gateway/src/router.js b/custos-demo-gateway/src/router.js
new file mode 100644
index 0000000..f4be213
--- /dev/null
+++ b/custos-demo-gateway/src/router.js
@@ -0,0 +1,159 @@
+import Vue from "vue";
+import Router from "vue-router";
+import Landing from "./components/landing/Landing.vue";
+import store from './store/index'
+
+
+Vue.use(Router)
+
+export default new Router({
+ mode: "history",
+ routes: [
+ {
+ path: "/",
+ name: "home",
+ component: Landing
+ },
+ {
+ path: "/register",
+ name: "account",
+ component: () =>
+ import(/*webpackChunkName:"account"*/ "./components/registration/CreateAccount")
+ },
+ {
+ path: "/workspace",
+ name: "workspace",
+ beforeEnter: async (to, from, next) => {
+ let data = {
+ client_id: process.env.VUE_APP_CLIENT_ID,
+ client_sec: process.env.VUE_APP_CLIENT_SEC
+ }
+ if (await store.dispatch('identity/isAuthenticated',data) == true) {
+ // You can use store variable here to access globalError or commit mutation
+ next(true)
+ } else {
+ next('/')
+ }
+ },
+ component: () =>
+ import(/*webpackChunkName:"workspace"*/ "./components/workspace/Workspace")
+ },
+ {
+ path: "/workspace/groups",
+ name: "groups",
+ beforeEnter: async (to, from, next) => {
+ let data = {
+ client_id: process.env.VUE_APP_CLIENT_ID,
+ client_sec: process.env.VUE_APP_CLIENT_SEC
+ }
+ if (await store.dispatch('identity/isAuthenticated',data) == true) {
+ // You can use store variable here to access globalError or commit mutation
+ next(true)
+ } else {
+ next('/')
+ }
+ },
+ component: () =>
+ import(/*webpackChunkName:"groups"*/ "./components/workspace/Groups")
+ },
+ {
+ path: "/workspace/logs",
+ name: "logs",
+ beforeEnter: async (to, from, next) => {
+ let data = {
+ client_id: process.env.VUE_APP_CLIENT_ID,
+ client_sec: process.env.VUE_APP_CLIENT_SEC
+ }
+ if (await store.dispatch('identity/isAuthenticated',data) == true) {
+ // You can use store variable here to access globalError or commit mutation
+ next(true)
+ } else {
+ next('/')
+ }
+ },
+ component: () =>
+ import(/*webpackChunkName:"logs"*/ "./components/workspace/Logs")
+ },
+ {
+ path: "/workspace/secrets",
+ name: "secrets",
+ beforeEnter: async (to, from, next) => {
+ let data = {
+ client_id: process.env.VUE_APP_CLIENT_ID,
+ client_sec: process.env.VUE_APP_CLIENT_SEC
+ }
+ if (await store.dispatch('identity/isAuthenticated',data) == true) {
+ // You can use store variable here to access globalError or commit mutation
+ next(true)
+ } else {
+ next('/')
+ }
+ },
+ component: () =>
+ import(/*webpackChunkName:"secrets"*/ "./components/workspace/Secrets")
+ },
+ {
+ path: "/workspace/sharings",
+ name: "sharings",
+ beforeEnter: async (to, from, next) => {
+ let data = {
+ client_id: process.env.VUE_APP_CLIENT_ID,
+ client_sec: process.env.VUE_APP_CLIENT_SEC
+ }
+ if (await store.dispatch('identity/isAuthenticated',data) == true) {
+ // You can use store variable here to access globalError or commit mutation
+ next(true)
+ } else {
+ next('/')
+ }
+ },
+ component: () =>
+ import(/*webpackChunkName:"sharings"*/ "./components/workspace/Sharing")
+ },
+ {
+ path: "/workspace/users",
+ name: "users",
+ beforeEnter: async (to, from, next) => {
+ let data = {
+ client_id: process.env.VUE_APP_CLIENT_ID,
+ client_sec: process.env.VUE_APP_CLIENT_SEC
+ }
+ if (await store.dispatch('identity/isAuthenticated',data) == true) {
+ // You can use store variable here to access globalError or commit mutation
+ next(true)
+ } else {
+ next('/')
+ }
+ },
+ component: () =>
+ import(/*webpackChunkName:"users"*/ "./components/workspace/Users")
+ },
+ {
+ path: "/workspace/agents",
+ name: "agents",
+ beforeEnter: async (to, from, next) => {
+ let data = {
+ client_id: process.env.VUE_APP_CLIENT_ID,
+ client_sec: process.env.VUE_APP_CLIENT_SEC
+ }
+ if (await store.dispatch('identity/isAuthenticated',data) == true) {
+ // You can use store variable here to access globalError or commit mutation
+ next(true)
+ } else {
+ next('/')
+ }
+ },
+ component: () =>
+ import(/*webpackChunkName:"account"*/ "./components/workspace/Agents")
+ },
+ {
+ path: "/callback",
+ name: "callback",
+ component: () =>
+ import(/*webpackChunkName:"users"*/ "./components/Callback")
+ },
+
+ ]
+})
+
+
diff --git a/custos-demo-gateway/src/service/agent_management.js b/custos-demo-gateway/src/service/agent_management.js
new file mode 100644
index 0000000..51986ca
--- /dev/null
+++ b/custos-demo-gateway/src/service/agent_management.js
@@ -0,0 +1,116 @@
+import api from "./api.js";
+import axios from "axios";
+
+
+const agentMgtEndpoint = "https://custos.scigap.org/apiserver/agent-management/v1.0.0"
+
+export default {
+
+ enableAgents(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = agentMgtEndpoint + "/enable"
+ return api().post(endpoint, {}, {
+ headers: authHeader
+ })
+ },
+
+ registerAgent(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = agentMgtEndpoint + "/agent"
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+ },
+
+ getAgent(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = agentMgtEndpoint + "/agent/" + params.agent_id
+ return api().get(endpoint, {
+ headers: authHeader
+ })
+ },
+
+ activateAgent(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = agentMgtEndpoint + "/agent/activation/" + params.agent_id
+ return api().post(endpoint, {}, {
+ headers: authHeader
+ })
+ },
+
+ deactivateAgent(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = agentMgtEndpoint + "/agent/deactivation/" + params.agent_id
+ return api().post(endpoint, {}, {
+ headers: authHeader
+ })
+ },
+
+
+ addAttributesToAgent(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = agentMgtEndpoint + "/agent/attributes"
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+
+ },
+
+ deleteAttributesFromAgent(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = agentMgtEndpoint + "/agent/attributes"
+
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+ },
+
+
+ getAllAgents(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = agentMgtEndpoint + "/agents"
+ return api().get(endpoint, {
+ headers: authHeader
+ })
+
+ },
+
+ addRolesToAgent(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = agentMgtEndpoint + "/agent/roles"
+
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+ },
+
+ deleteRolesFromAgent(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = agentMgtEndpoint + "/agent/roles"
+
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+ },
+
+
+
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/service/api.js b/custos-demo-gateway/src/service/api.js
new file mode 100644
index 0000000..b5c2abf
--- /dev/null
+++ b/custos-demo-gateway/src/service/api.js
@@ -0,0 +1,12 @@
+import axios from 'axios'
+
+export default() => {
+ return axios.create({
+ baseURL: 'https://custos.scigap.org/apiserver/',
+ withCredentials: false,
+ headers: {
+ 'Accept': '*/*',
+ 'Content-Type': 'application/json'
+ }
+ })
+}
diff --git a/custos-demo-gateway/src/service/auth.js b/custos-demo-gateway/src/service/auth.js
new file mode 100644
index 0000000..e256ab4
--- /dev/null
+++ b/custos-demo-gateway/src/service/auth.js
@@ -0,0 +1,96 @@
+import decode from 'jwt-decode';
+
+const ID_TOKEN_KEY = 'id_token';
+const ACCESS_TOKEN_KEY = 'access_token';
+const REFRESH_TOKEN_KEY = 'refresh_token';
+
+export default {
+
+ isLoggedIn() {
+ const idToken = this.getIdToken();
+ return !!idToken && !this.isTokenExpired(idToken);
+ },
+
+ isTokenExpired(token) {
+ const expirationDate = this.getTokenExpirationDate(token);
+ return expirationDate < new Date();
+ },
+
+ getTokenExpirationDate(encodedToken) {
+ const token = decode(encodedToken);
+ if (!token.exp) {
+ return null;
+ }
+
+ const date = new Date(0);
+ date.setUTCSeconds(token.exp);
+ return date;
+ },
+
+ logout() {
+ this.clearIdToken();
+ this.clearAccessToken();
+ window.location.href = "/"
+ },
+
+ setAccessToken(token) {
+ this.clearAccessToken()
+ localStorage.setItem(ACCESS_TOKEN_KEY, token)
+ },
+ setIdToken(token) {
+ this.clearIdToken();
+ localStorage.setItem(ID_TOKEN_KEY, token)
+ },
+
+
+ setRefreshToken(token) {
+ this.clearRefreshToken()
+ localStorage.setItem(REFRESH_TOKEN_KEY, token)
+ },
+
+ getIdToken() {
+ return localStorage.getItem(ID_TOKEN_KEY);
+ },
+
+ getAccessToken() {
+ return localStorage.getItem(ACCESS_TOKEN_KEY);
+ },
+
+ getRefreshToken(){
+ return localStorage.getItem(REFRESH_TOKEN_KEY)
+ },
+
+ clearIdToken() {
+ localStorage.removeItem(ID_TOKEN_KEY);
+ },
+
+ clearAccessToken() {
+ localStorage.removeItem(ACCESS_TOKEN_KEY);
+ },
+
+ clearRefreshToken() {
+ localStorage.removeItem(REFRESH_TOKEN_KEY)
+ },
+
+ isUserHasAdminAccess() {
+ let token = localStorage.getItem(ACCESS_TOKEN_KEY)
+ let decodedToken = decode(token)
+ let roles = decodedToken.realm_access.roles;
+ let condition = false
+ roles.forEach(role => {
+ if (role === 'admin') {
+
+ condition = true
+
+ }
+ })
+ return condition
+ },
+
+ getLoggedUsername() {
+ let token = localStorage.getItem(ACCESS_TOKEN_KEY)
+ let decodedToken = decode(token)
+ return decodedToken.preferred_username
+ }
+
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/service/group_management.js b/custos-demo-gateway/src/service/group_management.js
new file mode 100644
index 0000000..44b57be
--- /dev/null
+++ b/custos-demo-gateway/src/service/group_management.js
@@ -0,0 +1,157 @@
+import api from "./api.js";
+import axios from "axios";
+
+const groupMgtEndpoint = "https://custos.scigap.org/apiserver/group-management/v1.0.0"
+
+export default {
+
+ createGroup(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/groups"
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+ },
+
+ updateGroup(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/group/" + params.group_id
+ return api().put(endpoint, params.body, {
+ headers: authHeader
+ })
+ },
+
+ deleteGroup(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/group/" + params.group_id
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+ },
+
+
+ findGroup(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/group"
+ let par = {
+ group: {
+ id: params.group_id
+ }
+ }
+ return api().get(endpoint, {
+ params: par,
+ headers: authHeader
+ })
+ },
+
+ getAllGroups(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/groups"
+
+ return api().get(endpoint, {
+ headers: authHeader
+ })
+ },
+
+ addUserToGroup(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/user/group/membership"
+
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+
+ },
+
+ removeUserFromGroup(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/user/group/membership"
+
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+ },
+
+ changeGroupMembership(params) {
+ let authHeader = {'Authorization': 'Bearer ' +btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/user/group/membership"
+
+ return api().put(endpoint, params.body, {
+ headers: authHeader
+ })
+
+ },
+
+ addChildGroup(params) {
+ let authHeader = {'Authorization': 'Bearer ' +btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/group/membership"
+
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+
+ },
+
+ removeChildGroup(params) {
+ let authHeader = {'Authorization': 'Bearer ' +btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/group/membership"
+
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+
+ },
+
+ getAllChildUsers(params) {
+
+ let authHeader = {'Authorization': 'Bearer ' +btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/user/group/memberships/child"
+ let parm = {
+ 'group.id': params.group_id
+ }
+
+
+ return api().get(endpoint, {params: parm, headers: authHeader})
+
+ },
+
+ getAllChildGroups(params) {
+ let authHeader = {'Authorization': 'Bearer ' +btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = groupMgtEndpoint + "/groups/memberships/child"
+ let parm = {
+ 'group.id': params.group_id
+ }
+ return api().get(endpoint, {params: parm, headers: authHeader})
+
+ },
+
+
+}
+
diff --git a/custos-demo-gateway/src/service/identity_management.js b/custos-demo-gateway/src/service/identity_management.js
new file mode 100644
index 0000000..670c1db
--- /dev/null
+++ b/custos-demo-gateway/src/service/identity_management.js
@@ -0,0 +1,55 @@
+import api from "./api.js";
+
+
+const identityMgtEndpoint = "/identity-management/v1.0.0"
+
+export default {
+
+ getOpenIdConfig(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ return api().get(identityMgtEndpoint + '/.well-known/openid-configuration',
+ {params: {client_id: params.client_id}, headers: authHeader})
+ },
+
+ getToken(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let tokenEnpoint = params.token_endpoint
+ let code = params.code
+ let redirect_uri = params.redirect_uri
+ let body = {'code': code, 'redirect_uri': redirect_uri, 'grant_type': 'authorization_code'}
+ return api().post(tokenEnpoint,
+ body, {headers: authHeader})
+ },
+
+ localLogin(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let tokenEnpoint = params.token_endpoint
+ let username = params.username
+ let password = params.password
+ let body = {'grant_type': 'password', 'username': username, 'password': password}
+ return api().post(tokenEnpoint,
+ body, {headers: authHeader})
+ },
+
+
+ logout(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endSessionEndpoint = identityMgtEndpoint + "/user/logout"
+ let data = {
+ refresh_token: params.refresh_token
+ }
+ return api().post(endSessionEndpoint,
+ data, {headers: authHeader})
+ },
+
+
+ getTokenUsingRefreshToken(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let tokenEndpoint = identityMgtEndpoint + "/token"
+ let body = {'refresh_token': params.refresh_token, 'grant_type': 'refresh_token'}
+ return api().post(tokenEndpoint,
+ body, {headers: authHeader})
+ }
+
+
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/service/log_management.js b/custos-demo-gateway/src/service/log_management.js
new file mode 100644
index 0000000..e941fb0
--- /dev/null
+++ b/custos-demo-gateway/src/service/log_management.js
@@ -0,0 +1,36 @@
+import api from "./api.js";
+
+
+const logMgtEndpoint = "https://custos.scigap.org/apiserver/log-management/v1.0.0"
+
+export default {
+
+ getLogEvents(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = logMgtEndpoint + "/logs"
+ return api().get(endpoint, {
+ params:params.params,
+ headers: authHeader
+ })
+ },
+
+ isLoggingEnabled(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = logMgtEndpoint + "/status"
+ return api().get(endpoint, {
+ headers: authHeader
+ })
+
+ },
+
+ enableLogging(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = logMgtEndpoint + "/status"
+ return api().post(endpoint, {}, {
+ headers: authHeader
+ })
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/service/secret_management.js b/custos-demo-gateway/src/service/secret_management.js
new file mode 100644
index 0000000..9594a87
--- /dev/null
+++ b/custos-demo-gateway/src/service/secret_management.js
@@ -0,0 +1,98 @@
+import api from "./api.js";
+import axios from "axios";
+
+var qs = require('qs');
+
+const secretMgtEndpoint = "https://custos.scigap.org/apiserver/resource-secret-management/v1.0.0"
+
+export default {
+
+ addSSHCredential(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = secretMgtEndpoint + "/secret/ssh"
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+ },
+
+ addPasswordCredential(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = secretMgtEndpoint + "/secret/password"
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+ },
+
+ getSSHCredential(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = secretMgtEndpoint + "/secret/ssh"
+ return api().get(endpoint, {
+ params: {
+ token: params.token,
+ client_id: params.client_id
+ },
+ headers: authHeader
+ })
+ },
+
+ getPasswordCredential(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = secretMgtEndpoint + "/secret/password"
+ return api().get(endpoint, {
+ params: {
+ token: params.token,
+ client_id: params.client_id
+ },
+ headers: authHeader
+ })
+ },
+ deleteSSHCredential(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = secretMgtEndpoint + "/secret/ssh"
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ headers: authHeader,
+ params: {client_id: params.client_id, token: params.token}
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+ },
+
+ deletePasswordCredential(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = secretMgtEndpoint + "/secret/password"
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ headers: authHeader,
+ params: {client_id: params.client_id, token: params.token}
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+ },
+
+ getAllCredentials(par) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(par.client_id + ':' + par.client_sec)}
+ let endpoint = secretMgtEndpoint + "/secret/summaries"
+ console.log(par)
+ return api().get(endpoint, {
+ params: par.params,
+ headers: authHeader,
+ paramsSerializer: params => {
+ return qs.stringify(params, {indices: false})
+ }
+ })
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/service/sharing_management.js b/custos-demo-gateway/src/service/sharing_management.js
new file mode 100644
index 0000000..b908dd8
--- /dev/null
+++ b/custos-demo-gateway/src/service/sharing_management.js
@@ -0,0 +1,198 @@
+import api from "./api.js";
+import axios from "axios";
+
+const sharingMgtEndpoint = "https://custos.scigap.org/apiserver/sharing-management/v1.0.0"
+
+export default {
+
+ createPermissionType(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/permission/type"
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+ },
+
+ deletePermissionType(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/permission/type"
+
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+
+ },
+
+ getPermissionTypes(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/permission/types"
+ let par = {client_id: params.client_id}
+ return api().get(endpoint, {
+ params: par,
+ headers: authHeader
+ })
+ },
+
+ createEntityType(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/entity/type"
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+ },
+
+ deleteEntityType(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/entity/type"
+
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+
+ },
+
+ getEntityTypes(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/entity/types"
+ let par = {client_id: params.client_id}
+ return api().get(endpoint, {
+ params: par,
+ headers: authHeader
+ })
+ },
+
+ createEntity(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/entity"
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+ },
+
+ deleteEntity(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/entity"
+
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+
+ },
+
+ getEntities(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/entities"
+ return api().post(endpoint, params.body,{
+ headers: authHeader
+ })
+ },
+
+ getListOfSharedUsers(data) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(data.client_id + ':' + data.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/users/share"
+ return api().get(endpoint, {
+ params: data.params,
+ headers: authHeader
+ })
+ },
+
+ getListOfSharedGroups(data) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(data.client_id + ':' + data.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/groups/share"
+ return api().get(endpoint, {
+ params: data.params,
+ headers: authHeader
+ })
+ },
+
+ shareEntityWithUsers(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/users/share"
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+
+ },
+
+ shareEntityWithGroups(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/groups/share"
+ return api().post(endpoint, params.body, {
+ headers: authHeader
+ })
+
+ },
+
+ revokeEntitySharingFromUsers(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/users/share"
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+
+ },
+
+ revokeEntitySharingFromGroups(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/groups/share"
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+
+ },
+
+ userHasAccess(data) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(data.client_id + ':' + data.client_sec)}
+ let endpoint = sharingMgtEndpoint + "/entity/user/access"
+ return api().get(endpoint, {
+ params: data.params,
+ headers: authHeader
+ })
+ }
+
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/service/user_management.js b/custos-demo-gateway/src/service/user_management.js
new file mode 100644
index 0000000..d7b7483
--- /dev/null
+++ b/custos-demo-gateway/src/service/user_management.js
@@ -0,0 +1,161 @@
+import api from "./api.js";
+import axios from "axios";
+
+
+const usermgtEndpoint = "https://custos.scigap.org/apiserver/user-management/v1.0.0"
+const tenantmgtEndpoint = "https://custos.scigap.org/apiserver/tenant-management/v1.0.0"
+
+export default {
+
+ registerUser(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = usermgtEndpoint + "/user";
+ let body = {
+ 'client_id': params.client_id,
+ 'username': params.username,
+ 'first_name': params.first_name,
+ 'last_name': params.last_name,
+ 'password': params.password,
+ 'temporary_password': false,
+ 'email': params.email
+ }
+ return api().post(endpoint,
+ body, {headers: authHeader})
+ },
+
+ enableUser(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = usermgtEndpoint + "/user/activation";
+ let body = {
+ username: params.username
+ }
+ return api().post(endpoint, body
+ , {
+ headers: authHeader
+ })
+ },
+
+ disableUser(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = usermgtEndpoint + "/user/deactivation";
+ let body = {
+ username: params.username
+ }
+ return api().post(endpoint, body
+ , {
+ headers: authHeader
+ })
+ },
+
+ checkUsernameValidity(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = usermgtEndpoint + "/user/availability";
+ return api().get(endpoint,
+ {
+ params: {'user.username': params.username},
+ headers: authHeader
+ })
+ },
+
+ findUsers(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = usermgtEndpoint + "/users";
+ let id = params.username
+ let param = {offset: params.offset, limit: params.limit, client_id: params.client_id, 'user.id': id}
+ return api().get(endpoint,
+ {
+ params: param,
+ headers: authHeader
+ })
+ },
+
+ addUserAttribute(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = usermgtEndpoint + "/attributes";
+ return api().post(endpoint, params.body
+ , {
+ headers: authHeader
+ })
+ },
+
+ deleteUserAttribute(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = usermgtEndpoint + "/attributes";
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+
+
+ },
+
+ addRolesToUser(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = usermgtEndpoint + "/users/roles";
+ return api().post(endpoint, params.body
+ , {
+ headers: authHeader
+ })
+
+ },
+
+ deleteRolesFromUser(params) {
+ let authHeader = {'Authorization': 'Bearer ' + params.user_token}
+ let endpoint = usermgtEndpoint + "/user/roles";
+ return new Promise((resolve, reject) => {
+ axios({
+ method: 'delete',
+ url: endpoint,
+ data: params.body,
+ headers: authHeader
+ }).then((resp) => {
+ resolve(resp)
+ }).catch(errr => {
+ reject(errr)
+ })
+ })
+ },
+
+ updateProfile(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = usermgtEndpoint + "/user/profile";
+ console.log(authHeader)
+ return api().put(endpoint, params.body
+ , {
+ headers: authHeader
+ })
+
+ },
+
+
+ getTenantLevelRoles(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = tenantmgtEndpoint + "/roles"
+ return api().get(endpoint,
+ {
+ headers: authHeader
+ })
+ },
+
+ getClientLevelRoles(params) {
+ let authHeader = {'Authorization': 'Bearer ' + btoa(params.client_id + ':' + params.client_sec)}
+ let endpoint = tenantmgtEndpoint + "/roles"
+ let par = {client_level: true}
+ return api().get(endpoint,
+ {
+ params: par,
+ headers: authHeader
+ })
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/store/index.js b/custos-demo-gateway/src/store/index.js
new file mode 100644
index 0000000..4affb81
--- /dev/null
+++ b/custos-demo-gateway/src/store/index.js
@@ -0,0 +1,29 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import createLogger from 'vuex/dist/logger';
+import identity from './modules/identity.store';
+import user from './modules/user.store'
+import agent from './modules/agent.store'
+import group from './modules/group.store'
+import secret from './modules/secret.store'
+import log from './modules/log.store'
+import sharing from './modules/sharing.store'
+
+
+Vue.use(Vuex);
+
+const debug = process.env.NODE_ENV !== 'production';
+
+export default new Vuex.Store({
+ modules: {
+ identity,
+ user,
+ agent,
+ group,
+ secret,
+ log,
+ sharing
+ },
+ strict: debug,
+ plugins: debug ? [createLogger()] : [],
+})
\ No newline at end of file
diff --git a/custos-demo-gateway/src/store/modules/agent.store.js b/custos-demo-gateway/src/store/modules/agent.store.js
new file mode 100644
index 0000000..1dcfd5d
--- /dev/null
+++ b/custos-demo-gateway/src/store/modules/agent.store.js
@@ -0,0 +1,155 @@
+/*Agent.store.js*/
+
+import agent_management from "@/service/agent_management";
+
+
+const getDefaultState = () => {
+ return {
+ agents: [],
+ clientLevelRoles: [],
+ isAgentsEnabled: false
+ }
+}
+
+const state = getDefaultState()
+
+const actions = {
+
+ async enableAgents({commit}, data) {
+ let resp = await agent_management.enableAgents(data)
+ commit('SET_AGENTS_ENABLED', resp.data.status)
+ return resp.data.status
+ },
+
+ async registerAgent({commit}, data) {
+ let rep = await agent_management.registerAgent(data)
+ let id = rep.data.id
+ let da = {
+ id: id,
+ status: 'ACTIVE',
+ attributes: []
+ }
+ commit('ADD_AGENTS', da)
+ return rep.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async getAgent({commit}, data) {
+ let response = await agent_management.getAgent(data)
+ return response.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async activateAgent({commit}, data) {
+ let response = await agent_management.activateAgent(data)
+ let id = data.agent_id
+ commit('SET_ACTIVATED_AGENT', id)
+ return response.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async deactivateAgent({commit}, data) {
+ let response = await agent_management.deactivateAgent(data)
+ let id = data.agent_id
+ commit('SET_DEACTIVATED_AGENT', id)
+ return response.data
+ },
+
+
+ // eslint-disable-next-line no-unused-vars
+ async addAttributeToAgent({commit}, data) {
+ let response = await agent_management.addAttributesToAgent(data)
+ return response.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async deleteAttributeFromAgent({commit}, data) {
+ let response = await agent_management.deleteAttributesFromAgent(data)
+ return response.data
+ },
+
+
+ async get_all_agents({commit}, data) {
+ let response = await agent_management.getAllAgents(data)
+ let agents = response.data.agents
+ agents.forEach(agent => {
+ agent.status = (agent.isEnabled ? 'ACTIVE':'DISABLED')
+ })
+ commit('SET_AGENTS', response.data.agents)
+ return response.data.agents
+ },
+ // eslint-disable-next-line no-unused-vars
+ async reset({commit}, data){
+ commit('RESET')
+ return true
+ }
+
+}
+
+
+const mutations = {
+
+
+ ADD_AGENTS(state, data) {
+ state.agents.push(data)
+ },
+
+ SET_AGENTS(state, data) {
+ state.agents = data
+ },
+
+ SET_CLIENT_LEVEL_ROLES(state, data) {
+ state.clientLevelRoles = data
+ },
+
+ SET_AGENTS_ENABLED(state, data) {
+ state.isAgentsEnabled = data
+ },
+
+
+ SET_DEACTIVATED_AGENT(state, data) {
+ state.agents.forEach((agent) => {
+ if (agent.id == data) {
+ agent.status = "DISABLED"
+ }
+ })
+ },
+
+ SET_ACTIVATED_AGENT(state, data) {
+ state.agents.forEach((agent) => {
+ if (agent.id == data) {
+ agent.status = "ACTIVE"
+ }
+ })
+ },
+
+ RESET(state) {
+ Object.assign(state, getDefaultState())
+ }
+
+}
+
+const getters = {
+
+ getAgents(state) {
+ return state.agents
+ },
+
+ isAgentsAreEnabled(state) {
+ return state.isAgentsEnabled
+ },
+
+ getAgentClientRoles(state) {
+ return state.clientLevelRoles
+ }
+
+}
+
+export default {
+ namespaced: true,
+ state,
+ getters,
+ actions,
+ mutations
+}
+
diff --git a/custos-demo-gateway/src/store/modules/group.store.js b/custos-demo-gateway/src/store/modules/group.store.js
new file mode 100644
index 0000000..986a580
--- /dev/null
+++ b/custos-demo-gateway/src/store/modules/group.store.js
@@ -0,0 +1,153 @@
+/*Group.store.js*/
+
+import group_management from "@/service/group_management";
+
+
+const getDefaultState = () => {
+ return {
+ groups: [],
+ }
+}
+
+const state = getDefaultState()
+
+
+const actions = {
+
+ async createGroup({commit}, data) {
+ let resp = await group_management.createGroup(data)
+ let group = resp.data.groups[0];
+ commit('SET_GROUP', group)
+ return group
+ },
+
+ async loadAllGroups({commit}, data) {
+ let rep = await group_management.getAllGroups(data)
+ let groups = rep.data.groups
+ commit('SET_GROUPS', groups)
+ return groups
+ },
+
+
+ async updateGroup({commit}, data) {
+ let response = await group_management.updateGroup(data)
+ commit('SET_GROUP', response.data)
+ return response.data
+ },
+
+ async deleteGroup({commit}, data) {
+ let response = await group_management.deleteGroup(data)
+ if (response.data.status) {
+ commit('SET_DELETED_GROUP', data.group_id)
+ return response.data
+ }
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async getGroup({commit}, data) {
+ let response = await group_management.findGroup(data)
+ return response.data
+ },
+
+
+ // eslint-disable-next-line no-unused-vars
+ async addUserToGroup({commit}, data) {
+ let response = await group_management.addUserToGroup(data)
+ return response.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async removeUserFromGroup({commit}, data) {
+ let response = await group_management.removeUserFromGroup(data)
+ return response.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async addChildGroup({commit}, data) {
+ let response = await group_management.addChildGroup(data)
+ return response.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async removeChildGroup({commit}, data) {
+ let response = await group_management.removeChildGroup(data)
+ return response.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async changeGroupMembership({commit}, data) {
+ let response = await group_management.changeGroupMembership(data)
+ return response.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async getAllChildUsers({commit}, data) {
+ let response = await group_management.getAllChildUsers(data)
+ return response.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async getAllChildGroups({commit}, data) {
+ let response = await group_management.getAllChildGroups(data)
+ return response.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async reset({commit}, data){
+ commit('RESET')
+ return true
+ }
+
+}
+
+
+const mutations = {
+
+
+ SET_GROUP(state, data) {
+ let grs = []
+ state.groups.forEach((gr) => {
+ if (gr.id !== data.id) {
+ grs.push(gr)
+ }
+ })
+ grs.push(data)
+ state.groups = grs
+ },
+
+ SET_DELETED_GROUP(state, data) {
+ let grs = []
+ state.groups.forEach((gr) => {
+ if (gr.id !== data) {
+ grs.push(gr)
+ }
+ })
+ state.groups = grs
+ },
+
+ SET_GROUPS(state, data) {
+ state.groups = data
+ },
+
+
+ RESET(state) {
+ Object.assign(state, getDefaultState())
+ }
+
+}
+
+const getters = {
+
+ getGroups(state) {
+ return state.groups
+ }
+
+}
+
+export default {
+ namespaced: true,
+ state,
+ getters,
+ actions,
+ mutations
+}
diff --git a/custos-demo-gateway/src/store/modules/identity.store.js b/custos-demo-gateway/src/store/modules/identity.store.js
new file mode 100644
index 0000000..0bd66eb
--- /dev/null
+++ b/custos-demo-gateway/src/store/modules/identity.store.js
@@ -0,0 +1,134 @@
+/*Identity.store.js*/
+
+import identity_management from "@/service/identity_management";
+import auth from "@/service/auth";
+
+
+const state = {
+ authorizationEndpoint: null,
+ idToken: localStorage.getItem('id_token') || '',
+ accessToken: localStorage.getItem('access_token') || '',
+ refreshToken: localStorage.getItem('refresh_token') || '',
+ currentUserName: null
+}
+const actions = {
+
+ async fetchAuthorizationEndpoint({commit}, data) {
+ let resp = await identity_management.getOpenIdConfig(data)
+ let baseURL = resp.data.authorization_endpoint
+ this.authorizartionURL = baseURL + "?response_type=code&client_id=" + data.client_id + "&" +
+ "redirect_uri="+data.redirect_uri+"&scope=openid&kc_idp_hint=oidc"
+ commit('SET_AUTH_ENDPOINT', this.authorizartionURL)
+
+ },
+
+ async authenticateUsingCode({commit}, data) {
+ let resp = await identity_management.getToken(data)
+ commit('SET_AUTH_TOKEN', resp.data)
+ },
+
+ async authenticateLocally({commit}, data) {
+ try {
+ let resp = await identity_management.localLogin(data)
+ commit('SET_AUTH_TOKEN', resp.data)
+ }catch (e) {
+ return false
+ }
+ },
+
+ async logout({commit}, data) {
+ let dat = {
+ client_id: data.client_id,
+ client_sec: data.client_sec,
+ refresh_token: auth.getRefreshToken()
+ }
+ await identity_management.logout(dat)
+ commit('CLEAR_AUTH_TOKEN', data)
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async isAuthenticated({commit}, data) {
+ try {
+ let resp = auth.isLoggedIn()
+ if (!resp) {
+ let dat = {
+ client_id: data.client_id,
+ client_sec: data.client_sec,
+ refresh_token: auth.getRefreshToken()
+ }
+ let response = await identity_management.getTokenUsingRefreshToken(dat)
+ commit('SET_AUTH_TOKEN', response.data)
+ return auth.isLoggedIn()
+ }
+ return true
+ } catch (e) {
+ commit('CLEAR_AUTH_TOKEN')
+ }
+
+ },
+
+
+ // eslint-disable-next-line no-unused-vars
+ async isLoggedUserHasAdminAccess({commit, data}){
+ return auth.isUserHasAdminAccess()
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async getCurrentUserName({commit}, data){
+ return auth.getLoggedUsername()
+ }
+
+}
+
+
+const mutations = {
+
+ SET_AUTH_ENDPOINT(state, data) {
+ state.authorizationEndpoint = data
+ },
+
+ SET_AUTH_TOKEN(state, data) {
+ auth.clearIdToken()
+ auth.clearAccessToken()
+ auth.clearRefreshToken()
+ auth.setIdToken(data.id_token)
+ auth.setAccessToken(data.access_token)
+ auth.setRefreshToken(data.refresh_token)
+ state.token = data.id_token
+ state.accessToken = data.access_token
+ state.refreshToken = data.refresh_token
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ CLEAR_AUTH_TOKEN(state, data) {
+ auth.clearIdToken()
+ auth.clearAccessToken()
+ auth.clearRefreshToken()
+ state.idToken = ''
+ state.accessToken = ''
+ state.refreshToken = ''
+ }
+}
+
+const getters = {
+ getAuthorizationEndpoint(state) {
+ return state.authorizationEndpoint
+ },
+ isAuthenticated() {
+ return auth.isLoggedIn()
+ },
+
+ getAccessToken(state) {
+ return state.accessToken;
+ },
+
+
+}
+
+export default {
+ namespaced: true,
+ state,
+ getters,
+ actions,
+ mutations
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/store/modules/log.store.js b/custos-demo-gateway/src/store/modules/log.store.js
new file mode 100644
index 0000000..993b1c6
--- /dev/null
+++ b/custos-demo-gateway/src/store/modules/log.store.js
@@ -0,0 +1,46 @@
+/*log.store.js*/
+
+import log_management from "@/service/log_management";
+
+const getDefaultState = () => {
+ return {}
+}
+
+const state = getDefaultState()
+
+const actions = {
+
+ // eslint-disable-next-line no-unused-vars
+ async getLogEvents({commit}, data) {
+ let response = await log_management.getLogEvents(data)
+ return response.data.events
+ },
+
+
+ // eslint-disable-next-line no-unused-vars
+ async isLoggingEnabled({commit}, data) {
+ let response = await log_management.isLoggingEnabled(data)
+ return response.data.status
+ },
+
+
+ // eslint-disable-next-line no-unused-vars
+ async enableLogging({commit}, data) {
+ let response = await log_management.enableLogging(data)
+ return response.data.status
+ },
+
+
+}
+
+const mutations = {}
+
+const getters = {}
+
+export default {
+ namespaced: true,
+ state,
+ getters,
+ actions,
+ mutations
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/store/modules/secret.store.js b/custos-demo-gateway/src/store/modules/secret.store.js
new file mode 100644
index 0000000..68897cf
--- /dev/null
+++ b/custos-demo-gateway/src/store/modules/secret.store.js
@@ -0,0 +1,116 @@
+/*Secret.store.js*/
+
+import secret_management from "@/service/secret_management";
+
+
+const getDefaultState = () => {
+ return {
+ secrets: []
+ }
+}
+
+const state = getDefaultState()
+
+const actions = {
+
+ async addSSHCredential({commit}, data) {
+ let resp = await secret_management.addSSHCredential(data)
+ commit('ADD_SECRET', resp.data.token)
+ return resp.data
+ },
+
+
+ async addPasswordCredential({commit}, data) {
+ let resp = await secret_management.addPasswordCredential(data)
+ commit('ADD_SECRET', resp.data.token)
+ return resp.data
+ },
+
+
+ // eslint-disable-next-line no-unused-vars
+ async getSSHCredential({commit}, data) {
+ let resp = await secret_management.getSSHCredential(data)
+ return resp.data
+ },
+
+
+ // eslint-disable-next-line no-unused-vars
+ async getPasswordCredential({commit}, data) {
+ let resp = await secret_management.getPasswordCredential(data)
+ return resp.data
+ },
+
+ async deleteSSHCredential({commit}, data) {
+ let resp = await secret_management.deleteSSHCredential(data)
+ if (resp.data.status) {
+ commit('DELETE_SECRET', data.token)
+ }
+ return resp.data
+ },
+
+ async deletePassswordCredential({commit}, data) {
+ let resp = await secret_management.deletePasswordCredential(data)
+ if (resp.data.status) {
+ commit('DELETE_SECRET', data.token)
+ }
+ return resp.data
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async getAllCredentials({commit}, data) {
+ let dat = {
+ client_id: data.client_id, client_sec: data.client_sec, params: {
+ client_id: data.client_id,
+ accessible_tokens: data.accessible_tokens
+ }
+ }
+ console.log(dat)
+ let response = await secret_management.getAllCredentials(dat)
+ return response.data.metadata
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async reset({commit}, data){
+ commit('RESET')
+ return true
+ }
+
+}
+
+const mutations = {
+
+ ADD_SECRET(state, data) {
+ state.secrets.push(data)
+ },
+
+ DELETE_SECRET(state, data) {
+ let secrets = []
+ state.secrets.forEach(sec => {
+ if (sec != data) {
+ secrets.push(sec)
+ }
+ })
+ state.secrets = secrets
+ },
+
+ RESET(state) {
+ Object.assign(state, getDefaultState())
+ }
+
+}
+
+const getters = {
+
+ getSecrets(state) {
+ return state.secrets
+ }
+
+}
+
+export default {
+ namespaced: true,
+ state,
+ getters,
+ actions,
+ mutations
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/store/modules/sharing.store.js b/custos-demo-gateway/src/store/modules/sharing.store.js
new file mode 100644
index 0000000..2de7e5b
--- /dev/null
+++ b/custos-demo-gateway/src/store/modules/sharing.store.js
@@ -0,0 +1,227 @@
+import sharing_management from "@/service/sharing_management";
+
+const getDefaultState = () => {
+ return {
+ entities: [],
+ permissionTypes: [],
+ entityTypes: [],
+ sharings: []
+ }
+}
+
+const state = getDefaultState()
+
+const actions = {
+
+ async createPermissionType({commit}, data) {
+ let response = await sharing_management.createPermissionType(data)
+ if (response.data.status) {
+ commit('ADD_PERMISSION_TYPE', data.body.permission_type)
+ }
+ return state.permissionTypes
+ },
+
+ async deletePermissionType({commit}, data) {
+ let response = await sharing_management.deletePermissionType(data)
+ if (response.data.status) {
+ commit('REMOVE_PERMISSION_TYPE', data.body.permission_type)
+ }
+ return state.permissionTypes
+ },
+
+ async createEntityType({commit}, data) {
+ let response = await sharing_management.createEntityType(data)
+ if (response.data.status) {
+ commit('ADD_ENTITY_TYPE', data.body.entity_type)
+ }
+ return state.entityTypes
+ },
+
+ async deleteEntityType({commit}, data) {
+ let response = await sharing_management.deleteEntityType(data)
+ if (response.data.status) {
+ commit('REMOVE_ENTITY_TYPE', data.body.entity_type)
+ }
+ return state.entityTypes
+ },
+
+ async createEntity({commit}, data) {
+ let response = await sharing_management.createEntity(data)
+ if (response.data.status) {
+ commit('ADD_ENTITY', data.body.entity)
+ }
+ return state.entities
+ },
+
+ async deleteEntity({commit}, data) {
+ let response = await sharing_management.deleteEntity(data)
+ if (response.data.status) {
+ commit('REMOVE_ENTITY', data.body.entity)
+ }
+ return state.entities
+ },
+
+ async getPermissionTypes({commit}, data) {
+ let response = await sharing_management.getPermissionTypes(data)
+ commit('SET_PERMISSION_TYPES', response.data.types)
+ return response.data.types
+ },
+
+ async getEntityTypes({commit}, data) {
+ let response = await sharing_management.getEntityTypes(data)
+ commit('SET_ENTITY_TYPES', response.data.types)
+ return response.data.types
+ },
+
+ async getEntities({commit}, data) {
+ let response = await sharing_management.getEntities(data)
+ commit('SET_ENTITIES', response.data.entity_array)
+ return response.data.entity_array
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async getListOfSharedUsers({commit}, data) {
+ let response = await sharing_management.getListOfSharedUsers(data)
+ return response.data.owner_ids
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async getListOfSharedGroups({commit}, data) {
+ let response = await sharing_management.getListOfSharedGroups(data)
+ return response.data.owner_ids
+ },
+
+
+ // eslint-disable-next-line no-unused-vars
+ async shareEntityWithUsers({commit}, data) {
+ let response = await sharing_management.shareEntityWithUsers(data)
+ return response.data.status
+ },
+
+
+ // eslint-disable-next-line no-unused-vars
+ async shareEntityWithGroups({commit}, data) {
+ let response = await sharing_management.shareEntityWithGroups(data)
+ return response.data.status
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async revokeEntitySharingFromUsers({commit}, data) {
+ let response = await sharing_management.revokeEntitySharingFromUsers(data)
+ return response.data.status
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async revokeEntitySharingFromGroups({commit}, data) {
+ let response = await sharing_management.revokeEntitySharingFromGroups(data)
+ return response.data.status
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async userHasAccess({commit}, data) {
+ let response = await sharing_management.userHasAccess(data)
+ return response.data.status
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async reset({commit}, data){
+ commit('RESET')
+ return true
+ }
+}
+
+const mutations = {
+
+ ADD_PERMISSION_TYPE(state, data) {
+ state.permissionTypes.push(data)
+ },
+
+ REMOVE_PERMISSION_TYPE(state, data) {
+ let permTypes = []
+ state.permissionTypes.forEach(perm => {
+ if (perm.id != data.id) {
+ permTypes.push(perm)
+ }
+ })
+ state.permissionTypes = permTypes
+ },
+
+ ADD_ENTITY_TYPE(state, data) {
+ state.entityTypes.push(data)
+ },
+
+ REMOVE_ENTITY_TYPE(state, data) {
+ let permTypes = []
+ state.entityTypes.forEach(perm => {
+ if (perm.id != data.id) {
+ permTypes.push(perm)
+ }
+ })
+ state.entityTypes = permTypes
+ },
+
+ ADD_ENTITY(state, data) {
+ state.entities.push(data)
+ },
+
+ REMOVE_ENTITY(state, data) {
+ let permTypes = []
+ state.entities.forEach(perm => {
+ if (perm.id !== data.id) {
+ permTypes.push(perm)
+ }
+ })
+ state.entities = permTypes
+ },
+
+ SET_PERMISSION_TYPES(state, data) {
+ state.permissionTypes = data
+ },
+
+ SET_ENTITY_TYPES(state, data) {
+ state.entityTypes = data
+ },
+
+ SET_ENTITIES(state, data) {
+ state.entities = data
+ },
+
+ SET_SHARING(state, data) {
+ state.sharings = data
+ },
+
+ RESET(state) {
+ Object.assign(state, getDefaultState())
+ }
+
+
+}
+
+const getters = {
+
+ getEntities(state) {
+ return state.entities
+ },
+ getPermissionTypes(state) {
+ return state.permissionTypes
+ },
+ getEntityTypes(state) {
+ return state.entityTypes
+ },
+
+ getSharings(state) {
+ return state.sharings
+ },
+
+
+
+}
+
+
+export default {
+ namespaced: true,
+ state,
+ getters,
+ actions,
+ mutations
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/src/store/modules/user.store.js b/custos-demo-gateway/src/store/modules/user.store.js
new file mode 100644
index 0000000..24b80be
--- /dev/null
+++ b/custos-demo-gateway/src/store/modules/user.store.js
@@ -0,0 +1,149 @@
+import user_management from "@/service/user_management";
+
+
+const getDefaultState = () => {
+ return {
+ users: [],
+ tenantLevelRoles: [],
+ clientLevelRoles: []
+ }
+}
+
+const state = getDefaultState()
+
+const actions = {
+ // eslint-disable-next-line no-unused-vars
+ async registerUser({commit}, data) {
+ let resp = await user_management.registerUser(data)
+ if (resp.data.is_registered) {
+ let secData = {
+ 'username': data.username, 'client_id': data.client_id,
+ 'client_sec': data.client_sec,
+ }
+ await user_management.enableUser(secData)
+ return true
+ }
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async checkUsernameIsValid({commit}, data) {
+
+ let rep = await user_management.checkUsernameValidity(data)
+ return rep.data.status
+ },
+
+ async users({commit}, data) {
+ let response = await user_management.findUsers(data)
+ commit('SET_USERS', response.data.users)
+ return response.data.users
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async addUserAttributes({commit}, data) {
+ let response = await user_management.addUserAttribute(data)
+ return response.data.status
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async deleteUserAttributes({commit}, data) {
+ let response = await user_management.deleteUserAttribute(data)
+ return response.data.status
+ },
+
+ async getTenantLevelRoles({commit}, data) {
+ let roles = await user_management.getTenantLevelRoles(data)
+ let tRoles = []
+ roles.data.roles.forEach(r => {
+ tRoles.push(r.name)
+ })
+ commit('SET_TENANT_LEVEL_ROLES', tRoles)
+ return tRoles
+
+ },
+
+ async getClientLevelRoles({commit}, data) {
+ let roles = await user_management.getClientLevelRoles(data)
+ let tRoles = []
+ roles.data.roles.forEach(r => {
+ tRoles.push(r.name)
+ })
+ commit('SET_CLIENT_LEVEL_ROLES', tRoles)
+ return tRoles
+
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async addRoleToUser({commit}, data) {
+ let response = await user_management.addRolesToUser(data)
+ return response.data.status
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async deleteRoleFromUser({commit}, data) {
+ let response = await user_management.deleteRolesFromUser(data)
+ return response.data.status
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async enableUser ({commit}, data) {
+ let response = await user_management.enableUser(data)
+ return response.data.state
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async disableUser({commit}, data) {
+ let response = await user_management.disableUser(data)
+ return response.data.state
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async updateUserProfile({commit}, data) {
+ return await user_management.updateProfile(data)
+ },
+
+ // eslint-disable-next-line no-unused-vars
+ async reset({commit}, data){
+ commit('RESET')
+ return true
+ }
+
+}
+
+
+const mutations = {
+
+
+ SET_USERS(state, data) {
+ state.users = data
+ },
+
+
+ SET_TENANT_LEVEL_ROLES(state, data) {
+ state.tenantLevelRoles = data
+ },
+
+ SET_CLIENT_LEVEL_ROLES(state, data) {
+ state.clientLevelRoles = data
+ },
+
+ RESET(state) {
+ Object.assign(state, getDefaultState())
+ }
+
+}
+
+const getters = {
+
+ getUsers(state) {
+ return state.users
+ },
+
+}
+
+export default {
+ namespaced: true,
+ state,
+ getters,
+ actions,
+ mutations
+}
\ No newline at end of file
diff --git a/custos-demo-gateway/yarn-error.log b/custos-demo-gateway/yarn-error.log
new file mode 100644
index 0000000..0eb12e1
--- /dev/null
+++ b/custos-demo-gateway/yarn-error.log
@@ -0,0 +1,8587 @@
+Arguments:
+ /usr/local/Cellar/node@10/10.20.1_1/bin/node /usr/local/Cellar/yarn/1.22.4/libexec/bin/yarn.js install
+
+PATH:
+ /Library/Frameworks/Python.framework/Versions/3.6/bin:/usr/local/opt/node@10/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin:/opt/X11/bin
+
+Yarn version:
+ 1.22.4
+
+Node version:
+ 10.20.1
+
+Platform:
+ darwin x64
+
+Trace:
+ SyntaxError: /Users/isururanawaka/Documents/Airavata_Repository/custos-demo-gateway/package.json: Unexpected token } in JSON at position 631
+ at JSON.parse (<anonymous>)
+ at /usr/local/Cellar/yarn/1.22.4/libexec/lib/cli.js:1625:59
+ at Generator.next (<anonymous>)
+ at step (/usr/local/Cellar/yarn/1.22.4/libexec/lib/cli.js:310:30)
+ at /usr/local/Cellar/yarn/1.22.4/libexec/lib/cli.js:321:13
+
+npm manifest:
+ {
+ "name": "custos-demo-gateway",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "serve": "vue-cli-service serve",
+ "build": "vue-cli-service build",
+ "lint": "vue-cli-service lint"
+ },
+ "dependencies": {
+ "core-js": "^3.6.5",
+ "vue": "^2.6.11",
+ "vue-router": "^3.4.3",
+ "bootstrap-vue": "^2.16.0",
+ "axios": "^0.20.0"
+ },
+ "devDependencies": {
+ "@vue/cli-plugin-babel": "~4.5.0",
+ "@vue/cli-plugin-eslint": "~4.5.0",
+ "@vue/cli-service": "~4.5.0",
+ "babel-eslint": "^10.1.0",
+ "eslint": "^6.7.2",
+ "eslint-plugin-vue": "^6.2.2",
+ "vue-template-compiler": "^2.6.11",
+
+ },
+ "eslintConfig": {
+ "root": true,
+ "env": {
+ "node": true
+ },
+ "extends": [
+ "plugin:vue/essential",
+ "eslint:recommended"
+ ],
+ "parserOptions": {
+ "parser": "babel-eslint"
+ },
+ "rules": {}
+ },
+ "browserslist": [
+ "> 1%",
+ "last 2 versions",
+ "not dead"
+ ]
+ }
+
+yarn manifest:
+ No manifest
+
+Lockfile:
+ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+ # yarn lockfile v1
+
+
+ "@ant-design-vue/babel-helper-vue-transform-on@^1.0.0":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@ant-design-vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.1.tgz#d219d92f4e1fc5e7add211c347c7fa000518b623"
+ integrity sha512-dOAPf/tCM2lCG8FhvOMFBaOdMElMEGhOoocMXEWvHW2l1KIex+UibDcq4bdBEJpDMLrnbNOqci9E7P2dARP6lg==
+
+ "@ant-design-vue/babel-plugin-jsx@^1.0.0-0":
+ version "1.0.0-rc.1"
+ resolved "https://registry.yarnpkg.com/@ant-design-vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.0-rc.1.tgz#ae56cecbda9f08691bcf92dfe98e2416e77d758b"
+ integrity sha512-x7PfAHSs5/emIuey1Df7Bh/vJU27S9KBdufzoAA7kgwTpEpY85R7CXD9gl6sJFB7aG2pZpl4Tmm+FsHlzgp7fA==
+ dependencies:
+ "@ant-design-vue/babel-helper-vue-transform-on" "^1.0.0"
+ "@babel/helper-module-imports" "^7.0.0"
+ "@babel/plugin-syntax-jsx" "^7.0.0"
+ "@babel/traverse" "^7.0.0"
+ "@babel/types" "^7.0.0"
+ camelcase "^6.0.0"
+ html-tags "^3.1.0"
+ svg-tags "^1.0.0"
+
+ "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
+ integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==
+ dependencies:
+ "@babel/highlight" "^7.10.4"
+
+ "@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c"
+ integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==
+ dependencies:
+ browserslist "^4.12.0"
+ invariant "^2.2.4"
+ semver "^5.5.0"
+
+ "@babel/core@^7.11.0":
+ version "7.11.6"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651"
+ integrity sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/generator" "^7.11.6"
+ "@babel/helper-module-transforms" "^7.11.0"
+ "@babel/helpers" "^7.10.4"
+ "@babel/parser" "^7.11.5"
+ "@babel/template" "^7.10.4"
+ "@babel/traverse" "^7.11.5"
+ "@babel/types" "^7.11.5"
+ convert-source-map "^1.7.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.1"
+ json5 "^2.1.2"
+ lodash "^4.17.19"
+ resolve "^1.3.2"
+ semver "^5.4.1"
+ source-map "^0.5.0"
+
+ "@babel/generator@^7.11.5", "@babel/generator@^7.11.6":
+ version "7.11.6"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620"
+ integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==
+ dependencies:
+ "@babel/types" "^7.11.5"
+ jsesc "^2.5.1"
+ source-map "^0.5.0"
+
+ "@babel/helper-annotate-as-pure@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3"
+ integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==
+ dependencies:
+ "@babel/types" "^7.10.4"
+
+ "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3"
+ integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==
+ dependencies:
+ "@babel/helper-explode-assignable-expression" "^7.10.4"
+ "@babel/types" "^7.10.4"
+
+ "@babel/helper-compilation-targets@^7.10.4", "@babel/helper-compilation-targets@^7.9.6":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2"
+ integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==
+ dependencies:
+ "@babel/compat-data" "^7.10.4"
+ browserslist "^4.12.0"
+ invariant "^2.2.4"
+ levenary "^1.1.1"
+ semver "^5.5.0"
+
+ "@babel/helper-create-class-features-plugin@^7.10.4", "@babel/helper-create-class-features-plugin@^7.10.5":
+ version "7.10.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d"
+ integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==
+ dependencies:
+ "@babel/helper-function-name" "^7.10.4"
+ "@babel/helper-member-expression-to-functions" "^7.10.5"
+ "@babel/helper-optimise-call-expression" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/helper-replace-supers" "^7.10.4"
+ "@babel/helper-split-export-declaration" "^7.10.4"
+
+ "@babel/helper-create-regexp-features-plugin@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8"
+ integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.10.4"
+ "@babel/helper-regex" "^7.10.4"
+ regexpu-core "^4.7.0"
+
+ "@babel/helper-define-map@^7.10.4":
+ version "7.10.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30"
+ integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==
+ dependencies:
+ "@babel/helper-function-name" "^7.10.4"
+ "@babel/types" "^7.10.5"
+ lodash "^4.17.19"
+
+ "@babel/helper-explode-assignable-expression@^7.10.4":
+ version "7.11.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz#2d8e3470252cc17aba917ede7803d4a7a276a41b"
+ integrity sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==
+ dependencies:
+ "@babel/types" "^7.10.4"
+
+ "@babel/helper-function-name@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a"
+ integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==
+ dependencies:
+ "@babel/helper-get-function-arity" "^7.10.4"
+ "@babel/template" "^7.10.4"
+ "@babel/types" "^7.10.4"
+
+ "@babel/helper-get-function-arity@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2"
+ integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==
+ dependencies:
+ "@babel/types" "^7.10.4"
+
+ "@babel/helper-hoist-variables@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e"
+ integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==
+ dependencies:
+ "@babel/types" "^7.10.4"
+
+ "@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df"
+ integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==
+ dependencies:
+ "@babel/types" "^7.11.0"
+
+ "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.8.3":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620"
+ integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==
+ dependencies:
+ "@babel/types" "^7.10.4"
+
+ "@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359"
+ integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==
+ dependencies:
+ "@babel/helper-module-imports" "^7.10.4"
+ "@babel/helper-replace-supers" "^7.10.4"
+ "@babel/helper-simple-access" "^7.10.4"
+ "@babel/helper-split-export-declaration" "^7.11.0"
+ "@babel/template" "^7.10.4"
+ "@babel/types" "^7.11.0"
+ lodash "^4.17.19"
+
+ "@babel/helper-optimise-call-expression@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673"
+ integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==
+ dependencies:
+ "@babel/types" "^7.10.4"
+
+ "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375"
+ integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==
+
+ "@babel/helper-regex@^7.10.4":
+ version "7.10.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0"
+ integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==
+ dependencies:
+ lodash "^4.17.19"
+
+ "@babel/helper-remap-async-to-generator@^7.10.4":
+ version "7.11.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz#4474ea9f7438f18575e30b0cac784045b402a12d"
+ integrity sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.10.4"
+ "@babel/helper-wrap-function" "^7.10.4"
+ "@babel/template" "^7.10.4"
+ "@babel/types" "^7.10.4"
+
+ "@babel/helper-replace-supers@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf"
+ integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==
+ dependencies:
+ "@babel/helper-member-expression-to-functions" "^7.10.4"
+ "@babel/helper-optimise-call-expression" "^7.10.4"
+ "@babel/traverse" "^7.10.4"
+ "@babel/types" "^7.10.4"
+
+ "@babel/helper-simple-access@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461"
+ integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==
+ dependencies:
+ "@babel/template" "^7.10.4"
+ "@babel/types" "^7.10.4"
+
+ "@babel/helper-skip-transparent-expression-wrappers@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729"
+ integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==
+ dependencies:
+ "@babel/types" "^7.11.0"
+
+ "@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f"
+ integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==
+ dependencies:
+ "@babel/types" "^7.11.0"
+
+ "@babel/helper-validator-identifier@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
+ integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==
+
+ "@babel/helper-wrap-function@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87"
+ integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==
+ dependencies:
+ "@babel/helper-function-name" "^7.10.4"
+ "@babel/template" "^7.10.4"
+ "@babel/traverse" "^7.10.4"
+ "@babel/types" "^7.10.4"
+
+ "@babel/helpers@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044"
+ integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==
+ dependencies:
+ "@babel/template" "^7.10.4"
+ "@babel/traverse" "^7.10.4"
+ "@babel/types" "^7.10.4"
+
+ "@babel/highlight@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143"
+ integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.10.4"
+ chalk "^2.0.0"
+ js-tokens "^4.0.0"
+
+ "@babel/parser@^7.10.4", "@babel/parser@^7.11.5", "@babel/parser@^7.7.0":
+ version "7.11.5"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037"
+ integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==
+
+ "@babel/plugin-proposal-async-generator-functions@^7.10.4":
+ version "7.10.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558"
+ integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/helper-remap-async-to-generator" "^7.10.4"
+ "@babel/plugin-syntax-async-generators" "^7.8.0"
+
+ "@babel/plugin-proposal-class-properties@^7.10.4", "@babel/plugin-proposal-class-properties@^7.8.3":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807"
+ integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-proposal-decorators@^7.8.3":
+ version "7.10.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.5.tgz#42898bba478bc4b1ae242a703a953a7ad350ffb4"
+ integrity sha512-Sc5TAQSZuLzgY0664mMDn24Vw2P8g/VhyLyGPaWiHahhgLqeZvcGeyBZOrJW0oSKIK2mvQ22a1ENXBIQLhrEiQ==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.10.5"
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/plugin-syntax-decorators" "^7.10.4"
+
+ "@babel/plugin-proposal-dynamic-import@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e"
+ integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.0"
+
+ "@babel/plugin-proposal-export-namespace-from@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz#570d883b91031637b3e2958eea3c438e62c05f54"
+ integrity sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
+
+ "@babel/plugin-proposal-json-strings@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db"
+ integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/plugin-syntax-json-strings" "^7.8.0"
+
+ "@babel/plugin-proposal-logical-assignment-operators@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8"
+ integrity sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+
+ "@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a"
+ integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0"
+
+ "@babel/plugin-proposal-numeric-separator@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06"
+ integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+
+ "@babel/plugin-proposal-object-rest-spread@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af"
+ integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.0"
+ "@babel/plugin-transform-parameters" "^7.10.4"
+
+ "@babel/plugin-proposal-optional-catch-binding@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd"
+ integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.0"
+
+ "@babel/plugin-proposal-optional-chaining@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076"
+ integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.0"
+
+ "@babel/plugin-proposal-private-methods@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909"
+ integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d"
+ integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-syntax-async-generators@^7.8.0":
+ version "7.8.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
+ integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+ "@babel/plugin-syntax-class-properties@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c"
+ integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-syntax-decorators@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.10.4.tgz#6853085b2c429f9d322d02f5a635018cdeb2360c"
+ integrity sha512-2NaoC6fAk2VMdhY1eerkfHV+lVYC1u8b+jmRJISqANCJlTxYy19HGdIkkQtix2UtkcPuPu+IlDgrVseZnU03bw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
+ integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+ "@babel/plugin-syntax-export-namespace-from@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a"
+ integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.3"
+
+ "@babel/plugin-syntax-json-strings@^7.8.0":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
+ integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+ "@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.2.0", "@babel/plugin-syntax-jsx@^7.8.3":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c"
+ integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-syntax-logical-assignment-operators@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
+ integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
+ integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+ "@babel/plugin-syntax-numeric-separator@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97"
+ integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-syntax-object-rest-spread@^7.8.0":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
+ integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+ "@babel/plugin-syntax-optional-catch-binding@^7.8.0":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1"
+ integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+ "@babel/plugin-syntax-optional-chaining@^7.8.0":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a"
+ integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+ "@babel/plugin-syntax-top-level-await@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d"
+ integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-arrow-functions@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd"
+ integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-async-to-generator@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37"
+ integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==
+ dependencies:
+ "@babel/helper-module-imports" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/helper-remap-async-to-generator" "^7.10.4"
+
+ "@babel/plugin-transform-block-scoped-functions@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8"
+ integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-block-scoping@^7.10.4":
+ version "7.11.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215"
+ integrity sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-classes@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7"
+ integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.10.4"
+ "@babel/helper-define-map" "^7.10.4"
+ "@babel/helper-function-name" "^7.10.4"
+ "@babel/helper-optimise-call-expression" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/helper-replace-supers" "^7.10.4"
+ "@babel/helper-split-export-declaration" "^7.10.4"
+ globals "^11.1.0"
+
+ "@babel/plugin-transform-computed-properties@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb"
+ integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-destructuring@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5"
+ integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee"
+ integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-duplicate-keys@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47"
+ integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-exponentiation-operator@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e"
+ integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==
+ dependencies:
+ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-for-of@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9"
+ integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-function-name@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7"
+ integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==
+ dependencies:
+ "@babel/helper-function-name" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-literals@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c"
+ integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-member-expression-literals@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7"
+ integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-modules-amd@^7.10.4":
+ version "7.10.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1"
+ integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.10.5"
+ "@babel/helper-plugin-utils" "^7.10.4"
+ babel-plugin-dynamic-import-node "^2.3.3"
+
+ "@babel/plugin-transform-modules-commonjs@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0"
+ integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/helper-simple-access" "^7.10.4"
+ babel-plugin-dynamic-import-node "^2.3.3"
+
+ "@babel/plugin-transform-modules-systemjs@^7.10.4":
+ version "7.10.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85"
+ integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==
+ dependencies:
+ "@babel/helper-hoist-variables" "^7.10.4"
+ "@babel/helper-module-transforms" "^7.10.5"
+ "@babel/helper-plugin-utils" "^7.10.4"
+ babel-plugin-dynamic-import-node "^2.3.3"
+
+ "@babel/plugin-transform-modules-umd@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e"
+ integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-named-capturing-groups-regex@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6"
+ integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.10.4"
+
+ "@babel/plugin-transform-new-target@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888"
+ integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-object-super@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894"
+ integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/helper-replace-supers" "^7.10.4"
+
+ "@babel/plugin-transform-parameters@^7.10.4":
+ version "7.10.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a"
+ integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==
+ dependencies:
+ "@babel/helper-get-function-arity" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-property-literals@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0"
+ integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-regenerator@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63"
+ integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==
+ dependencies:
+ regenerator-transform "^0.14.2"
+
+ "@babel/plugin-transform-reserved-words@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd"
+ integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-runtime@^7.11.0":
+ version "7.11.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.5.tgz#f108bc8e0cf33c37da031c097d1df470b3a293fc"
+ integrity sha512-9aIoee+EhjySZ6vY5hnLjigHzunBlscx9ANKutkeWTJTx6m5Rbq6Ic01tLvO54lSusR+BxV7u4UDdCmXv5aagg==
+ dependencies:
+ "@babel/helper-module-imports" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+ resolve "^1.8.1"
+ semver "^5.5.1"
+
+ "@babel/plugin-transform-shorthand-properties@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6"
+ integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-spread@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc"
+ integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0"
+
+ "@babel/plugin-transform-sticky-regex@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d"
+ integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/helper-regex" "^7.10.4"
+
+ "@babel/plugin-transform-template-literals@^7.10.4":
+ version "7.10.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c"
+ integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-typeof-symbol@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc"
+ integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-unicode-escapes@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007"
+ integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/plugin-transform-unicode-regex@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8"
+ integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+ "@babel/preset-env@^7.11.0":
+ version "7.11.5"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.5.tgz#18cb4b9379e3e92ffea92c07471a99a2914e4272"
+ integrity sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==
+ dependencies:
+ "@babel/compat-data" "^7.11.0"
+ "@babel/helper-compilation-targets" "^7.10.4"
+ "@babel/helper-module-imports" "^7.10.4"
+ "@babel/helper-plugin-utils" "^7.10.4"
+ "@babel/plugin-proposal-async-generator-functions" "^7.10.4"
+ "@babel/plugin-proposal-class-properties" "^7.10.4"
+ "@babel/plugin-proposal-dynamic-import" "^7.10.4"
+ "@babel/plugin-proposal-export-namespace-from" "^7.10.4"
+ "@babel/plugin-proposal-json-strings" "^7.10.4"
+ "@babel/plugin-proposal-logical-assignment-operators" "^7.11.0"
+ "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4"
+ "@babel/plugin-proposal-numeric-separator" "^7.10.4"
+ "@babel/plugin-proposal-object-rest-spread" "^7.11.0"
+ "@babel/plugin-proposal-optional-catch-binding" "^7.10.4"
+ "@babel/plugin-proposal-optional-chaining" "^7.11.0"
+ "@babel/plugin-proposal-private-methods" "^7.10.4"
+ "@babel/plugin-proposal-unicode-property-regex" "^7.10.4"
+ "@babel/plugin-syntax-async-generators" "^7.8.0"
+ "@babel/plugin-syntax-class-properties" "^7.10.4"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.0"
+ "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
+ "@babel/plugin-syntax-json-strings" "^7.8.0"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.0"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.0"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.0"
+ "@babel/plugin-syntax-top-level-await" "^7.10.4"
+ "@babel/plugin-transform-arrow-functions" "^7.10.4"
+ "@babel/plugin-transform-async-to-generator" "^7.10.4"
+ "@babel/plugin-transform-block-scoped-functions" "^7.10.4"
+ "@babel/plugin-transform-block-scoping" "^7.10.4"
+ "@babel/plugin-transform-classes" "^7.10.4"
+ "@babel/plugin-transform-computed-properties" "^7.10.4"
+ "@babel/plugin-transform-destructuring" "^7.10.4"
+ "@babel/plugin-transform-dotall-regex" "^7.10.4"
+ "@babel/plugin-transform-duplicate-keys" "^7.10.4"
+ "@babel/plugin-transform-exponentiation-operator" "^7.10.4"
+ "@babel/plugin-transform-for-of" "^7.10.4"
+ "@babel/plugin-transform-function-name" "^7.10.4"
+ "@babel/plugin-transform-literals" "^7.10.4"
+ "@babel/plugin-transform-member-expression-literals" "^7.10.4"
+ "@babel/plugin-transform-modules-amd" "^7.10.4"
+ "@babel/plugin-transform-modules-commonjs" "^7.10.4"
+ "@babel/plugin-transform-modules-systemjs" "^7.10.4"
+ "@babel/plugin-transform-modules-umd" "^7.10.4"
+ "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4"
+ "@babel/plugin-transform-new-target" "^7.10.4"
+ "@babel/plugin-transform-object-super" "^7.10.4"
+ "@babel/plugin-transform-parameters" "^7.10.4"
+ "@babel/plugin-transform-property-literals" "^7.10.4"
+ "@babel/plugin-transform-regenerator" "^7.10.4"
+ "@babel/plugin-transform-reserved-words" "^7.10.4"
+ "@babel/plugin-transform-shorthand-properties" "^7.10.4"
+ "@babel/plugin-transform-spread" "^7.11.0"
+ "@babel/plugin-transform-sticky-regex" "^7.10.4"
+ "@babel/plugin-transform-template-literals" "^7.10.4"
+ "@babel/plugin-transform-typeof-symbol" "^7.10.4"
+ "@babel/plugin-transform-unicode-escapes" "^7.10.4"
+ "@babel/plugin-transform-unicode-regex" "^7.10.4"
+ "@babel/preset-modules" "^0.1.3"
+ "@babel/types" "^7.11.5"
+ browserslist "^4.12.0"
+ core-js-compat "^3.6.2"
+ invariant "^2.2.2"
+ levenary "^1.1.1"
+ semver "^5.5.0"
+
+ "@babel/preset-modules@^0.1.3":
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e"
+ integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-proposal-unicode-property-regex" "^7.4.4"
+ "@babel/plugin-transform-dotall-regex" "^7.4.4"
+ "@babel/types" "^7.4.4"
+ esutils "^2.0.2"
+
+ "@babel/runtime@^7.11.0", "@babel/runtime@^7.8.4":
+ version "7.11.2"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
+ integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
+ "@babel/template@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278"
+ integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/parser" "^7.10.4"
+ "@babel/types" "^7.10.4"
+
+ "@babel/traverse@^7.0.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.5", "@babel/traverse@^7.7.0":
+ version "7.11.5"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3"
+ integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/generator" "^7.11.5"
+ "@babel/helper-function-name" "^7.10.4"
+ "@babel/helper-split-export-declaration" "^7.11.0"
+ "@babel/parser" "^7.11.5"
+ "@babel/types" "^7.11.5"
+ debug "^4.1.0"
+ globals "^11.1.0"
+ lodash "^4.17.19"
+
+ "@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
+ version "7.11.5"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d"
+ integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.10.4"
+ lodash "^4.17.19"
+ to-fast-properties "^2.0.0"
+
+ "@hapi/address@2.x.x":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5"
+ integrity sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==
+
+ "@hapi/bourne@1.x.x":
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-1.3.2.tgz#0a7095adea067243ce3283e1b56b8a8f453b242a"
+ integrity sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==
+
+ "@hapi/hoek@8.x.x", "@hapi/hoek@^8.3.0":
+ version "8.5.1"
+ resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06"
+ integrity sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==
+
+ "@hapi/joi@^15.0.1":
+ version "15.1.1"
+ resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7"
+ integrity sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==
+ dependencies:
+ "@hapi/address" "2.x.x"
+ "@hapi/bourne" "1.x.x"
+ "@hapi/hoek" "8.x.x"
+ "@hapi/topo" "3.x.x"
+
+ "@hapi/topo@3.x.x":
+ version "3.1.6"
+ resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.6.tgz#68d935fa3eae7fdd5ab0d7f953f3205d8b2bfc29"
+ integrity sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==
+ dependencies:
+ "@hapi/hoek" "^8.3.0"
+
+ "@intervolga/optimize-cssnano-plugin@^1.0.5":
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/@intervolga/optimize-cssnano-plugin/-/optimize-cssnano-plugin-1.0.6.tgz#be7c7846128b88f6a9b1d1261a0ad06eb5c0fdf8"
+ integrity sha512-zN69TnSr0viRSU6cEDIcuPcP67QcpQ6uHACg58FiN9PDrU6SLyGW3MR4tiISbYxy1kDWAVPwD+XwQTWE5cigAA==
+ dependencies:
+ cssnano "^4.0.0"
+ cssnano-preset-default "^4.0.0"
+ postcss "^7.0.0"
+
+ "@mrmlnc/readdir-enhanced@^2.2.1":
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
+ integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==
+ dependencies:
+ call-me-maybe "^1.0.1"
+ glob-to-regexp "^0.3.0"
+
+ "@nodelib/fs.stat@^1.1.2":
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
+ integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
+
+ "@nuxt/opencollective@^0.3.0":
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/@nuxt/opencollective/-/opencollective-0.3.0.tgz#11d8944dcf2d526e31660bb69570be03f8fb72b7"
+ integrity sha512-Vf09BxCdj1iT2IRqVwX5snaY2WCTkvM0O4cWWSO1ThCFuc4if0Q/nNwAgCxRU0FeYHJ7DdyMUNSdswCLKlVqeg==
+ dependencies:
+ chalk "^2.4.2"
+ consola "^2.10.1"
+ node-fetch "^2.6.0"
+
+ "@soda/friendly-errors-webpack-plugin@^1.7.1":
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.1.tgz#706f64bcb4a8b9642b48ae3ace444c70334d615d"
+ integrity sha512-cWKrGaFX+rfbMrAxVv56DzhPNqOJPZuNIS2HGMELtgGzb+vsMzyig9mml5gZ/hr2BGtSLV+dP2LUEuAL8aG2mQ==
+ dependencies:
+ chalk "^1.1.3"
+ error-stack-parser "^2.0.0"
+ string-width "^2.0.0"
+
+ "@soda/get-current-script@^1.0.0":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@soda/get-current-script/-/get-current-script-1.0.2.tgz#a53515db25d8038374381b73af20bb4f2e508d87"
+ integrity sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==
+
+ "@types/anymatch@*":
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
+ integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==
+
+ "@types/body-parser@*":
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
+ integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==
+ dependencies:
+ "@types/connect" "*"
+ "@types/node" "*"
+
+ "@types/color-name@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
+ integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
+
+ "@types/connect-history-api-fallback@*":
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.3.tgz#4772b79b8b53185f0f4c9deab09236baf76ee3b4"
+ integrity sha512-7SxFCd+FLlxCfwVwbyPxbR4khL9aNikJhrorw8nUIOqeuooc9gifBuDQOJw5kzN7i6i3vLn9G8Wde/4QDihpYw==
+ dependencies:
+ "@types/express-serve-static-core" "*"
+ "@types/node" "*"
+
+ "@types/connect@*":
+ version "3.4.33"
+ resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546"
+ integrity sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==
+ dependencies:
+ "@types/node" "*"
+
+ "@types/express-serve-static-core@*":
+ version "4.17.12"
+ resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.12.tgz#9a487da757425e4f267e7d1c5720226af7f89591"
+ integrity sha512-EaEdY+Dty1jEU7U6J4CUWwxL+hyEGMkO5jan5gplfegUgCUsIUWqXxqw47uGjimeT4Qgkz/XUfwoau08+fgvKA==
+ dependencies:
+ "@types/node" "*"
+ "@types/qs" "*"
+ "@types/range-parser" "*"
+
+ "@types/express@*":
+ version "4.17.8"
+ resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.8.tgz#3df4293293317e61c60137d273a2e96cd8d5f27a"
+ integrity sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==
+ dependencies:
+ "@types/body-parser" "*"
+ "@types/express-serve-static-core" "*"
+ "@types/qs" "*"
+ "@types/serve-static" "*"
+
+ "@types/glob@^7.1.1":
+ version "7.1.3"
+ resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
+ integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==
+ dependencies:
+ "@types/minimatch" "*"
+ "@types/node" "*"
+
+ "@types/http-proxy-middleware@*":
+ version "0.19.3"
+ resolved "https://registry.yarnpkg.com/@types/http-proxy-middleware/-/http-proxy-middleware-0.19.3.tgz#b2eb96fbc0f9ac7250b5d9c4c53aade049497d03"
+ integrity sha512-lnBTx6HCOUeIJMLbI/LaL5EmdKLhczJY5oeXZpX/cXE4rRqb3RmV7VcMpiEfYkmTjipv3h7IAyIINe4plEv7cA==
+ dependencies:
+ "@types/connect" "*"
+ "@types/http-proxy" "*"
+ "@types/node" "*"
+
+ "@types/http-proxy@*":
+ version "1.17.4"
+ resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.4.tgz#e7c92e3dbe3e13aa799440ff42e6d3a17a9d045b"
+ integrity sha512-IrSHl2u6AWXduUaDLqYpt45tLVCtYv7o4Z0s1KghBCDgIIS9oW5K1H8mZG/A2CfeLdEa7rTd1ACOiHBc1EMT2Q==
+ dependencies:
+ "@types/node" "*"
+
+ "@types/json-schema@^7.0.5":
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
+ integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==
+
+ "@types/mime@*":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.3.tgz#c893b73721db73699943bfc3653b1deb7faa4a3a"
+ integrity sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==
+
+ "@types/mini-css-extract-plugin@^0.9.1":
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.1.tgz#d4bdde5197326fca039d418f4bdda03dc74dc451"
+ integrity sha512-+mN04Oszdz9tGjUP/c1ReVwJXxSniLd7lF++sv+8dkABxVNthg6uccei+4ssKxRHGoMmPxdn7uBdJWONSJGTGQ==
+ dependencies:
+ "@types/webpack" "*"
+
+ "@types/minimatch@*":
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
+ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
+
+ "@types/minimist@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6"
+ integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=
+
+ "@types/node@*":
+ version "14.6.4"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a"
+ integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==
+
+ "@types/normalize-package-data@^2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
+ integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
+
+ "@types/q@^1.5.1":
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
+ integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
+
+ "@types/qs@*":
+ version "6.9.4"
+ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.4.tgz#a59e851c1ba16c0513ea123830dd639a0a15cb6a"
+ integrity sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==
+
+ "@types/range-parser@*":
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
+ integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
+
+ "@types/serve-static@*":
+ version "1.13.5"
+ resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.5.tgz#3d25d941a18415d3ab092def846e135a08bbcf53"
+ integrity sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ==
+ dependencies:
+ "@types/express-serve-static-core" "*"
+ "@types/mime" "*"
+
+ "@types/source-list-map@*":
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
+ integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==
+
+ "@types/tapable@*":
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
+ integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==
+
+ "@types/uglify-js@*":
+ version "3.9.3"
+ resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.9.3.tgz#d94ed608e295bc5424c9600e6b8565407b6b4b6b"
+ integrity sha512-KswB5C7Kwduwjj04Ykz+AjvPcfgv/37Za24O2EDzYNbwyzOo8+ydtvzUfZ5UMguiVu29Gx44l1A6VsPPcmYu9w==
+ dependencies:
+ source-map "^0.6.1"
+
+ "@types/webpack-dev-server@^3.11.0":
+ version "3.11.0"
+ resolved "https://registry.yarnpkg.com/@types/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz#bcc3b85e7dc6ac2db25330610513f2228c2fcfb2"
+ integrity sha512-3+86AgSzl18n5P1iUP9/lz3G3GMztCp+wxdDvVuNhx1sr1jE79GpYfKHL8k+Vht3N74K2n98CuAEw4YPJCYtDA==
+ dependencies:
+ "@types/connect-history-api-fallback" "*"
+ "@types/express" "*"
+ "@types/http-proxy-middleware" "*"
+ "@types/serve-static" "*"
+ "@types/webpack" "*"
+
+ "@types/webpack-sources@*":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-1.4.2.tgz#5d3d4dea04008a779a90135ff96fb5c0c9e6292c"
+ integrity sha512-77T++JyKow4BQB/m9O96n9d/UUHWLQHlcqXb9Vsf4F1+wKNrrlWNFPDLKNT92RJnCSL6CieTc+NDXtCVZswdTw==
+ dependencies:
+ "@types/node" "*"
+ "@types/source-list-map" "*"
+ source-map "^0.7.3"
+
+ "@types/webpack@*", "@types/webpack@^4.0.0":
+ version "4.41.22"
+ resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.22.tgz#ff9758a17c6bd499e459b91e78539848c32d0731"
+ integrity sha512-JQDJK6pj8OMV9gWOnN1dcLCyU9Hzs6lux0wBO4lr1+gyEhIBR9U3FMrz12t2GPkg110XAxEAw2WHF6g7nZIbRQ==
+ dependencies:
+ "@types/anymatch" "*"
+ "@types/node" "*"
+ "@types/tapable" "*"
+ "@types/uglify-js" "*"
+ "@types/webpack-sources" "*"
+ source-map "^0.6.0"
+
+ "@vue/babel-helper-vue-jsx-merge-props@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0.tgz#048fe579958da408fb7a8b2a3ec050b50a661040"
+ integrity sha512-6tyf5Cqm4m6v7buITuwS+jHzPlIPxbFzEhXR5JGZpbrvOcp1hiQKckd305/3C7C36wFekNTQSxAtgeM0j0yoUw==
+
+ "@vue/babel-plugin-transform-vue-jsx@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.1.2.tgz#c0a3e6efc022e75e4247b448a8fc6b86f03e91c0"
+ integrity sha512-YfdaoSMvD1nj7+DsrwfTvTnhDXI7bsuh+Y5qWwvQXlD24uLgnsoww3qbiZvWf/EoviZMrvqkqN4CBw0W3BWUTQ==
+ dependencies:
+ "@babel/helper-module-imports" "^7.0.0"
+ "@babel/plugin-syntax-jsx" "^7.2.0"
+ "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0"
+ html-tags "^2.0.0"
+ lodash.kebabcase "^4.1.1"
+ svg-tags "^1.0.0"
+
+ "@vue/babel-preset-app@^4.5.4":
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/@vue/babel-preset-app/-/babel-preset-app-4.5.4.tgz#bb164e8ab55673c561e6e83511631eda19efd7e4"
+ integrity sha512-a+2s/lL3fE3h9/ekvpMVLhZTDjR3xt+jnpTwuQtEZ3KIuzFHxbmwAjueRZh6BKEGfB6kgZ3KqZHFX3vx/DRJ4w==
+ dependencies:
+ "@ant-design-vue/babel-plugin-jsx" "^1.0.0-0"
+ "@babel/core" "^7.11.0"
+ "@babel/helper-compilation-targets" "^7.9.6"
+ "@babel/helper-module-imports" "^7.8.3"
+ "@babel/plugin-proposal-class-properties" "^7.8.3"
+ "@babel/plugin-proposal-decorators" "^7.8.3"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.3"
+ "@babel/plugin-syntax-jsx" "^7.8.3"
+ "@babel/plugin-transform-runtime" "^7.11.0"
+ "@babel/preset-env" "^7.11.0"
+ "@babel/runtime" "^7.11.0"
+ "@vue/babel-preset-jsx" "^1.1.2"
+ babel-plugin-dynamic-import-node "^2.3.3"
+ core-js "^3.6.5"
+ core-js-compat "^3.6.5"
+ semver "^6.1.0"
+
+ "@vue/babel-preset-jsx@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@vue/babel-preset-jsx/-/babel-preset-jsx-1.1.2.tgz#2e169eb4c204ea37ca66c2ea85a880bfc99d4f20"
+ integrity sha512-zDpVnFpeC9YXmvGIDSsKNdL7qCG2rA3gjywLYHPCKDT10erjxF4U+6ay9X6TW5fl4GsDlJp9bVfAVQAAVzxxvQ==
+ dependencies:
+ "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0"
+ "@vue/babel-plugin-transform-vue-jsx" "^1.1.2"
+ "@vue/babel-sugar-functional-vue" "^1.1.2"
+ "@vue/babel-sugar-inject-h" "^1.1.2"
+ "@vue/babel-sugar-v-model" "^1.1.2"
+ "@vue/babel-sugar-v-on" "^1.1.2"
+
+ "@vue/babel-sugar-functional-vue@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.1.2.tgz#f7e24fba09e6f1ee70104560a8808057555f1a9a"
+ integrity sha512-YhmdJQSVEFF5ETJXzrMpj0nkCXEa39TvVxJTuVjzvP2rgKhdMmQzlJuMv/HpadhZaRVMCCF3AEjjJcK5q/cYzQ==
+ dependencies:
+ "@babel/plugin-syntax-jsx" "^7.2.0"
+
+ "@vue/babel-sugar-inject-h@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.1.2.tgz#8a5276b6d8e2ed16ffc8078aad94236274e6edf0"
+ integrity sha512-VRSENdTvD5htpnVp7i7DNuChR5rVMcORdXjvv5HVvpdKHzDZAYiLSD+GhnhxLm3/dMuk8pSzV+k28ECkiN5m8w==
+ dependencies:
+ "@babel/plugin-syntax-jsx" "^7.2.0"
+
+ "@vue/babel-sugar-v-model@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.1.2.tgz#1ff6fd1b800223fc9cb1e84dceb5e52d737a8192"
+ integrity sha512-vLXPvNq8vDtt0u9LqFdpGM9W9IWDmCmCyJXuozlq4F4UYVleXJ2Fa+3JsnTZNJcG+pLjjfnEGHci2339Kj5sGg==
+ dependencies:
+ "@babel/plugin-syntax-jsx" "^7.2.0"
+ "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0"
+ "@vue/babel-plugin-transform-vue-jsx" "^1.1.2"
+ camelcase "^5.0.0"
+ html-tags "^2.0.0"
+ svg-tags "^1.0.0"
+
+ "@vue/babel-sugar-v-on@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.1.2.tgz#b2ef99b8f2fab09fbead25aad70ef42e1cf5b13b"
+ integrity sha512-T8ZCwC8Jp2uRtcZ88YwZtZXe7eQrJcfRq0uTFy6ShbwYJyz5qWskRFoVsdTi9o0WEhmQXxhQUewodOSCUPVmsQ==
+ dependencies:
+ "@babel/plugin-syntax-jsx" "^7.2.0"
+ "@vue/babel-plugin-transform-vue-jsx" "^1.1.2"
+ camelcase "^5.0.0"
+
+ "@vue/cli-overlay@^4.5.4":
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/@vue/cli-overlay/-/cli-overlay-4.5.4.tgz#e07e3ccc2e4d770d4fdbd45cdde777d592822c19"
+ integrity sha512-nthli1n7rXaqaMZsH0KNdFqeYJxDOQNeaobp9SjeSdrpD1xAj/B0+RJMWQWIFsfdQn1AQP1UVMnkfdakTiLgxA==
+
+ "@vue/cli-plugin-babel@~4.5.0":
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/@vue/cli-plugin-babel/-/cli-plugin-babel-4.5.4.tgz#a01cdcb3d46064675dd88d61b640adadcc851e2b"
+ integrity sha512-pXEzj/vkl3qOs/brhgxAu37hULCOHcOLzYKF747r1oudJq0aV1TOnQzTrP8aCE/A1CnW4Dbw/l9bt20a7btDcg==
+ dependencies:
+ "@babel/core" "^7.11.0"
+ "@vue/babel-preset-app" "^4.5.4"
+ "@vue/cli-shared-utils" "^4.5.4"
+ babel-loader "^8.1.0"
+ cache-loader "^4.1.0"
+ thread-loader "^2.1.3"
+ webpack "^4.0.0"
+
+ "@vue/cli-plugin-eslint@~4.5.0":
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/@vue/cli-plugin-eslint/-/cli-plugin-eslint-4.5.4.tgz#0f1f307abfe1e4ad67dcb97693640942b15fae76"
+ integrity sha512-mWuhKtxMiAM70nPW/NnoWtf32YJoOPPt7SyNmsAjBKSRPcje+16Egl7BD8yuPKoF1MTkvs5CM/e7gp3AnSTFzQ==
+ dependencies:
+ "@vue/cli-shared-utils" "^4.5.4"
+ eslint-loader "^2.2.1"
+ globby "^9.2.0"
+ inquirer "^7.1.0"
+ webpack "^4.0.0"
+ yorkie "^2.0.0"
+
+ "@vue/cli-plugin-router@^4.5.4":
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/@vue/cli-plugin-router/-/cli-plugin-router-4.5.4.tgz#06f22408c7ed6aceddbf7302cb47a293b7af4347"
+ integrity sha512-9/qRICZbq1qucq9M9z6jYT5UWNvcTu9BgHtXgsaK9gJsdmpxDIfD0SvW9nzZaHb8xxixvDRotMM/0Juw2oCsKQ==
+ dependencies:
+ "@vue/cli-shared-utils" "^4.5.4"
+
+ "@vue/cli-plugin-vuex@^4.5.4":
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/@vue/cli-plugin-vuex/-/cli-plugin-vuex-4.5.4.tgz#6296e307388f61132117e0ac03188013652b0c55"
+ integrity sha512-X/F4E/dIRdiogKCdO4VGjUy5f4Fbxs7mu/gSi6Ubltle0eNE+tbBgLPH4r2g7GmHKNph4k39ikvfOMpXZcTFZg==
+
+ "@vue/cli-service@~4.5.0":
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/@vue/cli-service/-/cli-service-4.5.4.tgz#f903edf555d107404624de2fed5996da8cedc524"
+ integrity sha512-30zcebYno9tMvGsvZsnSPtieBvU5H3CkRW1JgiBmPG3Fcxp3BGSAy82Dl1gOUEj1VsAUqXWKMWX6frkYldi8UA==
+ dependencies:
+ "@intervolga/optimize-cssnano-plugin" "^1.0.5"
+ "@soda/friendly-errors-webpack-plugin" "^1.7.1"
+ "@soda/get-current-script" "^1.0.0"
+ "@types/minimist" "^1.2.0"
+ "@types/webpack" "^4.0.0"
+ "@types/webpack-dev-server" "^3.11.0"
+ "@vue/cli-overlay" "^4.5.4"
+ "@vue/cli-plugin-router" "^4.5.4"
+ "@vue/cli-plugin-vuex" "^4.5.4"
+ "@vue/cli-shared-utils" "^4.5.4"
+ "@vue/component-compiler-utils" "^3.1.2"
+ "@vue/preload-webpack-plugin" "^1.1.0"
+ "@vue/web-component-wrapper" "^1.2.0"
+ acorn "^7.4.0"
+ acorn-walk "^7.1.1"
+ address "^1.1.2"
+ autoprefixer "^9.8.6"
+ browserslist "^4.12.0"
+ cache-loader "^4.1.0"
+ case-sensitive-paths-webpack-plugin "^2.3.0"
+ cli-highlight "^2.1.4"
+ clipboardy "^2.3.0"
+ cliui "^6.0.0"
+ copy-webpack-plugin "^5.1.1"
+ css-loader "^3.5.3"
+ cssnano "^4.1.10"
+ debug "^4.1.1"
+ default-gateway "^5.0.5"
+ dotenv "^8.2.0"
+ dotenv-expand "^5.1.0"
+ file-loader "^4.2.0"
+ fs-extra "^7.0.1"
+ globby "^9.2.0"
+ hash-sum "^2.0.0"
+ html-webpack-plugin "^3.2.0"
+ launch-editor-middleware "^2.2.1"
+ lodash.defaultsdeep "^4.6.1"
+ lodash.mapvalues "^4.6.0"
+ lodash.transform "^4.6.0"
+ mini-css-extract-plugin "^0.9.0"
+ minimist "^1.2.5"
+ pnp-webpack-plugin "^1.6.4"
+ portfinder "^1.0.26"
+ postcss-loader "^3.0.0"
+ ssri "^7.1.0"
+ terser-webpack-plugin "^2.3.6"
+ thread-loader "^2.1.3"
+ url-loader "^2.2.0"
+ vue-loader "^15.9.2"
+ vue-style-loader "^4.1.2"
+ webpack "^4.0.0"
+ webpack-bundle-analyzer "^3.8.0"
+ webpack-chain "^6.4.0"
+ webpack-dev-server "^3.11.0"
+ webpack-merge "^4.2.2"
+ optionalDependencies:
+ vue-loader-v16 "npm:vue-loader@^16.0.0-beta.3"
+
+ "@vue/cli-shared-utils@^4.5.4":
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/@vue/cli-shared-utils/-/cli-shared-utils-4.5.4.tgz#ed36b2971dc02653f7f2ad4e66bbe9510e1bd414"
+ integrity sha512-7ZwAvGxl5szGuaJCc4jdPy/2Lb7oJvG847MDF+7pZ7FVl6bURwbUJjiUwL6DTxvpC4vch6B4tXfVvZFjzVP/bw==
+ dependencies:
+ "@hapi/joi" "^15.0.1"
+ chalk "^2.4.2"
+ execa "^1.0.0"
+ launch-editor "^2.2.1"
+ lru-cache "^5.1.1"
+ node-ipc "^9.1.1"
+ open "^6.3.0"
+ ora "^3.4.0"
+ read-pkg "^5.1.1"
+ request "^2.88.2"
+ semver "^6.1.0"
+ strip-ansi "^6.0.0"
+
+ "@vue/component-compiler-utils@^3.1.0", "@vue/component-compiler-utils@^3.1.2":
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.2.0.tgz#8f85182ceed28e9b3c75313de669f83166d11e5d"
+ integrity sha512-lejBLa7xAMsfiZfNp7Kv51zOzifnb29FwdnMLa96z26kXErPFioSf9BMcePVIQ6/Gc6/mC0UrPpxAWIHyae0vw==
+ dependencies:
+ consolidate "^0.15.1"
+ hash-sum "^1.0.2"
+ lru-cache "^4.1.2"
+ merge-source-map "^1.1.0"
+ postcss "^7.0.14"
+ postcss-selector-parser "^6.0.2"
+ source-map "~0.6.1"
+ vue-template-es2015-compiler "^1.9.0"
+ optionalDependencies:
+ prettier "^1.18.2"
+
+ "@vue/preload-webpack-plugin@^1.1.0":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz#ceb924b4ecb3b9c43871c7a429a02f8423e621ab"
+ integrity sha512-LIZMuJk38pk9U9Ur4YzHjlIyMuxPlACdBIHH9/nGYVTsaGKOSnSuELiE8vS9wa+dJpIYspYUOqk+L1Q4pgHQHQ==
+
+ "@vue/web-component-wrapper@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@vue/web-component-wrapper/-/web-component-wrapper-1.2.0.tgz#bb0e46f1585a7e289b4ee6067dcc5a6ae62f1dd1"
+ integrity sha512-Xn/+vdm9CjuC9p3Ae+lTClNutrVhsXpzxvoTXXtoys6kVRX9FkueSUAqSWAyZntmVLlR4DosBV4pH8y5Z/HbUw==
+
+ "@webassemblyjs/ast@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
+ integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==
+ dependencies:
+ "@webassemblyjs/helper-module-context" "1.9.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+ "@webassemblyjs/wast-parser" "1.9.0"
+
+ "@webassemblyjs/floating-point-hex-parser@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4"
+ integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==
+
+ "@webassemblyjs/helper-api-error@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2"
+ integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==
+
+ "@webassemblyjs/helper-buffer@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00"
+ integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==
+
+ "@webassemblyjs/helper-code-frame@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27"
+ integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==
+ dependencies:
+ "@webassemblyjs/wast-printer" "1.9.0"
+
+ "@webassemblyjs/helper-fsm@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8"
+ integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==
+
+ "@webassemblyjs/helper-module-context@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07"
+ integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+
+ "@webassemblyjs/helper-wasm-bytecode@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790"
+ integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==
+
+ "@webassemblyjs/helper-wasm-section@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346"
+ integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/helper-buffer" "1.9.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+ "@webassemblyjs/wasm-gen" "1.9.0"
+
+ "@webassemblyjs/ieee754@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4"
+ integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==
+ dependencies:
+ "@xtuc/ieee754" "^1.2.0"
+
+ "@webassemblyjs/leb128@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95"
+ integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==
+ dependencies:
+ "@xtuc/long" "4.2.2"
+
+ "@webassemblyjs/utf8@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab"
+ integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==
+
+ "@webassemblyjs/wasm-edit@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf"
+ integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/helper-buffer" "1.9.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+ "@webassemblyjs/helper-wasm-section" "1.9.0"
+ "@webassemblyjs/wasm-gen" "1.9.0"
+ "@webassemblyjs/wasm-opt" "1.9.0"
+ "@webassemblyjs/wasm-parser" "1.9.0"
+ "@webassemblyjs/wast-printer" "1.9.0"
+
+ "@webassemblyjs/wasm-gen@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c"
+ integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+ "@webassemblyjs/ieee754" "1.9.0"
+ "@webassemblyjs/leb128" "1.9.0"
+ "@webassemblyjs/utf8" "1.9.0"
+
+ "@webassemblyjs/wasm-opt@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61"
+ integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/helper-buffer" "1.9.0"
+ "@webassemblyjs/wasm-gen" "1.9.0"
+ "@webassemblyjs/wasm-parser" "1.9.0"
+
+ "@webassemblyjs/wasm-parser@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e"
+ integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/helper-api-error" "1.9.0"
+ "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+ "@webassemblyjs/ieee754" "1.9.0"
+ "@webassemblyjs/leb128" "1.9.0"
+ "@webassemblyjs/utf8" "1.9.0"
+
+ "@webassemblyjs/wast-parser@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914"
+ integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/floating-point-hex-parser" "1.9.0"
+ "@webassemblyjs/helper-api-error" "1.9.0"
+ "@webassemblyjs/helper-code-frame" "1.9.0"
+ "@webassemblyjs/helper-fsm" "1.9.0"
+ "@xtuc/long" "4.2.2"
+
+ "@webassemblyjs/wast-printer@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899"
+ integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==
+ dependencies:
+ "@webassemblyjs/ast" "1.9.0"
+ "@webassemblyjs/wast-parser" "1.9.0"
+ "@xtuc/long" "4.2.2"
+
+ "@xtuc/ieee754@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
+ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
+
+ "@xtuc/long@4.2.2":
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
+ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+
+ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
+ version "1.3.7"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
+ integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
+ dependencies:
+ mime-types "~2.1.24"
+ negotiator "0.6.2"
+
+ acorn-jsx@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
+ integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==
+
+ acorn-walk@^7.1.1:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
+ integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
+
+ acorn@^6.4.1:
+ version "6.4.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
+ integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
+
+ acorn@^7.1.1, acorn@^7.4.0:
+ version "7.4.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c"
+ integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==
+
+ address@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6"
+ integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==
+
+ aggregate-error@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
+ integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
+ dependencies:
+ clean-stack "^2.0.0"
+ indent-string "^4.0.0"
+
+ ajv-errors@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
+ integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==
+
+ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
+ integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
+
+ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4:
+ version "6.12.4"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234"
+ integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
+ alphanum-sort@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
+ integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=
+
+ ansi-colors@^3.0.0:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
+ integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
+
+ ansi-escapes@^4.2.1:
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61"
+ integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==
+ dependencies:
+ type-fest "^0.11.0"
+
+ ansi-html@0.0.7:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
+ integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4=
+
+ ansi-regex@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+ integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
+
+ ansi-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+ integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
+
+ ansi-regex@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
+ integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
+
+ ansi-regex@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
+ integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
+
+ ansi-styles@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+ integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
+
+ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ dependencies:
+ color-convert "^1.9.0"
+
+ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359"
+ integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==
+ dependencies:
+ "@types/color-name" "^1.1.1"
+ color-convert "^2.0.1"
+
+ any-promise@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
+ integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
+
+ anymatch@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
+ integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==
+ dependencies:
+ micromatch "^3.1.4"
+ normalize-path "^2.1.1"
+
+ anymatch@~3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
+ integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+ aproba@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
+ integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
+
+ arch@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.2.tgz#0c52bbe7344bb4fa260c443d2cbad9c00ff2f0bf"
+ integrity sha512-NTBIIbAfkJeIletyABbVtdPgeKfDafR+1mZV/AyyfC1UkVkp9iUjV+wwmqtUgphHYajbI86jejBJp5e+jkGTiQ==
+
+ argparse@^1.0.7:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+ integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+ dependencies:
+ sprintf-js "~1.0.2"
+
+ arr-diff@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
+ integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
+
+ arr-flatten@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
+ integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
+
+ arr-union@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
+ integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
+
+ array-flatten@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+ integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
+
+ array-flatten@^2.1.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099"
+ integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==
+
+ array-union@^1.0.1, array-union@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+ integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
+ dependencies:
+ array-uniq "^1.0.1"
+
+ array-uniq@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+ integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
+
+ array-unique@^0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
+ integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
+
+ asn1.js@^5.2.0:
+ version "5.4.1"
+ resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07"
+ integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==
+ dependencies:
+ bn.js "^4.0.0"
+ inherits "^2.0.1"
+ minimalistic-assert "^1.0.0"
+ safer-buffer "^2.1.0"
+
+ asn1@~0.2.3:
+ version "0.2.4"
+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
+ integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
+ dependencies:
+ safer-buffer "~2.1.0"
+
+ assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+ integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
+
+ assert@^1.1.1:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb"
+ integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==
+ dependencies:
+ object-assign "^4.1.1"
+ util "0.10.3"
+
+ assign-symbols@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
+ integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
+
+ astral-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
+ integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
+
+ async-each@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
+ integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
+
+ async-limiter@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
+ integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
+
+ async@^2.6.2:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
+ integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
+ dependencies:
+ lodash "^4.17.14"
+
+ asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
+
+ atob@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
+ integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
+
+ autoprefixer@^9.8.6:
+ version "9.8.6"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f"
+ integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==
+ dependencies:
+ browserslist "^4.12.0"
+ caniuse-lite "^1.0.30001109"
+ colorette "^1.2.1"
+ normalize-range "^0.1.2"
+ num2fraction "^1.2.2"
+ postcss "^7.0.32"
+ postcss-value-parser "^4.1.0"
+
+ aws-sign2@~0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
+ integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
+
+ aws4@^1.8.0:
+ version "1.10.1"
+ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428"
+ integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==
+
+ babel-eslint@^10.1.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
+ integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ "@babel/parser" "^7.7.0"
+ "@babel/traverse" "^7.7.0"
+ "@babel/types" "^7.7.0"
+ eslint-visitor-keys "^1.0.0"
+ resolve "^1.12.0"
+
+ babel-loader@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3"
+ integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==
+ dependencies:
+ find-cache-dir "^2.1.0"
+ loader-utils "^1.4.0"
+ mkdirp "^0.5.3"
+ pify "^4.0.1"
+ schema-utils "^2.6.5"
+
+ babel-plugin-dynamic-import-node@^2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3"
+ integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==
+ dependencies:
+ object.assign "^4.1.0"
+
+ balanced-match@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+ integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+
+ base64-js@^1.0.2:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
+ integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
+
+ base@^0.11.1:
+ version "0.11.2"
+ resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
+ integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==
+ dependencies:
+ cache-base "^1.0.1"
+ class-utils "^0.3.5"
+ component-emitter "^1.2.1"
+ define-property "^1.0.0"
+ isobject "^3.0.1"
+ mixin-deep "^1.2.0"
+ pascalcase "^0.1.1"
+
+ batch@0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
+ integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=
+
+ bcrypt-pbkdf@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
+ integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
+ dependencies:
+ tweetnacl "^0.14.3"
+
+ bfj@^6.1.1:
+ version "6.1.2"
+ resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f"
+ integrity sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==
+ dependencies:
+ bluebird "^3.5.5"
+ check-types "^8.0.3"
+ hoopy "^0.1.4"
+ tryer "^1.0.1"
+
+ big.js@^3.1.3:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
+ integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==
+
+ big.js@^5.2.2:
+ version "5.2.2"
+ resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
+ integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
+
+ binary-extensions@^1.0.0:
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
+ integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
+
+ binary-extensions@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9"
+ integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==
+
+ bindings@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
+ integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
+ dependencies:
+ file-uri-to-path "1.0.0"
+
+ bluebird@^3.1.1, bluebird@^3.5.5:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
+ integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
+
+ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0:
+ version "4.11.9"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
+ integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
+
+ bn.js@^5.1.1:
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b"
+ integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==
+
+ body-parser@1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
+ integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
+ dependencies:
+ bytes "3.1.0"
+ content-type "~1.0.4"
+ debug "2.6.9"
+ depd "~1.1.2"
+ http-errors "1.7.2"
+ iconv-lite "0.4.24"
+ on-finished "~2.3.0"
+ qs "6.7.0"
+ raw-body "2.4.0"
+ type-is "~1.6.17"
+
+ bonjour@^3.5.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5"
+ integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU=
+ dependencies:
+ array-flatten "^2.1.0"
+ deep-equal "^1.0.1"
+ dns-equal "^1.0.0"
+ dns-txt "^2.0.2"
+ multicast-dns "^6.0.1"
+ multicast-dns-service-types "^1.1.0"
+
+ boolbase@^1.0.0, boolbase@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+ integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
+
+ bootstrap-vue@^2.16.0:
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/bootstrap-vue/-/bootstrap-vue-2.16.0.tgz#07e7032ec9ffdd576470dc437da54f398ec16ba5"
+ integrity sha512-gLETwPmeRHCe5WHmhGxzb5PtTEuKqQPGl0TFvZ2Odbkg/7UuIHdqIexrJRerpnomP4ZzDQ+qYGL91Ls9lcQsJQ==
+ dependencies:
+ "@nuxt/opencollective" "^0.3.0"
+ bootstrap ">=4.5.0 <5.0.0"
+ popper.js "^1.16.1"
+ portal-vue "^2.1.7"
+ vue-functional-data-merge "^3.1.0"
+
+ "bootstrap@>=4.5.0 <5.0.0":
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.2.tgz#a85c4eda59155f0d71186b6e6ad9b875813779ab"
+ integrity sha512-vlGn0bcySYl/iV+BGA544JkkZP5LB3jsmkeKLFQakCOwCM3AOk7VkldBz4jrzSe+Z0Ezn99NVXa1o45cQY4R6A==
+
+ brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+ braces@^2.3.1, braces@^2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
+ integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
+ dependencies:
+ arr-flatten "^1.1.0"
+ array-unique "^0.3.2"
+ extend-shallow "^2.0.1"
+ fill-range "^4.0.0"
+ isobject "^3.0.1"
+ repeat-element "^1.1.2"
+ snapdragon "^0.8.1"
+ snapdragon-node "^2.0.1"
+ split-string "^3.0.2"
+ to-regex "^3.0.1"
+
+ braces@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+ brorand@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+ integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
+
+ browserify-aes@^1.0.0, browserify-aes@^1.0.4:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
+ integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==
+ dependencies:
+ buffer-xor "^1.0.3"
+ cipher-base "^1.0.0"
+ create-hash "^1.1.0"
+ evp_bytestokey "^1.0.3"
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
+ browserify-cipher@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0"
+ integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==
+ dependencies:
+ browserify-aes "^1.0.4"
+ browserify-des "^1.0.0"
+ evp_bytestokey "^1.0.0"
+
+ browserify-des@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c"
+ integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==
+ dependencies:
+ cipher-base "^1.0.1"
+ des.js "^1.0.0"
+ inherits "^2.0.1"
+ safe-buffer "^5.1.2"
+
+ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524"
+ integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=
+ dependencies:
+ bn.js "^4.1.0"
+ randombytes "^2.0.1"
+
+ browserify-sign@^4.0.0:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3"
+ integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==
+ dependencies:
+ bn.js "^5.1.1"
+ browserify-rsa "^4.0.1"
+ create-hash "^1.2.0"
+ create-hmac "^1.1.7"
+ elliptic "^6.5.3"
+ inherits "^2.0.4"
+ parse-asn1 "^5.1.5"
+ readable-stream "^3.6.0"
+ safe-buffer "^5.2.0"
+
+ browserify-zlib@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
+ integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==
+ dependencies:
+ pako "~1.0.5"
+
+ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.8.5:
+ version "4.14.1"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.1.tgz#cb2b490ba881d45dc3039078c7ed04411eaf3fa3"
+ integrity sha512-zyBTIHydW37pnb63c7fHFXUG6EcqWOqoMdDx6cdyaDFriZ20EoVxcE95S54N+heRqY8m8IUgB5zYta/gCwSaaA==
+ dependencies:
+ caniuse-lite "^1.0.30001124"
+ electron-to-chromium "^1.3.562"
+ escalade "^3.0.2"
+ node-releases "^1.1.60"
+
+ buffer-from@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+ integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
+
+ buffer-indexof@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c"
+ integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==
+
+ buffer-json@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/buffer-json/-/buffer-json-2.0.0.tgz#f73e13b1e42f196fe2fd67d001c7d7107edd7c23"
+ integrity sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw==
+
+ buffer-xor@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
+ integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
+
+ buffer@^4.3.0:
+ version "4.9.2"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8"
+ integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==
+ dependencies:
+ base64-js "^1.0.2"
+ ieee754 "^1.1.4"
+ isarray "^1.0.0"
+
+ builtin-status-codes@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
+ integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
+
+ bytes@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+ integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
+
+ bytes@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
+ integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
+
+ cacache@^12.0.2, cacache@^12.0.3:
+ version "12.0.4"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c"
+ integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==
+ dependencies:
+ bluebird "^3.5.5"
+ chownr "^1.1.1"
+ figgy-pudding "^3.5.1"
+ glob "^7.1.4"
+ graceful-fs "^4.1.15"
+ infer-owner "^1.0.3"
+ lru-cache "^5.1.1"
+ mississippi "^3.0.0"
+ mkdirp "^0.5.1"
+ move-concurrently "^1.0.1"
+ promise-inflight "^1.0.1"
+ rimraf "^2.6.3"
+ ssri "^6.0.1"
+ unique-filename "^1.1.1"
+ y18n "^4.0.0"
+
+ cacache@^13.0.1:
+ version "13.0.1"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c"
+ integrity sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==
+ dependencies:
+ chownr "^1.1.2"
+ figgy-pudding "^3.5.1"
+ fs-minipass "^2.0.0"
+ glob "^7.1.4"
+ graceful-fs "^4.2.2"
+ infer-owner "^1.0.4"
+ lru-cache "^5.1.1"
+ minipass "^3.0.0"
+ minipass-collect "^1.0.2"
+ minipass-flush "^1.0.5"
+ minipass-pipeline "^1.2.2"
+ mkdirp "^0.5.1"
+ move-concurrently "^1.0.1"
+ p-map "^3.0.0"
+ promise-inflight "^1.0.1"
+ rimraf "^2.7.1"
+ ssri "^7.0.0"
+ unique-filename "^1.1.1"
+
+ cache-base@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
+ integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==
+ dependencies:
+ collection-visit "^1.0.0"
+ component-emitter "^1.2.1"
+ get-value "^2.0.6"
+ has-value "^1.0.0"
+ isobject "^3.0.1"
+ set-value "^2.0.0"
+ to-object-path "^0.3.0"
+ union-value "^1.0.0"
+ unset-value "^1.0.0"
+
+ cache-loader@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/cache-loader/-/cache-loader-4.1.0.tgz#9948cae353aec0a1fcb1eafda2300816ec85387e"
+ integrity sha512-ftOayxve0PwKzBF/GLsZNC9fJBXl8lkZE3TOsjkboHfVHVkL39iUEs1FO07A33mizmci5Dudt38UZrrYXDtbhw==
+ dependencies:
+ buffer-json "^2.0.0"
+ find-cache-dir "^3.0.0"
+ loader-utils "^1.2.3"
+ mkdirp "^0.5.1"
+ neo-async "^2.6.1"
+ schema-utils "^2.0.0"
+
+ call-me-maybe@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
+ integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=
+
+ caller-callsite@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
+ integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=
+ dependencies:
+ callsites "^2.0.0"
+
+ caller-path@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4"
+ integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=
+ dependencies:
+ caller-callsite "^2.0.0"
+
+ callsites@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
+ integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=
+
+ callsites@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+ integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+ camel-case@3.0.x:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
+ integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=
+ dependencies:
+ no-case "^2.2.0"
+ upper-case "^1.1.1"
+
+ camelcase@^5.0.0, camelcase@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+ camelcase@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e"
+ integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==
+
+ caniuse-api@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
+ integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==
+ dependencies:
+ browserslist "^4.0.0"
+ caniuse-lite "^1.0.0"
+ lodash.memoize "^4.1.2"
+ lodash.uniq "^4.5.0"
+
+ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001124:
+ version "1.0.30001124"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001124.tgz#5d9998190258e11630d674fc50ea8e579ae0ced2"
+ integrity sha512-zQW8V3CdND7GHRH6rxm6s59Ww4g/qGWTheoboW9nfeMg7sUoopIfKCcNZUjwYRCOrvereh3kwDpZj4VLQ7zGtA==
+
+ case-sensitive-paths-webpack-plugin@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.3.0.tgz#23ac613cc9a856e4f88ff8bb73bbb5e989825cf7"
+ integrity sha512-/4YgnZS8y1UXXmC02xD5rRrBEu6T5ub+mQHLNRj0fzTRbgdBYhsNo2V5EqwgqrExjxsjtF/OpAKAMkKsxbD5XQ==
+
+ caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+ integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
+
+ chalk@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
+ dependencies:
+ ansi-styles "^2.2.1"
+ escape-string-regexp "^1.0.2"
+ has-ansi "^2.0.0"
+ strip-ansi "^3.0.0"
+ supports-color "^2.0.0"
+
+ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+ chalk@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
+ integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+ chalk@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
+ integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+ chardet@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
+ integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
+
+ check-types@^8.0.3:
+ version "8.0.3"
+ resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552"
+ integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==
+
+ chokidar@^2.1.8:
+ version "2.1.8"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
+ integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
+ dependencies:
+ anymatch "^2.0.0"
+ async-each "^1.0.1"
+ braces "^2.3.2"
+ glob-parent "^3.1.0"
+ inherits "^2.0.3"
+ is-binary-path "^1.0.0"
+ is-glob "^4.0.0"
+ normalize-path "^3.0.0"
+ path-is-absolute "^1.0.0"
+ readdirp "^2.2.1"
+ upath "^1.1.1"
+ optionalDependencies:
+ fsevents "^1.2.7"
+
+ chokidar@^3.4.1:
+ version "3.4.2"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d"
+ integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==
+ dependencies:
+ anymatch "~3.1.1"
+ braces "~3.0.2"
+ glob-parent "~5.1.0"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.4.0"
+ optionalDependencies:
+ fsevents "~2.1.2"
+
+ chownr@^1.1.1, chownr@^1.1.2:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
+ integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
+
+ chrome-trace-event@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
+ integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==
+ dependencies:
+ tslib "^1.9.0"
+
+ ci-info@^1.5.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
+ integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+
+ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
+ integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
+ dependencies:
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
+ class-utils@^0.3.5:
+ version "0.3.6"
+ resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
+ integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==
+ dependencies:
+ arr-union "^3.1.0"
+ define-property "^0.2.5"
+ isobject "^3.0.0"
+ static-extend "^0.1.1"
+
+ clean-css@4.2.x:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78"
+ integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==
+ dependencies:
+ source-map "~0.6.0"
+
+ clean-stack@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
+ integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
+
+ cli-cursor@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+ integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
+ dependencies:
+ restore-cursor "^2.0.0"
+
+ cli-cursor@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
+ integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
+ dependencies:
+ restore-cursor "^3.1.0"
+
+ cli-highlight@^2.1.4:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-2.1.4.tgz#098cb642cf17f42adc1c1145e07f960ec4d7522b"
+ integrity sha512-s7Zofobm20qriqDoU9sXptQx0t2R9PEgac92mENNm7xaEe1hn71IIMsXMK+6encA6WRCWWxIGQbipr3q998tlQ==
+ dependencies:
+ chalk "^3.0.0"
+ highlight.js "^9.6.0"
+ mz "^2.4.0"
+ parse5 "^5.1.1"
+ parse5-htmlparser2-tree-adapter "^5.1.1"
+ yargs "^15.0.0"
+
+ cli-spinners@^2.0.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.4.0.tgz#c6256db216b878cfba4720e719cec7cf72685d7f"
+ integrity sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA==
+
+ cli-width@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
+ integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
+
+ clipboardy@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290"
+ integrity sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==
+ dependencies:
+ arch "^2.1.1"
+ execa "^1.0.0"
+ is-wsl "^2.1.1"
+
+ cliui@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
+ integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==
+ dependencies:
+ string-width "^3.1.0"
+ strip-ansi "^5.2.0"
+ wrap-ansi "^5.1.0"
+
+ cliui@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
+ integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.0"
+ wrap-ansi "^6.2.0"
+
+ clone@^1.0.2:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
+ integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
+
+ coa@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3"
+ integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==
+ dependencies:
+ "@types/q" "^1.5.1"
+ chalk "^2.4.1"
+ q "^1.1.2"
+
+ collection-visit@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
+ integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=
+ dependencies:
+ map-visit "^1.0.0"
+ object-visit "^1.0.0"
+
+ color-convert@^1.9.0, color-convert@^1.9.1:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+ dependencies:
+ color-name "1.1.3"
+
+ color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+ color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+ integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+
+ color-name@^1.0.0, color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+ color-string@^1.5.2:
+ version "1.5.3"
+ resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc"
+ integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==
+ dependencies:
+ color-name "^1.0.0"
+ simple-swizzle "^0.2.2"
+
+ color@^3.0.0:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10"
+ integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==
+ dependencies:
+ color-convert "^1.9.1"
+ color-string "^1.5.2"
+
+ colorette@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
+ integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
+
+ combined-stream@^1.0.6, combined-stream@~1.0.6:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+ commander@2.17.x:
+ version "2.17.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
+ integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
+
+ commander@^2.18.0, commander@^2.20.0:
+ version "2.20.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+ commander@~2.19.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
+ integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
+
+ commondir@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+ integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
+
+ component-emitter@^1.2.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
+ integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
+
+ compressible@~2.0.16:
+ version "2.0.18"
+ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
+ integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
+ dependencies:
+ mime-db ">= 1.43.0 < 2"
+
+ compression@^1.7.4:
+ version "1.7.4"
+ resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
+ integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
+ dependencies:
+ accepts "~1.3.5"
+ bytes "3.0.0"
+ compressible "~2.0.16"
+ debug "2.6.9"
+ on-headers "~1.0.2"
+ safe-buffer "5.1.2"
+ vary "~1.1.2"
+
+ concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+
+ concat-stream@^1.5.0:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
+ integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
+ dependencies:
+ buffer-from "^1.0.0"
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
+ connect-history-api-fallback@^1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
+ integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
+
+ consola@^2.10.1:
+ version "2.15.0"
+ resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.0.tgz#40fc4eefa4d2f8ef2e2806147f056ea207fcc0e9"
+ integrity sha512-vlcSGgdYS26mPf7qNi+dCisbhiyDnrN1zaRbw3CSuc2wGOMEGGPsp46PdRG5gqXwgtJfjxDkxRNAgRPr1B77vQ==
+
+ console-browserify@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
+ integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
+
+ consolidate@^0.15.1:
+ version "0.15.1"
+ resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7"
+ integrity sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==
+ dependencies:
+ bluebird "^3.1.1"
+
+ constants-browserify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
+ integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
+
+ content-disposition@0.5.3:
+ version "0.5.3"
+ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
+ integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
+ dependencies:
+ safe-buffer "5.1.2"
+
+ content-type@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+ integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
+
+ convert-source-map@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
+ integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
+ dependencies:
+ safe-buffer "~5.1.1"
+
+ cookie-signature@1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+ integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
+
+ cookie@0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
+ integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
+
+ copy-concurrently@^1.0.0:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
+ integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==
+ dependencies:
+ aproba "^1.1.1"
+ fs-write-stream-atomic "^1.0.8"
+ iferr "^0.1.5"
+ mkdirp "^0.5.1"
+ rimraf "^2.5.4"
+ run-queue "^1.0.0"
+
+ copy-descriptor@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
+ integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
+
+ copy-webpack-plugin@^5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz#8a889e1dcafa6c91c6cd4be1ad158f1d3823bae2"
+ integrity sha512-Uh7crJAco3AjBvgAy9Z75CjK8IG+gxaErro71THQ+vv/bl4HaQcpkexAY8KVW/T6D2W2IRr+couF/knIRkZMIQ==
+ dependencies:
+ cacache "^12.0.3"
+ find-cache-dir "^2.1.0"
+ glob-parent "^3.1.0"
+ globby "^7.1.1"
+ is-glob "^4.0.1"
+ loader-utils "^1.2.3"
+ minimatch "^3.0.4"
+ normalize-path "^3.0.0"
+ p-limit "^2.2.1"
+ schema-utils "^1.0.0"
+ serialize-javascript "^4.0.0"
+ webpack-log "^2.0.0"
+
+ core-js-compat@^3.6.2, core-js-compat@^3.6.5:
+ version "3.6.5"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c"
+ integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==
+ dependencies:
+ browserslist "^4.8.5"
+ semver "7.0.0"
+
+ core-js@^3.6.5:
+ version "3.6.5"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a"
+ integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==
+
+ core-util-is@1.0.2, core-util-is@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+ integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+
+ cosmiconfig@^5.0.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
+ integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
+ dependencies:
+ import-fresh "^2.0.0"
+ is-directory "^0.3.1"
+ js-yaml "^3.13.1"
+ parse-json "^4.0.0"
+
+ create-ecdh@^4.0.0:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
+ integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==
+ dependencies:
+ bn.js "^4.1.0"
+ elliptic "^6.5.3"
+
+ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
+ integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
+ dependencies:
+ cipher-base "^1.0.1"
+ inherits "^2.0.1"
+ md5.js "^1.3.4"
+ ripemd160 "^2.0.1"
+ sha.js "^2.4.0"
+
+ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
+ integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
+ dependencies:
+ cipher-base "^1.0.3"
+ create-hash "^1.1.0"
+ inherits "^2.0.1"
+ ripemd160 "^2.0.0"
+ safe-buffer "^5.0.1"
+ sha.js "^2.4.8"
+
+ cross-spawn@^5.0.1:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
+ integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=
+ dependencies:
+ lru-cache "^4.0.1"
+ shebang-command "^1.2.0"
+ which "^1.2.9"
+
+ cross-spawn@^6.0.0, cross-spawn@^6.0.5:
+ version "6.0.5"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+ integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
+ dependencies:
+ nice-try "^1.0.4"
+ path-key "^2.0.1"
+ semver "^5.5.0"
+ shebang-command "^1.2.0"
+ which "^1.2.9"
+
+ cross-spawn@^7.0.0:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+ integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+ crypto-browserify@^3.11.0:
+ version "3.12.0"
+ resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
+ integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==
+ dependencies:
+ browserify-cipher "^1.0.0"
+ browserify-sign "^4.0.0"
+ create-ecdh "^4.0.0"
+ create-hash "^1.1.0"
+ create-hmac "^1.1.0"
+ diffie-hellman "^5.0.0"
+ inherits "^2.0.1"
+ pbkdf2 "^3.0.3"
+ public-encrypt "^4.0.0"
+ randombytes "^2.0.0"
+ randomfill "^1.0.3"
+
+ css-color-names@0.0.4, css-color-names@^0.0.4:
+ version "0.0.4"
+ resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
+ integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=
+
+ css-declaration-sorter@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22"
+ integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==
+ dependencies:
+ postcss "^7.0.1"
+ timsort "^0.3.0"
+
+ css-loader@^3.5.3:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645"
+ integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==
+ dependencies:
+ camelcase "^5.3.1"
+ cssesc "^3.0.0"
+ icss-utils "^4.1.1"
+ loader-utils "^1.2.3"
+ normalize-path "^3.0.0"
+ postcss "^7.0.32"
+ postcss-modules-extract-imports "^2.0.0"
+ postcss-modules-local-by-default "^3.0.2"
+ postcss-modules-scope "^2.2.0"
+ postcss-modules-values "^3.0.0"
+ postcss-value-parser "^4.1.0"
+ schema-utils "^2.7.0"
+ semver "^6.3.0"
+
+ css-select-base-adapter@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7"
+ integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==
+
+ css-select@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
+ integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=
+ dependencies:
+ boolbase "~1.0.0"
+ css-what "2.1"
+ domutils "1.5.1"
+ nth-check "~1.0.1"
+
+ css-select@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef"
+ integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==
+ dependencies:
+ boolbase "^1.0.0"
+ css-what "^3.2.1"
+ domutils "^1.7.0"
+ nth-check "^1.0.2"
+
+ css-tree@1.0.0-alpha.37:
+ version "1.0.0-alpha.37"
+ resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22"
+ integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==
+ dependencies:
+ mdn-data "2.0.4"
+ source-map "^0.6.1"
+
+ css-tree@1.0.0-alpha.39:
+ version "1.0.0-alpha.39"
+ resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb"
+ integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==
+ dependencies:
+ mdn-data "2.0.6"
+ source-map "^0.6.1"
+
+ css-what@2.1:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
+ integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
+
+ css-what@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.3.0.tgz#10fec696a9ece2e591ac772d759aacabac38cd39"
+ integrity sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg==
+
+ cssesc@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
+ integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+
+ cssnano-preset-default@^4.0.0, cssnano-preset-default@^4.0.7:
+ version "4.0.7"
+ resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76"
+ integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==
+ dependencies:
+ css-declaration-sorter "^4.0.1"
+ cssnano-util-raw-cache "^4.0.1"
+ postcss "^7.0.0"
+ postcss-calc "^7.0.1"
+ postcss-colormin "^4.0.3"
+ postcss-convert-values "^4.0.1"
+ postcss-discard-comments "^4.0.2"
+ postcss-discard-duplicates "^4.0.2"
+ postcss-discard-empty "^4.0.1"
+ postcss-discard-overridden "^4.0.1"
+ postcss-merge-longhand "^4.0.11"
+ postcss-merge-rules "^4.0.3"
+ postcss-minify-font-values "^4.0.2"
+ postcss-minify-gradients "^4.0.2"
+ postcss-minify-params "^4.0.2"
+ postcss-minify-selectors "^4.0.2"
+ postcss-normalize-charset "^4.0.1"
+ postcss-normalize-display-values "^4.0.2"
+ postcss-normalize-positions "^4.0.2"
+ postcss-normalize-repeat-style "^4.0.2"
+ postcss-normalize-string "^4.0.2"
+ postcss-normalize-timing-functions "^4.0.2"
+ postcss-normalize-unicode "^4.0.1"
+ postcss-normalize-url "^4.0.1"
+ postcss-normalize-whitespace "^4.0.2"
+ postcss-ordered-values "^4.1.2"
+ postcss-reduce-initial "^4.0.3"
+ postcss-reduce-transforms "^4.0.2"
+ postcss-svgo "^4.0.2"
+ postcss-unique-selectors "^4.0.1"
+
+ cssnano-util-get-arguments@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f"
+ integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=
+
+ cssnano-util-get-match@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d"
+ integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=
+
+ cssnano-util-raw-cache@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282"
+ integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==
+ dependencies:
+ postcss "^7.0.0"
+
+ cssnano-util-same-parent@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3"
+ integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==
+
+ cssnano@^4.0.0, cssnano@^4.1.10:
+ version "4.1.10"
+ resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2"
+ integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==
+ dependencies:
+ cosmiconfig "^5.0.0"
+ cssnano-preset-default "^4.0.7"
+ is-resolvable "^1.0.0"
+ postcss "^7.0.0"
+
+ csso@^4.0.2:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903"
+ integrity sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==
+ dependencies:
+ css-tree "1.0.0-alpha.39"
+
+ cyclist@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
+ integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
+
+ dashdash@^1.12.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+ integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
+ dependencies:
+ assert-plus "^1.0.0"
+
+ de-indent@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
+ integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=
+
+ debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+ dependencies:
+ ms "2.0.0"
+
+ debug@^3.1.1, debug@^3.2.5:
+ version "3.2.6"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
+ integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
+ dependencies:
+ ms "^2.1.1"
+
+ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+ integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
+ dependencies:
+ ms "^2.1.1"
+
+ decamelize@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+ integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+
+ decode-uri-component@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
+ integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
+
+ deep-equal@^1.0.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a"
+ integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==
+ dependencies:
+ is-arguments "^1.0.4"
+ is-date-object "^1.0.1"
+ is-regex "^1.0.4"
+ object-is "^1.0.1"
+ object-keys "^1.1.1"
+ regexp.prototype.flags "^1.2.0"
+
+ deep-is@~0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+ integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
+
+ deepmerge@^1.5.2:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753"
+ integrity sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==
+
+ default-gateway@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b"
+ integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==
+ dependencies:
+ execa "^1.0.0"
+ ip-regex "^2.1.0"
+
+ default-gateway@^5.0.5:
+ version "5.0.5"
+ resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-5.0.5.tgz#4fd6bd5d2855d39b34cc5a59505486e9aafc9b10"
+ integrity sha512-z2RnruVmj8hVMmAnEJMTIJNijhKCDiGjbLP+BHJFOT7ld3Bo5qcIBpVYDniqhbMIIf+jZDlkP2MkPXiQy/DBLA==
+ dependencies:
+ execa "^3.3.0"
+
+ defaults@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
+ integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
+ dependencies:
+ clone "^1.0.2"
+
+ define-properties@^1.1.2, define-properties@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
+ integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
+ dependencies:
+ object-keys "^1.0.12"
+
+ define-property@^0.2.5:
+ version "0.2.5"
+ resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
+ integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=
+ dependencies:
+ is-descriptor "^0.1.0"
+
+ define-property@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6"
+ integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY=
+ dependencies:
+ is-descriptor "^1.0.0"
+
+ define-property@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d"
+ integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==
+ dependencies:
+ is-descriptor "^1.0.2"
+ isobject "^3.0.1"
+
+ del@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4"
+ integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==
+ dependencies:
+ "@types/glob" "^7.1.1"
+ globby "^6.1.0"
+ is-path-cwd "^2.0.0"
+ is-path-in-cwd "^2.0.0"
+ p-map "^2.0.0"
+ pify "^4.0.1"
+ rimraf "^2.6.3"
+
+ delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
+
+ depd@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+ integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
+
+ des.js@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
+ integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==
+ dependencies:
+ inherits "^2.0.1"
+ minimalistic-assert "^1.0.0"
+
+ destroy@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+ integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
+
+ detect-node@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
+ integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
+
+ diffie-hellman@^5.0.0:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
+ integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==
+ dependencies:
+ bn.js "^4.1.0"
+ miller-rabin "^4.0.0"
... 13912 lines suppressed ...
[airavata-custos-portal] 07/09: tag local version
Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
isjarana pushed a commit to branch custos-tenant-portal
in repository https://gitbox.apache.org/repos/asf/airavata-custos-portal.git
commit 853bb8f47ae4128dc4fae26fa4bb6bcf8ff4cf47
Author: Isuru Ranawaka <ir...@gmail.com>
AuthorDate: Mon Oct 5 09:50:40 2020 -0400
tag local version
---
custos-demo-gateway/docker-compose.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/custos-demo-gateway/docker-compose.yml b/custos-demo-gateway/docker-compose.yml
index c774049..c68d7e0 100644
--- a/custos-demo-gateway/docker-compose.yml
+++ b/custos-demo-gateway/docker-compose.yml
@@ -1,11 +1,11 @@
version: "3.3"
services:
web:
- image : "apachecustos/custos-demo-gateway:latest"
+ image : "apachecustos/custos-demo-gateway-local:latest"
ports:
- "8080:8080"
environment:
- VUE_APP_CLIENT_ID: ''
- VUE_APP_CLIENT_SEC: ''
+ VUE_APP_CLIENT_ID: 'custos-irbc1ozdkvt5pnqtdyrr-10000584'
+ VUE_APP_CLIENT_SEC: 'HVdiZrAVolGeIblB2WXNBI295FQvGcC6WbJek9hg'
VUE_APP_REDIRECT_URI: 'http://localhost:8080/callback'
- VUE_APP_CUSTOS_TOKEN_ENDPOINT: 'https://custos.scigap.org/apiserver/identity-management/v1.0.0/token'
\ No newline at end of file
+ VUE_APP_CUSTOS_TOKEN_ENDPOINT: 'https://custos.scigap.org/apiserver/identity-management/v1.0.0/token'
[airavata-custos-portal] 08/09: tag local version
Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
isjarana pushed a commit to branch custos-tenant-portal
in repository https://gitbox.apache.org/repos/asf/airavata-custos-portal.git
commit 50ce1adf8d5df644edfefe8682faefd158a4be13
Author: Isuru Ranawaka <ir...@gmail.com>
AuthorDate: Mon Oct 5 09:56:37 2020 -0400
tag local version
---
custos-demo-gateway/docker-compose.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/custos-demo-gateway/docker-compose.yml b/custos-demo-gateway/docker-compose.yml
index c68d7e0..f65426b 100644
--- a/custos-demo-gateway/docker-compose.yml
+++ b/custos-demo-gateway/docker-compose.yml
@@ -5,7 +5,7 @@ services:
ports:
- "8080:8080"
environment:
- VUE_APP_CLIENT_ID: 'custos-irbc1ozdkvt5pnqtdyrr-10000584'
- VUE_APP_CLIENT_SEC: 'HVdiZrAVolGeIblB2WXNBI295FQvGcC6WbJek9hg'
+ VUE_APP_CLIENT_ID: ''
+ VUE_APP_CLIENT_SEC: ''
VUE_APP_REDIRECT_URI: 'http://localhost:8080/callback'
VUE_APP_CUSTOS_TOKEN_ENDPOINT: 'https://custos.scigap.org/apiserver/identity-management/v1.0.0/token'
[airavata-custos-portal] 01/09: adding a README
Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
isjarana pushed a commit to branch custos-tenant-portal
in repository https://gitbox.apache.org/repos/asf/airavata-custos-portal.git
commit a1b019c3dcb0fb52970fa01f7e3d667dcebc0024
Author: Suresh Marru <sm...@apache.org>
AuthorDate: Thu Apr 2 15:56:04 2020 -0400
adding a README
---
README | 3 +++
1 file changed, 3 insertions(+)
diff --git a/README b/README
new file mode 100644
index 0000000..2f43c32
--- /dev/null
+++ b/README
@@ -0,0 +1,3 @@
+# Apache Airavata Custos Portal
+
+Portal interface implemented in Django Framework to use and administer Custos Services
\ No newline at end of file
[airavata-custos-portal] 06/09: Merge pull request #15 from
isururanawaka/custos-tenant-portal
Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
isjarana pushed a commit to branch custos-tenant-portal
in repository https://gitbox.apache.org/repos/asf/airavata-custos-portal.git
commit add79252c2d580e3bcbb0b0a99904949ee817cd6
Merge: a051b0a c42eda9
Author: Isuru Ranawaka <ir...@gmail.com>
AuthorDate: Sun Oct 4 15:23:56 2020 -0400
Merge pull request #15 from isururanawaka/custos-tenant-portal
Initial code of custos-tenant-portal
.gitignore | 3 +
custos-demo-gateway/.dockerignore | 13 +
custos-demo-gateway/.env | 3 +
custos-demo-gateway/.idea/custos-demo-gateway.iml | 8 +
.../.idea/inspectionProfiles/Project_Default.xml | 6 +
custos-demo-gateway/.idea/misc.xml | 9 +
custos-demo-gateway/.idea/modules.xml | 8 +
custos-demo-gateway/.idea/vcs.xml | 6 +
custos-demo-gateway/.idea/workspace.xml | 141 +
custos-demo-gateway/Dockerfile | 19 +
custos-demo-gateway/README.md | 24 +
custos-demo-gateway/babel.config.js | 5 +
custos-demo-gateway/docker-compose.yml | 11 +
custos-demo-gateway/entrypoint.sh | 18 +
custos-demo-gateway/fullchain.pem | 59 +
custos-demo-gateway/nginx.conf | 35 +
custos-demo-gateway/package.json | 50 +
custos-demo-gateway/public/favicon.ico | Bin 0 -> 4286 bytes
custos-demo-gateway/public/index.html | 17 +
custos-demo-gateway/src/App.vue | 29 +
custos-demo-gateway/src/assets/bots.png | Bin 0 -> 5228 bytes
custos-demo-gateway/src/assets/credentials.png | Bin 0 -> 3332 bytes
custos-demo-gateway/src/assets/custos_home.png | Bin 0 -> 44021 bytes
custos-demo-gateway/src/assets/dblogs.png | Bin 0 -> 19538 bytes
custos-demo-gateway/src/assets/groups_web.png | Bin 0 -> 2934 bytes
custos-demo-gateway/src/assets/logo.png | Bin 0 -> 6849 bytes
custos-demo-gateway/src/assets/sharings.png | Bin 0 -> 2417 bytes
custos-demo-gateway/src/assets/users.png | Bin 0 -> 4824 bytes
custos-demo-gateway/src/components/Callback.vue | 86 +
.../src/components/TheNavigator.vue | 24 +
.../src/components/landing/Landing.vue | 229 +
.../src/components/registration/CreateAccount.vue | 206 +
.../src/components/workspace/Agents.vue | 295 +
.../src/components/workspace/Groups.vue | 653 ++
.../src/components/workspace/Logs.vue | 223 +
.../src/components/workspace/Secrets.vue | 355 +
.../src/components/workspace/Sharing.vue | 892 ++
.../src/components/workspace/Users.vue | 609 ++
.../src/components/workspace/Workspace.vue | 141 +
custos-demo-gateway/src/config.js | 41 +
custos-demo-gateway/src/main.js | 23 +
custos-demo-gateway/src/router.js | 159 +
.../src/service/agent_management.js | 116 +
custos-demo-gateway/src/service/api.js | 12 +
custos-demo-gateway/src/service/auth.js | 96 +
.../src/service/group_management.js | 157 +
.../src/service/identity_management.js | 55 +
custos-demo-gateway/src/service/log_management.js | 36 +
.../src/service/secret_management.js | 98 +
.../src/service/sharing_management.js | 198 +
custos-demo-gateway/src/service/user_management.js | 161 +
custos-demo-gateway/src/store/index.js | 29 +
.../src/store/modules/agent.store.js | 155 +
.../src/store/modules/group.store.js | 153 +
.../src/store/modules/identity.store.js | 134 +
custos-demo-gateway/src/store/modules/log.store.js | 46 +
.../src/store/modules/secret.store.js | 116 +
.../src/store/modules/sharing.store.js | 227 +
.../src/store/modules/user.store.js | 149 +
custos-demo-gateway/yarn-error.log | 8587 ++++++++++++++++++++
custos-demo-gateway/yarn.lock | 8534 +++++++++++++++++++
61 files changed, 23459 insertions(+)
[airavata-custos-portal] 03/09: changing labels to all lower case
Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
isjarana pushed a commit to branch custos-tenant-portal
in repository https://gitbox.apache.org/repos/asf/airavata-custos-portal.git
commit 8f5e0fde12c034e10c7958e3150e8fdb601eb7c5
Author: Suresh Marru <sm...@apache.org>
AuthorDate: Thu Apr 30 22:34:09 2020 -0400
changing labels to all lower case
---
.asf.yaml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.asf.yaml b/.asf.yaml
index 0d498c6..75f5e40 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -5,10 +5,10 @@ github:
- airavata
- apache
- security
- - OAuth2
- - OpenIDConnect
- - Authentication
- - Authorization
+ - oauth2
+ - openidconnect
+ - authentication
+ - authorization
features:
wiki: true
[airavata-custos-portal] 02/09: adding asf yaml file to enable wiki
and issues
Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
isjarana pushed a commit to branch custos-tenant-portal
in repository https://gitbox.apache.org/repos/asf/airavata-custos-portal.git
commit feb7e444dc91790cc126077917038167ffe2923f
Author: Suresh Marru <sm...@apache.org>
AuthorDate: Thu Apr 30 22:23:39 2020 -0400
adding asf yaml file to enable wiki and issues
---
.asf.yaml | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/.asf.yaml b/.asf.yaml
new file mode 100644
index 0000000..0d498c6
--- /dev/null
+++ b/.asf.yaml
@@ -0,0 +1,16 @@
+github:
+ description: "Portal Interface for Apache Airavata Custos Security"
+ homepage: https://airavata.apache.org/
+ labels:
+ - airavata
+ - apache
+ - security
+ - OAuth2
+ - OpenIDConnect
+ - Authentication
+ - Authorization
+
+ features:
+ wiki: true
+ issues: true
+ projects: true
[airavata-custos-portal] 04/09: adding notification section
Posted by is...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
isjarana pushed a commit to branch custos-tenant-portal
in repository https://gitbox.apache.org/repos/asf/airavata-custos-portal.git
commit a051b0af9442654344bb8be01a427e114000e1c4
Author: Suresh Marru <sm...@apache.org>
AuthorDate: Thu Apr 30 23:03:39 2020 -0400
adding notification section
---
.asf.yaml | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/.asf.yaml b/.asf.yaml
index 75f5e40..ba27dc5 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -14,3 +14,12 @@ github:
wiki: true
issues: true
projects: true
+
+ notifications:
+ commits: commits@airavata.apache.org
+ # Send all issue emails (new, closed, comments) to issues@
+ issues: issues@airavata.apache.org
+ # Send new/closed PR notifications to dev@
+ pullrequests_status: issues@airavata.apache.org
+ # Send individual PR comments/reviews to issues@
+ pullrequests_comment: issues@airavata.apache.org
\ No newline at end of file