diff --git a/.gitignore b/.gitignore index e91237ad7..cb73be599 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,7 @@ tunnel.log /.well-known-cache /**/tmp-* /testdata/bigAlloc_*.csv -/sessions \ No newline at end of file +/sessions +/changelog.json +/.current-version +/.current-changelog.md \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index db4ef096a..514846b63 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,8 +1,16 @@ +workflow: + rules: + - if: '$CI_PIPELINE_SOURCE == "push"' + when: always + - when: never + default: image: - name: fpco/stack-build:lts-16.11 + name: fpco/stack-build:lts-16.31 cache: &global_cache + key: default paths: + - .npm - node_modules - .stack - .stack-work @@ -21,6 +29,7 @@ variables: UPLOAD_S3_KEY_ID: gOel7KvadwNKgjjy UPLOAD_S3_KEY: ugO5pkEla7F0JW9MdPwLi4MWLT5ZbqAL N_PREFIX: "${HOME}/.n" + PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/uni2work" stages: - setup @@ -28,13 +37,16 @@ stages: - yesod:build - lint - test - - deploy + - prepare release + - upload packages + - release +# - deploy npm install: stage: setup script: - ./.npmrc.gup - - npm install + - npm ci --cache .npm --prefer-offline before_script: &npm - rm -rvf /etc/apt/sources.list /etc/apt/sources.list.d - install -v -T -m 0644 ${APT_SOURCES_LIST} /etc/apt/sources.list @@ -51,30 +63,26 @@ npm install: artifacts: paths: - node_modules/ - name: "${CI_JOB_NAME}" + name: "${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}" expire_in: "1 day" retry: 2 interruptible: true frontend:build: - cache: - <<: *global_cache - policy: pull stage: frontend:build script: - npm run frontend:build before_script: *npm needs: - - npm install + - job: npm install + artifacts: true artifacts: paths: - static - well-known - config/webpack.yml - name: "${CI_JOB_NAME}" + name: "${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}" expire_in: "1 day" - dependencies: - - npm install retry: 2 interruptible: true @@ -84,69 +92,235 @@ frontend:lint: - npm run frontend:lint before_script: *npm needs: - - npm install - dependencies: - - npm install + - job: npm install + artifacts: true retry: 2 interruptible: true yesod:build:dev: - services: &build-services + stage: yesod:build + script: + - stack build --test --copy-bins --local-bin-path $(pwd)/bin --fast --flag uniworx:-library-only --flag uniworx:dev --flag uniworx:pedantic --no-strip --no-run-tests + - cp $(stack path --dist-dir)/build/hlint/hlint bin/test-hlint + - cp $(stack path --dist-dir)/build/yesod/yesod bin/test-yesod + needs: + - job: npm install # transitive + artifacts: false + - job: frontend:build + artifacts: true + before_script: &haskell + - rm -rvf /etc/apt/sources.list /etc/apt/sources.list.d + - install -v -T -m 0644 ${APT_SOURCES_LIST} /etc/apt/sources.list + - apt-get update -y + - apt-get install -y --no-install-recommends locales-all openssh-client git-restore-mtime + - install -v -m 0700 -d ~/.ssh + - install -v -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts + - install -v -T -m 0400 ${SSH_DEPLOY_KEY} ~/.ssh/deploy && echo "IdentityFile ~/.ssh/deploy" >> ~/.ssh/config; + - stack install happy + - export PATH="${HOME}/.local/bin:$PATH" + - hash -r + - git restore-mtime + artifacts: + paths: + - bin/ + name: "${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}" + expire_in: "1 week" + + rules: + - if: $CI_COMMIT_REF_NAME =~ /(^v[0-9].*)|((^|\/)profile($|\/))/ + when: manual + allow_failure: true + - when: on_success + + retry: 2 + interruptible: true + +yesod:build: + stage: yesod:build + script: + - stack build --test --copy-bins --local-bin-path $(pwd)/bin --flag uniworx:-library-only --flag uniworx:-dev --flag uniworx:pedantic --no-strip --no-run-tests + - cp $(stack path --dist-dir)/build/hlint/hlint bin/test-hlint + - cp $(stack path --dist-dir)/build/yesod/yesod bin/test-yesod + needs: + - job: npm install # transitive + artifacts: false + - job: frontend:build + artifacts: true + before_script: *haskell + artifacts: + paths: + - bin/ + name: "${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}" + expire_in: "1 week" + + rules: + - if: $CI_COMMIT_REF_NAME =~ /^v[0-9].*/ + when: on_success + - when: manual + allow_failure: true + + retry: 2 + interruptible: true + resource_group: ram + +yesod:build:profile: + cache: + <<: *global_cache + policy: pull + + stage: yesod:build + script: + - stack build --profile --copy-bins --local-bin-path $(pwd)/bin --flag uniworx:-library-only --flag uniworx:-dev --flag uniworx:pedantic --no-strip + needs: + - job: npm install # transitive + artifacts: false + - job: frontend:build + artifacts: true + before_script: *haskell + artifacts: + paths: + - bin/ + name: "${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}" + expire_in: "1 week" + + rules: + - if: $CI_COMMIT_REF_NAME =~ /(^|\/)profile($|\/)/ + when: on_success + - when: manual + allow_failure: true + + retry: 2 + interruptible: true + resource_group: ram + +yesod:test:yesod: + stage: test + cache: {} + + services: &test-services - name: postgres:10.10 alias: postgres - name: minio/minio:RELEASE.2020-08-27T05-16-20Z alias: minio command: ["minio", "server", "/data"] - stage: yesod:build - script: - - stack build --test --copy-bins --local-bin-path $(pwd)/bin --fast --flag uniworx:-library-only --flag uniworx:dev --flag uniworx:pedantic --no-strip needs: - - frontend:build - before_script: &haskell - - rm -rvf /etc/apt/sources.list /etc/apt/sources.list.d - - install -v -T -m 0644 ${APT_SOURCES_LIST} /etc/apt/sources.list - - apt-get update -y - - apt-get install -y --no-install-recommends locales-all openssh-client - - install -v -m 0700 -d ~/.ssh - - install -v -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - - install -v -T -m 0400 ${SSH_DEPLOY_KEY} ~/.ssh/deploy && echo "IdentityFile ~/.ssh/deploy" >> ~/.ssh/config; - artifacts: - paths: - - bin/ - name: "${CI_JOB_NAME}" - expire_in: "1 week" - dependencies: - - frontend:build + - job: npm install # transitive + artifacts: false + - job: frontend:build #transitive + artifacts: false + - job: yesod:build + artifacts: true + + rules: + - if: $CI_COMMIT_REF_NAME =~ /^v[0-9].*/ + when: on_success + + script: + - bin/test-yesod - only: - variables: - - $CI_COMMIT_REF_NAME !~ /^v[0-9].*/ retry: 2 interruptible: true - -yesod:build: - services: *build-services - stage: yesod:build - script: - - stack build --test --copy-bins --local-bin-path $(pwd)/bin --flag uniworx:-library-only --flag uniworx:-dev --flag uniworx:pedantic --no-strip +yesod:test:yesod:dev: + stage: test + cache: {} + + services: *test-services + needs: - - frontend:build + - job: npm install # transitive + artifacts: false + - job: frontend:build #transitive + artifacts: false + - job: yesod:build:dev + artifacts: true + + rules: + - if: $CI_COMMIT_REF_NAME =~ /(^v[0-9].*)|((^|\/)profile($|\/))/ + when: manual + allow_failure: true + - when: on_success + + script: + - bin/test-yesod + + retry: 2 + interruptible: true + +yesod:test:hlint: + stage: lint + cache: &hlint_cache + key: hlint + paths: + - .stack + - .stack-work + + needs: + - job: npm install # transitive + artifacts: false + - job: frontend:build #transitive + artifacts: false + - job: yesod:build + artifacts: false + + rules: + - if: $CI_COMMIT_REF_NAME =~ /^v[0-9].*/ + when: on_success + before_script: *haskell + script: + - stack install hlint + - stack exec -- hlint --cc src > gl-code-quality-report.json + - jq . gl-code-quality-report.json + artifacts: paths: - - bin/ - name: "${CI_JOB_NAME}" - dependencies: - - frontend:build - - only: - variables: - - $CI_COMMIT_REF_NAME =~ /^v[0-9].*/ + - gl-code-quality-report.json + name: "${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}" + expire_in: "1 week" + + reports: + codequality: gl-code-quality-report.json + + retry: 2 + interruptible: true + +yesod:test:hlint:dev: + stage: lint + cache: *hlint_cache + + needs: + - job: npm install # transitive + artifacts: false + - job: frontend:build #transitive + artifacts: false + - job: yesod:build:dev + artifacts: false + + rules: + - if: $CI_COMMIT_REF_NAME =~ /(^v[0-9].*)|((^|\/)profile($|\/))/ + when: manual + allow_failure: true + - when: on_success + + before_script: *haskell + script: + - stack install hlint + - stack exec -- hlint --cc src > gl-code-quality-report.json + - jq . gl-code-quality-report.json + + artifacts: + paths: + - gl-code-quality-report.json + name: "${CI_JOB_NAME}-${CI_COMMIT_SHORT_SHA}" + expire_in: "1 week" + + reports: + codequality: gl-code-quality-report.json + retry: 2 interruptible: true - resource_group: ram frontend:test: cache: @@ -156,7 +330,8 @@ frontend:test: script: - npm run frontend:test needs: - - npm install + - job: npm install + artifacts: true before_script: - rm -rvf /etc/apt/sources.list /etc/apt/sources.list.d - install -v -T -m 0644 ${APT_SOURCES_LIST} /etc/apt/sources.list @@ -167,31 +342,137 @@ frontend:test: - npm install -g npm - hash -r - apt-get install -y --no-install-recommends chromium-browser - dependencies: - - npm install retry: 2 interruptible: true -deploy:uniworx3: +parse-changelog: cache: {} - stage: deploy - script: - - zip -qj - bin/uniworx bin/uniworxdb | ssh root@uniworx3.ifi.lmu.de /root/bin/accept_uni2work + stage: prepare release needs: - - yesod:build - - frontend:test # For sanity + - job: npm install + artifacts: true + rules: + - if: $CI_COMMIT_REF_NAME =~ /^v[0-9].*/ + when: on_success before_script: - rm -rvf /etc/apt/sources.list /etc/apt/sources.list.d - install -v -T -m 0644 ${APT_SOURCES_LIST} /etc/apt/sources.list - apt-get update -y - - apt-get install -y --no-install-recommends openssh-client - - install -v -m 0700 -d ~/.ssh - - install -v -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts - - install -v -T -m 0400 ${SSH_PRIVATE_KEY_UNIWORX3} ~/.ssh/uniworx3; echo "IdentityFile ~/.ssh/uniworx3" >> ~/.ssh/config; - dependencies: - - yesod:build + - apt-get install -y --no-install-recommends jq + script: + - npm run parse-changelog + - | + jq -r '.versions[0].version' changelog.json > .current-version + - | + jq -r '.versions[0].body' changelog.json > .current-changelog.md + artifacts: + paths: + - .current-version + - .current-changelog.md + name: "changelog-${CI_COMMIT_SHORT_SHA}" + expire_in: "1 day" + retry: 2 + interruptible: true + +upload: + cache: {} + variables: + GIT_STRATEGY: none + stage: upload packages + image: curlimages/curl:latest + needs: + - job: npm install # transitive + artifacts: false + - job: frontend:build # transitive + artifacts: false + - job: yesod:build + artifacts: true + - job: parse-changelog + artifacts: true + - job: frontend:lint # validation + artifacts: false + - job: frontend:test # validation + artifacts: false + - job: yesod:test:hlint # validation + artifacts: false + - job: yesod:test:yesod # validation + artifacts: false + rules: + - if: $CI_COMMIT_REF_NAME =~ /^v[0-9].*/ + when: on_success + before_script: + - export VERSION="$(cat .current-version)" + script: + - | + curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file bin/uniworx ${PACKAGE_REGISTRY_URL}/${VERSION}/uniworx + - | + curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file bin/uniworxdb ${PACKAGE_REGISTRY_URL}/${VERSION}/uniworxdb + - | + curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file bin/uniworxload ${PACKAGE_REGISTRY_URL}/${VERSION}/uniworxload + - | + curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file bin/uniworx-wflint ${PACKAGE_REGISTRY_URL}/${VERSION}/uniworx-wflint + +release: + cache: {} + variables: + GIT_STRATEGY: none + stage: release + image: registry.gitlab.com/gitlab-org/release-cli:latest + needs: + - job: upload + artifacts: false + - job: npm install # transitive + artifacts: false + - job: frontend:build # transitive + artifacts: false + - job: yesod:build # transitive + artifacts: false + - job: parse-changelog + artifacts: true + - job: frontend:lint # validation + artifacts: false + - job: frontend:test # validation + artifacts: false + - job: yesod:test:hlint # validation + artifacts: false + - job: yesod:test:yesod # validation + artifacts: false + rules: + - if: $CI_COMMIT_REF_NAME =~ /^v[0-9].*/ + when: on_success + before_script: + - export VERSION="$(cat .current-version)" + script: + - | + release-cli create --name "${VERSION}" --tag-name $CI_COMMIT_TAG --description .current-changelog.md \ + --assets-link "{\"name\":\"uniworx\",\"url\":\"${PACKAGE_REGISTRY_URL}/${VERSION}/uniworx\",\"filepath\":\"/uniworx\"}" \ + --assets-link "{\"name\":\"uniworxdb\",\"url\":\"${PACKAGE_REGISTRY_URL}/${VERSION}/uniworxdb\",\"filepath\":\"/uniworxdb\"}" \ + --assets-link "{\"name\":\"uniworxload\",\"url\":\"${PACKAGE_REGISTRY_URL}/${VERSION}/uniworxload\",\"filepath\":\"/uniworxload\"}" \ + --assets-link "{\"name\":\"uniworx-wflint\",\"url\":\"${PACKAGE_REGISTRY_URL}/${VERSION}/uniworx-wflint\",\"filepath\":\"/uniworx-wflint\"}" + + +# deploy:uniworx3: +# cache: {} +# stage: deploy +# variables: +# GIT_STRATEGY: none +# script: +# - zip -qj - bin/uniworx bin/uniworxdb | ssh root@uniworx3.ifi.lmu.de /root/bin/accept_uni2work +# needs: +# - yesod:build +# - frontend:test # For sanity +# before_script: +# - rm -rvf /etc/apt/sources.list /etc/apt/sources.list.d +# - install -v -T -m 0644 ${APT_SOURCES_LIST} /etc/apt/sources.list +# - apt-get update -y +# - apt-get install -y --no-install-recommends openssh-client +# - install -v -m 0700 -d ~/.ssh +# - install -v -T -m 0644 ${SSH_KNOWN_HOSTS} ~/.ssh/known_hosts +# - install -v -T -m 0400 ${SSH_PRIVATE_KEY_UNIWORX3} ~/.ssh/uniworx3; echo "IdentityFile ~/.ssh/uniworx3" >> ~/.ssh/config; +# dependencies: +# - yesod:build - only: - variables: - - $CI_COMMIT_REF_NAME =~ /^v[0-9].*/ - resource_group: uniworx3 +# only: +# variables: +# - $CI_COMMIT_REF_NAME =~ /^v[0-9].*/ +# resource_group: uniworx3 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..f19355bde --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "testdata/workflows"] + path = testdata/workflows + url = gitlab2.rz.ifi.lmu.de:uni2work/workflows diff --git a/.hlint.yaml b/.hlint.yaml index 5414d2724..24e2d327e 100644 --- a/.hlint.yaml +++ b/.hlint.yaml @@ -18,3 +18,184 @@ - -XQuasiQuotes - -XTemplateHaskell - -j + + - fixity: "infix 4 `isInfixOf`" + - fixity: "infix 4 `hasInfix`" + - fixity: "infixl 6 `strConcat`" + - fixity: "infix 4 `ciEq`" + - fixity: "infix 4 `maybeEq`" + - fixity: "infixl 8 ->." + - fixity: "infixl 8 #>>." + - fixity: "infixl 6 `diffDays`" + - fixity: "infixr 3 `predDNFAnd`" + - fixity: "infixr 2 `predDNFOr`" + - fixity: "infixl 6 |-" + - fixity: "infixr 5 <|" + - fixity: "infixr 5 `cons`" + - fixity: "infixl 5 |>" + - fixity: "infixl 5 `snoc`" + - fixity: "infixl 8 ^.." + - fixity: "infixl 8 ^?" + - fixity: "infixl 8 ^?!" + - fixity: "infixl 8 ^@.." + - fixity: "infixl 8 ^@?" + - fixity: "infixl 8 ^@?!" + - fixity: "infixl 8 ^." + - fixity: "infixl 8 ^@." + - fixity: "infixr 9 <.>" + - fixity: "infixr 9 <." + - fixity: "infixr 9 .>" + - fixity: "infixl 8 ^#" + - fixity: "infixr 4 %%@~" + - fixity: "infixr 4 <%@~" + - fixity: "infixr 4 <<%@~" + - fixity: "infixr 4 %%~" + - fixity: "infixr 4 <+~" + - fixity: "infixr 4 <*~" + - fixity: "infixr 4 <-~" + - fixity: "infixr 4 ~" + - fixity: "infixr 4 <%~" + - fixity: "infixr 4 <<%~" + - fixity: "infixr 4 <<.~" + - fixity: "infixr 4 <~" + - fixity: "infix 4 %%@=" + - fixity: "infix 4 <%@=" + - fixity: "infix 4 <<%@=" + - fixity: "infix 4 %%=" + - fixity: "infix 4 <+=" + - fixity: "infix 4 <*=" + - fixity: "infix 4 <-=" + - fixity: "infix 4 =" + - fixity: "infix 4 <%=" + - fixity: "infix 4 <<%=" + - fixity: "infix 4 <<.=" + - fixity: "infix 4 <=" + - fixity: "infixr 2 <<~" + - fixity: "infixl 1 ??" + - fixity: "infixl 1 &~" + - fixity: "infixr 9 ..." + - fixity: "infixr 8 #" + - fixity: "infixr 4 %@~" + - fixity: "infixr 4 .@~" + - fixity: "infixr 4 .~" + - fixity: "infixr 4 +~" + - fixity: "infixr 4 *~" + - fixity: "infixr 4 -~" + - fixity: "infixr 4 //~" + - fixity: "infixr 4 ^~" + - fixity: "infixr 4 ^^~" + - fixity: "infixr 4 **~" + - fixity: "infixr 4 &&~" + - fixity: "infixr 4 <>~" + - fixity: "infixr 4 ||~" + - fixity: "infixr 4 %~" + - fixity: "infixr 4 <.~" + - fixity: "infixr 4 ?~" + - fixity: "infixr 4 =" + - fixity: "infix 4 ||=" + - fixity: "infix 4 %=" + - fixity: "infix 4 <.=" + - fixity: "infix 4 ?=" + - fixity: "infix 4 " + - fixity: "infixr 4 .|.~" + - fixity: "infixr 4 .&.~" + - fixity: "infixr 4 <.|.~" + - fixity: "infixr 4 <.&.~" + - fixity: "infixr 4 <<.|.~" + - fixity: "infixr 4 <<.&.~" + - fixity: "infix 4 .|.=" + - fixity: "infix 4 .&.=" + - fixity: "infix 4 <.|.=" + - fixity: "infix 4 <.&.=" + - fixity: "infix 4 <<.|.=" + - fixity: "infix 4 <<.&.=" + - fixity: "infixr 4 ~" + - fixity: "infixr 4 <~" + - fixity: "infixr 4 <<~" + - fixity: "infixr 4 <.>~" + - fixity: "infixr 4 <<.>~" + - fixity: "infixr 4 <<<.>~" + - fixity: "infix 4 =" + - fixity: "infix 4 <=" + - fixity: "infix 4 <<=" + - fixity: "infix 4 <.>=" + - fixity: "infix 4 <<.>=" + - fixity: "infix 4 <<<.>=" + + - suggest: { lhs: maybeT (return ()), rhs: maybeT_ } + - suggest: { lhs: fromMaybe (return ()), rhs: maybeVoid } + - suggest: { lhs: maybe (return ()) void, rhs: maybeVoid } + + - warn: { lhs: length xs >= n, rhs: minLength n xs, note: IncreasesLaziness } + - warn: { lhs: n <= length xs, rhs: minLength n xs, note: IncreasesLaziness } + - warn: { lhs: length xs > n, rhs: minLength (n + 1) xs, note: IncreasesLaziness } + - warn: { lhs: n < length xs, rhs: minLength (n + 1) xs, note: IncreasesLaziness } + - warn: { lhs: length xs <= n, rhs: maxLength n xs, note: IncreasesLaziness } + - warn: { lhs: n >= length xs, rhs: maxLength n xs, note: IncreasesLaziness } + - warn: { lhs: length xs < n, rhs: maxLength (n - 1) xs, note: IncreasesLaziness } + - warn: { lhs: n > length xs, rhs: maxLength (n - 1) xs, note: IncreasesLaziness } + + - error: {lhs: v Database.Esqueleto.==. Database.Esqueleto.nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing} + - error: {lhs: v Database.Esqueleto.==. Database.Esqueleto.val Nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing} + - error: {lhs: v Database.Esqueleto.!=. Database.Esqueleto.nothing, rhs: Database.Esqueleto.Utils.isJust v, name: Use Esqueleto's not isNothing} + - error: {lhs: v Database.Esqueleto.!=. Database.Esqueleto.val Nothing, rhs: Database.Esqueleto.Utils.isJust v, name: Use Esqueleto's not isNothing} diff --git a/.mailmap b/.mailmap new file mode 100644 index 000000000..bd23a6e51 --- /dev/null +++ b/.mailmap @@ -0,0 +1,6 @@ +Gregor Kleen +Gregor Kleen +Felix Hamann +Steffen Jost +Sarah Vaupel +Sarah Vaupel Sarah Vaupel <> \ No newline at end of file diff --git a/.versionrc.js b/.versionrc.js new file mode 100644 index 000000000..50f38f817 --- /dev/null +++ b/.versionrc.js @@ -0,0 +1,27 @@ +const standardVersionUpdaterYaml = require.resolve('standard-version-updater-yaml'); + +module.exports = { + scripts: { + // postbump: './sync-versions.hs && git add -- package.yaml', // moved to bumpFiles + postchangelog: 'sed \'s/^### \\[/## [/g\' -i CHANGELOG.md' + }, + packageFiles: ['package.json', 'package.yaml'], + bumpFiles: [ + { + filename: 'package.json', + type: 'json' + }, + { + filename: 'package-lock.json', + type: 'json' + }, + { + filename: 'package.yaml', + updater: standardVersionUpdaterYaml + } + ], + commitUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/{{hash}}', + compareUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/{{previousTag}}...{{currentTag}}', + issueUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/{{id}}', + userUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/{{user}}' +}; diff --git a/CHANGELOG.md b/CHANGELOG.md index c4a0f40ff..8a82ef56c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,575 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [25.10.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.9.3...v25.10.0) (2021-04-15) + + +### Features + +* **workflows:** list involved users ([d8878a9](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/d8878a905e07f1b5fb5159ecdaf70f27e9c1dc37)) + +## [25.9.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.9.2...v25.9.3) (2021-04-14) + +## [25.9.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.9.1...v25.9.2) (2021-04-14) + +## [25.9.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.9.0...v25.9.1) (2021-04-14) + +## [25.9.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.8.1...v25.9.0) (2021-04-13) + + +### Features + +* partial support for lsf import ([37cdc77](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/37cdc775b5b2d3e4cd1cc22858b2c05e75de8a3c)), closes [#686](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/686) + + +### Bug Fixes + +* build ([5c709f1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/5c709f1bbb077d981fbd5d59e9c0f30cddbb468d)) +* prevent deleting sheet-referenced exam parts ([9859c2e](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/9859c2e99c1e0c7531ee38864a24ff279a8e6a7c)), closes [#681](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/681) + +## [25.8.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.8.0...v25.8.1) (2021-04-09) + +## [25.8.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.7.0...v25.8.0) (2021-04-08) + + +### Features + +* additional general purpose caching tier (memcachedLocal) ([939ab37](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/939ab37588bb71b14b8a9f3ab58d7440f598faf9)) + + +### Bug Fixes + +* typo ([f155a4b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/f155a4bf08d169309c05e3efbb47a246f3010816)) + +## [25.7.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.6.1...v25.7.0) (2021-03-30) + + +### Features + +* **course-users-table:** json export ([6f291b2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/6f291b2e6893554193732b059758794fe2b7fa51)) + +## [25.6.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.6.0...v25.6.1) (2021-03-30) + + +### Bug Fixes + +* **admin-tokens:** avoid option none ([af3ec98](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/af3ec98de512f72220d363b9dd0c06532ae1a960)) +* add missing do ([55319c8](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/55319c8c5060a0d8763abb56c27d30e852c51f52)) +* buttons know about ALL actions from other buttons ([11664dc](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/11664dcd82c13eef1c395e2e590c4fb0c587aa65)) +* check space of occurrences after ignoring ([fabf56c](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/fabf56c1640c94f806d43aaca264100cbc39b840)) +* correct rebase-sourced error ([02589e4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/02589e4d00de233d847d6be71e44f9fc451fbfe9)) +* correctly apply suggestion ([67d6fd7](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/67d6fd7d438a31b50e6f4e6e921873ee11b32e9c)) +* correctly handle original minimizeRooms-flag ([d5bd504](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/d5bd5042ad920b26df847845cc437c3f0616575c)) +* correctly report NoUsers for ExamRoomRandom ([16cbc78](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/16cbc78878615a8d123de5d8fda11136685a824c)) +* oops ([f6cbf99](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/f6cbf99245ffdd19a2d6c9acc7c0b9a7f8df45ca)) +* sort occurrences in the right order ([732df50](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/732df5053033c3533f52850cc6220dd06a7e3500)) +* use extraUsers instead of extraCapacity for unrestricted pseudo-capacity ([2be9d76](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/2be9d76af2b3e9fd52284c639a4c3f6dc1c51779)) + +## [25.6.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.5.3...v25.6.0) (2021-03-29) + + +### Features + +* **frontend:** password visibilty toggle ([f0e4547](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/f0e45477fa85a1d82750597cdaf122e41e9c7764)) + +## [25.5.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.5.2...v25.5.3) (2021-03-24) + +## [25.5.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.5.1...v25.5.2) (2021-03-24) + +## [25.5.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.5.0...v25.5.1) (2021-03-23) + + +### Bug Fixes + +* remove cached-db-runner ([ff82700](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ff8270042f74d8019e121aebf8636472e1e4d79e)) + +## [25.5.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.4.0...v25.5.0) (2021-03-23) + + +### Features + +* **course-participants:** csv export first name/surname separately ([1036926](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/1036926470792bf3409ba3a224886d48b7e1d314)) + +## [25.4.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.3.0...v25.4.0) (2021-03-19) + + +### Features + +* **submissions:** also warn correctors about multiple submissions ([8795edd](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8795edd1fa452d012704146481c8318d206634a5)) +* **submissions:** warn about multiple submissions for same user ([c19a00d](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/c19a00dcefb2dcae017026edb6e1c7cb6ce16841)) + + +### Bug Fixes + +* **auth:** wrong caching for external-exam-staff ([9d1f1c6](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/9d1f1c691085ec65ad0f19cc51602a59ee133fc4)) +* **submissions:** improve submission process ([7219131](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/72191315b6daed78cd0f31b02627e1d27db620f3)), closes [#675](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/675) + +## [25.3.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.2.0...v25.3.0) (2021-03-18) + + +### Features + +* **exams:** exam finish button ([78d0f25](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/78d0f2522db759c2ee465e040939c92b2f9a1891)) + + +### Bug Fixes + +* **submissions:** take care when to display corrections ([a6390ec](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/a6390eccbd164ee5e821d3ecb0fab794a417425a)) + +## [25.2.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.1.2...v25.2.0) (2021-03-18) + + +### Features + +* **csv-export:** .xlsx ([5c51394](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/5c513946c15ed215f6958be1c7a435f03314f115)) +* **submissions:** improve behaviour of sheet-type-exam-part ([91a5166](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/91a51664c32bd17e4c2d1cd496bf05338146291d)), closes [#676](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/676) + + +### Bug Fixes + +* **csv-export:** mime confusion ([8bdaae0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8bdaae0881fe98c4c5f69f1332ac2ffb0ca83081)) + +## [25.1.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.1.1...v25.1.2) (2021-03-17) + +## [25.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.1.0...v25.1.1) (2021-03-16) + + +### Bug Fixes + +* weight random token impersonation towards active users ([a314f64](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/a314f64a70d9e7e427383c8d656d9bdceed5f9f3)) + +## [25.1.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.0.5...v25.1.0) (2021-03-16) + + +### Features + +* admins can efficiently generate many tokens for random users ([600bbe5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/600bbe5d7e9051e4a4eac540b01ff358666ebc9c)) + + +### Bug Fixes + +* typo ([f931c67](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/f931c67a9ecf37bd9a6c9814ee61de7cb054dcc5)) +* **test:** isNullResultJustified reported false positives ([292f5cf](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/292f5cf91b56953189ee72e42b822d66761ff3bb)) +* check if number of relevant user is >0 to prevent crash ([317b95b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/317b95be317ea038ad9fa398fc0c0c456b53495d)) +* correctly calculate maximum user name length ([cd07a56](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/cd07a56a9fd3ee99b74e5304581574671e3689a0)) +* handle rare cases where a mappingDescription with start>end would be produced ([c99d96e](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/c99d96ecb8a43400eb10dfe192bf751cb00a9d25)) +* make sure to report NoUsers, regardless of rule ([9c928b0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/9c928b0375c1aab0c46768101849ce8daeae9b81)) +* **test:** fixed compiler errors (oops) ([bc42f30](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/bc42f3072fd37ee6f37c70a0b3999d9ac793b240)) +* ensure termination for non-{'A'..'Z']-names ([873d5a0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/873d5a02adae8f33db349bd9de3c7bd49331d27f)) +* examAutoOccurence no longer user >100% of a room ([eaf245b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/eaf245beaaa1f739d6b857712f1e4ea5b53e7c82)) +* increase size of test instances again (oops) ([4e76fe7](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/4e76fe7e504515845d468fc3251a38c90aaaaf66)) +* make sure it compiles again + add 2-letter name ([d60f935](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/d60f93561f5ee84d460645a945db35ac6b55e97d)) +* make sure line-break algorithm respects available lines ([e487cef](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/e487ceff5858671eb0bcbd813e9de0d3b4c74f75)) +* make sure unfortunate combination doesn't only produce 0-9 ranges for matrikelnummer ([8e4cb09](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8e4cb0917db1098f5b19be0dfad4c6fafb900c49)) +* mappingDescription doesn't overlap for the first n rooms/with small names/matrikelnummer ([fc35fd2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/fc35fd26c1eb699d6eb8aa1b9febb48641c26d05)) +* shown ranges "include" special mappings ([7e1b75c](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/7e1b75c2e167c75ebc3a05f881ad7fb07c29af55)) +* spelling plugin had a suggestion; actually Hello World commit :p ([7b0fd61](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/7b0fd61f7f8bf1e995209bec7b44231b5ba011a6)) +* user with a pre-assigned room count towards the capacity limit ([4fc0535](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/4fc05351fa8048752f2ec3260dcaac64f962c9a3)) + +## [25.0.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.0.4...v25.0.5) (2021-03-13) + + +### Bug Fixes + +* **authorisation:** inverted logic for empty ([65814c0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/65814c005e2637bb5f6347bf1f35133654538e7a)) + +## [25.0.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.0.3...v25.0.4) (2021-03-12) + + +### Bug Fixes + +* tests ([4803026](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/4803026a2c091128a7370c12f0c06de9bd7b9180)) + +## [25.0.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.0.2...v25.0.3) (2021-03-12) + + +### Bug Fixes + +* invalidate nav caches ([e88b6d6](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/e88b6d6bab3ea4577af3cd9465e66aa7e48177a2)) + +## [25.0.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.0.1...v25.0.2) (2021-03-12) + +## [25.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v25.0.0...v25.0.1) (2021-03-11) + + +### Bug Fixes + +* **auth-caching:** submission-group ([896bd41](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/896bd41e3b415283cce16cb84a8219b8d4c1702c)) + +## [25.0.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.9.2...v25.0.0) (2021-03-08) + + +### ⚠ BREAKING CHANGES + +* **auth:** additional authorisation caching + +### Features + +* **auth:** user independent authorisation caching ([63f0d3c](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/63f0d3c37ad4a02a5cbdf76398d4a9c74a0a0b59)) +* **messages:** implement custom parser for message files ([bb877eb](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/bb877eb81396211a801496061ea603b39753829b)) +* **messages:** mkMessageAddition ([ea33d84](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ea33d844cc4acb2503fc4780c7895299eb9d5ef5)) + +## [24.9.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.9.1...v24.9.2) (2021-03-01) + +## [24.9.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.9.0...v24.9.1) (2021-03-01) + + +### Bug Fixes + +* build ([cf33f0a](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/cf33f0af84166b040de4b9a685a58d9884bc67f8)) + +## [24.9.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.8.0...v24.9.0) (2021-02-26) + + +### Features + +* **db:** track source of database accesses ([23ff9d9](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/23ff9d9222d7a75b2931827a6cc0335aafe753a1)) +* **transaction-log:** more details about submission files ([b9cc5b9](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/b9cc5b9970cc0b1f61c9df03c54901d9d6e822d0)) + + +### Bug Fixes + +* **jobs:** wake more often during waitUntil ([6115b83](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/6115b83bb32d767ef54f2a2ae210ad1c7415e69c)) + +## [24.8.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.7.0...v24.8.0) (2021-02-23) + + +### Features + +* **monitoring:** observe database connection opening/closing ([d801a2f](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/d801a2f84ae42862dfc357a58ee47dd6dc39eef8)) + +## [24.7.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.6.0...v24.7.0) (2021-02-23) + + +### Features + +* **db:** provide our own implementation of connection pooling ([50fdcb4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/50fdcb4540e6bfbc8da9ed10ed06d6f6ce443cf9)) + +## [24.6.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.5.0...v24.6.0) (2021-02-21) + + +### Features + +* **db:** optionally disable some db connection pooling ([35ac503](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/35ac503bf971ace21c49646aa15e8b94b7a3e823)) + +## [24.5.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.4.3...v24.5.0) (2021-02-21) + + +### Features + +* **bot-mitigations:** only logged in table sorting ([fb6ae08](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/fb6ae089c63174edc1d84512ea35378ab8cd0e0e)) + +## [24.4.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.4.2...v24.4.3) (2021-02-20) + + +### Bug Fixes + +* **jobs:** use more read only/deferrable transactions ([db48bbb](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/db48bbb7765604aaab8f8d5c540793b1ceaff16a)) + +## [24.4.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.4.1...v24.4.2) (2021-02-19) + + +### Bug Fixes + +* **missing-files:** properly account for workflows ([c272618](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/c272618aa6dd68a1acb5b959c6d905978b26eb07)) + +## [24.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.4.0...v24.4.1) (2021-02-19) + + +### Bug Fixes + +* **files:** count personalised sheet files as alive ([e54b985](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/e54b985815fbbc637d8f4681ac55b3d46e2263a3)) + +## [24.4.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.3.0...v24.4.0) (2021-02-17) + + +### Features + +* **caching:** introduce cache prewarming ([8d1f216](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8d1f216b5b6ee2a59c3fb80f5dd4a701d9dad5ef)) + +## [24.3.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.2.1...v24.3.0) (2021-02-15) + + +### Features + +* **minio:** use separate bucket for temporary files ([1cd79d3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/1cd79d35e2761d84bb904a77e74d5cacb0b2244c)) +* **personalised-sheet-files:** restrict download by exam ([a8f2688](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/a8f268852a256209f6ab187167c2a1c066618c4c)) + + +### Bug Fixes + +* **exam-bonus:** avoid divide by zero if all sheets are bonus ([0fd7e86](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/0fd7e86695f47047c9e4e1bb8efe9477103707ab)), closes [#671](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/671) +* **exam-bonus:** fix rounding ([854fa6b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/854fa6b968ed01d60dea0d9ba6fc93d37e5ec361)), closes [#672](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/672) + +## [24.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.2.0...v24.2.1) (2021-02-11) + + +### Bug Fixes + +* **arc:** reduce lock contention ([1be391f](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/1be391f5f5bf2588939fea92809dd629c0a69d99)) + +## [24.2.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.1.5...v24.2.0) (2021-02-10) + + +### Features + +* implement in-memory cache for file download ([36debd8](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/36debd865f6e74856c74bd658dc4694140183fed)) + + +### Bug Fixes + +* unbreak arc ([8ecb460](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8ecb460f39f48557b5935b1cd18709ba197d3490)) +* **jobs:** prevent offloading instances from deleting cron last exec ([e61b561](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/e61b5611b1568180aa3ccfc3e3b981eb9a13cd53)) + +## [24.1.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.1.4...v24.1.5) (2021-02-09) + +## [24.1.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.1.3...v24.1.4) (2021-02-09) + +## [24.1.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.1.2...v24.1.3) (2021-02-09) + +## [24.1.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.1.1...v24.1.2) (2021-02-09) + +## [24.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.1.0...v24.1.1) (2021-02-09) + +## [24.1.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v24.0.0...v24.1.0) (2021-02-08) + + +### Features + +* ensure cached study feature relevance is up to date ([8798f54](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8798f547a60a7fa7c0849e20e1b0e9d012ac9312)) + + +### Bug Fixes + +* restore storting for exam-office exams ([5698e9c](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/5698e9ca0bb19585b9a9d2d3c10f8b5f99ae5db9)) + +## [24.0.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.7.0...v24.0.0) (2021-02-01) + + +### ⚠ BREAKING CHANGES + +* **jobs:** Job offloading + +### Features + +* **jobs:** batch job offloading ([09fb26f](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/09fb26f1a892feba32185166223f8f95611ea9ef)) + + +### Bug Fixes + +* **workflows:** don't cache instance-list empty for correctness ([cb1e715](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/cb1e715e9b2da2f5ac0bd03b636de0f961307efd)) + +## [23.7.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.6.0...v23.7.0) (2021-01-27) + + +### Features + +* **dbtable:** extra representations ([2c0fc63](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/2c0fc63be1de02e8acffbc6a9c5ee83b061c5825)) +* **exams:** exam sheets ([500000b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/500000ba0f6f3b3c32cfd7593e5468796660d46b)) + + +### Bug Fixes + +* more verbose watchdog notification failures ([48028c4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/48028c40532577f74430340ed924af7116b8bd96)) +* **mass-input:** properly escape query selector ([9a3f401](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/9a3f401b38e86e2f9e7fa722698a437d853b422e)) +* nonmoving-gc still segfaults ([c404ce9](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/c404ce9b3529cf402a0f9d649ca3299df09ba089)) + +## [23.6.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.5.0...v23.6.0) (2020-12-15) + + +### Features + +* **massinput:** reduce size of ajax requests ([72838e2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/72838e2592f159ab79c9f245ac28a4f9bd807e19)) + +## [23.5.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.4.3...v23.5.0) (2020-12-12) + + +### Features + +* **auth:** record student ldap role ([50455e6](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/50455e68a1e89e16a5905b976a09d265afa08bba)) +* **workflows:** explanation text ([aba6737](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/aba673756e9e40057625c41da8b32d378e9b67c6)) + + +### Bug Fixes + +* **tokens:** introduce clock leniency and remove start for downloads ([8939a8b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8939a8b90a39a26614da18dd3985aee253cd191f)) +* hopefully improve workflow auth performance ([1d3fd8c](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/1d3fd8c8a7824d6c6d043f4114067238af4bdc6e)) + +## [23.4.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.4.2...v23.4.3) (2020-12-10) + +## [23.4.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.4.1...v23.4.2) (2020-12-10) + + +### Bug Fixes + +* hopefully speed up aeson via ffi ([a00ba10](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/a00ba10e9cf1ffa534908b9125730e88179052eb)) + +## [23.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.4.0...v23.4.1) (2020-12-10) + +## [23.4.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.3.0...v23.4.0) (2020-12-09) + + +### Features + +* use c++ library for json parsing from database ([f226751](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/f22675189e19d1cce20362121ef8c8aebe3628f1)) + + +### Bug Fixes + +* **jobs:** weaken crontab guarantees for performance ([212e316](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/212e316c7e256f7883e0b883942e98bf795d870b)) + +## [23.3.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.2.2...v23.3.0) (2020-12-09) + + +### Features + +* don't redirect monitoring routes & crontab tokens ([3a106d1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/3a106d1ee5998ddeea852b3b0398c2f330664a63)) +* **admin-crontab:** export as json ([bbd4916](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/bbd4916f3a556ce4c05eb3b2b5268c9c072fdfdd)) +* **jobs:** queue by jobctl priority ([a27a553](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/a27a553e0a9782eda6023ec0b8b1055757bb511f)) + +## [23.2.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.2.1...v23.2.2) (2020-12-09) + + +### Bug Fixes + +* **jobs:** adjust job handling to hopefully reduce load ([ed38f93](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ed38f93537b57b5b3e4563dc0259d805760071bc)) + +## [23.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.2.0...v23.2.1) (2020-12-08) + + +### Bug Fixes + +* **downloads:** do download links via redirect ([3ba41d8](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/3ba41d8f24b4358ad7a045eba0f630e1e2b67663)) +* **files:** better configuration for file batch jobs ([3a90c88](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/3a90c88b359f3e0cb0ed03df6e81b1532509ea48)) + +## [23.2.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.1.2...v23.2.0) (2020-12-06) + + +### Features + +* **workflows:** improve linter ([316097a](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/316097a07ed89e40ecbf3dd8a7160eca95bd7a67)) + + +### Bug Fixes + +* **auth:** fix infinite auth loop for workflow files ([21cf6cf](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/21cf6cfa873b841c2f9f8ab9f69c08ea72fc2420)) + +## [23.1.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.1.1...v23.1.2) (2020-12-05) + + +### Bug Fixes + +* submission download token generation broke viewing ([e1b6084](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/e1b60844cb77b1fd41900d0a3c4829ba21b6b3fe)) + +## [23.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.1.0...v23.1.1) (2020-12-05) + + +### Bug Fixes + +* remove manually inserted error for testing ([8c17f33](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8c17f3354a6e7768ecf427e4c0a899cbff9c7e0a)) + +## [23.1.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.0.3...v23.1.0) (2020-12-04) + + +### Features + +* **admin-workflows:** allow uploading graph spec as file ([48208c9](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/48208c9105ba49feb784ea3143b610ed5b11b517)) +* **errors:** redirect errors back to ApprootDefault ([fbf21d7](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/fbf21d7313d7c2795c171b85a621ad2235eb68c9)) +* **inject-files:** additionally throttle by file count ([3cf0335](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/3cf033560e90ddc104e4056c470459f92b6eb4ae)) +* **workflows:** edge messages ([c22004e](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/c22004e1b2f3cd85297faaf41d76954c0625e308)) +* **workflows:** make admin or token sufficient for all roles ([7a7cd4d](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/7a7cd4d07c907611cf72e5ebe3ae41c3a401ef64)) +* **workflows:** proper workflow-workflow-tables ([ac08846](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ac08846c267f20fa053e3bd73bea72b224b636c6)) +* allow separating user generated content into separate domain ([707b41d](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/707b41d4ec9fa92238eaeb4e77f32d8bd8052c46)) +* **workflows:** prepare for admin-workflow-instance-edit ([ee6fecb](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ee6fecb79e4807beceadd15f19e41393f7707135)) + + +### Bug Fixes + +* **admin-workflows:** fix workflow definition descriptions forms ([f9d933b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/f9d933bdacaf21618da9dc74e7bd6bea5e369aa7)) +* **errors:** better handling of errors from separated approots ([833b674](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/833b674c31ef3d4bf3b9b1af13201f33c98ef82f)) +* **tests:** generate sensible WorkflowPayloadLabels ([8a888d3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8a888d3945f0fd0d67ef83bae621744c943b99de)) +* **workflows:** properly offer previous payload files ([aa0404a](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/aa0404a0075acbcd4c6f94984acdbb4d68f08d0a)) + +## [23.0.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.0.2...v23.0.3) (2020-11-29) + + +### Bug Fixes + +* build ([68b8b45](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/68b8b458b1e02ec992df811cca2cda08a2f77d9a)) +* build ([6322fd4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/6322fd449bd83edf2e1909b95c6aa4c795d49a54)) +* build ([b1641ad](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/b1641ad57e036c33d12cc9002f2355231676f9d1)) +* build ([43bb0ab](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/43bb0abe7218f6d43b52d9a64e62f0dc29b9972e)) +* **rooms:** honor roomHidden ([ed5d871](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ed5d871182954e2f0a9a5063f61277d925628c40)) + +## [23.0.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.0.1...v23.0.2) (2020-11-28) + + +### Bug Fixes + +* **tests:** remove invalid claim of commutativity ([d2f0361](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/d2f0361e49114e6dc6c55e64b677b8c842e93bee)) +* build ([23a21b9](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/23a21b905c902bea5fe88abd84da600e757a194e)) + +## [23.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v23.0.0...v23.0.1) (2020-11-27) + + +### Bug Fixes + +* csp-sandbox downloads ([50cbba1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/50cbba114a850469ed6893e697d0c329c8e894e0)) +* non-dev build ([dfea399](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/dfea39907cd114e6d8aea29ae3835dd323ca4df8)) +* **auth:** authorize exam offices by school ([946a42b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/946a42b7f01016652d03dd214fdf2bc7202ab8ab)) +* **csv:** ignore empty lines ([211ff5e](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/211ff5eacc83bb47e564dd88e11bc18ae7e0a6af)) + +## [23.0.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v22.1.1...v23.0.0) (2020-11-25) + + +### ⚠ BREAKING CHANGES + +* **migration:** ManualMigration +* **workflows:** digests now json encode via base64 + +Also improve efficiency of marking workflow files as referenced + +### Features + +* **exams:** optionally close on finish ([4b525ea](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/4b525ea8246706d191fce109d4a9d1f5cc4c22d1)), closes [#652](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/652) +* **external-exams:** open defaults wrt. external exam schools ([ef1411e](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ef1411efdb644e300656403c071cfcdef9caf077)), closes [#651](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/651) +* **migration:** switch from versions to enum ([f2fb7d8](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/f2fb7d8c267fed96f0dbdb237f4984c8996fbce8)) +* **rooms:** different room types & hidden rooms ([319c75a](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/319c75a85aa5e5f7e2f2af328d69960e1df3cb80)) +* **theses:** additional state explanation ([1e38734](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/1e3873485e3da81b25dd0a0eb5aed7b9e0fe42b2)) +* **workflows:** add missing instances; correct Int64 workaround ([8b32ede](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8b32edee64509ca5a3d5fc206192d4fa43cc1971)) +* **workflows:** additional work on WorkflowWorkflowWorkflow ([5108e14](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/5108e1494aa8b2bc8b383a349d1d2a4e0249501f)) +* **workflows:** create new workflow definitions ([4d63d30](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/4d63d306347ed452822b6bea101cdf4391363ed1)) +* **workflows:** definition route stubs & i18n ([e3b5b93](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/e3b5b93c71e49203e428382cfabb3d536f290cc4)) +* **workflows:** delete definitions ([bda4f81](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/bda4f81702d94d81427a4980b217be8cae2b9152)) +* **workflows:** further work on WorkflowWorkflowWorkflow ([5b897c7](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/5b897c7a42067d6a7918dc7bc9640b5c3d8a1367)) +* **workflows:** initiate ([fd7c91f](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/fd7c91f5b8aa2645e0e072115d6a7da58323971a)) +* **workflows:** list & edit definitions ([ff370c6](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ff370c68c735c492e8e588a8bb8e4055aa8cc0f4)) +* **workflows:** node messages ([6a7a892](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/6a7a892c74ad7da906a841fbfd031cca59174a8c)) +* **workflows:** placeholder handlers ([baea302](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/baea302e48dd6c603eebba7040923f0c23266f40)) +* **workflows:** wire up ws-school ([82b3a63](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/82b3a6364c77c64a653e927cd0242d64ffcf9d2a)) + + +### Bug Fixes + +* **i18n:** missing workflow translations ([ed4ee13](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ed4ee1320bd2eaeb462a1e6b72b0f4ff24e447f3)) +* **workflow:** add missing optional ([8608e83](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8608e83ef80497b7ddcc451759a98a07b435fc08)) +* **workflow:** fix false instance with atrocious instances ([8812f24](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8812f24d9060314d60c3ae495ea7daccdabff30d)) +* **workflow:** fix node and graph FromJSON instances ([263fee1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/263fee19f25a4782bf426347e385eedd1742c8da)) +* **workflow:** fix types ([ce1acec](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ce1acec444762d254ccf07b37c280ffb02934669)) +* **workflow:** fix types ([4334253](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/4334253122f4208fb4dc61f5cbf4436f122b14e2)) +* **workflow-types:** fix Int64 workaround; update test defs ([ce9648e](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ce9648e47a870e3a051591631c2eb3a26c6b4b3c)) +* **workflow-types:** minor import fix ([b19c1b3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/b19c1b31b7b079f3abe6aff93e3b5603050c6131)) +* **workflows:** add missing import/reexport ([5e92a6e](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/5e92a6e04aeb9a54ab361f83c7168e57ae5e9c33)) +* **workflows:** cleanup ([0a3eaa2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/0a3eaa29946ba00ba0c9597d124f4ca5cc25620d)) +* **workflows:** integrate in new master ([99f3fca](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/99f3fca6d08f098b996931c8c4736eefbc9db77c)) +* **workflows:** navigation order ([c5eea64](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/c5eea64b270369ef69e1aa368ec87f0a8846e1fd)) +* **workflows:** prefer payload label from target state ([2619b08](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/2619b08ad1be2921d2cdd568f9419852c374df10)) +* tests ([3c322af](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/3c322af49e2021b2963fef9fbe303fa70ec77e18)) +* **workflows:** refer by id in model ([94f78a0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/94f78a07d9376670122a2adce01cf7180a64d33d)) +* **workflows:** ui improvements ([c7f4fa0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/c7f4fa0e412d2b920a3819ffed5b79b8aeea2842)) + +## [22.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v22.1.0...v22.1.1) (2020-11-14) + ## [22.1.0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v22.0.0...v22.1.0) (2020-11-10) @@ -26,7 +595,7 @@ All notable changes to this project will be documented in this file. See [standa * **html-field:** introduce stored-markup ([e25e8a2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/e25e8a2f4ca65afc29acc8a3884df9acf77d4398)) -### [21.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v21.1.0...v21.1.1) (2020-11-06) +## [21.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v21.1.0...v21.1.1) (2020-11-06) ### Bug Fixes @@ -40,21 +609,21 @@ All notable changes to this project will be documented in this file. See [standa * **sheets:** upload-empty-ok ([ab1940c](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ab1940cb09e824fbba03264b5451fa8b17c5c804)) -### [21.0.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v21.0.2...v21.0.3) (2020-11-05) +## [21.0.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v21.0.2...v21.0.3) (2020-11-05) ### Bug Fixes * **mails:** prevent emails being resent to due archiving errors ([8cf39dc](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8cf39dcbe68cefcc50691ae8a7194315d18420d6)) -### [21.0.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v21.0.1...v21.0.2) (2020-11-04) +## [21.0.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v21.0.1...v21.0.2) (2020-11-04) ### Bug Fixes * build ([fa61b46](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/fa61b46d308753354623df17241b5312f324321e)) -### [21.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v21.0.0...v21.0.1) (2020-11-04) +## [21.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v21.0.0...v21.0.1) (2020-11-04) ### Bug Fixes @@ -105,7 +674,7 @@ All notable changes to this project will be documented in this file. See [standa * **allocations:** fix allocation-course-accept-substitutes ([b4df980](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/b4df98069982752e36e69571f5557a6179b44cff)) -### [20.12.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.12.0...v20.12.1) (2020-10-14) +## [20.12.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.12.0...v20.12.1) (2020-10-14) ### Bug Fixes @@ -120,7 +689,7 @@ All notable changes to this project will be documented in this file. See [standa * **ldap:** expose active directory errors ([51ed7e0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/51ed7e0a26a94d2178a4ca10ad7ea36b99076b54)) -### [20.11.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.11.0...v20.11.1) (2020-10-14) +## [20.11.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.11.0...v20.11.1) (2020-10-14) ### Bug Fixes @@ -155,7 +724,7 @@ All notable changes to this project will be documented in this file. See [standa * **exams:** auth ExamResults by ExamExamOfficeSchools ([29a3e24](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/29a3e24bcf01cd9c893857eda00dcd249e6cbbe2)) * **exams:** exam staff & additional schools ([94436ee](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/94436ee0e1ce2cbf13a66f9ad81883d7286acb9b)) -### [20.8.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.8.0...v20.8.1) (2020-10-12) +## [20.8.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.8.0...v20.8.1) (2020-10-12) ### Bug Fixes @@ -188,7 +757,7 @@ All notable changes to this project will be documented in this file. See [standa * **study-features:** also apply caching to table columns ([564c0b9](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/564c0b975ae65881cb3a168855b36e4b1614a6cb)) -### [20.5.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.5.0...v20.5.1) (2020-09-29) +## [20.5.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.5.0...v20.5.1) (2020-09-29) ### Bug Fixes @@ -213,7 +782,7 @@ All notable changes to this project will be documented in this file. See [standa * **allocations:** notify for new course upon registration ([9e0b43a](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/9e0b43a60d26a05f6e1b9d4dae2b2f75dd52fff1)) * tests ([ca81f3b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ca81f3b0f2913431cbaf399c33ed30a21979ce69)) -### [20.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.4.0...v20.4.1) (2020-09-23) +## [20.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.4.0...v20.4.1) (2020-09-23) ### Bug Fixes @@ -232,14 +801,14 @@ All notable changes to this project will be documented in this file. See [standa * **jobs:** better flushing, correct metrics, better etas ([e4416e7](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/e4416e7f0e2ea2cf9db0e61cf2d20c27260ccaf8)) -### [20.3.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.3.1...v20.3.2) (2020-09-22) +## [20.3.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.3.1...v20.3.2) (2020-09-22) ### Bug Fixes * **files:** don't inject serializable ([2ca024b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/2ca024b9351df800b57d3235c4a00776cd669952)) -### [20.3.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.3.0...v20.3.1) (2020-09-22) +## [20.3.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.3.0...v20.3.1) (2020-09-22) ### Bug Fixes @@ -267,7 +836,7 @@ All notable changes to this project will be documented in this file. See [standa * **exam-form:** sort occurrences and parts ([6d47549](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/6d475497c0caee49ad34c5c3c6e7b1bf91ca0ba2)) -### [20.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.1.0...v20.1.1) (2020-09-18) +## [20.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v20.1.0...v20.1.1) (2020-09-18) ### Bug Fixes @@ -309,7 +878,7 @@ All notable changes to this project will be documented in this file. See [standa * zip handling & tests ([350ee79](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/350ee79af3c8fcc480970166a559596873beab2a)) -### [19.3.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.3.0...v19.3.1) (2020-09-10) +## [19.3.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.3.0...v19.3.1) (2020-09-10) ### Bug Fixes @@ -343,14 +912,14 @@ All notable changes to this project will be documented in this file. See [standa * tests ([018d26f](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/018d26f4a1a1cf411324aeac56ce4d4203670942)) * tests ([5541619](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/5541619372f4a4e46ccc403004e869afdfaed7b0)) -### [19.2.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.2.1...v19.2.2) (2020-08-26) +## [19.2.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.2.1...v19.2.2) (2020-08-26) ### Bug Fixes * have exam deregistration always delete stored grades ([24f428b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/24f428b13bb181bec99417b4e69fc538e35acbcf)) -### [19.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.2.0...v19.2.1) (2020-08-26) +## [19.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.2.0...v19.2.1) (2020-08-26) ### Bug Fixes @@ -372,23 +941,23 @@ All notable changes to this project will be documented in this file. See [standa -### [19.1.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.1.4...v19.1.5) (2020-08-19) +## [19.1.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.1.4...v19.1.5) (2020-08-19) -### [19.1.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.1.3...v19.1.4) (2020-08-18) +## [19.1.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.1.3...v19.1.4) (2020-08-18) -### [19.1.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.1.2...v19.1.3) (2020-08-17) +## [19.1.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.1.2...v19.1.3) (2020-08-17) -### [19.1.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.1.1...v19.1.2) (2020-08-17) +## [19.1.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.1.1...v19.1.2) (2020-08-17) -### [19.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.1.0...v19.1.1) (2020-08-17) +## [19.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v19.1.0...v19.1.1) (2020-08-17) @@ -532,7 +1101,7 @@ All notable changes to this project will be documented in this file. See [standa -### [18.2.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v18.2.1...v18.2.2) (2020-07-23) +## [18.2.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v18.2.1...v18.2.2) (2020-07-23) ### Bug Fixes @@ -542,7 +1111,7 @@ All notable changes to this project will be documented in this file. See [standa -### [18.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v18.2.0...v18.2.1) (2020-07-22) +## [18.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v18.2.0...v18.2.1) (2020-07-22) @@ -628,7 +1197,7 @@ All notable changes to this project will be documented in this file. See [standa -### [17.6.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.6.4...v17.6.5) (2020-06-26) +## [17.6.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.6.4...v17.6.5) (2020-06-26) ### Bug Fixes @@ -637,19 +1206,19 @@ All notable changes to this project will be documented in this file. See [standa -### [17.6.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.6.3...v17.6.4) (2020-06-24) +## [17.6.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.6.3...v17.6.4) (2020-06-24) -### [17.6.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.6.2...v17.6.3) (2020-06-24) +## [17.6.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.6.2...v17.6.3) (2020-06-24) -### [17.6.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.6.1...v17.6.2) (2020-06-24) +## [17.6.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.6.1...v17.6.2) (2020-06-24) -### [17.6.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.6.0...v17.6.1) (2020-06-24) +## [17.6.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.6.0...v17.6.1) (2020-06-24) ### Bug Fixes @@ -694,7 +1263,7 @@ All notable changes to this project will be documented in this file. See [standa -### [17.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.4.0...v17.4.1) (2020-06-15) +## [17.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.4.0...v17.4.1) (2020-06-15) @@ -729,7 +1298,7 @@ All notable changes to this project will be documented in this file. See [standa -### [17.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.2.0...v17.2.1) (2020-05-28) +## [17.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.2.0...v17.2.1) (2020-05-28) @@ -748,7 +1317,7 @@ All notable changes to this project will be documented in this file. See [standa -### [17.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.1.0...v17.1.1) (2020-05-26) +## [17.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v17.1.0...v17.1.1) (2020-05-26) ### Bug Fixes @@ -817,11 +1386,11 @@ All notable changes to this project will be documented in this file. See [standa -### [16.4.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.4.1...v16.4.2) (2020-05-13) +## [16.4.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.4.1...v16.4.2) (2020-05-13) -### [16.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.4.0...v16.4.1) (2020-05-13) +## [16.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.4.0...v16.4.1) (2020-05-13) ### Bug Fixes @@ -849,7 +1418,7 @@ All notable changes to this project will be documented in this file. See [standa -### [16.3.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.3.0...v16.3.1) (2020-05-10) +## [16.3.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.3.0...v16.3.1) (2020-05-10) ### Bug Fixes @@ -867,7 +1436,7 @@ All notable changes to this project will be documented in this file. See [standa -### [16.2.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.2.1...v16.2.2) (2020-05-08) +## [16.2.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.2.1...v16.2.2) (2020-05-08) ### Bug Fixes @@ -876,7 +1445,7 @@ All notable changes to this project will be documented in this file. See [standa -### [16.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.2.0...v16.2.1) (2020-05-08) +## [16.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.2.0...v16.2.1) (2020-05-08) ### Bug Fixes @@ -914,7 +1483,7 @@ All notable changes to this project will be documented in this file. See [standa -### [16.0.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.0.4...v16.0.5) (2020-05-06) +## [16.0.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.0.4...v16.0.5) (2020-05-06) ### Bug Fixes @@ -923,7 +1492,7 @@ All notable changes to this project will be documented in this file. See [standa -### [16.0.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.0.3...v16.0.4) (2020-05-06) +## [16.0.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.0.3...v16.0.4) (2020-05-06) ### Bug Fixes @@ -932,7 +1501,7 @@ All notable changes to this project will be documented in this file. See [standa -### [16.0.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.0.2...v16.0.3) (2020-05-05) +## [16.0.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.0.2...v16.0.3) (2020-05-05) ### Bug Fixes @@ -942,7 +1511,7 @@ All notable changes to this project will be documented in this file. See [standa -### [16.0.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.0.1...v16.0.2) (2020-05-05) +## [16.0.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.0.1...v16.0.2) (2020-05-05) ### Bug Fixes @@ -952,7 +1521,7 @@ All notable changes to this project will be documented in this file. See [standa -### [16.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.0.0...v16.0.1) (2020-05-05) +## [16.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v16.0.0...v16.0.1) (2020-05-05) ### Bug Fixes @@ -981,7 +1550,7 @@ All notable changes to this project will be documented in this file. See [standa -### [15.6.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v15.6.0...v15.6.1) (2020-04-30) +## [15.6.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v15.6.0...v15.6.1) (2020-04-30) ### Bug Fixes @@ -1025,7 +1594,7 @@ All notable changes to this project will be documented in this file. See [standa -### [15.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v15.4.0...v15.4.1) (2020-04-26) +## [15.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v15.4.0...v15.4.1) (2020-04-26) ### Bug Fixes @@ -1085,7 +1654,7 @@ All notable changes to this project will be documented in this file. See [standa -### [15.1.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v15.1.1...v15.1.2) (2020-04-19) +## [15.1.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v15.1.1...v15.1.2) (2020-04-19) ### Bug Fixes @@ -1094,7 +1663,7 @@ All notable changes to this project will be documented in this file. See [standa -### [15.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v15.1.0...v15.1.1) (2020-04-17) +## [15.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v15.1.0...v15.1.1) (2020-04-17) ### Bug Fixes @@ -1246,7 +1815,7 @@ All notable changes to this project will be documented in this file. See [standa -### [14.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v14.1.0...v14.1.1) (2020-03-06) +## [14.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v14.1.0...v14.1.1) (2020-03-06) ### Bug Fixes @@ -1301,7 +1870,7 @@ relative when priorities are ordinal -### [13.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v13.0.0...v13.0.1) (2020-02-24) +## [13.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v13.0.0...v13.0.1) (2020-02-24) ### Bug Fixes @@ -1370,7 +1939,7 @@ relative when priorities are ordinal -### [11.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v11.1.0...v11.1.1) (2020-02-14) +## [11.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v11.1.0...v11.1.1) (2020-02-14) ### Bug Fixes @@ -1568,7 +2137,7 @@ relative when priorities are ordinal -### [10.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v10.4.0...v10.4.1) (2020-01-17) +## [10.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v10.4.0...v10.4.1) (2020-01-17) ### Bug Fixes @@ -1678,7 +2247,7 @@ relative when priorities are ordinal -### [10.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v10.0.0...v10.0.1) (2019-12-19) +## [10.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v10.0.0...v10.0.1) (2019-12-19) ### Bug Fixes @@ -1738,7 +2307,7 @@ relative when priorities are ordinal -### [9.0.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v9.0.2...v9.0.3) (2019-12-03) +## [9.0.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v9.0.2...v9.0.3) (2019-12-03) ### Bug Fixes @@ -1747,7 +2316,7 @@ relative when priorities are ordinal -### [9.0.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v9.0.1...v9.0.2) (2019-12-02) +## [9.0.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v9.0.1...v9.0.2) (2019-12-02) ### Bug Fixes @@ -1756,7 +2325,7 @@ relative when priorities are ordinal -### [9.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v9.0.0...v9.0.1) (2019-11-28) +## [9.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v9.0.0...v9.0.1) (2019-11-28) ### Bug Fixes @@ -1779,7 +2348,7 @@ relative when priorities are ordinal -### [8.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v8.0.0...v8.0.1) (2019-11-27) +## [8.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v8.0.0...v8.0.1) (2019-11-27) ### Bug Fixes @@ -1817,7 +2386,7 @@ relative when priorities are ordinal -### [7.25.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.25.0...v7.25.1) (2019-11-22) +## [7.25.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.25.0...v7.25.1) (2019-11-22) @@ -1847,7 +2416,7 @@ relative when priorities are ordinal -### [7.23.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.23.1...v7.23.2) (2019-11-19) +## [7.23.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.23.1...v7.23.2) (2019-11-19) ### Bug Fixes @@ -1857,7 +2426,7 @@ relative when priorities are ordinal -### [7.23.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.23.0...v7.23.1) (2019-11-19) +## [7.23.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.23.0...v7.23.1) (2019-11-19) ### Bug Fixes @@ -1884,7 +2453,7 @@ relative when priorities are ordinal -### [7.22.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.22.0...v7.22.1) (2019-11-14) +## [7.22.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.22.0...v7.22.1) (2019-11-14) @@ -1906,23 +2475,23 @@ relative when priorities are ordinal -### [7.21.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.21.4...v7.21.5) (2019-11-13) +## [7.21.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.21.4...v7.21.5) (2019-11-13) -### [7.21.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.21.3...v7.21.4) (2019-11-13) +## [7.21.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.21.3...v7.21.4) (2019-11-13) -### [7.21.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.21.2...v7.21.3) (2019-11-13) +## [7.21.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.21.2...v7.21.3) (2019-11-13) -### [7.21.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.21.1...v7.21.2) (2019-11-12) +## [7.21.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.21.1...v7.21.2) (2019-11-12) -### [7.21.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.21.0...v7.21.1) (2019-11-11) +## [7.21.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.21.0...v7.21.1) (2019-11-11) @@ -1991,7 +2560,7 @@ relative when priorities are ordinal -### [7.19.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.19.1...v7.19.2) (2019-10-28) +## [7.19.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.19.1...v7.19.2) (2019-10-28) ### Bug Fixes @@ -2000,7 +2569,7 @@ relative when priorities are ordinal -### [7.19.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.19.0...v7.19.1) (2019-10-25) +## [7.19.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.19.0...v7.19.1) (2019-10-25) ### Bug Fixes @@ -2023,7 +2592,7 @@ relative when priorities are ordinal -### [7.18.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.18.2...v7.18.3) (2019-10-23) +## [7.18.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.18.2...v7.18.3) (2019-10-23) ### Bug Fixes @@ -2032,11 +2601,11 @@ relative when priorities are ordinal -### [7.18.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.18.1...v7.18.2) (2019-10-20) +## [7.18.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.18.1...v7.18.2) (2019-10-20) -### [7.18.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.18.0...v7.18.1) (2019-10-20) +## [7.18.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.18.0...v7.18.1) (2019-10-20) ### Bug Fixes @@ -2060,7 +2629,7 @@ relative when priorities are ordinal -### [7.17.14](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.13...v7.17.14) (2019-10-17) +## [7.17.14](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.13...v7.17.14) (2019-10-17) ### Bug Fixes @@ -2069,7 +2638,7 @@ relative when priorities are ordinal -### [7.17.13](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.12...v7.17.13) (2019-10-17) +## [7.17.13](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.12...v7.17.13) (2019-10-17) ### Bug Fixes @@ -2078,11 +2647,11 @@ relative when priorities are ordinal -### [7.17.12](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.11...v7.17.12) (2019-10-17) +## [7.17.12](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.11...v7.17.12) (2019-10-17) -### [7.17.11](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.10...v7.17.11) (2019-10-16) +## [7.17.11](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.10...v7.17.11) (2019-10-16) ### Bug Fixes @@ -2091,7 +2660,7 @@ relative when priorities are ordinal -### [7.17.10](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.9...v7.17.10) (2019-10-16) +## [7.17.10](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.9...v7.17.10) (2019-10-16) ### Bug Fixes @@ -2100,7 +2669,7 @@ relative when priorities are ordinal -### [7.17.9](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.8...v7.17.9) (2019-10-16) +## [7.17.9](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.8...v7.17.9) (2019-10-16) ### Bug Fixes @@ -2109,7 +2678,7 @@ relative when priorities are ordinal -### [7.17.8](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.7...v7.17.8) (2019-10-16) +## [7.17.8](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.7...v7.17.8) (2019-10-16) ### Bug Fixes @@ -2118,7 +2687,7 @@ relative when priorities are ordinal -### [7.17.7](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.6...v7.17.7) (2019-10-15) +## [7.17.7](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.6...v7.17.7) (2019-10-15) ### Bug Fixes @@ -2127,7 +2696,7 @@ relative when priorities are ordinal -### [7.17.6](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.5...v7.17.6) (2019-10-15) +## [7.17.6](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.5...v7.17.6) (2019-10-15) ### Bug Fixes @@ -2136,7 +2705,7 @@ relative when priorities are ordinal -### [7.17.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.4...v7.17.5) (2019-10-15) +## [7.17.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.4...v7.17.5) (2019-10-15) ### Bug Fixes @@ -2145,7 +2714,7 @@ relative when priorities are ordinal -### [7.17.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.3...v7.17.4) (2019-10-15) +## [7.17.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.3...v7.17.4) (2019-10-15) ### Bug Fixes @@ -2154,11 +2723,11 @@ relative when priorities are ordinal -### [7.17.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.2...v7.17.3) (2019-10-14) +## [7.17.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.2...v7.17.3) (2019-10-14) -### [7.17.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.1...v7.17.2) (2019-10-14) +## [7.17.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.1...v7.17.2) (2019-10-14) ### Bug Fixes @@ -2167,7 +2736,7 @@ relative when priorities are ordinal -### [7.17.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.0...v7.17.1) (2019-10-14) +## [7.17.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.17.0...v7.17.1) (2019-10-14) ### Bug Fixes @@ -2205,7 +2774,7 @@ relative when priorities are ordinal -### [7.14.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.14.0...v7.14.1) (2019-10-13) +## [7.14.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.14.0...v7.14.1) (2019-10-13) ### Bug Fixes @@ -2294,7 +2863,7 @@ relative when priorities are ordinal -### [7.9.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.9.0...v7.9.1) (2019-10-07) +## [7.9.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.9.0...v7.9.1) (2019-10-07) ### Bug Fixes @@ -2312,7 +2881,7 @@ relative when priorities are ordinal -### [7.8.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.8.4...v7.8.5) (2019-10-05) +## [7.8.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.8.4...v7.8.5) (2019-10-05) ### Bug Fixes @@ -2321,7 +2890,7 @@ relative when priorities are ordinal -### [7.8.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.8.3...v7.8.4) (2019-10-05) +## [7.8.4](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.8.3...v7.8.4) (2019-10-05) ### Bug Fixes @@ -2330,7 +2899,7 @@ relative when priorities are ordinal -### [7.8.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.8.2...v7.8.3) (2019-10-05) +## [7.8.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.8.2...v7.8.3) (2019-10-05) ### Bug Fixes @@ -2339,7 +2908,7 @@ relative when priorities are ordinal -### [7.8.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.8.1...v7.8.2) (2019-10-04) +## [7.8.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.8.1...v7.8.2) (2019-10-04) ### Bug Fixes @@ -2348,7 +2917,7 @@ relative when priorities are ordinal -### [7.8.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.8.0...v7.8.1) (2019-10-04) +## [7.8.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.8.0...v7.8.1) (2019-10-04) ### Bug Fixes @@ -2401,7 +2970,7 @@ relative when priorities are ordinal -### [7.4.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.4.1...v7.4.2) (2019-10-01) +## [7.4.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.4.1...v7.4.2) (2019-10-01) ### Bug Fixes @@ -2410,7 +2979,7 @@ relative when priorities are ordinal -### [7.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.4.0...v7.4.1) (2019-10-01) +## [7.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.4.0...v7.4.1) (2019-10-01) ### Bug Fixes @@ -2428,7 +2997,7 @@ relative when priorities are ordinal -### [7.3.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.3.1...v7.3.2) (2019-10-01) +## [7.3.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.3.1...v7.3.2) (2019-10-01) ### Bug Fixes @@ -2438,7 +3007,7 @@ relative when priorities are ordinal -### [7.3.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.3.0...v7.3.1) (2019-09-30) +## [7.3.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.3.0...v7.3.1) (2019-09-30) ### Bug Fixes @@ -2461,7 +3030,7 @@ relative when priorities are ordinal -### [7.2.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.2.1...v7.2.2) (2019-09-30) +## [7.2.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.2.1...v7.2.2) (2019-09-30) ### Bug Fixes @@ -2470,7 +3039,7 @@ relative when priorities are ordinal -### [7.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.2.0...v7.2.1) (2019-09-28) +## [7.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.2.0...v7.2.1) (2019-09-28) ### Bug Fixes @@ -2495,7 +3064,7 @@ relative when priorities are ordinal -### [7.1.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.1.1...v7.1.2) (2019-09-26) +## [7.1.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.1.1...v7.1.2) (2019-09-26) ### Bug Fixes @@ -2504,7 +3073,7 @@ relative when priorities are ordinal -### [7.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.1.0...v7.1.1) (2019-09-26) +## [7.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v7.1.0...v7.1.1) (2019-09-26) ### Bug Fixes @@ -2571,7 +3140,7 @@ relative when priorities are ordinal -### [6.11.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v6.11.0...v6.11.1) (2019-09-17) +## [6.11.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v6.11.0...v6.11.1) (2019-09-17) ### Bug Fixes @@ -2720,7 +3289,7 @@ relative when priorities are ordinal -### [6.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v6.2.0...v6.2.1) (2019-09-04) +## [6.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v6.2.0...v6.2.1) (2019-09-04) ### Bug Fixes @@ -2854,7 +3423,7 @@ relative when priorities are ordinal -### [5.2.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v5.2.2...v5.2.3) (2019-08-22) +## [5.2.3](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v5.2.2...v5.2.3) (2019-08-22) ### Bug Fixes @@ -2863,11 +3432,11 @@ relative when priorities are ordinal -### [5.2.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v5.2.1...v5.2.2) (2019-08-22) +## [5.2.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v5.2.1...v5.2.2) (2019-08-22) -### [5.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v5.2.0...v5.2.1) (2019-08-21) +## [5.2.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v5.2.0...v5.2.1) (2019-08-21) ### Bug Fixes @@ -2907,7 +3476,7 @@ relative when priorities are ordinal -### [5.0.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v5.0.1...v5.0.2) (2019-08-13) +## [5.0.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v5.0.1...v5.0.2) (2019-08-13) ### Bug Fixes @@ -2916,7 +3485,7 @@ relative when priorities are ordinal -### [5.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v5.0.0...v5.0.1) (2019-08-12) +## [5.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v5.0.0...v5.0.1) (2019-08-12) @@ -2977,7 +3546,7 @@ them together now) -### [4.13.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v4.13.0...v4.13.1) (2019-08-07) +## [4.13.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v4.13.0...v4.13.1) (2019-08-07) ### Bug Fixes @@ -2997,7 +3566,7 @@ them together now) -### [4.12.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v4.12.0...v4.12.1) (2019-08-06) +## [4.12.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v4.12.0...v4.12.1) (2019-08-06) ### Bug Fixes @@ -3161,7 +3730,7 @@ them together now) -### [4.1.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v4.1.1...v4.1.2) (2019-07-17) +## [4.1.2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v4.1.1...v4.1.2) (2019-07-17) ### Bug Fixes @@ -3170,7 +3739,7 @@ them together now) -### [4.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v4.1.0...v4.1.1) (2019-07-17) +## [4.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v4.1.0...v4.1.1) (2019-07-17) ### Bug Fixes @@ -3191,7 +3760,7 @@ them together now) -### [4.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v4.0.0...v4.0.1) (2019-07-16) +## [4.0.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v4.0.0...v4.0.1) (2019-07-16) ### Bug Fixes @@ -3241,7 +3810,7 @@ them together now) -### [2.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v2.1.0...v2.1.1) (2019-07-10) +## [2.1.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v2.1.0...v2.1.1) (2019-07-10) ### Bug Fixes @@ -3288,7 +3857,7 @@ them together now) -### [1.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v1.4.0...v1.4.1) (2019-07-04) +## [1.4.1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v1.4.0...v1.4.1) (2019-07-04) diff --git a/config/settings.yml b/config/settings.yml index fd1b4bccb..081cdc1f4 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -12,6 +12,9 @@ host: "_env:HOST:*4" # any IPv4 host port: "_env:PORT:3000" ip-from-header: "_env:IP_FROM_HEADER:false" approot: "_env:APPROOT:http://localhost:3000" +# approot: +# default: "http://localhost:3000" +# user-generated: "http://127.0.0.1:3000" mail-from: name: "_env:MAILFROM_NAME:Uni2work" email: "_env:MAILFROM_EMAIL:uniworx@localhost" @@ -60,6 +63,9 @@ health-check-matching-cluster-config-timeout: "_env:HEALTHCHECK_MATCHING_CLUSTER synchronise-ldap-users-within: "_env:SYNCHRONISE_LDAP_WITHIN:1209600" synchronise-ldap-users-interval: "_env:SYNCHRONISE_LDAP_INTERVAL:3600" +study-features-recache-relevance-within: 172800 +study-features-recache-relevance-interval: 293 + log-settings: detailed: "_env:DETAILED_LOGGING:false" all: "_env:LOG_ALL:false" @@ -84,6 +90,7 @@ auth-pw-hash: # reload-templates: false # mutable-static: false # skip-combining: false +# clear-cache: false database: user: "_env:PGUSER:uniworx" @@ -150,6 +157,10 @@ memcached: limit: "_env:MEMCACHED_LIMIT:1024" timeout: "_env:MEMCACHED_TIMEOUT:20" expiration: "_env:MEMCACHED_EXPIRATION:300" +memcache-auth: true +memcached-local: + maximum-ghost: 512 + maximum-weight: 104857600 # 100MiB upload-cache: host: "_env:UPLOAD_S3_HOST:" @@ -161,9 +172,11 @@ upload-cache: auto-discover-region: "_env:UPLOAD_S3_AUTO_DISCOVER_REGION:true" disable-cert-validation: "_env:UPLOAD_S3_DISABLE_CERT_VALIDATION:false" upload-cache-bucket: "uni2work-uploads" +upload-tmp-bucket: "uni2work-tmp" inject-files: 601 rechunk-files: 1201 +check-missing-files: 7207 file-upload-db-chunksize: 4194304 # 4MiB file-chunking-target-exponent: 21 # 2MiB @@ -174,9 +187,13 @@ server-sessions: absolute-timeout: 604801 timeout-resolution: 601 persistent-cookies: true +session-token-start: null session-token-expiration: 28807 session-token-encoding: HS256 +session-token-clock-leniency-start: 5 +bearer-token-clock-leniency-start: 5 + cookies: SESSION: same-site: lax @@ -204,7 +221,7 @@ cookies: secure: "_env:COOKIES_SECURE:true" user-defaults: - max-favourites: 12 + max-favourites: 0 max-favourite-terms: 2 theme: Default date-time-format: "%a %d %b %Y %R" @@ -246,6 +263,10 @@ token-buckets: depth: 20971520 # 20MiB inv-rate: 9.5e-7 # 1MiB/s initial-value: 0 + inject-files-count: + depth: 100 + inv-rate: 1 + initial-value: 0 prune-files: depth: 1572864000 # 1500MiB inv-rate: 1.9e-6 # 2MiB/s @@ -256,3 +277,19 @@ token-buckets: initial-value: 0 fallback-personalised-sheet-files-keys-expire: 2419200 + +download-token-expire: 604801 + +file-source-arc: + maximum-ghost: 512 + maximum-weight: 1073741824 # 1GiB +file-source-prewarm: + maximum-weight: 1073741824 # 1GiB + start: 1800 # 30m + end: 600 # 10m + inhibit: 3600 # 60m + steps: 20 + max-speedup: 3 + +bot-mitigations: + - only-logged-in-table-sorting diff --git a/config/test-settings.yml b/config/test-settings.yml index 905639ac1..02db6b3fc 100644 --- a/config/test-settings.yml +++ b/config/test-settings.yml @@ -1,6 +1,7 @@ database: database: "_env:PGDATABASE_TEST:uniworx_test" upload-cache-bucket: "uni2work-test-uploads" +upload-tmp-bucket: "uni2work-test-tmp" log-settings: detailed: true diff --git a/frontend/src/app.js b/frontend/src/app.js index 66a9760b9..3cf868dc1 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -4,6 +4,8 @@ import { I18n } from './services/i18n/i18n'; import { UtilRegistry } from './services/util-registry/util-registry'; import { isValidUtility } from './core/utility'; +import 'css.escape'; + import './app.sass'; export class App { diff --git a/frontend/src/app.sass b/frontend/src/app.sass index 220a2f42d..0369a011b 100644 --- a/frontend/src/app.sass +++ b/frontend/src/app.sass @@ -165,7 +165,7 @@ h4 margin-top: var(--current-header-height) margin-left: 0 - :target:not(table :target)::before + :target:not(table, .show-hide__toggle)::before content: "" display: block height: var(--current-header-height) @@ -280,7 +280,10 @@ button:not(.btn-link), .buttongroup display: grid - grid: min-content / auto-flow 1fr + grid: min-content / auto-flow max-content + + .buttongroup--inline + display: inline-grid input[type="submit"][disabled]:not(.btn-link), input[type="button"][disabled]:not(.btn-link), @@ -337,6 +340,10 @@ input[type="button"].btn-info:not(.btn-link):hover, &:not([disabled]):hover color: var(--color-link-hover) +// STACK ICON STYLE +.icon--stacked + font-size: 0.5rem + // GENERAL TABLE STYLES .table margin: 21px 0 @@ -412,6 +419,9 @@ input[type="button"].btn-info:not(.btn-link):hover, font-weight: 600 color: var(--color-fontsec) +.table__td--tooltip + width: 2em + .table__td font-size: 16px color: var(--color-font) @@ -470,7 +480,7 @@ input[type="button"].btn-info:not(.btn-link):hover, overflow-y: auto .table--vertical - th + th, .table__th background-color: transparent color: var(--color-font) width: 170px @@ -478,7 +488,16 @@ input[type="button"].btn-info:not(.btn-link):hover, padding-right: 15px font-weight: 400 - td + a + color: var(--color-lin) + + &:hover + color: var(--color-link-hover) + + &::before + display: none + + td, .table__td font-weight: 600 color: var(--color-font) @@ -588,13 +607,35 @@ section padding-bottom: 30px border-bottom: 1px solid #d3d3d3 - + section + & + section, & + .two-column-sections margin-top: 20px &:last-child border-bottom: none padding-bottom: 0px +.two-column-sections + padding-bottom: 30px + border-bottom: 1px solid #d3d3d3 + + & + section, & + .two-column-sections + margin-top: 20px + + &:last-child + border-bottom: none + padding-bottom: 0px + + @media (min-width: 768px) + display: flex + justify-content: space-between + + & > section + padding: 0 + border: none + + margin: 0 auto + width: calc(50% - 7px) + .headline-one margin-bottom: 10px @@ -692,7 +733,7 @@ section color: var(--color-lightblack) .notification-success - color: var(--color-warning) + color: var(--color-success-dark) // "Heated" element. // Set custom property "--hotness" to a value from 0 to 1 to turn @@ -729,7 +770,7 @@ section background-color: hsla($hue, 75%, 50%, $opacity) !important -.uuid, .pseudonym, .ldap-primary-key, .email, .file-path, .metric-value, .metric-label +.uuid, .pseudonym, .ldap-primary-key, .email, .file-path, .metric-value, .metric-label, .workflow-payload--text, .cryptoid font-family: var(--font-monospace) .shown @@ -946,7 +987,7 @@ th, td right: 5px top: 5px -.occurrence--not-registered, .no-bonus, .allocation-course--excluded, .allocation-course--inactive +.occurrence--not-registered, .no-bonus, .allocation-course--excluded, .allocation-course--inactive, .occurrence--ignored text-decoration: line-through .result @@ -975,18 +1016,29 @@ th, td dd, .dd margin-left: 12px -.explanation - font-style: italic +.note font-size: 0.9rem font-weight: 600 color: var(--color-fontsec) +.explanation + font-style: italic + @extend .note + + emph + font-style: normal + // SORTABLE TABLE-HEADERS .table__th.sortable position: relative padding-right: 24px cursor: pointer +.table__th.presorted, +.table__th.presorted + position: relative + padding-right: 24px + .table__th.sortable::after, .table__th.sortable::before content: '' @@ -1016,6 +1068,28 @@ th, td .table__th.sorted-desc::after border-bottom-color: white !important +.table__th.presorted::before, +.table__th.presorted::after + content: '' + position: absolute + top: 50% + right: 4px + width: 0 + height: 0 + border-left: 8px solid transparent + border-right: 8px solid transparent + border-bottom: 8px solid rgba(255, 255, 255, 0.2) + +.table__th.presorted.sorted-asc::before, +.table__th.presorted.sorted-desc::after + border-bottom-color: white !important + +.table__th.presorted::before + transform: translateY(150%) scale(1, -1) + transform-origin: top +.table__th.presorted::after + transform: translateY(-150%) + \:root --color-grey-light: #efefef --color-grey-lighter: #f5f5f5 @@ -1037,6 +1111,22 @@ th, td border-left: 8px solid transparent border-right: 8px solid transparent border-bottom: 8px solid rgba(255, 255, 255, 0.4) + +.inactive-course-header::before, +.inactive-course-header::after + content: '' + position: absolute + right: 10px + top: 20px + width: 0 + height: 0 + border-left: 8px solid transparent + border-right: 8px solid transparent + border-bottom: 8px solid rgba(255,255,255, 0.2) + +.inactive-course-header.sorted-asc::before, +.inactive-course-header.sorted-desc::after + border-bottom-color: white !important .course-header::before // magic numbers to move arrow back in the right position after flipping it. @@ -1047,6 +1137,12 @@ th, td .course-header::after transform: translateY(-150%) +.inactive-course-header::before + transform: translateY(150%) scale(1, -1) + transform-origin: top +.inactive-course-header::after + transform: translateY(-150%) + .course-header:hover::before, .course-header:hover::after border-bottom-color: rgba(255, 255, 255, 0.7) @@ -1408,6 +1504,114 @@ a.breadcrumbs__home .multi-user-invitation-field__wrapper max-width: 25rem +.json, .yaml + white-space: pre-wrap + font-family: var(--font-monospace) + +pre, tt, code + font-family: var(--font-monospace) + +.workflow-instances + margin: 0 + list-style: none + + & > li + margin: 0 0 0.5rem + padding: 0 10px 12px 7px + border-left: 1px solid var(--color-grey) + + &:nth-child(2n) + background-color: rgba(0, 0, 0, 0.015) + + .workflow-instance--name, .workflow-instance--title + font-size: 1.2rem + font-weight: 600 + + .workflow-instance--name + font-family: var(--font-monospace) + + .workflow-instance--actions + margin: 0 0 0.5rem 11px + +.workflow-history-labels + display: flex + flex-direction: column + &__own + align-self: flex-end + text-align: right + &__others + align-self: flex-start + text-align: left + +.workflow-history + @extend .list--iconless + + display: flex + flex-direction: column + position: relative + + .workflow-history--item + border: 1px solid var(--color-grey) + align-self: flex-start + padding: 7px + margin: 12px 0 + min-width: 45% + display: grid + grid-template-areas: 'user time' 'action-states action-states' 'payload payload' + margin-right: 10vw + + &.workflow-history-item__self + align-self: flex-end + margin-left: 10vw + margin-right: 0 + + &:last-child + margin-bottom: 0 + &:first-child + margin-bottom: 0 + + .workflow-history--item-user + grid-area: user + .workflow-history--item-time + grid-area: time + text-align: right + .workflow-history--item-action-states + grid-area: action-states + + margin-top: 7px + + .deflist__dt, .deflist__dd + padding-top: 0 + padding-bottom: 0 + .workflow-history--item-payload-changes + grid-area: payload + + margin-top: 12px + border-top: 1px solid var(--color-grey) + padding-top: 12px + + .workflow-history--item-payload-changes-label + font-size: 20px + font-weight: 600 + + + .workflow-history--item-user-special, .workflow-history--item-action-special, .workflow-history--item-state-special + @extend .explanation + +.workflow-state + margin-top: 7px + + .deflist__dt, .deflist__dd + padding-top: 0 + padding-bottom: 0 + +.workflow-payload + margin-top: 12px + + .workflow-payload--label + font-size: 20px + font-weight: 600 + video max-width: 100% max-height: calc(90vh - var(--current-header-height)) diff --git a/frontend/src/utils/asidenav/asidenav.sass b/frontend/src/utils/asidenav/asidenav.sass index c6d6b070e..5bca8b347 100644 --- a/frontend/src/utils/asidenav/asidenav.sass +++ b/frontend/src/utils/asidenav/asidenav.sass @@ -1,3 +1,6 @@ +@use "../../common" as * +@use "../../app" as * + .main__aside position: fixed box-shadow: 0 0 10px rgba(0, 0, 0, 0.3) @@ -90,6 +93,18 @@ padding: 0 13px margin: 3px 0 +.asidenav__box-explanation + @extend .explanation + padding: 0 13px + margin: 3px 0 + opacity: .66 + font-size: .7rem + + /* transition: opacity .2s ease, font-size .2s ease + /* &:hover + /* font-size: .9rem + /* opacity: 1 + // LOGO .asidenav__logo @@ -217,9 +232,30 @@ .asidenav__link-shorthand display: none +.asidenav__link-favourite-toggle + opacity: .33 + + &:hover + opacity: 1 + + button + display: flex + text-decoration: none + .asidenav__link-label + display: flex + justify-content: space-between + align-items: center line-height: 1 + & > .asidenav__link-label-text + word-break: break-word + flex: 1 1 auto + + & > .asidenav__link-favourite-toggle + flex: 0 0 $fa-fw-width + margin: 0 5px + // hover sub-menus .asidenav__nested-list-wrapper position: absolute diff --git a/frontend/src/utils/async-table/async-table.js b/frontend/src/utils/async-table/async-table.js index 52ee85e02..3dbaad95e 100644 --- a/frontend/src/utils/async-table/async-table.js +++ b/frontend/src/utils/async-table/async-table.js @@ -355,6 +355,9 @@ export class AsyncTable { _linkClickHandler = (event) => { event.preventDefault(); let url = this._getClickDestination(event.target); + if (!url) + return; + if (!url.match(/^http/)) { url = window.location.origin + window.location.pathname + url; } @@ -363,7 +366,7 @@ export class AsyncTable { _getClickDestination(el) { if (!el.matches('a') && !el.querySelector('a')) { - return ''; + return null; } return el.getAttribute('href') || el.querySelector('a').getAttribute('href'); } diff --git a/frontend/src/utils/course-teaser/course-teaser.sass b/frontend/src/utils/course-teaser/course-teaser.sass index 56831de4f..d8866b21f 100644 --- a/frontend/src/utils/course-teaser/course-teaser.sass +++ b/frontend/src/utils/course-teaser/course-teaser.sass @@ -216,7 +216,10 @@ line-height: 1.4 max-width: 85vw - .course-header + .explanation + clear: both + + .course-header, .inactive-course-header float: left background-color: var(--color-dark) position: relative diff --git a/frontend/src/utils/form/datepicker.js b/frontend/src/utils/form/datepicker.js index 655ffd1c8..21b09eb19 100644 --- a/frontend/src/utils/form/datepicker.js +++ b/frontend/src/utils/form/datepicker.js @@ -3,6 +3,8 @@ import './datepicker.css'; import { Utility } from '../../core/utility'; import moment from 'moment'; +import * as defer from 'lodash.defer'; + const KEYCODE_ESCAPE = 27; const Z_INDEX_MODAL = 9999; @@ -77,8 +79,11 @@ export class Datepicker { datepickerInstance; _element; elementType; + initialValue; _locale; + _unloadIsDueToSubmit = false; + constructor(element) { if (!element) { throw new Error('Datepicker utility needs to be passed an element!'); @@ -100,6 +105,9 @@ export class Datepicker { // store the previously set type to select the input format this.elementType = this._element.getAttribute('type'); + // store initial value prior to changing type + this.initialValue = this._element.value || this._element.getAttribute('value'); + // manually set the type attribute to text because datepicker handles displaying the date this._element.setAttribute('type', 'text'); @@ -120,7 +128,7 @@ export class Datepicker { // FIXME dirty hack below; fix tail.datetime instead // get date object from internal format before datetime does nasty things with it - let parsedMomentDate = moment(this._element.value, [ FORM_DATE_FORMAT[this.elementType], FORM_DATE_FORMAT_MOMENT[this.elementType] ], true); + let parsedMomentDate = moment(this.initialValue, [ FORM_DATE_FORMAT[this.elementType], FORM_DATE_FORMAT_MOMENT[this.elementType] ], true); if (parsedMomentDate && parsedMomentDate.isValid()) { parsedMomentDate = parsedMomentDate.toDate(); } else { @@ -222,7 +230,7 @@ export class Datepicker { }); // format the date value of the form input element of this datepicker before form submission - this._element.form.addEventListener('submit', () => this.formatElementValue()); + this._element.form.addEventListener('submit', this._submitHandler.bind(this)); } destroy() { @@ -257,6 +265,16 @@ export class Datepicker { } } + _submitHandler() { + this._unloadIsDueToSubmit = true; + this.formatElementValue(false); + + defer(() => { // Restore state after event loop is settled + this._unloadIsDueToSubmit = false; + this.formatElementValue(true); + }); + } + /** * Returns a datestring in internal format from the current state of the input element value. * @param {*} toFancy Format date from internal to fancy or vice versa. When omitted, toFancy is falsy and results in fancy -> internal diff --git a/frontend/src/utils/form/navigate-away-prompt.js b/frontend/src/utils/form/navigate-away-prompt.js index fdb92fa79..8890e198e 100644 --- a/frontend/src/utils/form/navigate-away-prompt.js +++ b/frontend/src/utils/form/navigate-away-prompt.js @@ -5,6 +5,8 @@ import { AUTO_SUBMIT_INPUT_UTIL_SELECTOR } from './auto-submit-input'; import { InteractiveFieldset } from './interactive-fieldset'; import { Datepicker } from './datepicker'; +import * as defer from 'lodash.defer'; + /** * Key generator from an arbitrary number of FormData objects. * @param {...any} formDatas FormData objects @@ -67,6 +69,7 @@ export class NavigateAwayPrompt { this._element.addEventListener('submit', () => { this._unloadDueToSubmit = true; + defer(() => { this._unloadDueToSubmit = false; } ); // Restore state after event loop is settled }); } @@ -95,9 +98,8 @@ export class NavigateAwayPrompt { // allow the event to happen if the form was not touched by the // user (i.e. if the current FormData is equal to the initial FormData) // or the unload event was initiated by a form submit - if (!formDataHasChanged || this._unloadDueToSubmit) { - return false; - } + if (!formDataHasChanged || this._unloadDueToSubmit) + return; // cancel the unload event. This is the standard to force the prompt to appear. event.preventDefault(); diff --git a/frontend/src/utils/inputs/inputs.js b/frontend/src/utils/inputs/inputs.js index 9b438bf6e..a072c2196 100644 --- a/frontend/src/utils/inputs/inputs.js +++ b/frontend/src/utils/inputs/inputs.js @@ -1,6 +1,7 @@ import { Checkbox } from './checkbox'; import { FileInput } from './file-input'; import { FileMaxSize } from './file-max-size'; +import { Password } from './password'; import './inputs.sass'; import './radio-group.sass'; @@ -9,4 +10,5 @@ export const InputUtils = [ Checkbox, FileInput, FileMaxSize, + Password, ]; diff --git a/frontend/src/utils/inputs/inputs.sass b/frontend/src/utils/inputs/inputs.sass index 022efa71d..a8c49a716 100644 --- a/frontend/src/utils/inputs/inputs.sass +++ b/frontend/src/utils/inputs/inputs.sass @@ -49,12 +49,20 @@ color: var(--color-fontsec) font-size: 0.9rem -.form-group--required .form-group-label__caption::after, .form-group__required-marker::before +.form-group--required > .form-group-label > .form-group-label__caption::after, .form-group__required-marker::before content: ' *' color: var(--color-error) font-weight: 600 font-style: normal +.form-group--potentially-required > .form-group-label > .form-group-label__caption::after, .form-group__potentially-required-marker::before + content: ' †' + color: var(--color-warning) + font-weight: 600 + font-style: normal + vertical-align: super + font-size: 80% + .form-group--submit .form-group__input grid-column: 2 @@ -225,11 +233,15 @@ option margin: 10px 0 color: var(--color-fontsec) +.file-input__list-wrapper + overflow: auto + max-height: 75vh + max-width: 30vw + .file-input__list margin-left: 40px margin-top: 10px font-weight: 600 - max-width: 25vw tr:last-child td padding-bottom: 0 @@ -237,6 +249,7 @@ option .file-input__list-item font-family: var(--font-monospace) font-size: 15px + word-break: break-all // PREVIOUSLY UPLOADED FILES @@ -250,3 +263,40 @@ option .checkbox margin-left: 12px + +.form--vertical .form-group__input + grid-column: unset + grid-row: 2 + +.form-group.form--vertical + grid-template: auto auto / auto + +.form--vertical__cell + vertical-align: top + +// PASSWORD INPUT + +.password-input__wrapper + display: grid + grid-template-areas: 'input toggle' + width: 100% + max-width: 600px + grid-template-rows: auto + grid-template-columns: 1fr auto + + .password-input__input + grid-area: input + + .password-input__toggle + grid-area: toggle + + display: flex + justify-content: center + align-content: center + flex-direction: column + padding: 7px + + cursor: pointer + color: var(--color-fontsec) + &:hover + color: var(--color-font) diff --git a/frontend/src/utils/inputs/password.js b/frontend/src/utils/inputs/password.js new file mode 100644 index 000000000..2bb750802 --- /dev/null +++ b/frontend/src/utils/inputs/password.js @@ -0,0 +1,77 @@ +import { Utility } from '../../core/utility'; + +const PASSWORD_INITIALIZED_CLASS = 'password-input--initialized'; + +@Utility({ + selector: 'input[type="password"]:not([uw-no-password])', +}) +export class Password { + _element; + _iconEl; + _toggleContainerEl; + + constructor(element) { + if (!element) + throw new Error('Password utility cannot be setup without an element!'); + + if (element.classList.contains(PASSWORD_INITIALIZED_CLASS)) + return false; + + this._element = element; + + this._element.classList.add('password-input__input'); + + const siblingEl = this._element.nextSibling; + const parentEl = this._element.parentElement; + + const wrapperEl = document.createElement('div'); + wrapperEl.classList.add('password-input__wrapper'); + wrapperEl.appendChild(this._element); + + this._toggleContainerEl = document.createElement('div'); + this._toggleContainerEl.classList.add('password-input__toggle'); + wrapperEl.appendChild(this._toggleContainerEl); + + this._iconEl = document.createElement('i'); + this._iconEl.classList.add('fas', 'fa-fw'); + this._toggleContainerEl.appendChild(this._iconEl); + + parentEl.insertBefore(wrapperEl, siblingEl); + + this._element.classList.add(PASSWORD_INITIALIZED_CLASS); + } + + start() { + this.updateVisibleIcon(this.isVisible()); + + this._toggleContainerEl.addEventListener('mouseover', () => { + this.updateVisibleIcon(!this.isVisible()); + }); + this._toggleContainerEl.addEventListener('mouseout', () => { + this.updateVisibleIcon(this.isVisible()); + }); + this._toggleContainerEl.addEventListener('click', (event) => { + event.preventDefault(); + event.stopPropagation(); + this.setVisible(!this.isVisible()); + }); + } + + isVisible() { + return this._element.type !== 'password'; + } + + setVisible(visible) { + this._element.type = visible ? 'text' : 'password'; + this.updateVisibleIcon(visible); + } + + updateVisibleIcon(visible) { + function visibleClass(visible) { + return 'fa-' + (visible ? 'eye' : 'eye-slash'); + } + + this._iconEl.classList.remove(visibleClass(!visible)); + this._iconEl.classList.add(visibleClass(!!visible)); + } +} diff --git a/frontend/src/utils/mass-input/mass-input.js b/frontend/src/utils/mass-input/mass-input.js index 9e6a19d01..aaa5f7d0c 100644 --- a/frontend/src/utils/mass-input/mass-input.js +++ b/frontend/src/utils/mass-input/mass-input.js @@ -226,8 +226,21 @@ export class MassInput { } _serializeForm(submitButton, enctype) { + const rawFormData = new FormData(this._massInputForm); + const extraneousKeys = new Set(); + for (const k of rawFormData.keys()) { + const n = k.replace(/\[\]$/, ''); + const inputElements = Array.from(this._massInputForm.querySelectorAll(`[name="${CSS.escape(n)}"]`)); + const isBelowMassinput = inputElements.some((elem) => this._element.contains(elem)); + const isFile = inputElements.some((elem) => elem.type === 'file'); + + if (!isBelowMassinput && isFile) + extraneousKeys.add(k); + } + for (const k of extraneousKeys) + rawFormData.delete(k); // create new FormData and format any date values - const formData = Datepicker.unformatAll(this._massInputForm, new FormData(this._massInputForm)); + const formData = Datepicker.unformatAll(this._massInputForm, rawFormData); // manually add name and value of submit button to formData formData.append(submitButton.name, submitButton.value); diff --git a/hlint.sh b/hlint.sh index c6772fda7..5f30751cc 100755 --- a/hlint.sh +++ b/hlint.sh @@ -4,4 +4,15 @@ set -e [ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en .stack-work.lock "$0" "$@" || : +move-back() { + mv -v .stack-work .stack-work-test + [[ -d .stack-work-build ]] && mv -v .stack-work-build .stack-work +} + +if [[ -d .stack-work-test ]]; then + [[ -d .stack-work ]] && mv -v .stack-work .stack-work-build + mv -v .stack-work-test .stack-work + trap move-back EXIT +fi + exec -- stack build --test --fast --flag uniworx:dev --flag uniworx:library-only uniworx:test:hlint diff --git a/load/Load.hs b/load/Load.hs index 7c0020ca4..b2eec491d 100644 --- a/load/Load.hs +++ b/load/Load.hs @@ -50,13 +50,6 @@ import Data.List (genericLength) import qualified Control.Retry as Retry -instance (a ~ b, Monad m) => Monoid (Kleisli m a b) where - mempty = Kleisli return - -instance (a ~ b, Monad m) => Semigroup (Kleisli m a b) where - Kleisli f <> Kleisli g = Kleisli $ f <=< g - - data Normal k = Normal { dAvg :: k , dRelDev :: Centi @@ -367,5 +360,5 @@ sheetZipURI :: ReaderT SimulationContext IO URI sheetZipURI = do LoadOptions{..} <- asks loadOptions let zipURI = nullURI { uriPath = unpack . Text.intercalate "/" $ "." : zipPath } - where (zipPath, _) = renderRoute . CSheetR loadTerm loadSchool loadCourse loadSheet $ SZipR SheetExercise + where (zipPath, _) = renderRoute . CSheetR loadTerm loadSchool loadCourse loadSheet $ SZipR SheetExercise -- FIXME: Broken with ApprootUserGenerated return $ zipURI `relativeTo` loadBaseURI diff --git a/messages/uniworx/de-de-formal.msg b/messages/uniworx/misc/de-de-formal.msg similarity index 90% rename from messages/uniworx/de-de-formal.msg rename to messages/uniworx/misc/de-de-formal.msg index 77ba3219f..cc69743bb 100644 --- a/messages/uniworx/de-de-formal.msg +++ b/messages/uniworx/misc/de-de-formal.msg @@ -1,5 +1,3 @@ -PrintDebugForStupid name@Text: Debug message "#{name}" - Logo: Uni2work BtnSubmit: Senden @@ -17,7 +15,7 @@ BtnExamSwitchOccurrence: Zu Prüfungstermin/-raum wechseln BtnExamDeregister: Von der Prüfung abmelden BtnHijack: Sitzung übernehmen BtnSave: Speichern -PressSaveToSave: Änderungen werden erst durch Drücken des Knopfes "Speichern" gespeichert. +PressSaveToSave: Änderungen werden erst durch Drücken des Knopfes „_{MsgBtnSave}“ gespeichert. BtnHandIn: Abgeben BtnNameCandidatesInfer: Studienfach-Namens-Zuordnung automatisch lernen BtnNameCandidatesDeleteConflicts: Namenskonflikte löschen @@ -227,7 +225,7 @@ CourseMemberOf: Teilnehmer von CourseAssociatedWith: assoziiert mit CourseMembersCount n@Int: #{n} CourseMembersCountLimited n@Int max@Int: #{n}/#{max} -CourseMembersCountOf n@Int mbNum@IntMaybe: #{n} Kursanmeldungen #{maybeToMessage " von " mbNum " möglichen"} +CourseMembersCountOf n@Int mbNum@(Maybe Int): #{n} Kursanmeldungen #{maybeToMessage " von " mbNum " möglichen"} CourseName: Kurstitel CourseDescription: Beschreibung CourseHomepageExternal: Externe Homepage @@ -480,6 +478,10 @@ SubmissionUserAlreadyAdded: Dieser Nutzer ist bereits als Mitabgebende(r) einget NoOpenSubmissions: Keine unkorrigierten Abgaben vorhanden SubmissionFilesCorrected: Abgegebene & Korrigierte Dateien RatingUpdatedFiles: Bei der Korrektur wurden Dateien angepasst oder hinzugefügt +SubmissionFilesUnchanged: Abgabedateien beibehalten +SubmissionFilesUnchangedTip: Sollen die bestehenden Abgabedateien beim Ersetzen der Abgabe unverändert übernommen werden? +SubmissionUserDuplicateWarning: Dieser Teilnehmende ist bereits an einer anderen Abgabe beteiligt +SubmissionSomeUsersDuplicateWarning: Manche Abgebende sind auch an einer anderen Abgabe beteiligt SubmissionsDeleteQuestion n@Int: Wollen Sie #{pluralDE n "die unten aufgeführte Abgabe" "die unten aufgeführten Abgaben"} wirklich löschen? SubmissionsDeleted n@Int: #{pluralDE n "Abgabe gelöscht" "Abgaben gelöscht"} @@ -532,7 +534,8 @@ MaterialVideoDownload: Herunterladen Unauthorized: Sie haben hierfür keine explizite Berechtigung. UnauthorizedAnd l@Text r@Text: (#{l} UND #{r}) UnauthorizedOr l@Text r@Text: (#{l} ODER #{r}) -UnauthorizedNot r@Text: (NICHT #{r}) +UnauthorizedNot r@Text: #{r} +UnauthorizedI18nMismatch: Es wurden unterschiedliche Authorisierungs-Ergebnisse für verschiedene Sprachen berechnet UnauthorizedNoToken: Ihrer Anfrage war kein Authorisierungs-Token beigefügt. UnauthorizedTokenExpired: Ihr Authorisierungs-Token ist abgelaufen. UnauthorizedTokenNotStarted: Ihr Authorisierungs-Token ist noch nicht gültig. @@ -542,12 +545,14 @@ UnauthorizedTokenInvalidNoAuthority: Ihr Authorisierungs-Token nennt keine Nutze UnauthorizedTokenInvalidAuthority: Ihr Authorisierungs-Token basiert auf den Rechten eines Nutzers, der nicht mehr existiert. UnauthorizedTokenInvalidAuthorityGroup: Ihr Authorisierungs-Token basiert auf den Rechten einer Gruppe von Nutzern, die nicht mehr existiert. UnauthorizedTokenInvalidAuthorityValue: Ihr Authorisierungs-Token basiert auf Rechten, deren Spezifikation nicht interpretiert werden konnte. +UnauthorizedTokenInvalidImpersonation: Ihr Authorisierungs-Token enthält die Anweisung sich als ein Nutzer auszugeben, dies ist jedoch nicht allen Benutzern, auf deren Rechten ihr Authorisierungs-Token basiert, erlaubt. UnauthorizedToken404: Authorisierungs-Tokens können nicht auf Fehlerseiten ausgewertet werden. UnauthorizedSiteAdmin: Sie sind kein System-weiter Administrator. UnauthorizedSchoolAdmin: Sie sind nicht als Administrator für dieses Institut eingetragen. UnauthorizedAdminEscalation: Sie sind nicht Administrator für alle Institute, für die dieser Nutzer Administrator oder Veranstalter ist. UnauthorizedExamOffice: Sie sind nicht mit Prüfungsverwaltung beauftragt. UnauthorizedExamExamOffice: Es existieren keine Prüfungsergebnisse für Nutzer, für die Sie mit der Prüfungsverwaltung beauftragt sind. +UnauthorizedSchoolExamOffice: Sie sind nicht mit Prüfungsverwaltung für dieses Institut beauftragt. UnauthorizedSystemExamOffice: Sie sind nicht mit systemweiter Prüfungsverwaltung beauftragt. UnauthorizedExternalExamExamOffice: Es existieren keine Prüfungsergebnisse für Nutzer, für die Sie mit der Prüfungsverwaltung beauftragt sind. UnauthorizedEvaluation: Sie sind nicht mit der Kursumfragenverwaltung beauftragt. @@ -572,6 +577,7 @@ UnauthorizedParticipantSelf: Sie sind kein Teilnehmer dieser Veranstaltung. UnauthorizedApplicant: Angegebener Benutzer hat sich nicht für diese Veranstaltung beworben. UnauthorizedApplicantSelf: Sie sind kein Bewerber für diese Veranstaltung. UnauthorizedCourseTime: Dieser Kurs ist momentan nicht freigegeben. +UnauthorizedCorrectionExamTime: Sichtbarkeitseinstellungen der relevanten Prüfung verhindern momentan die Freigabe. UnauthorizedCourseRegistrationTime: Dieses Kurs erlaubt momentan keine Anmeldungen. UnauthorizedAllocationRegisterTime: Diese Zentralanmeldung erlaubt momentan keine Bewerbungen. UnauthorizedSheetTime: Dieses Übungsblatt ist momentan nicht freigegeben. @@ -616,6 +622,20 @@ UnauthorizedPasswordResetToken: Dieses Authorisierungs-Token kann nicht mehr zum UnauthorizedAllocatedCourseRegister: Direkte Anmeldungen zum Kurs sind aufgrund einer Zentralanmeldung aktuell nicht gestattet UnauthorizedAllocatedCourseDeregister: Abmeldungen vom Kurs sind aufgrund einer Zentralanmeldung aktuell nicht gestattet UnauthorizedAllocatedCourseDelete: Kurse, die an einer Zentralanmeldung teilnehmen, dürfen nicht gelöscht werden +UnauthorizedWorkflowInitiate: Sie dürfen keinen neuen laufenden Workflow initiieren +UnauthorizedWorkflowWrite: Sie dürfen aktuell keinen Zustandsübergang im Workflow auslösen +UnauthorizedWorkflowRead: Der Workflow enthält aktuell keine Zustände oder Daten die Sie einsehen dürfen +UnauthorizedWorkflowInstancesNotEmpty: Es gibt Workflow Instanzen für die Sie einen neuen laufenden Workflow initiieren dürfen +UnauthorizedWorkflowWorkflowsNotEmpty: Es gibt laufende Workflows, die Sie einsehen dürfen +UnauthorizedWorkflowFiles: Sie dürfen die angegebenen Workflow-Dateien nicht im angegebenen historischen Zustand herunterladen +UnauthorizedNotAuthenticatedInDifferentApproot: Sie konnten im Kontext einer separierten Domain (z.B. zum sicheren Download von Dateien) nicht authentifiziert werden. Vermutlich haben Sie kein oder ein abgelaufenes Token verwendet. Sie können versuchen auf die gewünschte Resource mit einem neu generierten Download-Link zuzugreifen. +UnauthorizedCsrfDisabled: Ihre Anfrage hätte wmgl. Änderungen am Server-Zustand ausgelöst. Da die sog. CSRF-Protection für Ihre Anfrage deaktiviert ist, musste sie daher abgelehnt werden. +UnauthorizedStudent: Sie sind kein Student + +WorkflowRoleUserMismatch: Sie sind nicht einer der vom Workflow geforderten Benutzer +WorkflowRoleAlreadyInitiated: Dieser Workflow wurde bereits initiiert +WorkflowRoleNoSuchWorkflowWorkflow: Der angegebene Workflow konnte nicht gefunden werden +WorkflowRoleNoPayload: Dieser Workflow enthält keine Daten EMail: E-Mail EMailUnknown email@UserEmail: E-Mail #{email} gehört zu keinem bekannten Benutzer. @@ -717,6 +737,7 @@ CorrAutoSetCorrector: Korrekturen verteilen CorrDelete: Abgaben löschen NatField name@Text: #{name} muss eine natürliche Zahl sein! JSONFieldDecodeFailure aesonFailure@String: Konnte JSON nicht parsen: #{aesonFailure} +YAMLFieldDecodeFailure yamlFailure@String: Konnte YAML nicht parsen: #{yamlFailure} SecretJSONFieldDecryptFailure: Konnte versteckte vertrauliche Daten nicht entschlüsseln SubmissionsAlreadyAssigned num@Int64: #{num} #{pluralDE num "Abgabe" "Abgaben"} waren bereits einem Korrektor zugeteilt und wurden nicht verändert: @@ -778,6 +799,8 @@ RatingTime: Korrigiert RatingComment: Kommentar SubmissionUsers: Studenten Rating: Korrektur +IsRated: Korrigiert +SheetTypeIsExam: Anrechnung „als Prüfungsaufgabe“ RatingPoints: Punkte RatingDone: Bewertung abgeschlossen RatingDoneTip: Das Korrekturergebnis ist nur dann für die Abgebenden sichtbar und kann gegen etwaige Prüfungs-Bonuspunkte verrechnet werden, wenn die Bewertung abgeschlossen ist. @@ -1185,9 +1208,10 @@ SheetGradingPassPoints': Bestehen nach Punkten SheetGradingPassBinary': Bestanden/Nicht bestanden SheetGradingPassAlways': Automatisch bestanden, sobald korrigiert -SheetTypeBonus grading@SheetGrading: Bonus -SheetTypeNormal grading@SheetGrading: Normal -SheetTypeInformational grading@SheetGrading: Ohne Anrechnung +SheetTypeBonus: Bonus +SheetTypeNormal: Normal +SheetTypeInformational: Ohne Anrechnung +SheetTypeExamPartPoints: Als Prüfungsaufgabe SheetTypeNotGraded: Keine Korrektur SheetTypeInfoNormalLecturer: Normale Blätter werden zur Berechnung eines etwaigen Prüfungsbonus herangezogen. Der Bonus kann sowohl anhand der zu bestehenden Blätter als auch der erreichbaren Maximalpunktzahl automatisch oder manuell berechnet werden. SheetTypeInfoNotGraded: Keine Korrektur bedeutet, dass es gar kein Feedback gibt. @@ -1197,6 +1221,11 @@ SheetGradingBonusIncluded: Erzielte Bonuspunkte wurden hier bereits zu den errei SummaryTitle: Zusammenfassung über SheetGradingSummaryTitle intgr@Integer: #{intgr} #{pluralDE intgr "Blatt" "Blätter"} SubmissionGradingSummaryTitle intgr@Integer: #{intgr} #{pluralDE intgr "Abgabe" "Abgaben"} +SheetTypeExamPartPointsWeightNegative: Gewichtung darf nicht negativ sein +SheetTypeExamPartPointsWeight: Gewichtung +SheetTypeExamPartPointsExamPartOption examn@ExamName examPartNumber@ExamPartNumber: #{examn} - Teil #{view _ExamPartNumber examPartNumber} +SheetTypeInfoExamPartPoints: Bei diesem Übungsblatt erreichte Punkte werden direkt auf die Punktezahl eines Prüfungsteils angerechnet. Wenn die Anzahl von über Übungsblättern erreichbaren Punkten nicht der Maximalpunktzahl des Prüfungsteils entspricht, werden die Übungsblattpunkte anhand der angegebenen Gewichtung skaliert. Korrekturen für dieses Übungsblatt werden den Teilnehmenden erst angezeigt sobald die Prüfungsfrist „_{MsgExamFinished}“ verstrichen ist. +SheetTypeExamPartPointsExamPart: Prüfungsteil SheetTypeBonus': Bonus SheetTypeNormal': Normal @@ -1484,6 +1513,23 @@ MenuFaq: FAQ MenuSheetPersonalisedFiles: Personalisierte Dateien herunterladen MenuCourseSheetPersonalisedFiles: Vorlage für personalisierte Übungsblatt-Dateien herunterladen MenuAdminCrontab: Crontab +MenuAdminWorkflowDefinitionList: Workflows +MenuAdminWorkflowDefinitionNew: Neue Workflow-Definition +MenuAdminWorkflowDefinitionDelete: Löschen +MenuAdminWorkflowInstanceList: Workflow-Instanzen +MenuAdminWorkflowInstanceNew: Neue Workflow-Instanz +MenuAdminWorkflowDefinitionInstantiate: Instanziieren +MenuWorkflowInstanceDelete: Löschen +MenuWorkflowInstanceWorkflows: Laufende Workflows +MenuWorkflowInstanceInitiate: Workflow starten +MenuWorkflowInstanceEdit: Bearbeiten +MenuWorkflowWorkflowList: Laufende Workflows +MenuWorkflowWorkflowEdit: Editieren +MenuWorkflowWorkflowDelete: Löschen +MenuGlobalWorkflowInstanceList: Systemweite Workflows +MenuTopWorkflowInstanceList: Workflows +MenuTopWorkflowWorkflowList: Laufende Workflows +MenuTopWorkflowWorkflowListHeader: Workflows BreadcrumbSubmissionFile: Datei BreadcrumbSubmissionUserInvite: Einladung zur Abgabe @@ -1562,6 +1608,31 @@ BreadcrumbFaq: FAQ BreadcrumbSheetPersonalisedFiles: Personalisierte Dateien herunterladen BreadcrumbCourseSheetPersonalisedFiles: Vorlage für personalisierte Übungsblatt-Dateien herunterladen BreadcrumbAdminCrontab: Crontab +BreadcrumbAdminWorkflowDefinitionList: Workflow-Definitionen +BreadcrumbAdminWorkflowDefinitionNew: Neue Workflow-Definition +BreadcrumbAdminWorkflowDefinitionEdit renderedWorkflowScope'@Text wfdn@WorkflowDefinitionName: #{wfdn} (#{renderedWorkflowScope'}) +BreadcrumbAdminWorkflowDefinitionDelete: Löschen +BreadcrumbAdminWorkflowDefinitionInstantiate: Instanziieren +BreadcrumbAdminWorkflowInstanceList: Workflow-Instanzen +BreadcrumbAdminWorkflowInstanceNew: Neue Workflow-Instanz +BreadcrumbAdminWorkflowInstanceEdit: Instanz bearbeiten +BreadcrumbAdminWorkflowWorkflowList: Initiierte Workflows +BreadcrumbAdminWorkflowWorkflowNew: Workflow initiieren +BreadcrumbWorkflowInstanceEdit win@WorkflowInstanceName: #{win} +BreadcrumbWorkflowInstanceDelete: Löschen +BreadcrumbWorkflowInstanceWorkflowList: Laufende Workflows +BreadcrumbWorkflowInstanceInitiate: Workflow starten +BreadcrumbWorkflowInstanceList: Workflows +BreadcrumbWorkflowInstanceNew: Neuer Workflow +BreadcrumbWorkflowWorkflowList: Laufende Workflows +BreadcrumbWorkflowWorkflow workflow@CryptoFileNameWorkflowWorkflow: #{toPathPiece workflow} +BreadcrumbWorkflowWorkflowFiles: Dateien +BreadcrumbWorkflowWorkflowEdit: Editieren +BreadcrumbWorkflowWorkflowDelete: Löschen +BreadcrumbGlobalWorkflowInstanceList: Systemweite Workflows +BreadcrumbTopWorkflowInstanceList: Workflows +BreadcrumbTopWorkflowWorkflowList: Laufende Workflows +BreadcrumbError: Fehler ExternalExamEdit coursen@CourseName examn@ExamName: Bearbeiten: #{coursen}, #{examn} ExternalExamGrades coursen@CourseName examn@ExamName: Prüfungsleistungen: #{coursen}, #{examn} @@ -1592,6 +1663,7 @@ AuthTagTime: Zeitliche Einschränkungen sind erfüllt AuthTagStaffTime: Zeitliche Einschränkungen für Lehrbeteiligte sind erfüllt AuthTagAllocationTime: Zeitliche Einschränkungen durch Zentralanmeldung sind erfüllt AuthTagCourseTime: Zeitliche Einschränkungen für Kurssichtbarkeit sind erfüllt +AuthTagExamTime: Zeitliche Einschränkungen durch relevante Prüfung sind erfüllt AuthTagCourseRegistered: Nutzer ist Kursteilnehmer AuthTagAllocationRegistered: Nutzer nimmt an der Zentralanmeldung teil AuthTagTutorialRegistered: Nutzer ist Tutoriumsteilnehmer @@ -1603,7 +1675,7 @@ AuthTagParticipant: Nutzer ist mit Kurs assoziiert AuthTagApplicant: Nutzer ist mit Bewerber zum Kurs AuthTagRegisterGroup: Nutzer ist nicht Mitglied eines anderen Tutoriums mit der selben Registrierungs-Gruppe AuthTagCapacity: Kapazität ist ausreichend -AuthTagEmpty: Kurs hat keine Teilnehmer +AuthTagEmpty: Ressource ist „leer“ AuthTagMaterials: Kursmaterialien sind freigegeben AuthTagOwner: Nutzer ist Besitzer AuthTagPersonalisedSheetFiles: Nutzer verfügt über personalisierte Übungsblatt-Dateien @@ -1617,6 +1689,8 @@ AuthTagAuthentication: Nutzer ist angemeldet, falls erforderlich AuthTagRead: Zugriff ist nur lesend AuthTagWrite: Zugriff ist i.A. schreibend AuthTagSubmissionGroup: Nutzer ist Mitglied in registrierter Abgabegruppe +AuthTagWorkflow: Nutzer hat passende Workflow-Rolle +AuthTagStudent: Nutzer ist Student DeleteCopyStringIfSure n@Int: Wenn Sie sich sicher sind, dass Sie #{pluralDE n "das obige Objekt" "obige Objekte"} unwiderbringlich löschen möchten, schreiben Sie bitte zunächst den angezeigten Text ab. DeletePressButtonIfSure n@Int: Wenn Sie sich sicher sind, dass Sie #{pluralDE n "das obige Objekt" "obige Objekte"} unwiderbringlich löschen möchten, bestätigen Sie dies bitte durch Drücken des untigen Knopfes. @@ -1640,6 +1714,7 @@ CommSuccess n@Int: Nachricht wurde an #{n} Empfänger versandt CommTestSuccess: Nachricht wurde zu Testzwecken nur an Sie selbst versandt CommUndisclosedRecipients: Verborgene Empfänger CommAllRecipients: alle-empfaenger +CommAllRecipientsSheet: Empfänger CommCourseHeading: Kursmitteilung CommTutorialHeading: Tutorium-Mitteilung @@ -1775,6 +1850,10 @@ TutorialParticipants: Teilnehmer TutorialCapacity: Kapazität TutorialFreeCapacity: Freie Plätze TutorialRoom: Regulärer Raum +TutorialRoomHidden: Raum nur für Teilnehmer +TutorialRoomHiddenTip: Soll der Raum nur den Teilnehmern des Tutoriums angezeigt werden? +TutorialRoomIsUnset: — +TutorialRoomIsHidden: Raum wird nur Teilnehmern angezeigt TutorialTime: Zeit TutorialRegistered: Angemeldet TutorialRegGroup: Registrierungs-Gruppe @@ -1876,6 +1955,7 @@ ExamFinished: Ergebnisse sichtbar ab ExamFinishedOffice: Noten bekannt gegeben ExamFinishedParticipant: Bewertung voraussichtlich abgeschlossen ExamFinishedTip: Zeitpunkt zu dem Prüfungergebnisse den Teilnehmern gemeldet werden; ohne Datum werden die Prüfungsergebnisse zunächst nie gemeldet +ExamFinishedTipCloseOnFinished: Zeitpunkt zu dem Prüfungergebnisse den Teilnehmern und den Prüfungsverwaltungen gemeldet werden; ohne Datum werden die Prüfungsergebnisse zunächst nie gemeldet ExamClosed: Noten gemeldet ExamClosedTip: Prüfungsbeauftraget, die im System Noten einsehen, werden zu diesem Zeitpunkt benachrichtigt und danach bei Änderungen informiert ExamGradingMode: Bewertungsmodus @@ -1899,6 +1979,7 @@ ExamBonusRule: Prüfungsbonus aus Übungsbetrieb ExamNoBonus': Kein automatischer Bonus ExamBonusPoints': Umrechnung von Übungspunkten ExamBonusManual': Manuelle Berechnung +ExamBonusInfoPoints: Zur Berechnung von Bonuspunkten werden nur jene Blätter herangezogen, deren Aktivitätszeitraum vor Start des jeweiligen Termin/Prüfung begonnen hat ExamRegisterForOccurrence: Anmeldung zur Prüfung erfolgt durch Anmeldung zu einem Termin/Raum @@ -1923,6 +2004,8 @@ ExamRoomSurname': Nach Nachname ExamRoomMatriculation': Nach Matrikelnummer ExamRoomRandom': Zufällig pro Teilnehmer ExamRoomFifo': Auswahl durch Teilnehmer bei Anmeldung +ExamOccurrenceRoomIsUnset: — +ExamOccurrenceRoomIsHidden: Raum wird nur Teilnehmern angezeigt ExamOccurrence: Termin/Raum ExamNoOccurrence: Kein Termin/Raum @@ -1931,9 +2014,12 @@ ExamOccurrences: Termine ExamRooms: Räume ExamTimes: Termine ExamRoomRoom: Raum +ExamRoomRoomHidden: Raum nur für Angemeldete +ExamRoomRoomHiddenTip: Soll der Raum nur zu diesem Termin/Raum angemeldeten Prüfungsteilnehmern angezeigt werden? ExamRoomAlreadyExists: Prüfung ist bereits eingetragen ExamRoomName: Interne Bezeichnung ExamRoomCapacity: Kapazität +ExamRoomCapacityTip: Maximale Anzahl an Prüfungsteilnehmern für diesen Termin/Raum; leer lassen für unbeschränkte Teilnehmeranzahl ExamRoomCapacityNegative: Kapazität darf nicht negativ sein ExamRoomTime: Termin ExamRoomStart: Beginn @@ -2008,10 +2094,15 @@ ExamPartMaxPoints: Maximalpunktzahl ExamPartWeight: Gewichtung ExamPartWeightTip: Wird vor Anzeige oder automatischen Notenberechnung mit der erreichten Punktzahl und der Maximalpunktzahl multipliziert; Änderungen hier passen also auch bestehende Korrekturergebnisse an (derart geänderte Noten müssen erneut manuell übernommen werden) ExamPartResultPoints: Erreichte Punkte +ExamPartSheets: Übungsblätter -ExamNameTaken exam@ExamName: Es existiert bereits eine Prüfung mit Namen #{exam} +ExamPartsFrom: Teile anzeigen ab +ExamPartsFromTip: Ab dem gegebenen Zeitpunkt wird die Liste von Prüfungsteilen/Aufgaben veröffentlicht, nicht jedoch die jeweilige Maximalpunktzahl. Ohne Zeitpunkt wird die Liste ab "Ergebnisse sichtbar ab" angezeigt. + +ExamEditExamNameTaken exam@ExamName: Es existiert bereits eine Prüfung mit Namen #{exam} ExamCreated exam@ExamName: #{exam} erfolgreich angelegt ExamEdited exam@ExamName: #{exam} erfolgreich bearbeitet +ExamEditWouldBreakSheetTypeReference: Durch Ihre Änderungen würde ein Prüfungsteil gelöscht, auf den durch ein Übungsblatt noch eine Referenz besteht. ExamNoShow: Nicht erschienen ExamVoided: Entwertet @@ -2045,6 +2136,7 @@ ExamRegistrationMustFollowSchoolSeparationFromStart dayCount@Int: Nach Regeln de ExamRegistrationMustFollowSchoolDuration dayCount@Int: Nach Regeln des Instituts #{pluralDE dayCount "muss" "müssen"} zwischen "Anmeldung ab" und "Anmeldung bis" mindestens #{dayCount} #{pluralDE dayCount "Tag" "Tage"} liegen. ExamModeRequiredForRegistration: Nach Regeln des Institus muss die "Ausgestaltung der Prüfung" vollständig angegeben sein, bevor "Anmeldung ab" festgelegt werden kann. ExamModeSchoolDiscouraged: Nach Regeln des Instituts wird von der angegebenen "Ausgestaltung der Prüfung" abgeraten +ExamPartsFromMustBeBeforeFinished: "Teile anzeigen ab" muss vor "Ergebnisse sichtbar ab" liegen ExamOccurrenceEndMustBeAfterStart eoName@ExamOccurrenceName: Beginn des Termins #{eoName} muss vor seinem Ende liegen ExamOccurrenceStartMustBeAfterExamStart eoName@ExamOccurrenceName: Beginn des Termins #{eoName} muss nach Beginn der Prüfung liegen @@ -2053,6 +2145,7 @@ ExamOccurrenceDuplicate eoRoom@Text eoRange@Text: Raum #{eoRoom}, Termin #{eoRan ExamOccurrenceDuplicateName eoName@ExamOccurrenceName: Interne Terminbezeichnung #{eoName} kommt mehrfach vor ExamOccurrenceCannotBeDeletedDueToRegistrations eoName@ExamOccurrenceName: Termin #{eoName} kann nicht gelöscht werden, da noch Teilnehmer diesem Termin zugewiesen sind. Über die Liste von Prüfungsteilnehmern können Sie zunächst die entsprechenden Terminzuweisungen entfernen. ExamPartCannotBeDeletedDueToResults exampartnum@ExamPartNumber: Teil #{exampartnum} kann nicht gelöscht werden, da bereits Prüfungsergebnisse für diesen Teil eingetragen wurden. +ExamPartCannotBeDeletedDueToSheetReference exampartnum@ExamPartNumber sheetName@SheetName: Teil #{exampartnum} kann nicht gelöscht werden, da Übungsblatt #{sheetName} den Bewertungsmodus „als Prüfungsaufgabe“ trägt. VersionHistory: Versionsgeschichte KnownBugs: Bekannte Bugs @@ -2066,6 +2159,7 @@ ExamUserAssignOccurrence: Termin/Raum zuweisen ExamUserAcceptComputedResult: Berechnetes Prüfungsergebnis übernehmen ExamUserResetToComputedResult: Prüfungsergebnis zurücksetzen ExamUserResetBonus: Auch Bonuspunkte zurücksetzen +ExamUserResetParts: Auch Teilergebnisse zurücksetzen ExamUserSetPartResult: Teilergebnis setzen ExamUserSetBonus: Bonuspunkte setzen ExamUserSetResult: Prüfungsergebnis setzen @@ -2141,14 +2235,19 @@ CsvImportExplanationLabel: Hinweise zum CSV-Import CsvExampleData: Beispiel-Datei CsvExportExample: Beispiel-CSV exportieren -Proportion c@Text of@Text prop@Rational: #{c}/#{of} (#{rationalToFixed2 (100 * prop)}%) -ProportionNoRatio c@Text of@Text: #{c}/#{of} +Proportion c@Text of'@Text prop@Rational: #{c}/#{of'} (#{rationalToFixed2 (100 * prop)}%) +ProportionNoRatio c@Text of'@Text: #{c}/#{of'} CourseUserCsvName tid@TermId ssh@SchoolId csh@CourseShorthand: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-teilnehmer +CourseUserCsvSheetName tid@TermId ssh@SchoolId csh@CourseShorthand: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh} Teilnehmer ExamUserCsvName tid@TermId ssh@SchoolId csh@CourseShorthand examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn}-teilnehmer +ExamUserCsvSheetName tid@TermId ssh@SchoolId csh@CourseShorthand examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn} Teilnehmer ExternalExamUserCsvName tid@TermId ssh@SchoolId coursen@CourseName examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase coursen}-#{foldedCase examn}-teilnehmer +ExternalExamUserCsvSheetName tid@TermId ssh@SchoolId coursen@CourseName examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase coursen}-#{foldedCase examn} Teilnehmer CourseApplicationsTableCsvName tid@TermId ssh@SchoolId csh@CourseShorthand: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-bewerbungen +CourseApplicationsTableCsvSheetName tid@TermId ssh@SchoolId csh@CourseShorthand: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh} Bewerbungen ParticipantsCsvName tid@TermId ssh@SchoolId: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-kursteilnehmer +ParticipantsCsvSheetName tid@TermId ssh@SchoolId: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)} Kursteilnehmer CourseUserCsvIncludeSheets: Übungsblätter CourseUserCsvIncludeSheetsTip: Soll die exportierte CSV-Datei zusätzlich eine Spalte pro Übungsblatt enthalten? @@ -2172,6 +2271,8 @@ CsvColumnExamUserParts: Erreichte Punktezahlen in den Teilprüfungen, sofern vor CsvColumnExamUserResult: Erreichte Prüfungsleistung; "passed", "failed", "no-show", "voided", oder eine Note ("1.0", "1.3", "1.7", ..., "4.0", "5.0") CsvColumnExamUserCourseNote: Notizen zum Teilnehmer +CsvColumnUserSurname: Nachname(n) des Teilnehmers +CsvColumnUserFirstName: Vorname(n) des Teilnehmers CsvColumnUserName: Voller Name des Teilnehmers CsvColumnUserMatriculation: Matrikelnummer des Teilnehmers CsvColumnUserSex: Geschlecht @@ -2538,8 +2639,14 @@ BtnCloseExam: Prüfung abschließen ExamCloseTip: Wenn eine Prüfung abgeschlossen wird, werden Prüfungsbeauftragte, die im System Noten einsehen, benachrichtigt und danach bei Änderungen informiert. ExamCloseReminder: Bitte schließen Sie die Prüfung frühstmöglich, sobald die Prüfungsleistungen sich voraussichtlich nicht mehr ändern werden. Z.B. direkt nach der Klausureinsicht. ExamDidClose: Prüfung erfolgreich abgeschlossen +ExamCloseTipOnFinished: Die Prüfung wird automatisch abgeschlossen, also Prüfungsbeauftragte, die im System Note einsehen, benachrichtigt und danach bei Änderungen informiert, sobald die Noten für die Prüfungsteilnehmer veröffentlicht werden. +ExamFinishHeading: Prüfungsergebnisse sichtbar schalten +BtnFinishExam: Prüfungsergebnisse sichtbar schalten +ExamFinishTip: Wenn die Prufungsergebnisse sichtbar geschaltet sind, können Teilnehmende ihre Ergebnisse im System einsehen und werden über diesen Umstand informiert. Es wird die Prüfungfrist „_{MsgExamFinished}“ auf den aktuellen Zeitpunkt gesetzt. +ExamDidFinish: Prüfungsergbnisse sichtbar geschaltet ExamClosedSince time@Text: Prüfung abgeschlossen seit #{time} +ExamFinishedSince time@Text: Prüfungsergebnisse sichtbar seit #{time} LecturerInfoTooltipNew: Neues Feature LecturerInfoTooltipProblem: Feature mit bekannten Problemen @@ -2562,8 +2669,9 @@ CsvOptionsTip: Diese Einstellungen betreffen primär den CSV-Export; beim Import CsvFormatOptions: Dateiformat CsvTimestamp: Zeitstempel CsvTimestampTip: Soll an den Namen jeder exportierten CSV-Datei ein Zeitstempel vorne angehängt werden? -CsvPresetRFC: Standard-Konform (RFC 4180) -CsvPresetExcel: Excel-Kompatibel +CsvPresetRFC: Standard-Konforme .csv Dateien (RFC 4180) +CsvPresetExcel: Excel-Kompatible .csv Dateien (Excel <2010) +CsvPresetXlsx: .xlsx Dateien (ECMA-376; Excel ≥2010) CsvCustom: Benutzerdefiniert CsvDelimiter: Trennzeichen CsvUseCrLf: Zeilenumbrüche @@ -2588,6 +2696,9 @@ CsvQuoteMinimal: Nur wenn nötig CsvQuoteAll: Immer CsvOptionsUpdated: CSV-Optionen erfolgreich angepasst CsvChangeOptionsLabel: Export-Optionen +CsvFormatField: Dateiformat +CsvFormatCsv: .csv (Comma-Separated Values) +CsvFormatXlsx: .xlsx (Office Open XML) CourseNews: Aktuelles CourseNewsArchiveName tid@TermId ssh@SchoolId csh@CourseShorthand newsTitle@Text: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldCase newsTitle} @@ -2645,12 +2756,15 @@ AllocationResultsTip: Die folgenden Informationen entsprechen dem aktuellen Stan AllocationResultsStudentTip: Unten aufgeführt sind alle Plätze, die Sie im Rahmen der genannten Zentralanmeldung erhalten haben und von denen Sie seit dem weder abgemeldet wurden, noch sich selbst abgemeldet haben. Plätze, über die Sie ggf. bereits informiert wurden, können also erneut aufgeführt sein. AllocationResultStudentRegistrationTip: Sie sind zu oben genanntem Kurs in Uni2work angemeldet. AllocationResultsStudentRegistrationTip: Sie sind zu den oben genannten Kursen in Uni2work angemeldet. +AllocationResultsStudentConsultFaq n@Int: Falls Sie Fragen oder Anmerkungen haben, beachten Sie bitte auch die Informationen auf #{pluralDE n "der" "den"} folgenden #{pluralDE n "Seite" "Seiten"}: FavouriteVisited: Kürzlich besucht FavouriteParticipant: Ihre Kurse FavouriteManual: Favoriten FavouriteCurrent: Aktueller Kurs +FavouritesEmptyTip: Hier werden Ihre Kurse, sowie zuletzt besuchte Kurse angezeigt. +FavouritesToggleTip: Der Anzeigemodus für den aktuellen Kurs kann über einen Klick auf das Stern-Symbol zwischen automatisch, permanent und nie gewechselt werden. FavouritesUnavailableTip: Das Schnellzugriffsmenü für diesen Kurs ist aktuell nicht verfügbar. CourseEvents: Termine @@ -2658,6 +2772,10 @@ CourseEventType: Art CourseEventTypePlaceholder: Vorlesung, Zentralübung, ... CourseEventTime: Zeit CourseEventRoom: Regulärer Raum +CourseEventRoomHidden: Raum nur für Teilnehmer +CourseEventRoomHiddenTip: Soll der Raum nur angemeldeten Kursteilnehmern angezeigt werden? +CourseEventRoomIsUnset: — +CourseEventRoomIsHidden: Raum wird nur Kurs-assoziierten Personen (Teilnehmer, Tutoren, Korrektoren, etc.) angezeigt CourseEventNote: Notiz CourseEventActions: Aktionen CourseEventsActionEdit: Bearbeiten @@ -2788,13 +2906,17 @@ ExamAutoOccurrenceParticipantsAssigned num@Int64: Verteilungstabelle erfolgreich TitleExamAutoOccurrence tid@TermId ssh@SchoolId csh@CourseShorthand examn@ExamName: #{tid} - #{ssh} - #{csh} #{examn}: Automatische Raum-/Terminverteilung BtnExamAutoOccurrenceCalculate: Verteilungstabelle berechnen BtnExamAutoOccurrenceAccept: Verteilung akzeptieren -BtnExamAutoOccurrenceNudgeUp: + -BtnExamAutoOccurrenceNudgeDown: - ExamRoomMappingSurname: Nachnamen beginnend mit ExamRoomMappingMatriculation: Matrikelnummern endend in +ExamRoomMappingRandom: Verteilung +ExamRoomMappingRandomHere: Zufällig ExamRoomLoad: Auslastung ExamRegisteredCount: Anmeldungen ExamRegisteredCountOf num@Int64 count@Int64: #{num}/#{count} +ExamAutoOccurrenceExceptionRuleNoOp: Kein Verfahren zur automatischen Verteilung gewählt +ExamAutoOccurrenceExceptionNotEnoughSpace: Mehr Teilnehmende als verfügbare Plätze +ExamAutoOccurrenceExceptionNoUsers: Nach dem gewähltem Verfahren können keine Teilnehmenden verteilt werden +ExamAutoOccurrenceExceptionRoomTooSmall: Automatische Verteilung gescheitert. Ein anderes Verteil-Verfahren kann erfolgreich sein. Alternativ kann es helfen Räume zu minimieren oder kleine Räume zu entfernen. NoFilter: Keine Einschränkung @@ -2808,7 +2930,7 @@ InfoLecturerTutorials: Tutorien InfoLecturerExams: Prüfungen InfoLecturerAllocations: Zentralanmeldungen -ParticipantsIntersectCourseOption tid@TermId ssh@SchoolId coursen@CourseName: #{tid} - #{ssh} - #{coursen} +ParticipantsIntersectCourseOption tid@TermId ssh@SchoolId csh@CourseShorthand coursen@CourseName: #{tid} - #{ssh} - #{csh}: #{coursen} ParticipantsIntersectCourses: Kurse AllocationUsersTitle tid@TermId ssh@SchoolId ash@AllocationShorthand: #{tid}-#{ssh}-#{ash}: Bewerber @@ -2830,6 +2952,7 @@ CsvColumnAllocationUserAssigned: Anzahl von Plätzen, die der Bewerber durch die CsvColumnAllocationUserNewAssigned: Anzahl von Plätzen, die der Bewerber, nach Akzeptieren der berechneten Verteilung, zusätzlich erhalten würde CsvColumnAllocationUserPriority: Zentrale Dringlichkeit des Bewerbers; entweder einzelne Zahl für Sortierungsbasierte Dringlichkeiten (höhere Dringlichkeit entspricht größerer Zahl) oder Komma-separierte Liste von numerischen Dringlichkeiten in eckigen Klammern (z.B. [1, 2, 3]) AllocationUsersCsvName tid@TermId ssh@SchoolId ash@AllocationShorthand: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase ash}-bewerber +AllocationUsersCsvSheetName tid@TermId ssh@SchoolId ash@AllocationShorthand: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase ash} Bewerber AllocationPrioritiesMode: Modus AllocationPrioritiesNumeric: Numerische Dringlichkeiten @@ -2899,7 +3022,7 @@ AllocationUsersCount: Teilnehmer AllocationCoursesCount: Kurse AllocationCourseEligible: Berücksichtigt -CourseOption tid@TermId ssh@SchoolId coursen@CourseName: #{tid} - #{ssh} - #{coursen} +CourseOption tid@TermId ssh@SchoolId csh@CourseShorthand coursen@CourseName: #{tid} - #{ssh} - #{csh}: #{coursen} BearerTokenUsageWarning: Mit diesem Interface können quesi beliebige Rechte als Tokens kodiert und somit ohne wesentliche weitere Beschränkung frei übertragen werden. Benutzen Sie dieses Interface nur, wenn Sie von einem erfahrenen Entwickler über die Auswirkungen des konkreten Tokens, dass sie ausstellen möchten, beraten wurden! BearerTokenAuthorityGroups: Token-Authorität (Gruppen) @@ -2922,6 +3045,16 @@ BearerTokenExpires: Ablaufzeitpunkt BearerTokenExpiresTip: Wird der Ablaufzeitpunkt überschrieben und kein Ablaufzeitpunkt angegeben, ist das Token für immer gültig. BearerTokenOverrideStart: Startzeitpunkt BearerTokenOverrideStartTip: Wird kein Startzeitpunkt angegeben, wird bei Verwendung des Tokens nur der Ablaufzeitpunkt überprüft. +BearerTokenImpersonate: Auftreten als +BearerTokenImpersonateNone: Keine Änderung +BearerTokenImpersonateSingle: Einzelner Benutzer +BearerTokenImpersonateRandom: Zufälliger Benutzer +BearerTokenImpersonateSingleUser: Benutzer +BearerTokenImpersonateRandomNegative: Anzahl muss positiv sein +BearerTokenImpersonateRandomCount: Anzahl +BearerTokenImpersonateUnknownUser email@UserEmail: Ein Nutzer mit E-Mail #{email} ist dem System nicht bekannt +BearerTokenImpersonateRandomWeightActivity: Nach Aktivität gewichten +BearerTokenArchiveName: tokens.zip FaqTitle: Häufig gestellte Fragen AdditionalFaqs: Weitere häufig gestellte Fragen @@ -2987,6 +3120,9 @@ PersonalisedSheetFilesIgnored count@Int64: Es #{pluralDE count "wurde" "wurden"} PersonalisedSheetFilesIgnoredIntro: Es wurden die folgenden Dateien ignoriert: CourseUserHasPersonalisedSheetFilesFilter: Teilnehmer hat personalisierte Übungsblatt-Dateien für SheetPersonalisedFilesUsersList: Liste von Teilnehmern mit personalisierten Übungsblatt-Dateien +PersonalisedSheetFilesDownloadRestrictByExamNone: Keine Einschränkung +PersonalisedSheetFilesDownloadRestrictByExam: Nur Prüfungsteilnehmer +PersonalisedSheetFilesDownloadRestrictByExamTip: Sollen nur personalisierte Übungsblatt-Dateien exportiert werden, für jene Kursteilnehmer, die auch Teilnehmer einer bestimmten Prüfung sind? AdminCrontabNotGenerated: (Noch) keine Crontab generiert CronMatchAsap: ASAP @@ -2994,6 +3130,144 @@ CronMatchNone: Nie SystemExamOffice: Prüfungsverwaltung SystemFaculty: Fakultätsmitglied +SystemStudent: Student + +WorkflowScopeKindGlobal: Systemweit +WorkflowScopeKindTerm: Pro Semester +WorkflowScopeKindSchool: Pro Institut +WorkflowScopeKindTermSchool: Pro Institut & Semester +WorkflowScopeKindCourse: Pro Veranstaltung +WorkflowScopeGlobal: Systemweit +WorkflowScopeTermSchool tid@TermId ssh@SchoolId: #{tid} #{ssh} +WorkflowScopeCourse tid@TermId ssh@SchoolId csh@CourseShorthand: #{tid} #{ssh} #{csh} +WorkflowDefinitionScope: Bereich +WorkflowDefinitionName: Name +WorkflowDefinitionDescriptions: Beschreibung +WorkflowDefinitionDescriptionsLanguageExists: Eine Beschreibung in dieser Sprache existiert bereits +WorkflowDefinitionGraph: Spezifikation +WorkflowDefinitionKeyDoesNotExist renderedCryptoID@Text: Referenziert ID existiert nicht: #{renderedCryptoID} +WorkflowDefinitionFiles: Dateien +WorkflowFileIdentDoesNotExist fileIdent@Text: Referenzierte Datei existiert nicht: #{fileIdent} +WorkflowUserDoesNotExist userIdent@Text: Referenzierter Benutzer existiert nicht: #{userIdent} +WorkflowDefinitionFileIdentExists: Eine Datei mit dieser ID existiert bereits +WorkflowDefinitionFileIdent: Dateireferenz +WorkflowDefinitionFile: Datei +WorkflowDefinitionCreated: Workflow-Definition angelegt +WorkflowDefinitionEdited: Workflow-Definition ersetzt +WorkflowDefinitionCollision: Es existiert bereits eine Workflow-Definition mit diesem Namen und Bereich +WorkflowDefinitionNewTitle: Workflow-Definition anlegen +WorkflowDefinitionEditTitle: Workflow-Definition Bearbeiten +WorkflowDefinitionInstanceCategory: Kategorie +WorkflowDefinitionWarningLinterIssuesMessage: Es sind Linter issues aufgetreten +WorkflowDefinitionWarningLinterIssues: Es sind folgende Linter issues aufgetreten: + +WorkflowDefinitionListTitle: Workflow-Definitionen +WorkflowDefinitionInstanceCount: Instanzen +WorkflowDefinitionWorkflowCount: Workflows +WorkflowDefinitionConcreteInstanceCount num@Int64: #{num} Instanzen +WorkflowDefinitionConcreteWorkflowCount num@Int64: #{num} Workflows +WorkflowDefinitionDeleteQuestion: Wollen Sie die unten aufgeführte Workflow-Definition wirklich löschen? +WorkflowDefinitionDeleted: Workflow-Definition gelöscht +WorkflowDefinitionInstantiateTitle: Workflow-Definition instanziieren +WorkflowDefinitionInstantiated: Instanz angelegt + +WorkflowScope: Bereich +WorkflowInstanceName: Name +WorkflowInstanceCategory: Kategorie +WorkflowInstanceCollision: Es existiert bereits eine Workflow-Instanz mit diesem Namen und Bereich +WorkflowInstanceListTitle: Workflow-Instanzen +WorkflowInstanceDescription: Instanz-Beschreibung +WorkflowInstanceDescriptions: Instanz-Beschreibung +WorkflowInstanceDescriptionsLanguageExists: Eine Instanz-Beschreibung in dieser Sprache existiert bereits +WorkflowInstanceCreated: Instanz angelegt +WorkflowInstanceDescriptionTitle: Instanz-Titel +WorkflowInstanceWorkflowCount: Workflows + +WorkflowInstanceInitiateSuccess: Workflow erfolgreich initiiert + +WorkflowDescriptionLanguage: Sprach-Code (RFC1766) +WorkflowDescriptionTitle: Titel +WorkflowDescription: Beschreibung + +GlobalWorkflowInstancesHeading: Workflows (Systemweit) +GlobalWorkflowInstancesTitle: Workflows (Systemweit) + +GlobalWorkflowInstanceInitiateHeading workflowInstanceTitle@Text: Workflow initiieren: #{workflowInstanceTitle} +GlobalWorkflowInstanceInitiateTitle: Workflow initiieren + +SchoolWorkflowInstancesHeading ssh@SchoolId: Workflows (#{ssh}) +SchoolWorkflowInstancesTitle ssh@SchoolId: Workflows (#{ssh}) + +SchoolWorkflowInstanceInitiateHeading ssh@SchoolId workflowInstanceTitle@Text: Workflow initiieren: #{ssh}, #{workflowInstanceTitle} +SchoolWorkflowInstanceInitiateTitle ssh@SchoolId: Workflow initiieren: #{ssh} + +WorkflowEdgeNumberedVariant edgeLabel@Text i@Natural: #{edgeLabel} (Variante #{i}) +WorkflowEdgeFormEdge: Aktion +WorkflowEdgeFormHiddenPayload i@Natural: Versteckter Datensatz #{i} +WorkflowEdgeFormPayloadOneFieldRequired: Es muss mindestens ein Feld pro Datensatz ausgefüllt werden +WorkflowEdgeFormPayloadOneFieldRequiredFor payloadDisplayLabel@Text: Es muss mindestens ein Feld für “#{payloadDisplayLabel}” ausgefüllt werden +WorkflowEdgeFormFieldNumberTooSmall minSci@Scientific: Zahl muss mindestens #{formatScientific Scientific.Generic Nothing minSci} sein +WorkflowEdgeFormFieldNumberTooLarge maxSci@Scientific: Zahl muss höchstens #{formatScientific Scientific.Generic Nothing maxSci} sein +WorkflowEdgeFormFieldUserNotFound: E-Mail Adresse konnte keinem Benutzer zugeordnet werden +WorkflowEdgeFormFieldMultipleNoneAdded: (Noch) keine Einträge +WorkflowEdgeFormFieldCaptureUserLabel: Aktueller Benutzer + +WorkflowWorkflowWorkflowHistoryHeading: Verlauf +WorkflowWorkflowWorkflowEdgeFormHeading: Aktion im Workflow auslösen +WorkflowWorkflowWorkflowEdgeSuccess: Aktion erfolgreich ausgelöst +WorkflowWorkflowWorkflowHistoryUserSelf: Sie selbst +WorkflowWorkflowWorkflowHistoryUserNotLoggedIn: Nicht eingeloggter Benutzer +WorkflowWorkflowWorkflowHistoryUserGone: Gelöschter Benutzer +WorkflowWorkflowWorkflowHistoryUserHidden: Versteckter Benutzer +WorkflowWorkflowWorkflowHistoryUserAutomatic: Automatisch +WorkflowWorkflowWorkflowHistoryActionAutomatic: Automatisch +WorkflowWorkflowWorkflowHistoryStateHidden: Versteckter Zustand +WorkflowWorkflowWorkflowHistoryActionLabel: Aktion +WorkflowWorkflowWorkflowHistoryFromLabel: Vorheriger Zustand +WorkflowWorkflowWorkflowHistoryToLabel: Neuer Zustand +WorkflowWorkflowWorkflowHistoryPayloadLabel: Datensatz-Änderungen +WorkflowWorkflowFilesArchiveName wwCID@CryptoFileNameWorkflowWorkflow wpl@WorkflowPayloadLabel stCID@CryptoUUIDWorkflowStateIndex: #{foldCase (toPathPiece wwCID)}-#{foldCase (toPathPiece stCID)}-#{foldCase (foldMap unidecode (toPathPiece wpl))}.zip +WorkflowWorkflowWorkflowStateHeading: Zustand/Daten +WorkflowWorkflowWorkflowPayloadHeading: Aktueller Datensatz +WorkflowWorkflowWorkflowStateStateLabel: Aktueller Zustand +WorkflowWorkflowWorkflowStateStateHidden: Versteckter Zustand +WorkflowWorkflowWorkflowHistoryLabelOthers: Aktionen Anderer +WorkflowWorkflowWorkflowHistoryLabelOwn: Eigene Aktionen + +WorkflowPayloadFiles: Datei(en) +WorkflowPayloadBoolTrue: Ja +WorkflowPayloadBoolFalse: Nein +WorkflowPayloadUserGone: Gelöschter Benutzer + +TopWorkflowInstancesHeading: Workflows +TopWorkflowInstancesTitle: Workflows + +GlobalWorkflowWorkflowWorkflowHeading workflowWorkflowId@CryptoFileNameWorkflowWorkflow: Workflow #{toPathPiece workflowWorkflowId} +GlobalWorkflowWorkflowWorkflowTitle workflowWorkflowId@CryptoFileNameWorkflowWorkflow: Workflow #{toPathPiece workflowWorkflowId} + +SchoolWorkflowWorkflowWorkflowHeading ssh@SchoolId workflowWorkflowId@CryptoFileNameWorkflowWorkflow: Workflow #{ssh}, #{toPathPiece workflowWorkflowId} +SchoolWorkflowWorkflowWorkflowTitle ssh@SchoolId workflowWorkflowId@CryptoFileNameWorkflowWorkflow: Workflow #{ssh}, #{toPathPiece workflowWorkflowId} + +WorkflowWorkflowListScopeTitle rScope@Text: Laufende Workflows - #{rScope} +WorkflowWorkflowListScopeHeading rScope@Text: Laufende Workflows (#{rScope}) +WorkflowWorkflowListInstanceTitle: Laufende Workflows für Instanz +WorkflowWorkflowListInstanceHeading: Laufende Workflows für Instanz +WorkflowWorkflowListNamedInstanceTitle rScope@Text wiTitle@Text: Laufende Workflows - #{rScope}, #{wiTitle} +WorkflowWorkflowListNamedInstanceHeading rScope@Text wiTitle@Text: Laufende Workflows (#{rScope}, #{wiTitle}) +WorkflowWorkflowListTopTitle: Laufende Workflows +WorkflowWorkflowListTopHeading: Laufende Workflows +AdminWorkflowWorkflowListTitle: Laufende Workflows +AdminWorkflowWorkflowListHeading: Laufende Workflows + +WorkflowWorkflowListNumber: Nummer +WorkflowWorkflowListScope: Bereich +WorkflowWorkflowListInstance: Instanz +WorkflowWorkflowListCurrentState: Aktueller Zustand +WorkflowWorkflowListLastActionTime: Zeitpunkt, letzte Aktion +WorkflowWorkflowListLastActionUser: Benutzer, letzte Aktion +WorkflowWorkflowListIsFinal: Abgeschlossen? + +FormFieldWorkflowDatasetTip: Mindestens ein gekennzeichnetes Feld pro Datensatz muss ausgefüllt werden ChangelogItemFeature: Feature ChangelogItemBugfix: Bugfix @@ -3009,3 +3283,35 @@ InvalidCredentialsADTooManyContextIds: Benutzereintrag trägt zu viele Sicherhei InvalidCredentialsADAccountExpired: Benutzereintrag abgelaufen InvalidCredentialsADPasswordMustChange: Passwort muss geändert werden InvalidCredentialsADAccountLockedOut: Benutzereintrag wurde durch Eindringlingserkennung gesperrt + +ExamCloseModeSeparate: Separat +ExamCloseModeOnFinished: Mit Veröffentlichung +ExamCloseModeOnFinishedHidden: Mit Veröffentlichung (versteckt) +ExamCloseMode: Prüfungs-Abschluss + +RoomReferenceSimple: Text +RoomReferenceLink: Link & Anweisungen +RoomReferenceSimpleText: Raum +RoomReferenceSimpleTextPlaceholder: Raum +RoomReferenceLinkLink: Link +RoomReferenceLinkLinkPlaceholder: URL +RoomReferenceLinkInstructions: Anweisungen +RoomReferenceLinkInstructionsPlaceholder: Anweisungen +RoomReferenceNone: — + +UrlFieldCouldNotParseAbsolute: Konnte nicht als absolute URL interpretiert werden + +WGFTextInput: Textfeld +WGFFileUpload: Dateifeld +WorkflowGraphFormUploadIsDirectory: Upload ist Verzeichnis +WorkflowGraphFormInvalidNumberOfFiles: Es muss genau eine Datei hochgeladen werden + +CourseSortingOnlyLoggedIn: Das Benutzerinterface zur Sortierung dieser Tabelle ist nur für eingeloggte Benutzer aktiv + +CorrectionInvisibleExamUnfinished: Die Frist „_{MsgExamFinished}“ für die relevante Prüfung ist noch nicht verstrichen +CorrectionInvisibleRatingNotDone: Die Bewertung ist nicht als „Abgeschlossen“ markiert +CorrectionInvisibleWarning: Die Bewertung dieser Abgabe ist aktuell für mindestens eine an der Abgabe beteiligte Person nicht sichtbar! +CorrectionInvisibleReasons: Mögliche Gründe hierfür: + + +WorkflowWorkflowListPersons: Beteiligte Benutzer diff --git a/messages/uniworx/en-eu.msg b/messages/uniworx/misc/en-eu.msg similarity index 90% rename from messages/uniworx/en-eu.msg rename to messages/uniworx/misc/en-eu.msg index 8f101495f..4846fbd7c 100644 --- a/messages/uniworx/en-eu.msg +++ b/messages/uniworx/misc/en-eu.msg @@ -1,5 +1,3 @@ -PrintDebugForStupid name: Debug message "#{name}" - Logo: Uni2work BtnSubmit: Submit @@ -142,6 +140,7 @@ ScheduleOffsetWeekForwardDays n: #{n} #{pluralEN n "day" "days"} forward ScheduleOffsetWeekForwardWeek: 1 week forward ScheduleWeekSlotIsCont: Cont. +ScheduleWeekHoliday: Holiday ScheduleOptActions: Schedule ScheduleOptOut: Unsubscribe @@ -478,6 +477,10 @@ SubmissionUserAlreadyAdded: This user is already configured as a submittor NoOpenSubmissions: No open submissions exist SubmissionFilesCorrected: Submitted & Corrected files RatingUpdatedFiles: During correction files were added or changed +SubmissionFilesUnchanged: Keep submission files +SubmissionFilesUnchangedTip: Should the existing submission files be retained unchanged while replacing the submission? +SubmissionUserDuplicateWarning: This participant is already a submittor for a different submission +SubmissionSomeUsersDuplicateWarning: Some submittors are also submittors for a different submission SubmissionsDeleteQuestion n: Do you really want to delete the #{pluralEN n "submission" "submissions"} mentioned below? SubmissionsDeleted n: #{pluralEN n "Submission" "Submissions"} deleted @@ -530,6 +533,7 @@ Unauthorized: You do not have explicit authorisation. UnauthorizedAnd l r: (#{l} AND #{r}) UnauthorizedOr l r: (#{l} OR #{r}) UnauthorizedNot r: (NOT #{r}) +UnauthorizedI18nMismatch: Different authentication results were calculated for different languages UnauthorizedNoToken: No authorisation-token was provided with your request. UnauthorizedTokenExpired: Your authorisation-token is expired. UnauthorizedTokenNotStarted: Your authorisation-token is not yet valid. @@ -539,6 +543,7 @@ UnauthorizedTokenInvalidNoAuthority: Your authorisation-token does not list any UnauthorizedTokenInvalidAuthority: Your authorisation-token is based in an user's rights who does not exist anymore. UnauthorizedTokenInvalidAuthorityGroup: Your authorisation-token is based in an user groups rights which does not exist anymore. UnauthorizedTokenInvalidAuthorityValue: The specification of the rights in which your authorisation-token is based, could not be interpreted. +UnauthorizedTokenInvalidImpersonation: Your authorisation-token contains an instruction to impersonate an user. Not all users on whose rights your token is based however are permitted to do so. UnauthorizedToken404: Authorisation-tokens cannot be processed on error pages. UnauthorizedSiteAdmin: You are no system-wide administrator. UnauthorizedSchoolAdmin: You are no administrator for this department. @@ -547,6 +552,7 @@ UnauthorizedExamOffice: You are not part of an exam office. UnauthorizedEvaluation: You are not charged with course evaluation. UnauthorizedAllocationAdmin: You are not charged with the administration of central allocations. UnauthorizedExamExamOffice: You are not part of the appropriate exam office for any of the participants of this exam. +UnauthorizedSchoolExamOffice: You are not part of an exam office for this school. UnauthorizedSystemExamOffice: You are not charged with system wide exam administration UnauthorizedExternalExamExamOffice: You are not part of the appropriate exam office for any of the participants of this exam. UnauthorizedSchoolLecturer: You are no lecturer for this department. @@ -569,6 +575,7 @@ UnauthorizedParticipantSelf: You are no participant of this course. UnauthorizedApplicant: The specified user is no applicant for this course. UnauthorizedApplicantSelf: You are no applicant for this course. UnauthorizedCourseTime: This course is not currently available. +UnauthorizedCorrectionExamTime: Visibility restrictions of the relevant exam are restricting access. UnauthorizedCourseRegistrationTime: This course does not currently allow enrollment. UnauthorizedAllocationRegisterTime: This central allocation does not currently allow applications. UnauthorizedSheetTime: This sheet is not currently available. @@ -613,6 +620,20 @@ UnauthorizedPasswordResetToken: This authorisation-token may no longer be used t UnauthorizedAllocatedCourseRegister: Direct enrollment to this course is currently not allowed due to participation in a central allocation UnauthorizedAllocatedCourseDeregister: Deregistration from this course is currently not allowed due to participation in a central allocation UnauthorizedAllocatedCourseDelete: Courses that participate in a central allocation may not be deleted +UnauthorizedWorkflowInitiate: You currently may not initiate a new running workflow +UnauthorizedWorkflowWrite: You are currently not allowed to initiate any state transition within the workflow +UnauthorizedWorkflowRead: The workflow currently contains no states or data you are permitted to view +UnauthorizedWorkflowInstancesNotEmpty: There are workflow instances for which you are allowed to initiate a new running workflow +UnauthorizedWorkflowWorkflowsNotEmpty: There are running workflows, which you may view +UnauthorizedWorkflowFiles: You are not allowed to download the given workflow files in the given historical state +UnauthorizedNotAuthenticatedInDifferentApproot: You could not be authenticated in the context of a separate domain (e.g. for secure downloading of files). You probably used no or an expired token. You can try to access the resource with a newly generated download link. +UnauthorizedCsrfDisabled: Your request might have triggered a state change on the server. Since CSRF-protection was disabled for your request, it had to be rejected. +UnauthorizedStudent: You are not a student. + +WorkflowRoleUserMismatch: You aren't any of the users authorized by the workflow +WorkflowRoleAlreadyInitiated: This workflow was already initiated +WorkflowRoleNoSuchWorkflowWorkflow: The given workflow could not be found +WorkflowRoleNoPayload: This workflow does not contain any data EMail: Email EMailUnknown email: Email #{email} does not belong to any known user. @@ -714,6 +735,7 @@ CorrAutoSetCorrector: Distribute corrections CorrDelete: Delete submissions NatField name: #{name} must be a natural number! JSONFieldDecodeFailure aesonFailure: Could not parse JSON: #{aesonFailure} +YAMLFieldDecodeFailure yamlFailure: Could not parse YAML: #{yamlFailure} SecretJSONFieldDecryptFailure: Could not decrypt hidden data SubmissionsAlreadyAssigned num: #{num} #{pluralEN num "correction" "corrections"} were already assigned to a corrector and were left unchanged: @@ -775,6 +797,8 @@ RatingTime: Marked RatingComment: Comment SubmissionUsers: Submittors Rating: Marking +IsRated: Marked +SheetTypeIsExam: Rating „as an exam part“ RatingPoints: Points RatingDone: Rating finished RatingDoneTip: The rating is only visible to the submittors and considered for any exam bonuses if it is finished. @@ -1186,9 +1210,10 @@ SheetGradingPassPoints': Passing by points SheetGradingPassBinary': Pass/Fail SheetGradingPassAlways': Automatically passed when corrected -SheetTypeBonus grading: Bonus -SheetTypeNormal grading: Normal -SheetTypeInformational grading: Informational +SheetTypeBonus: Bonus +SheetTypeNormal: Normal +SheetTypeInformational: Informational +SheetTypeExamPartPoints: As an exam part SheetTypeNotGraded: Not marked SheetTypeInfoNormalLecturer: Normal sheets are used to calculate exam bonuses. Bonuses may be calculated from the number of sheets that can be passed or the maximum number of points achievable either manually or automatically. SheetTypeInfoNotGraded: "Not marked" means that there will be no feedback at all. @@ -1198,6 +1223,11 @@ SheetGradingBonusIncluded: Achieved bonus points are already counted among the a SummaryTitle: Summary of SheetGradingSummaryTitle intgr: #{intgr} #{pluralEN intgr "sheet" "sheets"} SubmissionGradingSummaryTitle intgr: #{intgr} #{pluralEN intgr "submission" "submissions"} +SheetTypeExamPartPointsWeightNegative: Weight may not be negative +SheetTypeExamPartPointsWeight: Weight +SheetTypeExamPartPointsExamPartOption examn examPartNumber: #{examn} - Part #{view _ExamPartNumber examPartNumber} +SheetTypeInfoExamPartPoints: Points achieved in this exercise sheet will be directly applied to the result of an exam part. If the number of points achievable via exercise sheets for an exam part does not match the maximum number of points of that exam part, the points achieved via exercise sheets will be scaled according to their weight. Corrections for this sheet will only be displayed to participants once the exam timestamp “_{MsgExamFinished}” has passed. +SheetTypeExamPartPointsExamPart: Exam part SheetTypeBonus': Bonus SheetTypeNormal': Normal @@ -1484,6 +1514,23 @@ MenuFaq: FAQ MenuSheetPersonalisedFiles: Download personalised sheet files MenuCourseSheetPersonalisedFiles: Download template for personalised sheet files MenuAdminCrontab: Crontab +MenuAdminWorkflowDefinitionList: Workflows +MenuAdminWorkflowDefinitionNew: New workflow definition +MenuAdminWorkflowDefinitionDelete: Delete +MenuAdminWorkflowInstanceList: Workflow instances +MenuAdminWorkflowInstanceNew: New workflow instance +MenuAdminWorkflowDefinitionInstantiate: Instantiate +MenuWorkflowInstanceDelete: Delete +MenuWorkflowInstanceWorkflows: Running workflows +MenuWorkflowInstanceInitiate: Start workflow +MenuWorkflowInstanceEdit: Edit +MenuWorkflowWorkflowList: Running workflows +MenuWorkflowWorkflowEdit: Edit +MenuWorkflowWorkflowDelete: Delete +MenuGlobalWorkflowInstanceList: System-wide workflows +MenuTopWorkflowInstanceList: Workflows +MenuTopWorkflowWorkflowList: Running workflows +MenuTopWorkflowWorkflowListHeader: Workflows BreadcrumbSubmissionFile: File BreadcrumbSubmissionUserInvite: Invitation to participate in a submission @@ -1562,6 +1609,31 @@ BreadcrumbFaq: FAQ BreadcrumbSheetPersonalisedFiles: Download personalised sheet files BreadcrumbCourseSheetPersonalisedFiles: Download template for personalised sheet files BreadcrumbAdminCrontab: Crontab +BreadcrumbAdminWorkflowDefinitionList: Workflow definitions +BreadcrumbAdminWorkflowDefinitionNew: New workflow definition +BreadcrumbAdminWorkflowDefinitionEdit renderedWorkflowScope' wfdn: #{wfdn} (#{renderedWorkflowScope'}) +BreadcrumbAdminWorkflowDefinitionDelete: Delete +BreadcrumbAdminWorkflowDefinitionInstantiate: Instantiate +BreadcrumbAdminWorkflowInstanceList: Workflow instances +BreadcrumbAdminWorkflowInstanceNew: New workflow-instance +BreadcrumbAdminWorkflowInstanceEdit: Edit instance +BreadcrumbAdminWorkflowWorkflowList: Initiated workflows +BreadcrumbAdminWorkflowWorkflowNew: Initiate workflow +BreadcrumbWorkflowInstanceEdit win: #{win} +BreadcrumbWorkflowInstanceDelete: Delete +BreadcrumbWorkflowInstanceWorkflowList: Running workflows +BreadcrumbWorkflowInstanceInitiate: Start workflow +BreadcrumbWorkflowInstanceList: Workflows +BreadcrumbWorkflowInstanceNew: New workflow +BreadcrumbWorkflowWorkflowList: Running workflows +BreadcrumbWorkflowWorkflow workflow: #{toPathPiece workflow} +BreadcrumbWorkflowWorkflowFiles: Files +BreadcrumbWorkflowWorkflowEdit: Edit +BreadcrumbWorkflowWorkflowDelete: Delete +BreadcrumbGlobalWorkflowInstanceList: System-wide workflows +BreadcrumbTopWorkflowInstanceList: Workflows +BreadcrumbTopWorkflowWorkflowList: Running workflows +BreadcrumbError: Error ExternalExamEdit coursen examn: Edit: #{coursen}, #{examn} ExternalExamGrades coursen examn: Exam achievements: #{coursen}, #{examn} @@ -1592,6 +1664,7 @@ AuthTagTime: Time restrictions are fulfilled AuthTagStaffTime: Time restrictions wrt. staff are fulfilled AuthTagAllocationTime: Time restrictions due to a central allocation are fulfilled AuthTagCourseTime: Time restrictions wrt. course visibility are fulfilled +AuthTagExamTime: Exam time restrictions are satisfied AuthTagCourseRegistered: User is enrolled in course AuthTagAllocationRegistered: User participates in central allocation AuthTagTutorialRegistered: User is tutorial participant @@ -1603,7 +1676,7 @@ AuthTagParticipant: User participates in course AuthTagApplicant: User is applicant for course AuthTagRegisterGroup: User is not participant in any tutorial of the same registration group AuthTagCapacity: Capacity is sufficient -AuthTagEmpty: Course is empty +AuthTagEmpty: Resource is “empty” AuthTagMaterials: Course material is publicly accessable AuthTagOwner: User is owner AuthTagPersonalisedSheetFiles: User has been assigned personalised sheet files @@ -1617,6 +1690,8 @@ AuthTagAuthentication: User is authenticated AuthTagRead: Access is read only AuthTagWrite: Access might write AuthTagSubmissionGroup: User is part of a submission group +AuthTagWorkflow: User has matching workflow role +AuthTagStudent: User is a student DeleteCopyStringIfSure n: If you are sure that you want to permanently delete the #{pluralEN n "object" "objects"} listed below, please copy the shown text. DeletePressButtonIfSure n: If you are sure that you want to permanently delete the #{pluralEN n "object" "objects"} listed below, please confirm the action by pressing the button. @@ -1640,6 +1715,7 @@ CommSuccess n: Message was sent to #{n} #{pluralEN n "recipient" "recipients"} CommTestSuccess: Message was sent only to yourself for testing purposes CommUndisclosedRecipients: Undisclosed recipients CommAllRecipients: all-recipients +CommAllRecipientsSheet: Recipients CommCourseHeading: Course message CommTutorialHeading: Tutorial message @@ -1773,6 +1849,10 @@ TutorialParticipants: Participants TutorialCapacity: Capacity TutorialFreeCapacity: Free capacity TutorialRoom: Regular room +TutorialRoomHidden: Room only for participants +TutorialRoomHiddenTip: Should the room only be displayed to tutorial participants? +TutorialRoomIsUnset: — +TutorialRoomIsHidden: Room is only displayed to participants TutorialTime: Time TutorialRegistered: Registered TutorialRegGroup: Registration group @@ -1874,6 +1954,7 @@ ExamFinished: Results visible from ExamFinishedOffice: Exam achievements published ExamFinishedParticipant: Marking expected to be finished ExamFinishedTip: At this participants are informed of their exam achievements. If left empty participants are never informed of their exam achievements. +ExamFinishedTipCloseOnFinished: At this time participants and exam offices are informed of the exam achievements. If left empty participants and exam offices are never informed of the exam achievements. ExamClosed: Exam achievements registered ExamClosedTip: At this time exam offices, which pull exam achievements from Uni2work, are informed. Changes to exam achievements trigger further notifications ExamGradingMode: Grading mode @@ -1897,6 +1978,7 @@ ExamBonusRule: Bonus points from exercises ExamNoBonus': No automatic exam bonus ExamBonusPoints': Compute from exercise achievements ExamBonusManual': Manual computation +ExamBonusInfoPoints: When calculating an exam bonus only those sheets will be considered, for which the submission period started before the start of the relevant occurrence/room ExamRegisterForOccurrence: Registration for this exam is done by registering for an occurrence/room @@ -1921,6 +2003,8 @@ ExamRoomSurname': By surname ExamRoomMatriculation': By matriculation ExamRoomRandom': Randomly ExamRoomFifo': Selected by the participants when registering +ExamOccurrenceRoomIsUnset: — +ExamOccurrenceRoomIsHidden: Room is only displayed to participants registered for this occurrence/room ExamOccurrence: Occurrence/room ExamNoOccurrence: No occurrence/room @@ -1929,9 +2013,12 @@ ExamOccurrences: Exams ExamRooms: Rooms ExamTimes: Times ExamRoomRoom: Room +ExamRoomRoomHidden: Room only for participants +ExamRoomRoomHiddenTip: Should the room only be displayed to participants registered for this occurrence/room? ExamRoomAlreadyExists: Occurrence already configured ExamRoomName: Internal name ExamRoomCapacity: Capacity +ExamRoomCapacityTip: Maximum number of participants for this occurrence/room; leave empty for unlimited capacity ExamRoomCapacityNegative: Capacity may not be negative ExamRoomTime: Time ExamRoomStart: Start @@ -2006,10 +2093,15 @@ ExamPartMaxPoints: Maximum points ExamPartWeight: Weight ExamPartWeightTip: Will be multiplied with the achieved number of points before they are shown to the participant or used in automatic grade computation. Thus this also affects existing exam results (changed exam achievements have to be accepted manually again) ExamPartResultPoints: Achieved points +ExamPartSheets: Exercise sheets -ExamNameTaken exam: There already is an exam named #{exam} +ExamPartsFrom: Parts visible from +ExamPartsFromTip: At this time the list of exam parts/questions will be published, but without their respective maximum number of points. If left empty the list will be published with “Results visible from” + +ExamEditExamNameTaken exam: There already is an exam named #{exam} ExamCreated exam: Successfully created #{exam} ExamEdited exam: Successfully edited #{exam} +ExamEditWouldBreakSheetTypeReference: Your changes include deleting an exam part to which a reference still exists through an exercise sheet. ExamNoShow: Not present ExamVoided: Voided @@ -2043,6 +2135,7 @@ ExamRegistrationMustFollowSchoolSeparationFromStart dayCount: As per school rule ExamRegistrationMustFollowSchoolDuration dayCount: As per school rules there #{pluralEN dayCount "needs" "need"} to be at least #{dayCount} #{pluralEN dayCount "day" "days"} between "Register from" and "Register to". ExamModeRequiredForRegistration: As per school rules "Exam design" needs to be fully specified before "Register from" may be set. ExamModeSchoolDiscouraged: As per school rules the specified "Exam design" is discouraged +ExamPartsFromMustBeBeforeFinished: “Parts visible from” must be before “Results visible from” ExamOccurrenceEndMustBeAfterStart eoName: End of the occurrence #{eoName} must be after it's start ExamOccurrenceStartMustBeAfterExamStart eoName: Start of the occurrence #{eoName} must be after the exam start @@ -2051,6 +2144,7 @@ ExamOccurrenceDuplicate eoRoom eoRange: Combination of room #{eoRoom} and occurr ExamOccurrenceDuplicateName eoName: Internal name #{eoName} occurs multiple times ExamOccurrenceCannotBeDeletedDueToRegistrations eoName: Occurrence #{eoName} cannot be deleted because participants are registered for it. You can remove the offending registrations via the list of exam participants. ExamPartCannotBeDeletedDueToResults exampartnum: Part #{exampartnum} cannot be deleted because some exam part results were already entered for it. +ExamPartCannotBeDeletedDueToSheetReference exampartnum sheetName: Part #{exampartnum} cannot be deleted, since exercise sheet #{sheetName} is configured “as an exam part”. VersionHistory: Version history KnownBugs: Known bugs @@ -2064,6 +2158,7 @@ ExamUserAssignOccurrence: Assign occurrence/room ExamUserAcceptComputedResult: Accept computed result ExamUserResetToComputedResult: Reset result ExamUserResetBonus: Also reset exam bonus +ExamUserResetParts: Also reset exam part results ExamUserSetPartResult: Set exam part result ExamUserSetBonus: Set exam bonus ExamUserSetResult: Set exam result @@ -2139,14 +2234,19 @@ CsvImportExplanationLabel: Informating regarding CSV import CsvExampleData: Example data CsvExportExample: Export example CSV -Proportion c of prop: #{c}/#{of} (#{rationalToFixed2 (100 * prop)}%) -ProportionNoRatio c of: #{c}/#{of} +Proportion c of' prop: #{c}/#{of'} (#{rationalToFixed2 (100 * prop)}%) +ProportionNoRatio c of': #{c}/#{of'} CourseUserCsvName tid ssh csh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-participants +CourseUserCsvSheetName tid ssh csh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh} Participants ExamUserCsvName tid ssh csh examn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn}-participants +ExamUserCsvSheetName tid ssh csh examn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn} Participants ExternalExamUserCsvName tid@TermId ssh@SchoolId coursen@CourseName examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase coursen}-#{foldedCase examn}-participants +ExternalExamUserCsvSheetName tid@TermId ssh@SchoolId coursen@CourseName examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase coursen}-#{foldedCase examn} Participants CourseApplicationsTableCsvName tid ssh csh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-applications +CourseApplicationsTableCsvSheetName tid ssh csh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh} Applications ParticipantsCsvName tid ssh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-participants +ParticipantsCsvSheetName tid ssh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)} Participants CourseUserCsvIncludeSheets: Exercise sheets CourseUserCsvIncludeSheetsTip: Should the exportet CSV-file additionally contain one column per exercise sheet? @@ -2170,6 +2270,8 @@ CsvColumnExamUserParts: Number of points the participant achieved per exam part. CsvColumnExamUserResult: Exam achievement; "passed", "failed", "no-show", "voided", or any number grade ("1.0", "1.3", "1.7", ..., "4.0", "5.0") CsvColumnExamUserCourseNote: Course notes for the participant +CsvColumnUserSurname: Participant's surname +CsvColumnUserFirstName: Participant's given name CsvColumnUserName: Participant's full name CsvColumnUserMatriculation: Participant's matriculation CsvColumnUserSex: Participant's sex @@ -2537,8 +2639,14 @@ BtnCloseExam: Close exam ExamCloseTip: When an exam is closed all relevant exam offices, which pull exam achievements from Uni2work, are informed and kept up to date with changes. ExamCloseReminder: Please close the exam as soon as possible, when exam achievements are no longer expected to change e.g. after inspection of the exam has concluced. ExamDidClose: Successfully closed exam +ExamCloseTipOnFinished: The exam will be closed automatically as soon as exam participants are informed of their exam achievements. That means exam offices will be able notified once and after that each time a grade changes. +ExamFinishHeading: Make results visible +BtnFinishExam: Make results visible +ExamFinishTip: After results are made visible participants are notified and can view their result in Uni2work. The exam timestamp “_{MsgExamFinished}” will be set to the current time. +ExamDidFinish: Successfully made results visible ExamClosedSince time: Exam closed since #{time} +ExamFinishedSince time: Exam results visible since #{time} LecturerInfoTooltipNew: New feature LecturerInfoTooltipProblem: Feature with known issues @@ -2561,8 +2669,9 @@ CsvOptionsTip: These settings primarily affect CSV export. During import most se CsvFormatOptions: File format CsvTimestamp: Timestamp CsvTimestampTip: Should the name of every exported csv file contain a timestamp? -CsvPresetRFC: Standards-compliant (RFC 4180) -CsvPresetExcel: Excel compatible +CsvPresetRFC: Standards-compliant .csv files (RFC 4180) +CsvPresetExcel: Excel compatible .csv files (Excel <2010) +CsvPresetXlsx: .xlsx files (ECMA-376; Excel ≥2010) CsvCustom: User defined CsvDelimiter: Separator character CsvUseCrLf: Linebreaks @@ -2587,6 +2696,9 @@ CsvQuoteMinimal: Only when necessary CsvQuoteAll: Always CsvOptionsUpdated: Successfully changed CSV options CsvChangeOptionsLabel: Export options +CsvFormatField: File format +CsvFormatCsv: .csv (comma-separated values) +CsvFormatXlsx: .xlsx (Office Open XML) CourseNews: News CourseNewsArchiveName tid ssh csh newsTitle: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldCase newsTitle} @@ -2644,12 +2756,15 @@ AllocationResultsTip: The following information reflect the current state of the AllocationResultsStudentTip: Listed below are placements in courses which you have received due to the mentioned central allocation and for which you have not left the respective course or have been deregistered. Thus placements you have been informed of already may be listed again. AllocationResultStudentRegistrationTip: You were enrolled in the course mentioned above in Uni2work. AllocationResultsStudentRegistrationTip: You were enrolled in the courses mentioned above in Uni2work. +AllocationResultsStudentConsultFaq n@Int: If you have questions or remarks, please also take into account the information on the following #{pluralEN n "page" "pages"}: FavouriteVisited: Visited FavouriteParticipant: Your courses FavouriteManual: Favourites FavouriteCurrent: Current course +FavouritesEmptyTip: Your courses and recently visited courses are shown here. +FavouritesToggleTip: The display mode for the current course can be changed between automatic, permanent and never with a click on the star symbol. FavouritesUnavailableTip: Quick Actions for this course are currently not available. CourseEvents: Occurrences @@ -2657,6 +2772,10 @@ CourseEventType: Type CourseEventTypePlaceholder: Lecture, Exercise discussion, ... CourseEventTime: Time CourseEventRoom: Regular room +CourseEventRoomHidden: Room only for participants +CourseEventRoomHiddenTip: Should the room only be displayde to course participants? +CourseEventRoomIsUnset: — +CourseEventRoomIsHidden: Room is only displayed to course associated persons (participants, tutor, correctors, etc.) CourseEventNote: Note CourseEventActions: Actions CourseEventsActionEdit: Edit @@ -2783,17 +2902,21 @@ ExamAutoOccurrenceHeading: Automatic occurrence/room distribution ExamAutoOccurrenceMinimizeRooms: Minimize number of occurrences used ExamAutoOccurrenceMinimizeRoomsTip: Should the list of occurrences/rooms be reduced prior to distribution? Only as many occurrence/rooms as necessary would be used (starting with the biggest). ExamAutoOccurrenceOccurrencesChangedInFlight: Occurrences/rooms changed -ExamAutoOccurrenceParticipantsAssigned num: Occurrence/room assignment rule saved successfully. Also assigned occurence/room to #{num} #{pluralEN num "participant" "participants"} +ExamAutoOccurrenceParticipantsAssigned num: Occurrence/room assignment rule saved successfully. Also assigned occurrence/room to #{num} #{pluralEN num "participant" "participants"} TitleExamAutoOccurrence tid ssh csh examn: #{tid} - #{ssh} - #{csh} #{examn}: Automatic occurrence/room distribution BtnExamAutoOccurrenceCalculate: Calculate assignment rules BtnExamAutoOccurrenceAccept: Accept assignments -BtnExamAutoOccurrenceNudgeUp: + -BtnExamAutoOccurrenceNudgeDown: - ExamRoomMappingSurname: Surnames starting with ExamRoomMappingMatriculation: Matriculation numbers ending in +ExamRoomMappingRandom: Distribution +ExamRoomMappingRandomHere: Random ExamRoomLoad: Utilisation ExamRegisteredCount: Registrations ExamRegisteredCountOf num count: #{num}/#{count} +ExamAutoOccurrenceExceptionRuleNoOp: Didn't chose an automatic distribution procedure +ExamAutoOccurrenceExceptionNotEnoughSpace: More participants than available space +ExamAutoOccurrenceExceptionNoUsers: No participants can be distributed with the chosen procedure +ExamAutoOccurrenceExceptionRoomTooSmall: Automatic distribution failed. A different distribution procedure might succeed. Alternatively, minimizing rooms or removing small rooms might help. NoFilter: No restriction @@ -2807,7 +2930,7 @@ InfoLecturerTutorials: Tutorials InfoLecturerExams: Exams InfoLecturerAllocations: Central allocations -ParticipantsIntersectCourseOption tid@TermId ssh@SchoolId coursen@CourseName: #{tid} - #{ssh} - #{coursen} +ParticipantsIntersectCourseOption tid ssh csh coursen: #{tid} - #{ssh} - #{csh}: #{coursen} ParticipantsIntersectCourses: Courses AllocationUsersTitle tid ssh ash: #{tid}-#{ssh}-#{ash}: Applicants @@ -2829,6 +2952,7 @@ CsvColumnAllocationUserAssigned: Number of assignments the applicant has already CsvColumnAllocationUserNewAssigned: Number of assignments the applicant would receive, if the calculated matching is accepted CsvColumnAllocationUserPriority: Central priority of this applicant; either a number based on the applicants position in the list sorted by priority (higher numbers mean a higher priority) or a comma-separated list of numerical priorities in square brackets (e.g. [1, 2, 3]) AllocationUsersCsvName tid ssh ash: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase ash}-applicants +AllocationUsersCsvSheetName tid ssh ash: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase ash} Applicants AllocationPrioritiesMode: Mode AllocationPrioritiesNumeric: Numeric priorities @@ -2898,7 +3022,7 @@ AllocationUsersCount: Participants AllocationCoursesCount: Courses AllocationCourseEligible: Considered -CourseOption tid ssh coursen: #{tid} - #{ssh} - #{coursen} +CourseOption tid ssh csh coursen: #{tid} - #{ssh} - #{csh}: #{coursen} BearerTokenUsageWarning: Using this interface you are able to encode essentially arbitrary permissions inte bearer tokens. This allows you to freely hand permissions off arbitrarily and without relevant restrictions. Only use this interface if you have discussed the consequences of the specific token, that you want to issue, with an experienced developer! BearerTokenAuthorityGroups: Authority (groups) @@ -2921,6 +3045,16 @@ BearerTokenExpires: Expiration time BearerTokenExpiresTip: If no expiration time is given, the token will not expire. It will be valid forever. BearerTokenOverrideStart: Start time BearerTokenOverrideStartTip: If no start time is given, only the expiration time will be checked when the token is used. +BearerTokenImpersonate: Impersonate +BearerTokenImpersonateNone: No one +BearerTokenImpersonateSingle: A specific user +BearerTokenImpersonateRandom: Random users +BearerTokenImpersonateSingleUser: User +BearerTokenImpersonateRandomNegative: Count must be positive +BearerTokenImpersonateRandomCount: Count +BearerTokenImpersonateUnknownUser email: Could not find any user with email #{email} +BearerTokenImpersonateRandomWeightActivity: Weight by activity +BearerTokenArchiveName: tokens.zip FaqTitle: Frequently asked questions AdditionalFaqs: More frequently asked questions @@ -2987,6 +3121,9 @@ PersonalisedSheetFilesIgnored count: #{count} uploaded #{pluralEN count "file wa PersonalisedSheetFilesIgnoredIntro: The following files were ignored: CourseUserHasPersonalisedSheetFilesFilter: Participant has personalised sheet files for SheetPersonalisedFilesUsersList: List of course participants who have personalised sheet files +PersonalisedSheetFilesDownloadRestrictByExamNone: No restriction +PersonalisedSheetFilesDownloadRestrictByExam: Restrict to exam participants +PersonalisedSheetFilesDownloadRestrictByExamTip: Only download personalised sheet files for participants also registered to a certain exam? AdminCrontabNotGenerated: Crontab not (yet) generated CronMatchAsap: ASAP @@ -2994,6 +3131,143 @@ CronMatchNone: Never SystemExamOffice: Exam office SystemFaculty: Faculty member +SystemStudent: Student + +WorkflowScopeKindGlobal: Global +WorkflowScopeKindTerm: Per term +WorkflowScopeKindSchool: Per school +WorkflowScopeKindTermSchool: Per school & term +WorkflowScopeKindCourse: Per course +WorkflowScopeGlobal: System-wide +WorkflowScopeTermSchool tid ssh: #{tid} #{ssh} +WorkflowScopeCourse tid ssh csh: #{tid} #{ssh} #{csh} +WorkflowDefinitionScope: Scope +WorkflowDefinitionName: Name +WorkflowDefinitionDescriptions: Description +WorkflowDefinitionDescriptionsLanguageExists: A description in this language already exists +WorkflowDescriptionLanguage: Language code (RFC1766) +WorkflowDescriptionTitle: Title +WorkflowDescription: Description + +GlobalWorkflowInstancesHeading: Workflows (system-wide) +GlobalWorkflowInstancesTitle: Workflows (system-wide) + +GlobalWorkflowInstanceInitiateHeading workflowInstanceTitle: Initiate workflow: #{workflowInstanceTitle} +GlobalWorkflowInstanceInitiateTitle: Initiate workflow + +SchoolWorkflowInstancesHeading ssh: Workflows (#{ssh}) +SchoolWorkflowInstancesTitle ssh: Workflows (#{ssh}) + +SchoolWorkflowInstanceInitiateHeading ssh workflowInstanceTitle: Initiate workflow: #{ssh}, #{workflowInstanceTitle} +SchoolWorkflowInstanceInitiateTitle ssh: Initiate workflow: #{ssh} + +WorkflowEdgeNumberedVariant edgeLabel i: #{edgeLabel} (variant #{i}) +WorkflowEdgeFormEdge: Action +WorkflowEdgeFormHiddenPayload i: Hidden dataset #{i} +WorkflowEdgeFormPayloadOneFieldRequired: At least one field per dataset needs to be filled +WorkflowEdgeFormPayloadOneFieldRequiredFor payloadDisplayLabel: At least one field for “#{payloadDisplayLabel}” needs to be filled +WorkflowEdgeFormFieldNumberTooSmall minSci: Number must be at least #{formatScientific Scientific.Generic Nothing minSci} +WorkflowEdgeFormFieldNumberTooLarge maxSci: Number must be at most #{formatScientific Scientific.Generic Nothing maxSci} +WorkflowEdgeFormFieldUserNotFound: Email could not be resolved to an user +WorkflowEdgeFormFieldMultipleNoneAdded: No entries (yet) +WorkflowEdgeFormFieldCaptureUserLabel: Current user + +WorkflowWorkflowWorkflowHistoryHeading: History +WorkflowWorkflowWorkflowEdgeFormHeading: Trigger action within workflow +WorkflowWorkflowWorkflowEdgeSuccess: Successfully triggered action +WorkflowWorkflowWorkflowHistoryUserSelf: You +WorkflowWorkflowWorkflowHistoryUserNotLoggedIn: Not-logged in user +WorkflowWorkflowWorkflowHistoryUserGone: Deleted user +WorkflowWorkflowWorkflowHistoryUserHidden: Hidden user +WorkflowWorkflowWorkflowHistoryUserAutomatic: Automatic +WorkflowWorkflowWorkflowHistoryActionAutomatic: Automatic +WorkflowWorkflowWorkflowHistoryStateHidden: Hidden state +WorkflowWorkflowWorkflowHistoryActionLabel: Action +WorkflowWorkflowWorkflowHistoryFromLabel: Previous state +WorkflowWorkflowWorkflowHistoryToLabel: New state +WorkflowWorkflowWorkflowHistoryPayloadLabel: Data changes +WorkflowWorkflowFilesArchiveName wwCID wpl stCID: #{foldCase (toPathPiece wwCID)}-#{foldCase (toPathPiece stCID)}-#{foldCase (foldMap unidecode (toPathPiece wpl))}.zip +WorkflowWorkflowWorkflowStateHeading: State/Data +WorkflowWorkflowWorkflowPayloadHeading: Current data +WorkflowWorkflowWorkflowStateStateLabel: Current state +WorkflowWorkflowWorkflowStateStateHidden: Hidden state +WorkflowWorkflowWorkflowHistoryLabelOthers: Other users' actions +WorkflowWorkflowWorkflowHistoryLabelOwn: Your actions + +WorkflowPayloadFiles: File(s) +WorkflowPayloadBoolTrue: Yes +WorkflowPayloadBoolFalse: No +WorkflowPayloadUserGone: Deleted user + +TopWorkflowInstancesHeading: Workflows +TopWorkflowInstancesTitle: Workflows + +GlobalWorkflowWorkflowWorkflowHeading workflowWorkflowId: Workflow #{toPathPiece workflowWorkflowId} +GlobalWorkflowWorkflowWorkflowTitle workflowWorkflowId: Workflow #{toPathPiece workflowWorkflowId} + +SchoolWorkflowWorkflowWorkflowHeading ssh workflowWorkflowId: Workflow #{ssh}, #{toPathPiece workflowWorkflowId} +SchoolWorkflowWorkflowWorkflowTitle ssh workflowWorkflowId: Workflow #{ssh}, #{toPathPiece workflowWorkflowId} + +WorkflowWorkflowListScopeTitle rScope: Running workflows - #{rScope} +WorkflowWorkflowListScopeHeading rScope: Running workflows (#{rScope}) +WorkflowWorkflowListInstanceTitle: Running workflows for an instance +WorkflowWorkflowListInstanceHeading: Running workflows for an instance +WorkflowWorkflowListNamedInstanceTitle rScope wiTitle: Running workflows - #{rScope}, #{wiTitle} +WorkflowWorkflowListNamedInstanceHeading rScope wiTitle: Running workflows (#{rScope}, #{wiTitle}) +WorkflowWorkflowListTopTitle: Running workflows +WorkflowWorkflowListTopHeading: Running workflows +AdminWorkflowWorkflowListTitle: Running workflows +AdminWorkflowWorkflowListHeading: Running workflows + +WorkflowWorkflowListNumber: Number +WorkflowWorkflowListScope: Scope +WorkflowWorkflowListInstance: Instance +WorkflowWorkflowListCurrentState: Current state +WorkflowWorkflowListLastActionTime: Timestamp of last action +WorkflowWorkflowListLastActionUser: User for last action +WorkflowWorkflowListIsFinal: Finalised? + +FormFieldWorkflowDatasetTip: At least one of the marked fields must be filled +WorkflowDefinitionGraph: Specification +WorkflowDefinitionKeyDoesNotExist renderedCryptoID: Referenced id does not exist: #{renderedCryptoID} +WorkflowDefinitionFiles: Files +WorkflowFileIdentDoesNotExist fileIdent: Referenced file does not exist: #{fileIdent} +WorkflowUserDoesNotExist userIdent: Referenced user does not exist: #{userIdent} +WorkflowDefinitionFileIdentExists: A file with the given reference id already exists +WorkflowDefinitionFileIdent: File reference id +WorkflowDefinitionFile: File +WorkflowDefinitionCreated: Successfully created workflow definition +WorkflowDefinitionEdited: Successfully replaced workflow definition +WorkflowDefinitionCollision: A workflow definition with this name already exists +WorkflowDefinitionNewTitle: Create new workflow definition +WorkflowDefinitionEditTitle: Edit workflow definition +WorkflowDefinitionInstanceCategory: Category +WorkflowDefinitionWarningLinterIssuesMessage: There were linter issues +WorkflowDefinitionWarningLinterIssues: There are the following linter issues: + +WorkflowDefinitionListTitle: Workflow definitions +WorkflowDefinitionInstanceCount: Instances +WorkflowDefinitionWorkflowCount: Workflows +WorkflowDefinitionConcreteInstanceCount num: #{num} instances +WorkflowDefinitionConcreteWorkflowCount num: #{num} workflows +WorkflowDefinitionDeleteQuestion: Do you really want to delete the workflow definition listed below? +WorkflowDefinitionDeleted: Successfully deleted workflow definition +WorkflowDefinitionInstantiateTitle: Instantiate workflow definition +WorkflowDefinitionInstantiated: Instance created + +WorkflowScope: Scope +WorkflowInstanceName: Name +WorkflowInstanceCategory: Category +WorkflowInstanceCollision: There already exists a workflow instance with the given name and category +WorkflowInstanceListTitle: Workflow instances +WorkflowInstanceDescription: Instance description +WorkflowInstanceDescriptions: Instance description +WorkflowInstanceDescriptionsLanguageExists: A instance description in the given language already exists +WorkflowInstanceCreated: Instance created +WorkflowInstanceDescriptionTitle: Instance title +WorkflowInstanceWorkflowCount: Workflows + +WorkflowInstanceInitiateSuccess: Successfully initiated workflow ChangelogItemFeature: Feature ChangelogItemBugfix: Bugfix @@ -3009,3 +3283,35 @@ InvalidCredentialsADTooManyContextIds: Account carries to many security identifi InvalidCredentialsADAccountExpired: Account expired InvalidCredentialsADPasswordMustChange: Password needs to be changed InvalidCredentialsADAccountLockedOut: Account disabled by intruder detection + +ExamCloseModeSeparate: Seperately +ExamCloseModeOnFinished: With publication of achievements +ExamCloseModeOnFinishedHidden: With publication of achievements (hidden) +ExamCloseMode: Exam closure + +RoomReferenceSimple: Text +RoomReferenceLink: Link & Instructions +RoomReferenceSimpleText: Room +RoomReferenceSimpleTextPlaceholder: Room +RoomReferenceLinkLink: Link +RoomReferenceLinkLinkPlaceholder: URL +RoomReferenceLinkInstructions: Instructions +RoomReferenceLinkInstructionsPlaceholder: Instructions +RoomReferenceNone: — + +UrlFieldCouldNotParseAbsolute: Could not parse as an absolute URL + +WGFTextInput: Text field +WGFFileUpload: File field +WorkflowGraphFormUploadIsDirectory: Upload is a directory +WorkflowGraphFormInvalidNumberOfFiles: You need to upload exactly one file + +CourseSortingOnlyLoggedIn: The user interface for sorting this table is only active for logged in users + +CorrectionInvisibleExamUnfinished: The time configured in “_{MsgExamFinished}” of the relevant exam has not yet passed +CorrectionInvisibleRatingNotDone: The correction is not marked as “finished” +CorrectionInvisibleWarning: This correction is currently invisible for at least one of the submittors! +CorrectionInvisibleReasons: Possible reasons include: + + +WorkflowWorkflowListPersons: Involved users \ No newline at end of file diff --git a/messages/uniworx/test/de-de-formal.msg b/messages/uniworx/test/de-de-formal.msg new file mode 100644 index 000000000..001e9a1cf --- /dev/null +++ b/messages/uniworx/test/de-de-formal.msg @@ -0,0 +1 @@ +PrintDebugForStupid name@Text: Debug message "#{name}" diff --git a/messages/uniworx/test/en-eu.msg b/messages/uniworx/test/en-eu.msg new file mode 100644 index 000000000..bc2776f24 --- /dev/null +++ b/messages/uniworx/test/en-eu.msg @@ -0,0 +1 @@ +PrintDebugForStupid name: Debug message "#{name}" diff --git a/models/allocations.model b/models/allocations.model index e4e96f6b2..a7773ab3b 100644 --- a/models/allocations.model +++ b/models/allocations.model @@ -31,6 +31,7 @@ AllocationMatching fingerprint AllocationFingerprint time UTCTime log FileContentReference + deriving Generic AllocationCourse allocation AllocationId @@ -38,24 +39,26 @@ AllocationCourse minCapacity Int -- if the course would get assigned fewer than this many applicants, restart the assignment process without the course acceptSubstitutes UTCTime Maybe UniqueAllocationCourse course + deriving Generic AllocationUser allocation AllocationId user UserId - totalCourses Natural -- number of total allocated courses for this user must be <= than this number + totalCourses Word64 -- number of total allocated courses for this user must be <= than this number priority AllocationPriority Maybe UniqueAllocationUser allocation user - deriving Eq Ord Show + deriving Eq Ord Show Generic AllocationDeregister -- self-inflicted user-deregistrations from an allocated course user UserId course CourseId Maybe time UTCTime reason Text Maybe -- if this deregistration was done by proxy (e.g. the lecturer pressed the button) - deriving Eq Ord Show + deriving Eq Ord Show Generic AllocationNotificationSetting user UserId allocation AllocationId isOptOut Bool - UniqueAllocationNotificationSetting user allocation \ No newline at end of file + UniqueAllocationNotificationSetting user allocation + deriving Generic \ No newline at end of file diff --git a/models/audit.model b/models/audit.model index 4524fdaf1..f2336b3cc 100644 --- a/models/audit.model +++ b/models/audit.model @@ -5,4 +5,4 @@ TransactionLog initiator UserId Maybe -- User associated with performing this action remote IP Maybe -- Remote party that triggered this action via HTTP info Value -- JSON-encoded `Transaction` - deriving Eq Read Show Generic Typeable \ No newline at end of file + deriving Eq Read Show Generic \ No newline at end of file diff --git a/models/changelog.model b/models/changelog.model index 4cc42cb12..58ec60aa0 100644 --- a/models/changelog.model +++ b/models/changelog.model @@ -2,3 +2,4 @@ ChangelogItemFirstSeen item ChangelogItem firstSeen Day Primary item + deriving Generic diff --git a/models/config.model b/models/config.model index 5ec2357d6..202160cc7 100644 --- a/models/config.model +++ b/models/config.model @@ -3,4 +3,5 @@ ClusterConfig setting ClusterSettingsKey -- I.e. Symmetric key for encrypting database-ids for use in URLs, Symmetric key for encrypting user-sessions so they can be saved directly as a browser-cookie, Symmetric key for encrypting error messages which might contain secret information, ... value Value -- JSON-encoded value - Primary setting \ No newline at end of file + Primary setting + deriving Generic \ No newline at end of file diff --git a/models/courses.model b/models/courses.model index 612137ed4..0ed28b2ee 100644 --- a/models/courses.model +++ b/models/courses.model @@ -3,10 +3,11 @@ DegreeCourse json -- for which degree programmes this course is appropriate fo degree StudyDegreeId terms StudyTermsId UniqueDegreeCourse course degree terms + deriving Generic Course -- Information about a single course; contained info is always visible to all users name CourseName description StoredMarkup Maybe -- user-defined large Html, ought to contain module description - linkExternal Text Maybe -- arbitrary user-defined url for external course page + linkExternal URI Maybe -- arbitrary user-defined url for external course page shorthand (CI Text) -- practical shorthand of course name, used for identification term TermId -- semester this course is taught school SchoolId @@ -34,19 +35,23 @@ CourseScheduleOpt -- opt-in/-out for displaying occurrence related to this co user UserId opt Bool UniqueCourseScheduleOpt course user + deriving Generic CourseEvent type CourseEventType course CourseId - room CourseEventRoom + room RoomReference Maybe + roomHidden Bool default=false time Occurrences note StoredMarkup Maybe lastChanged UTCTime default=now() + deriving Generic CourseEventScheduleOpt -- opt-in/-out for course event display in a user's schedule (TODO: currently for all occurrences of a course event; separate opt-ins/-outs per occurrence in CourseEventTime instead?) courseEvent CourseEventId user UserId opt Bool -- whether the course event should be displayed; False <=> opt-out, True <=> opt-in UniqueCourseEventScheduleOpt courseEvent user + deriving Generic CourseAppInstructionFile course CourseId @@ -54,16 +59,19 @@ CourseAppInstructionFile content FileContentReference Maybe modified UTCTime UniqueCourseAppInstructionFile course title + deriving Generic CourseEdit -- who edited when a row in table "Course", kept indefinitely (might be replaced by generic Audit Table; like all ...-Edit tables) user UserId time UTCTime course CourseId + deriving Generic Lecturer -- course ownership user UserId course CourseId type LecturerType default='"lecturer"'::jsonb UniqueLecturer user course -- note: multiple lecturers per course are allowed, but no duplicated rows in this table + deriving Generic CourseParticipant -- course enrolement course CourseId user UserId @@ -72,7 +80,7 @@ CourseParticipant -- course enrolement allocated AllocationId Maybe -- participant was centrally allocated state CourseParticipantState UniqueParticipant user course - deriving Eq Ord Show + deriving Eq Ord Show Generic -- Replace the last two by the following, once an audit log is available -- CourseUserNote -- lecturers of a specific course may share a text note on each enrolled student -- course CourseId @@ -86,13 +94,16 @@ CourseUserNote -- lecturers of a specific course may share a tex user UserId note StoredMarkup -- arbitrary user-defined text; visible only to lecturer of this course UniqueCourseUserNote user course + deriving Generic CourseUserNoteEdit -- who edited a participants course note when user UserId time UTCTime note CourseUserNoteId -- PROBLEM: deleted notes have no modification date any more + deriving Generic CourseUserExamOfficeOptOut course CourseId user UserId school SchoolId UniqueCourseUserExamOfficeOptOut course user school + deriving Generic diff --git a/models/courses/applications.model b/models/courses/applications.model index 8e7d6c8d5..b5c342198 100644 --- a/models/courses/applications.model +++ b/models/courses/applications.model @@ -7,9 +7,10 @@ CourseApplication ratingPoints ExamGrade Maybe ratingComment Text Maybe allocation AllocationId Maybe - allocationPriority Natural Maybe + allocationPriority Word64 Maybe time UTCTime default=now() ratingTime UTCTime Maybe + deriving Generic CourseApplicationFile application CourseApplicationId @@ -17,3 +18,4 @@ CourseApplicationFile content FileContentReference Maybe modified UTCTime UniqueCourseApplicationFile application title + deriving Generic diff --git a/models/courses/favourite.model b/models/courses/favourite.model index 1c5077b77..f42f5f6c4 100644 --- a/models/courses/favourite.model +++ b/models/courses/favourite.model @@ -4,7 +4,9 @@ CourseFavourite -- which user accessed which course when, only display reason FavouriteReason lastVisit UTCTime UniqueCourseFavourite user course + deriving Generic CourseNoFavourite user UserId course CourseId - UniqueCourseNoFavourite user course \ No newline at end of file + UniqueCourseNoFavourite user course + deriving Generic \ No newline at end of file diff --git a/models/courses/materials.model b/models/courses/materials.model index 3a4767ec5..d020271bc 100644 --- a/models/courses/materials.model +++ b/models/courses/materials.model @@ -12,4 +12,5 @@ MaterialFile -- a file that is part of a material distribution title FilePath content FileContentReference Maybe modified UTCTime - UniqueMaterialFile material title \ No newline at end of file + UniqueMaterialFile material title + deriving Generic \ No newline at end of file diff --git a/models/courses/news.model b/models/courses/news.model index c31312d2e..c12bbe5d7 100644 --- a/models/courses/news.model +++ b/models/courses/news.model @@ -6,9 +6,11 @@ CourseNews content StoredMarkup summary StoredMarkup Maybe lastEdit UTCTime + deriving Generic CourseNewsFile news CourseNewsId title FilePath content FileContentReference Maybe modified UTCTime - UniqueCourseNewsFile news title \ No newline at end of file + UniqueCourseNewsFile news title + deriving Generic \ No newline at end of file diff --git a/models/exam-office.model b/models/exam-office.model index ab45e3abd..0fbd7330d 100644 --- a/models/exam-office.model +++ b/models/exam-office.model @@ -3,17 +3,21 @@ ExamOfficeField field StudyTermsId forced Bool UniqueExamOfficeField office field + deriving Generic ExamOfficeUser office UserId user UserId UniqueExamOfficeUser office user + deriving Generic ExamOfficeResultSynced school SchoolId Maybe office UserId result ExamResultId time UTCTime + deriving Generic ExamOfficeExternalResultSynced school SchoolId Maybe office UserId result ExternalExamResultId - time UTCTime \ No newline at end of file + time UTCTime + deriving Generic \ No newline at end of file diff --git a/models/exams.model b/models/exams.model index f65a470ee..4735361ff 100644 --- a/models/exams.model +++ b/models/exams.model @@ -19,7 +19,9 @@ Exam description StoredMarkup Maybe examMode ExamMode staff Text Maybe + partsFrom UTCTime Maybe UniqueExam course name + deriving Generic ExamPart exam ExamId number ExamPartNumber @@ -28,57 +30,64 @@ ExamPart weight Rational UniqueExamPartNumber exam number UniqueExamPartName exam name !force + deriving Read Show Eq Ord Generic ExamOccurrence exam ExamId name ExamOccurrenceName - room ExamOccurrenceRoom - capacity Natural + room RoomReference Maybe + roomHidden Bool default=false + capacity Word64 Maybe start UTCTime end UTCTime Maybe description StoredMarkup Maybe UniqueExamOccurrence exam name + deriving Generic ExamOccurrenceScheduleOpt examOccurrence ExamOccurrenceId user UserId opt Bool UniqueExamOccurrenceScheduleOpt examOccurrence user + deriving Generic ExamRegistration exam ExamId user UserId occurrence ExamOccurrenceId Maybe time UTCTime default=now() UniqueExamRegistration exam user - deriving Eq Ord Show + deriving Eq Ord Show Generic ExamPartResult examPart ExamPartId user UserId result ExamResultPoints lastChanged UTCTime default=now() UniqueExamPartResult examPart user - deriving Eq Ord Show + deriving Eq Ord Show Generic ExamBonus exam ExamId user UserId bonus Points lastChanged UTCTime default=now() UniqueExamBonus exam user - deriving Eq Ord Show + deriving Eq Ord Show Generic ExamResult exam ExamId user UserId result ExamResultPassedGrade lastChanged UTCTime default=now() UniqueExamResult exam user - deriving Eq Ord Show + deriving Eq Ord Show Generic ExamCorrector exam ExamId user UserId UniqueExamCorrector exam user + deriving Generic ExamPartCorrector part ExamPartId corrector ExamCorrectorId UniqueExamPartCorrector part corrector + deriving Generic ExamOfficeSchool school SchoolId exam ExamId UniqueExamOfficeSchool exam school + deriving Generic diff --git a/models/external-exams.model b/models/external-exams.model index 0efe62669..06d83b688 100644 --- a/models/external-exams.model +++ b/models/external-exams.model @@ -6,6 +6,7 @@ ExternalExam defaultTime UTCTime Maybe gradingMode ExamGradingMode UniqueExternalExam term school courseName examName + deriving Generic ExternalExamResult user UserId exam ExternalExamId @@ -13,12 +14,14 @@ ExternalExamResult time UTCTime lastChanged UTCTime UniqueExternalExamResult exam user - deriving Eq Ord Show + deriving Eq Ord Show Generic ExternalExamStaff user UserId exam ExternalExamId UniqueExternalExamStaff exam user + deriving Generic ExternalExamOfficeSchool school SchoolId exam ExternalExamId - UniqueExternalExamOfficeSchool exam school \ No newline at end of file + UniqueExternalExamOfficeSchool exam school + deriving Generic \ No newline at end of file diff --git a/models/files.model b/models/files.model index 2a8656a3e..eb0c3ebf3 100644 --- a/models/files.model +++ b/models/files.model @@ -1,30 +1,36 @@ FileContentEntry hash FileContentReference - ix Natural + ix Word64 chunkHash FileContentChunkId UniqueFileContentEntry hash ix + deriving Generic FileContentChunk hash FileContentChunkReference content ByteString contentBased Bool default=false -- For Migration Primary hash + deriving Generic FileContentChunkUnreferenced hash FileContentChunkId since UTCTime UniqueFileContentChunkUnreferenced hash + deriving Generic SessionFile content FileContentReference Maybe touched UTCTime + deriving Generic FileLock content FileContentReference instance InstanceId time UTCTime + deriving Generic FileChunkLock hash FileContentChunkReference instance InstanceId - time UTCTime \ No newline at end of file + time UTCTime + deriving Generic \ No newline at end of file diff --git a/models/invitations.model b/models/invitations.model index c915d08e4..91e3ba610 100644 --- a/models/invitations.model +++ b/models/invitations.model @@ -3,4 +3,5 @@ Invitation for Value data Value expiresAt UTCTime Maybe - UniqueInvitation email for \ No newline at end of file + UniqueInvitation email for + deriving Generic \ No newline at end of file diff --git a/models/jobs.model b/models/jobs.model index 4b8cf82f2..e238f49c6 100644 --- a/models/jobs.model +++ b/models/jobs.model @@ -6,7 +6,7 @@ QueuedJob lockInstance InstanceId Maybe -- instance that has started to execute this job lockTime UTCTime Maybe -- time when execution had begun writeLastExec Bool default=false -- record successful execution to CronLastExec - deriving Eq Read Show Generic Typeable + deriving Eq Read Show Generic -- Jobs are deleted from @QueuedJob@ after they are executed successfully and recorded in @CronLastExec@ -- There is a Cron-system that, at set intervals, queries the database for work to be done in the background (i.e. if a lecturer has set a sheet's submissions to be automatically distributed and the submission deadline passed since the last check, then queue a new job to actually do the distribution) @@ -16,9 +16,11 @@ CronLastExec time UTCTime -- When was the job executed instance InstanceId -- Which uni2work-instance did the work UniqueCronLastExec job + deriving Generic TokenBucket ident TokenBucketIdent lastValue Int64 lastAccess UTCTime - Primary ident \ No newline at end of file + Primary ident + deriving Generic \ No newline at end of file diff --git a/models/mail.model b/models/mail.model index 114c37ce9..b24420e74 100644 --- a/models/mail.model +++ b/models/mail.model @@ -6,8 +6,10 @@ SentMail recipient UserId Maybe headers MailHeaders contentRef SentMailContentId + deriving Generic SentMailContent hash MailContentReference content MailContent - Primary hash \ No newline at end of file + Primary hash + deriving Generic \ No newline at end of file diff --git a/models/schools.model b/models/schools.model index 950b1c624..33975b7a3 100644 --- a/models/schools.model +++ b/models/schools.model @@ -7,6 +7,7 @@ School json examMinimumRegisterDuration NominalDiffTime Maybe examRequireModeForRegistration Bool default=false examDiscouragedModes ExamModeDNF + examCloseMode ExamCloseMode default='separate' UniqueSchool name UniqueSchoolShorthand shorthand -- required for Normalisation of CI Text Primary shorthand -- newtype Key School = SchoolKey { unSchoolKey :: SchoolShorthand } @@ -15,7 +16,9 @@ SchoolLdap school SchoolId Maybe orgUnit (CI Text) UniqueOrgUnit orgUnit + deriving Generic SchoolTerms school SchoolId terms StudyTermsId - UniqueSchoolTerms school terms \ No newline at end of file + UniqueSchoolTerms school terms + deriving Generic \ No newline at end of file diff --git a/models/sheets.model b/models/sheets.model index 6f0bb6176..92845f112 100644 --- a/models/sheets.model +++ b/models/sheets.model @@ -2,7 +2,7 @@ Sheet -- exercise sheet for a given course course CourseId name (CI Text) description StoredMarkup Maybe - type SheetType -- Does it count towards overall course grade? + type (SheetType SqlBackendKey) -- ExamPartId; Does it count towards overall course grade? grouping SheetGroup -- May participants submit in groups of certain sizes? markingText StoredMarkup Maybe -- Instructons for correctors, included in marking templates visibleFrom UTCTime Maybe -- Invisible to enrolled participants before @@ -21,6 +21,7 @@ SheetEdit -- who edited when a row in table "Course", kept i user UserId time UTCTime sheet SheetId + deriving Generic -- For anonoymous external submissions (i.e. paper submission tracked in uni2work) -- Map pseudonyms to users injectively in the context of a single sheet; for the next sheet all-new pseudonyms need to be created @@ -31,13 +32,14 @@ SheetPseudonym user UserId UniqueSheetPseudonym sheet pseudonym UniqueSheetPseudonymUser sheet user + deriving Generic SheetCorrector -- grant corrector role to user for a sheet user UserId sheet SheetId load Load -- portion of work that will be assigned to this corrector state CorrectorState default='CorrectorNormal' -- whether a corrector is assigned his load this time (e.g. in case of sickness) UniqueSheetCorrector user sheet - deriving Show Eq Ord + deriving Show Eq Ord Generic SheetFile -- a file that is part of an exercise sheet sheet SheetId type SheetFileType -- excercise, marking, hint or solution @@ -45,6 +47,7 @@ SheetFile -- a file that is part of an exercise sheet content FileContentReference Maybe modified UTCTime UniqueSheetFile sheet type title + deriving Generic PersonalisedSheetFile sheet SheetId user UserId @@ -53,11 +56,12 @@ PersonalisedSheetFile content FileContentReference Maybe modified UTCTime UniquePersonalisedSheetFile sheet user type title - deriving Eq Ord Read Show Generic Typeable + deriving Eq Ord Read Show Typeable Generic FallbackPersonalisedSheetFilesKey course CourseId index Word24 secret ByteString generated UTCTime - UniqueFallbackPersonalisedSheetFilesKey course index \ No newline at end of file + UniqueFallbackPersonalisedSheetFilesKey course index + deriving Generic \ No newline at end of file diff --git a/models/study-features.model b/models/study-features.model index 71b72ad0f..1c9c9cb20 100644 --- a/models/study-features.model +++ b/models/study-features.model @@ -8,15 +8,16 @@ StudyFeatures -- multiple entries possible for students pursuing several degree firstObserved UTCTime Maybe lastObserved UTCTime default=now() -- last update from LDAP valid Bool default=true - relevanceCached Bool default=false + relevanceCached UUID Maybe UniqueStudyFeatures user degree field type semester - deriving Eq Show + deriving Eq Show Generic -- UniqueUserSubject ubuser degree field -- There exists a counterexample RelevantStudyFeatures term TermId studyFeatures StudyFeaturesId UniqueRelevantStudyFeatures term studyFeatures + deriving Generic StudyDegree -- Studienabschluss key Int -- LMU-internal key @@ -24,7 +25,7 @@ StudyDegree -- Studienabschluss name Text Maybe -- description given by LDAP Primary key -- column key is used as actual DB row key -- newtype Key StudyDegree = StudyDegreeKey' { unStudyDegreeKey :: Int } - deriving Eq Show + deriving Eq Show Generic StudyTerms -- Studiengang key Int -- standardised key shorthand Text Maybe -- admin determined shorthand @@ -33,11 +34,12 @@ StudyTerms -- Studiengang defaultType StudyFieldType Maybe Primary key -- column key is used as actual DB row key -- newtype Key StudyTerms = StudyTermsKey' { unStudyTermsKey :: Int } - deriving Eq Ord Show + deriving Eq Ord Show Generic StudySubTerms child StudyTermsId parent StudyTermsId UniqueStudySubTerms child parent + deriving Generic StudyTermNameCandidate -- No one at LMU is willing and able to tell us the meaning of the keys for StudyDegrees and StudyTerms. -- Each LDAP login provides an unordered set of keys and an unordered set of plain text description with an unknown 1-1 correspondence. -- This table helps us to infer which key belongs to which plain text by recording possible combinations at login. @@ -45,14 +47,14 @@ StudyTermNameCandidate -- No one at LMU is willing and able to tell us the me incidence TermCandidateIncidence -- random id, generated once per login to associate matching pairs key Int -- a possible key for the studyTermName or studySubTermName name Text -- studyTermName as plain text from LDAP - deriving Show Eq Ord + deriving Show Eq Ord Generic StudySubTermParentCandidate incidence TermCandidateIncidence key Int parent Int - deriving Show Eq Ord + deriving Show Eq Ord Generic StudyTermStandaloneCandidate incidence TermCandidateIncidence key Int - deriving Show Eq Ord + deriving Show Eq Ord Generic diff --git a/models/submissions.model b/models/submissions.model index abfe0c6bd..9b9b500fb 100644 --- a/models/submissions.model +++ b/models/submissions.model @@ -10,7 +10,8 @@ SubmissionEdit -- user uploads new version of their submissio user UserId Maybe -- track id, important for group submissions time UTCTime submission SubmissionId -SubmissionFile -- files that are part of a submission + deriving Generic +SubmissionFile json -- files that are part of a submission submission SubmissionId title FilePath content FileContentReference Maybe @@ -18,17 +19,19 @@ SubmissionFile -- files that are part of a submission isUpdate Bool -- is this the file updated by a corrector (original will always be retained) isDeletion Bool -- only set if isUpdate is also set, but file was deleted by corrector UniqueSubmissionFile submission title isUpdate - deriving Show + deriving Eq Ord Read Show Generic SubmissionUser -- which submission belongs to whom user UserId submission SubmissionId UniqueSubmissionUser user submission -- multiple users may share same submission, in case of (ad-hoc) submission groups + deriving Generic SubmissionGroup -- pre-defined submission groups; some courses only allow pre-defined submission groups course CourseId name SubmissionGroupName UniqueSubmissionGroup course name + deriving Generic SubmissionGroupUser -- Registered submission groups, just for checking upon submission, but independent of actual SubmissionUser submissionGroup SubmissionGroupId user UserId UniqueSubmissionGroupUser submissionGroup user - deriving Eq Ord Show \ No newline at end of file + deriving Eq Ord Show Generic \ No newline at end of file diff --git a/models/system-messages.model b/models/system-messages.model index e8dfbd9ad..5ba6b3c53 100644 --- a/models/system-messages.model +++ b/models/system-messages.model @@ -6,13 +6,14 @@ SystemMessage newsOnly Bool default=false authenticatedOnly Bool -- Show message to all users upon visiting the site or only upon login? severity MessageStatus -- Success, Warning, Error, Info, ... - manualPriority Natural Maybe + manualPriority Word64 Maybe created UTCTime default=now() lastChanged UTCTime default=now() lastUnhide UTCTime default=now() defaultLanguage Lang -- Language of @content@ and @summary@ content StoredMarkup -- Detailed message shown when clicking on the @summary@-popup or when no @summary@ is specified summary StoredMarkup Maybe + deriving Generic SystemMessageTranslation -- Translation of a @SystemMessage@ into another language; which language to choose is determined by user-sent HTTP-headers message SystemMessageId @@ -20,9 +21,11 @@ SystemMessageTranslation -- Translation of a @SystemMessage@ into another langua content StoredMarkup summary StoredMarkup Maybe UniqueSystemMessageTranslation message language + deriving Generic SystemMessageHidden message SystemMessageId user UserId time UTCTime - UniqueSystemMessageHidden user message \ No newline at end of file + UniqueSystemMessageHidden user message + deriving Generic \ No newline at end of file diff --git a/models/tutorials.model b/models/tutorials.model index b5877360e..229312642 100644 --- a/models/tutorials.model +++ b/models/tutorials.model @@ -3,7 +3,8 @@ Tutorial json course CourseId type TutorialType -- "Tutorium", "Zentralübung", ... capacity Int Maybe -- limit for enrolment in this tutorial - room Text Maybe + room RoomReference Maybe + roomHidden Bool default=false time Occurrences regGroup (CI Text) Maybe -- each participant may register for one tutorial per regGroup registerFrom UTCTime Maybe @@ -17,13 +18,16 @@ Tutor tutorial TutorialId user UserId UniqueTutor tutorial user + deriving Generic TutorialParticipant tutorial TutorialId user UserId UniqueTutorialParticipant tutorial user deriving Eq Ord Show + deriving Generic TutorialScheduleOpt tutorial TutorialId user UserId opt Bool UniqueTutorialScheduleOpt tutorial user + deriving Generic diff --git a/models/users.model b/models/users.model index 502d9faeb..0ef2a9098 100644 --- a/models/users.model +++ b/models/users.model @@ -51,21 +51,25 @@ UserFunction -- Administratively assigned functions (lecturer, admin, evaluation school SchoolId function SchoolFunction UniqueUserFunction user school function + deriving Generic UserSystemFunction user UserId function SystemFunction manual Bool isOptOut Bool UniqueUserSystemFunction user function + deriving Generic UserExamOffice user UserId field StudyTermsId UniqueUserExamOffice user field + deriving Generic UserSchool -- Managed by users themselves, encodes "schools of interest" user UserId school SchoolId isOptOut Bool -- true if this a marker, that the user manually deleted this entry; it should not be recreated automatically UniqueUserSchool user school + deriving Generic UserGroupMember group UserGroupName @@ -74,4 +78,6 @@ UserGroupMember UniquePrimaryUserGroupMember group primary !force UniqueUserGroupMember group user + + deriving Generic diff --git a/models/workflows.model b/models/workflows.model new file mode 100644 index 000000000..d68a91cee --- /dev/null +++ b/models/workflows.model @@ -0,0 +1,53 @@ +SharedWorkflowGraph + hash WorkflowGraphReference + graph (WorkflowGraph FileReference SqlBackendKey) -- UserId + Primary hash + deriving Generic + +WorkflowDefinition + graph SharedWorkflowGraphId + scope WorkflowScope' + name WorkflowDefinitionName + instanceCategory WorkflowInstanceCategory Maybe + UniqueWorkflowDefinition name scope + deriving Generic + +WorkflowDefinitionDescription + definition WorkflowDefinitionId + language Lang + title Text + description StoredMarkup Maybe + UniqueWorkflowDefinitionDescription definition language + deriving Generic + +WorkflowDefinitionInstanceDescription + definition WorkflowDefinitionId + language Lang + title Text + description StoredMarkup Maybe + UniqueWorkflowDefinitionInstanceDescription definition language + deriving Generic + +WorkflowInstance + definition WorkflowDefinitionId Maybe + graph SharedWorkflowGraphId + scope (WorkflowScope TermIdentifier SchoolShorthand SqlBackendKey) -- TermId, SchoolId, CourseId + name WorkflowInstanceName + category WorkflowInstanceCategory Maybe + UniqueWorkflowInstance name scope + deriving Generic + +WorkflowInstanceDescription + instance WorkflowInstanceId + language Lang + title Text + description StoredMarkup Maybe + UniqueWorkflowInstanceDescription instance language + deriving Generic + +WorkflowWorkflow + instance WorkflowInstanceId Maybe + scope (WorkflowScope TermIdentifier SchoolShorthand SqlBackendKey) -- TermId, SchoolId, CourseId + graph SharedWorkflowGraphId + state (WorkflowState FileReference SqlBackendKey) -- UserId + deriving Generic diff --git a/package-lock.json b/package-lock.json index 36b02a12e..400589d5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { "name": "uni2work", - "version": "22.1.0", + "version": "25.10.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@babel/cli": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.10.5.tgz", - "integrity": "sha512-j9H9qSf3kLdM0Ao3aGPbGZ73mEA9XazuupcS6cDGWuiyAcANoguhP0r2Lx32H5JGw4sSSoHG3x/mxVnHgvOoyA==", + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.11.6.tgz", + "integrity": "sha512-+w7BZCvkewSmaRM6H4L2QM3RL90teqEIHDIFXAmrW33+0jhlymnDAEdqVeCZATvxhQuio1ifoGVlJJbIiH9Ffg==", "dev": true, "requires": { "chokidar": "^2.1.8", @@ -19,23 +19,15 @@ "make-dir": "^2.1.0", "slash": "^2.0.0", "source-map": "^0.5.0" - }, - "dependencies": { - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - } } }, "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", "dev": true, "requires": { - "@babel/highlight": "^7.0.0" + "@babel/highlight": "^7.10.4" } }, "@babel/compat-data": { @@ -49,36 +41,6 @@ "semver": "^5.5.0" }, "dependencies": { - "browserslist": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz", - "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001111", - "electron-to-chromium": "^1.3.523", - "escalade": "^3.0.2", - "node-releases": "^1.1.60" - } - }, - "caniuse-lite": { - "version": "1.0.30001117", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001117.tgz", - "integrity": "sha512-4tY0Fatzdx59kYjQs+bNxUwZB03ZEBgVmJ1UkFPz/Q8OLiUUbjct2EdpnXj0fvFTPej2EkbPIG0w8BWsjAyk1Q==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.544", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.544.tgz", - "integrity": "sha512-jx6H7M1db76Q/dI3MadZC4qwNTvpiq8tdYEJswxexrIm5bH+LKRdg+VAteMF1tJJbBLrcuogE9N3nxT3Dp1gag==", - "dev": true - }, - "node-releases": { - "version": "1.1.60", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", - "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", - "dev": true - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -88,19 +50,19 @@ } }, "@babel/core": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz", - "integrity": "sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==", + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", + "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.4", + "@babel/generator": "^7.11.6", "@babel/helper-module-transforms": "^7.11.0", "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.11.4", + "@babel/parser": "^7.11.5", "@babel/template": "^7.10.4", - "@babel/traverse": "^7.11.0", - "@babel/types": "^7.11.0", + "@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", @@ -111,22 +73,13 @@ "source-map": "^0.5.0" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/generator": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", - "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", "dev": true, "requires": { - "@babel/types": "^7.11.0", + "@babel/types": "^7.11.5", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -166,21 +119,10 @@ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/template": { @@ -195,26 +137,26 @@ } }, "@babel/traverse": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", - "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", + "@babel/generator": "^7.11.5", "@babel/helper-function-name": "^7.10.4", "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.0", - "@babel/types": "^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": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -232,12 +174,12 @@ } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -255,12 +197,12 @@ } }, "@babel/generator": { - "version": "7.9.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz", - "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==", + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.5.tgz", + "integrity": "sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==", "dev": true, "requires": { - "@babel/types": "^7.9.6", + "@babel/types": "^7.9.5", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" @@ -282,9 +224,9 @@ "dev": true }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -311,9 +253,9 @@ "dev": true }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -336,36 +278,6 @@ "semver": "^5.5.0" }, "dependencies": { - "browserslist": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz", - "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001111", - "electron-to-chromium": "^1.3.523", - "escalade": "^3.0.2", - "node-releases": "^1.1.60" - } - }, - "caniuse-lite": { - "version": "1.0.30001117", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001117.tgz", - "integrity": "sha512-4tY0Fatzdx59kYjQs+bNxUwZB03ZEBgVmJ1UkFPz/Q8OLiUUbjct2EdpnXj0fvFTPej2EkbPIG0w8BWsjAyk1Q==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.544", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.544.tgz", - "integrity": "sha512-jx6H7M1db76Q/dI3MadZC4qwNTvpiq8tdYEJswxexrIm5bH+LKRdg+VAteMF1tJJbBLrcuogE9N3nxT3Dp1gag==", - "dev": true - }, - "node-releases": { - "version": "1.1.60", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", - "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", - "dev": true - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -388,15 +300,6 @@ "@babel/helper-split-export-declaration": "^7.10.4" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/helper-function-name": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", @@ -432,21 +335,10 @@ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/template": { @@ -461,9 +353,9 @@ } }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -495,15 +387,6 @@ "lodash": "^4.17.19" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/helper-function-name": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", @@ -530,21 +413,10 @@ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/template": { @@ -559,9 +431,9 @@ } }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -587,9 +459,9 @@ "dev": true }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -635,9 +507,9 @@ "dev": true }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -663,9 +535,9 @@ "dev": true }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -691,9 +563,9 @@ "dev": true }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -718,15 +590,6 @@ "lodash": "^4.17.19" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/helper-split-export-declaration": { "version": "7.11.0", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", @@ -742,21 +605,10 @@ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/template": { @@ -771,9 +623,9 @@ } }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -799,9 +651,9 @@ "dev": true }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -838,36 +690,16 @@ "@babel/types": "^7.10.4" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/helper-validator-identifier": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/template": { @@ -882,9 +714,9 @@ } }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -906,22 +738,13 @@ "@babel/types": "^7.10.4" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/generator": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", - "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", "dev": true, "requires": { - "@babel/types": "^7.11.0", + "@babel/types": "^7.11.5", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -961,21 +784,10 @@ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/template": { @@ -990,26 +802,26 @@ } }, "@babel/traverse": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", - "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", + "@babel/generator": "^7.11.5", "@babel/helper-function-name": "^7.10.4", "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.0", - "@babel/types": "^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": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -1018,12 +830,12 @@ } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -1044,36 +856,16 @@ "@babel/types": "^7.10.4" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/helper-validator-identifier": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/template": { @@ -1088,9 +880,9 @@ } }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -1116,9 +908,9 @@ "dev": true }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -1155,22 +947,13 @@ "@babel/types": "^7.10.4" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/generator": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", - "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", "dev": true, "requires": { - "@babel/types": "^7.11.0", + "@babel/types": "^7.11.5", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -1210,21 +993,10 @@ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/template": { @@ -1239,26 +1011,26 @@ } }, "@babel/traverse": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", - "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", + "@babel/generator": "^7.11.5", "@babel/helper-function-name": "^7.10.4", "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.0", - "@babel/types": "^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": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -1267,12 +1039,12 @@ } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -1294,22 +1066,13 @@ "@babel/types": "^7.10.4" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/generator": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", - "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", "dev": true, "requires": { - "@babel/types": "^7.11.0", + "@babel/types": "^7.11.5", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -1349,21 +1112,10 @@ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/template": { @@ -1378,26 +1130,26 @@ } }, "@babel/traverse": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", - "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", + "@babel/generator": "^7.11.5", "@babel/helper-function-name": "^7.10.4", "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.0", - "@babel/types": "^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": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -1406,12 +1158,12 @@ } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -1423,20 +1175,28 @@ } }, "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "dev": true, "requires": { + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + } } }, "@babel/parser": { - "version": "7.9.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz", - "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==", + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", + "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -1754,15 +1514,6 @@ "globals": "^11.1.0" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/helper-function-name": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", @@ -1798,21 +1549,10 @@ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/template": { @@ -1827,9 +1567,9 @@ } }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -1905,15 +1645,6 @@ "@babel/helper-plugin-utils": "^7.10.4" }, "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, "@babel/helper-function-name": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", @@ -1940,21 +1671,10 @@ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/template": { @@ -1969,9 +1689,9 @@ } }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -2098,9 +1818,9 @@ "dev": true }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -2138,9 +1858,9 @@ } }, "@babel/plugin-transform-runtime": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.0.tgz", - "integrity": "sha512-LFEsP+t3wkYBlis8w6/kmnd6Kb1dxTd+wGJ8MlxTGzQo//ehtqlVL4S9DNUa53+dtPSQobN2CXx4d81FqC58cw==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.5.tgz", + "integrity": "sha512-9aIoee+EhjySZ6vY5hnLjigHzunBlscx9ANKutkeWTJTx6m5Rbq6Ic01tLvO54lSusR+BxV7u4UDdCmXv5aagg==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.10.4", @@ -2225,9 +1945,9 @@ } }, "@babel/preset-env": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.0.tgz", - "integrity": "sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.5.tgz", + "integrity": "sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==", "dev": true, "requires": { "@babel/compat-data": "^7.11.0", @@ -2292,7 +2012,7 @@ "@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.0", + "@babel/types": "^7.11.5", "browserslist": "^4.12.0", "core-js-compat": "^3.6.2", "invariant": "^2.2.2", @@ -2307,9 +2027,9 @@ "dev": true }, "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -2317,36 +2037,6 @@ "to-fast-properties": "^2.0.0" } }, - "browserslist": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz", - "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001111", - "electron-to-chromium": "^1.3.523", - "escalade": "^3.0.2", - "node-releases": "^1.1.60" - } - }, - "caniuse-lite": { - "version": "1.0.30001117", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001117.tgz", - "integrity": "sha512-4tY0Fatzdx59kYjQs+bNxUwZB03ZEBgVmJ1UkFPz/Q8OLiUUbjct2EdpnXj0fvFTPej2EkbPIG0w8BWsjAyk1Q==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.544", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.544.tgz", - "integrity": "sha512-jx6H7M1db76Q/dI3MadZC4qwNTvpiq8tdYEJswxexrIm5bH+LKRdg+VAteMF1tJJbBLrcuogE9N3nxT3Dp1gag==", - "dev": true - }, - "node-releases": { - "version": "1.1.60", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", - "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", - "dev": true - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -2356,9 +2046,9 @@ } }, "@babel/preset-modules": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz", - "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -2374,13 +2064,6 @@ "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", "requires": { "regenerator-runtime": "^0.13.4" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" - } } }, "@babel/template": { @@ -2417,17 +2100,17 @@ } }, "@babel/traverse": { - "version": "7.9.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz", - "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==", + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz", + "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==", "dev": true, "requires": { "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.6", + "@babel/generator": "^7.9.5", "@babel/helper-function-name": "^7.9.5", "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.9.6", - "@babel/types": "^7.9.6", + "@babel/parser": "^7.9.0", + "@babel/types": "^7.9.5", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" @@ -2454,12 +2137,12 @@ } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -2471,9 +2154,9 @@ } }, "@babel/types": { - "version": "7.9.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz", - "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==", + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", + "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.9.5", @@ -2501,12 +2184,6 @@ "yargs": "^15.1.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", @@ -2527,17 +2204,6 @@ "supports-color": "^7.1.0" } }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2553,150 +2219,20 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } }, @@ -2777,9 +2313,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -2867,65 +2403,16 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "cosmiconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", - "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "parse-json": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", - "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -2971,28 +2458,6 @@ "jsonfile": "^6.0.1", "universalify": "^1.0.0" } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "jsonfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", - "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^1.0.0" - } - }, - "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "dev": true } } }, @@ -3006,14 +2471,6 @@ "lodash": "^4.17.19", "resolve-from": "^5.0.0", "resolve-global": "^1.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } } }, "@commitlint/rules": { @@ -3079,12 +2536,6 @@ "requires": { "p-limit": "^3.0.2" } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true } } }, @@ -3157,12 +2608,20 @@ "dev": true, "requires": { "mkdirp": "^1.0.4" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } } }, "@samverschueren/stream-to-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", - "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", + "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", "dev": true, "requires": { "any-observable": "^0.3.0" @@ -3225,27 +2684,20 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true - }, "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", "dev": true, "requires": { - "@types/events": "*", "@types/minimatch": "*", "@types/node": "*" } }, "@types/json-schema": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", - "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", "dev": true }, "@types/minimatch": { @@ -3261,9 +2713,9 @@ "dev": true }, "@types/node": { - "version": "12.7.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz", - "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ==", + "version": "14.11.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.2.tgz", + "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==", "dev": true }, "@types/normalize-package-data": { @@ -3279,9 +2731,9 @@ "dev": true }, "@types/q": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", - "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", + "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", "dev": true }, "@types/source-list-map": { @@ -3291,15 +2743,15 @@ "dev": true }, "@types/tapable": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.4.tgz", - "integrity": "sha512-78AdXtlhpCHT0K3EytMpn4JNxaf5tbqbLcbIRoQIHzpTIyjpxLQKRoxU55ujBXAtg3Nl2h/XWvfDa9dsMOd0pQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", + "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", "dev": true }, "@types/uglify-js": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.0.4.tgz", - "integrity": "sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ==", + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.9.3.tgz", + "integrity": "sha512-KswB5C7Kwduwjj04Ykz+AjvPcfgv/37Za24O2EDzYNbwyzOo8+ydtvzUfZ5UMguiVu29Gx44l1A6VsPPcmYu9w==", "dev": true, "requires": { "source-map": "^0.6.1" @@ -3314,9 +2766,9 @@ } }, "@types/webpack": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.0.tgz", - "integrity": "sha512-tWkdf9nO0zFgAY/EumUKwrDUhraHKDqCPhwfFR/R8l0qnPdgb9le0Gzhvb7uzVpouuDGBgiE//ZdY+5jcZy2TA==", + "version": "4.41.22", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.22.tgz", + "integrity": "sha512-JQDJK6pj8OMV9gWOnN1dcLCyU9Hzs6lux0wBO4lr1+gyEhIBR9U3FMrz12t2GPkg110XAxEAw2WHF6g7nZIbRQ==", "dev": true, "requires": { "@types/anymatch": "*", @@ -3336,20 +2788,20 @@ } }, "@types/webpack-sources": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz", - "integrity": "sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-1.4.2.tgz", + "integrity": "sha512-77T++JyKow4BQB/m9O96n9d/UUHWLQHlcqXb9Vsf4F1+wKNrrlWNFPDLKNT92RJnCSL6CieTc+NDXtCVZswdTw==", "dev": true, "requires": { "@types/node": "*", "@types/source-list-map": "*", - "source-map": "^0.6.1" + "source-map": "^0.7.3" }, "dependencies": { "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", "dev": true } } @@ -3568,9 +3020,9 @@ "dev": true }, "acorn-jsx": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", - "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", "dev": true }, "add-stream": { @@ -3592,34 +3044,36 @@ "regex-parser": "2.2.10" }, "dependencies": { - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, - "requires": { - "util": "0.10.3" - } - }, "camelcase": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", "dev": true }, - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "inherits": "2.0.1" + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" } } } @@ -3647,23 +3101,15 @@ "requires": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" - }, - "dependencies": { - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - } } }, "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" @@ -3676,9 +3122,9 @@ "dev": true }, "ajv-keywords": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", - "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true }, "alphanum-sort": { @@ -3694,9 +3140,9 @@ "dev": true }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "ansi-styles": { @@ -3774,12 +3220,6 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, - "array-filter": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", - "dev": true - }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -3798,18 +3238,6 @@ "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", "dev": true }, - "array-map": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", - "dev": true - }, - "array-reduce": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", - "dev": true - }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -3873,30 +3301,12 @@ } }, "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", "dev": true, "requires": { - "object-assign": "^4.1.1", "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } } }, "assert-plus": { @@ -3912,10 +3322,13 @@ "dev": true }, "ast-types": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.2.tgz", - "integrity": "sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA==", - "dev": true + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", + "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", + "dev": true, + "requires": { + "tslib": "^2.0.1" + } }, "astral-regex": { "version": "1.0.0", @@ -3924,12 +3337,12 @@ "dev": true }, "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "^4.17.14" } }, "async-each": { @@ -3975,70 +3388,6 @@ "num2fraction": "^1.2.2", "postcss": "^7.0.32", "postcss-value-parser": "^4.1.0" - }, - "dependencies": { - "browserslist": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz", - "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001111", - "electron-to-chromium": "^1.3.523", - "escalade": "^3.0.2", - "node-releases": "^1.1.60" - } - }, - "caniuse-lite": { - "version": "1.0.30001117", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001117.tgz", - "integrity": "sha512-4tY0Fatzdx59kYjQs+bNxUwZB03ZEBgVmJ1UkFPz/Q8OLiUUbjct2EdpnXj0fvFTPej2EkbPIG0w8BWsjAyk1Q==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.544", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.544.tgz", - "integrity": "sha512-jx6H7M1db76Q/dI3MadZC4qwNTvpiq8tdYEJswxexrIm5bH+LKRdg+VAteMF1tJJbBLrcuogE9N3nxT3Dp1gag==", - "dev": true - }, - "node-releases": { - "version": "1.1.60", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", - "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", - "dev": true - }, - "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, "aws-sign2": { @@ -4048,9 +3397,9 @@ "dev": true }, "aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", "dev": true }, "axios": { @@ -4100,6 +3449,12 @@ "js-tokens": "^3.0.2" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -4125,6 +3480,15 @@ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "dev": true }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -4189,9 +3553,9 @@ }, "dependencies": { "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -4339,9 +3703,9 @@ }, "dependencies": { "ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -4404,9 +3768,9 @@ } }, "schema-utils": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz", - "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-5KXuwKziQrTVHh8j/Uxz+QUbxkaLW9X/86NBlx/gnKgtsZA2GIVMUn17qWhRFwF8jdYb3Dig5hRO/W5mZqy6SQ==", "dev": true, "requires": { "ajv": "^6.12.0", @@ -4813,25 +4177,10 @@ }, "dependencies": { "core-js": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", - "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", "dev": true - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } } } }, @@ -4846,9 +4195,15 @@ }, "dependencies": { "core-js": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", - "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true } } @@ -5082,9 +4437,9 @@ "dev": true }, "bluebird": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", - "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, "bn.js": { @@ -5094,21 +4449,21 @@ "dev": true }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", "dev": true, "requires": { - "bytes": "3.1.0", + "bytes": "3.0.0", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", + "depd": "~1.1.1", + "http-errors": "~1.6.2", + "iconv-lite": "0.4.19", "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "~1.6.15" } }, "boolbase": { @@ -5234,12 +4589,6 @@ "safe-buffer": "^5.2.0" }, "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -5269,14 +4618,15 @@ } }, "browserslist": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.2.tgz", - "integrity": "sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA==", + "version": "4.14.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.5.tgz", + "integrity": "sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001015", - "electron-to-chromium": "^1.3.322", - "node-releases": "^1.1.42" + "caniuse-lite": "^1.0.30001135", + "electron-to-chromium": "^1.3.571", + "escalade": "^3.1.0", + "node-releases": "^1.1.61" } }, "buffer": { @@ -5315,62 +4665,73 @@ "dev": true }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, "cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", + "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", "dev": true, "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", "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", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" + "rimraf": "^3.0.2", + "ssri": "^8.0.0", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" }, "dependencies": { "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "yallist": "^3.0.2" + "yallist": "^4.0.0" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "requires": { - "minimist": "^1.2.5" + "aggregate-error": "^3.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" } }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } @@ -5470,9 +4831,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001015", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001015.tgz", - "integrity": "sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ==", + "version": "1.0.30001137", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001137.tgz", + "integrity": "sha512-54xKQZTqZrKVHmVz0+UvdZR6kQc7pJDgfhsMYDG19ID1BWoNnDMFm5Q3uSBSU401pBvKYMsHAt9qhEDcxmk8aw==", "dev": true }, "caseless": { @@ -5501,84 +4862,84 @@ "yargs": "12.0.1" }, "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "ajv": "^5.1.0", - "har-schema": "^2.0.0" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" } }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "decamelize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", + "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", + "dev": true, + "requires": { + "xregexp": "4.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, - "log4js": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.3.tgz", - "integrity": "sha512-M08IQsdodHJGaNMgKb5YqSGiosrngoybVpm1F4Ff0UqcccnNRp92EayInmVawlbjEa9u9ZZVDT9rVNvdnOFiZQ==", - "dev": true, - "requires": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "streamroller": "0.7.0" - } - }, "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, "requires": { "minimist": "^1.2.5" } @@ -5586,25 +4947,21 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, "request": { @@ -5635,34 +4992,105 @@ "uuid": "^3.1.0" } }, - "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "punycode": "^1.4.1" + "ansi-regex": "^3.0.0" } }, - "ws": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.0.0.tgz", - "integrity": "sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==", + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { - "async-limiter": "~1.0.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "yargs": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.1.tgz", + "integrity": "sha512-B0vRAp1hRX4jgIOWFtjfNjd9OA9RWYZ6tqGA9/I/IrTMsxmKvtWy+ersM+jzpQqbC3YfLzeABPdeTgcJ9eu1qQ==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^2.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^10.1.0" + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" } } } @@ -5687,6 +5115,16 @@ "supports-color": "^5.3.0" } }, + "changelog-parser": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/changelog-parser/-/changelog-parser-2.8.0.tgz", + "integrity": "sha512-ZtSwN0hY7t+WpvaXqqXz98RHCNhWX9HsvCRAv1aBLlqJ7BpKtqdM6Nu6JOiUhRAWR7Gov0aN0fUnmflTz0WgZg==", + "dev": true, + "requires": { + "line-reader": "^0.2.4", + "remove-markdown": "^0.2.2" + } + }, "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -5717,24 +5155,6 @@ "lodash.some": "^4.4.0" }, "dependencies": { - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", - "dev": true - }, "dom-serializer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", @@ -5745,16 +5165,6 @@ "entities": "^1.1.1" } }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, "entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", @@ -5784,9 +5194,9 @@ } }, "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true }, "chrome-trace-event": { @@ -5796,6 +5206,14 @@ "dev": true, "requires": { "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + } } }, "ci-info": { @@ -5844,9 +5262,9 @@ } }, "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", "dev": true, "requires": { "source-map": "~0.6.0" @@ -5874,53 +5292,6 @@ "requires": { "@types/webpack": "^4.4.31", "del": "^4.1.1" - }, - "dependencies": { - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@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" - } - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } } }, "cli-color": { @@ -5937,14 +5308,11 @@ "timers-ext": "0.1" }, "dependencies": { - "d": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", - "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true } } }, @@ -5967,6 +5335,12 @@ "string-width": "^1.0.1" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -5992,88 +5366,33 @@ "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } } } }, "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", "dev": true }, "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - } + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, "clone-deep": { @@ -6107,15 +5426,6 @@ "memoizee": "0.3.x", "timers-ext": "0.1.x" } - }, - "d": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", - "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } } } }, @@ -6209,9 +5519,9 @@ } }, "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true }, "commondir": { @@ -6264,15 +5574,28 @@ "dev": true }, "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", "dev": true, "requires": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", - "readable-stream": "^2.2.2", + "readable-stream": "^3.0.2", "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "connect": { @@ -6285,6 +5608,29 @@ "finalhandler": "1.1.2", "parseurl": "~1.3.3", "utils-merge": "1.0.1" + }, + "dependencies": { + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + } } }, "console-browserify": { @@ -6312,22 +5658,45 @@ "dev": true }, "conventional-changelog": { - "version": "3.1.23", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.23.tgz", - "integrity": "sha512-sScUu2NHusjRC1dPc5p8/b3kT78OYr95/Bx7Vl8CPB8tF2mG1xei5iylDTRjONV5hTlzt+Cn/tBWrKdd299b7A==", + "version": "3.1.24", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.24.tgz", + "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", "dev": true, "requires": { - "conventional-changelog-angular": "^5.0.11", - "conventional-changelog-atom": "^2.0.7", - "conventional-changelog-codemirror": "^2.0.7", - "conventional-changelog-conventionalcommits": "^4.4.0", - "conventional-changelog-core": "^4.2.0", - "conventional-changelog-ember": "^2.0.8", - "conventional-changelog-eslint": "^3.0.8", - "conventional-changelog-express": "^2.0.5", - "conventional-changelog-jquery": "^3.0.10", - "conventional-changelog-jshint": "^2.0.8", + "conventional-changelog-angular": "^5.0.12", + "conventional-changelog-atom": "^2.0.8", + "conventional-changelog-codemirror": "^2.0.8", + "conventional-changelog-conventionalcommits": "^4.5.0", + "conventional-changelog-core": "^4.2.1", + "conventional-changelog-ember": "^2.0.9", + "conventional-changelog-eslint": "^3.0.9", + "conventional-changelog-express": "^2.0.6", + "conventional-changelog-jquery": "^3.0.11", + "conventional-changelog-jshint": "^2.0.9", "conventional-changelog-preset-loader": "^2.3.4" + }, + "dependencies": { + "conventional-changelog-angular": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.12.tgz", + "integrity": "sha512-5GLsbnkR/7A89RyHLvvoExbiGbd9xKdKqDTrArnPbOqBqG/2wIosu0fHwpeIRI8Tl94MhVNBXcLJZl92ZQ5USw==", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + } + }, + "conventional-changelog-conventionalcommits": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.5.0.tgz", + "integrity": "sha512-buge9xDvjjOxJlyxUnar/+6i/aVEVGA7EEh4OafBCXPlLUQPGbRUBhBUveWRxzvR8TEjhKEP4BdepnpG2FSZXw==", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + } + } } }, "conventional-changelog-angular": { @@ -6341,18 +5710,18 @@ } }, "conventional-changelog-atom": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.7.tgz", - "integrity": "sha512-7dOREZwzB+tCEMjRTDfen0OHwd7vPUdmU0llTy1eloZgtOP4iSLVzYIQqfmdRZEty+3w5Jz+AbhfTJKoKw1JeQ==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", + "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-codemirror": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.7.tgz", - "integrity": "sha512-Oralk1kiagn3Gb5cR5BffenWjVu59t/viE6UMD/mQa1hISMPkMYhJIqX+CMeA1zXgVBO+YHQhhokEj99GP5xcg==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", + "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", "dev": true, "requires": { "q": "^1.5.1" @@ -6376,104 +5745,74 @@ } }, "conventional-changelog-core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.0.tgz", - "integrity": "sha512-8+xMvN6JvdDtPbGBqA7oRNyZD4od1h/SIzrWqHcKZjitbVXrFpozEeyn4iI4af1UwdrabQpiZMaV07fPUTGd4w==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.2.tgz", + "integrity": "sha512-7pDpRUiobQDNkwHyJG7k9f6maPo9tfPzkSWbRq97GGiZqisElhnvUZSvyQH20ogfOjntB5aadvv6NNcKL1sReg==", "dev": true, "requires": { "add-stream": "^1.0.0", - "conventional-changelog-writer": "^4.0.17", - "conventional-commits-parser": "^3.1.0", + "conventional-changelog-writer": "^4.0.18", + "conventional-commits-parser": "^3.2.0", "dateformat": "^3.0.0", "get-pkg-repo": "^1.0.0", - "git-raw-commits": "2.0.0", + "git-raw-commits": "^2.0.8", "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^4.1.0", + "git-semver-tags": "^4.1.1", "lodash": "^4.17.15", - "normalize-package-data": "^2.3.5", + "normalize-package-data": "^3.0.0", "q": "^1.5.1", "read-pkg": "^3.0.0", "read-pkg-up": "^3.0.0", "shelljs": "^0.8.3", - "through2": "^3.0.0" + "through2": "^4.0.0" }, "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "camelcase-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", - "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "conventional-commits-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.0.tgz", + "integrity": "sha512-XmJiXPxsF0JhAKyfA2Nn+rZwYKJ60nanlbSWwwkGwLQFbugsc0gv1rzc7VbbUWAzJfR1qR87/pNgv9NgmxtBMQ==", "dev": true, "requires": { - "camelcase": "^4.1.0", - "map-obj": "^2.0.0", - "quick-lru": "^1.0.0" - } - }, - "dargs": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", - "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" + "JSONStream": "^1.0.4", + "is-text-path": "^1.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^2.0.0", + "through2": "^4.0.0", + "trim-off-newlines": "^1.0.0" } }, "git-raw-commits": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.0.tgz", - "integrity": "sha512-w4jFEJFgKXMQJ0H0ikBk2S+4KP2VEjhCvLCNqbNRQC8BgGWgLKNCO7a9K9LI+TVT7Gfoloje502sEnctibffgg==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.10.tgz", + "integrity": "sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==", "dev": true, "requires": { - "dargs": "^4.0.1", - "lodash.template": "^4.0.2", - "meow": "^4.0.0", - "split2": "^2.0.0", - "through2": "^2.0.0" + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" }, "dependencies": { - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "readable-stream": "^3.0.0" } } } }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "hosted-git-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "lru-cache": "^6.0.0" } }, "locate-path": { @@ -6486,37 +5825,109 @@ "path-exists": "^3.0.0" } }, - "map-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", - "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", - "dev": true - }, - "meow": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", - "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "camelcase-keys": "^4.0.0", - "decamelize-keys": "^1.0.0", - "loud-rejection": "^1.0.0", - "minimist": "^1.1.3", - "minimist-options": "^3.0.1", - "normalize-package-data": "^2.3.4", - "read-pkg-up": "^3.0.0", - "redent": "^2.0.0", - "trim-newlines": "^2.0.0" + "yallist": "^4.0.0" } }, - "minimist-options": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "normalize-package-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz", + "integrity": "sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==", + "dev": true, + "requires": { + "hosted-git-info": "^3.0.6", + "resolve": "^1.17.0", + "semver": "^7.3.2", + "validate-npm-package-license": "^3.0.1" } }, "p-limit": { @@ -6543,6 +5954,12 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", @@ -6558,12 +5975,6 @@ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, - "quick-lru": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", - "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", - "dev": true - }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -6573,6 +5984,32 @@ "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", "path-type": "^3.0.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "read-pkg-up": { @@ -6583,88 +6020,108 @@ "requires": { "find-up": "^2.0.0", "read-pkg": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + } } }, - "redent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", - "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { - "indent-string": "^3.0.0", - "strip-indent": "^2.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } }, "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" + "readable-stream": "3" } }, - "trim-newlines": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", - "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true } } }, "conventional-changelog-ember": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.8.tgz", - "integrity": "sha512-JEMEcUAMg4Q9yxD341OgWlESQ4gLqMWMXIWWUqoQU8yvTJlKnrvcui3wk9JvnZQyONwM2g1MKRZuAjKxr8hAXA==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", + "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-eslint": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.8.tgz", - "integrity": "sha512-5rTRltgWG7TpU1PqgKHMA/2ivjhrB+E+S7OCTvj0zM/QGg4vmnVH67Vq/EzvSNYtejhWC+OwzvDrLk3tqPry8A==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", + "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-express": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.5.tgz", - "integrity": "sha512-pW2hsjKG+xNx/Qjof8wYlAX/P61hT5gQ/2rZ2NsTpG+PgV7Rc8RCfITvC/zN9K8fj0QmV6dWmUefCteD9baEAw==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", + "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-jquery": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.10.tgz", - "integrity": "sha512-QCW6wF8QgPkq2ruPaxc83jZxoWQxLkt/pNxIDn/oYjMiVgrtqNdd7lWe3vsl0hw5ENHNf/ejXuzDHk6suKsRpg==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", + "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", "dev": true, "requires": { "q": "^1.5.1" } }, "conventional-changelog-jshint": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.8.tgz", - "integrity": "sha512-hB/iI0IiZwnZ+seYI+qEQ4b+EMQSEC8jGIvhO2Vpz1E5p8FgLz75OX8oB1xJWl+s4xBMB6f8zJr0tC/BL7YOjw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", + "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", "dev": true, "requires": { "compare-func": "^2.0.0", @@ -6678,45 +6135,127 @@ "dev": true }, "conventional-changelog-writer": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.17.tgz", - "integrity": "sha512-IKQuK3bib/n032KWaSb8YlBFds+aLmzENtnKtxJy3+HqDq5kohu3g/UdNbIHeJWygfnEbZjnCKFxAW0y7ArZAw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.1.0.tgz", + "integrity": "sha512-WwKcUp7WyXYGQmkLsX4QmU42AZ1lqlvRW9mqoyiQzdD+rJWbTepdWoKJuwXTS+yq79XKnQNa93/roViPQrAQgw==", "dev": true, "requires": { "compare-func": "^2.0.0", - "conventional-commits-filter": "^2.0.6", + "conventional-commits-filter": "^2.0.7", "dateformat": "^3.0.0", "handlebars": "^4.7.6", "json-stringify-safe": "^5.0.1", "lodash": "^4.17.15", - "meow": "^7.0.0", + "meow": "^8.0.0", "semver": "^6.0.0", "split": "^1.0.0", - "through2": "^3.0.0" + "through2": "^4.0.0" }, "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "hosted-git-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", "dev": true, "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" + "lru-cache": "^6.0.0" } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + } + }, + "normalize-package-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz", + "integrity": "sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==", + "dev": true, + "requires": { + "hosted-git-info": "^3.0.6", + "resolve": "^1.17.0", + "semver": "^7.3.2", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "requires": { + "readable-stream": "3" + } + }, + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true } } }, "conventional-commits-filter": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.6.tgz", - "integrity": "sha512-4g+sw8+KA50/Qwzfr0hL5k5NWxqtrOVw4DDk3/h6L85a9Gz0/Eqp3oP+CWCNfesBvZZZEFHF7OTEbRe+yYSyKw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", + "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", "dev": true, "requires": { "lodash.ismatch": "^4.4.0", @@ -6736,39 +6275,21 @@ "split2": "^2.0.0", "through2": "^3.0.0", "trim-off-newlines": "^1.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - } } }, "conventional-recommended-bump": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.0.10.tgz", - "integrity": "sha512-2ibrqAFMN3ZA369JgVoSbajdD/BHN6zjY7DZFKTHzyzuQejDUCjQ85S5KHxCRxNwsbDJhTPD5hOKcis/jQhRgg==", + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.0.11.tgz", + "integrity": "sha512-FciYBMwzwwBZ1K4NS8c57rsOfSc51e1V6UVSNIosrjH+A6xXkyiA4ELwoWyRKdMhJ+m3O6ru9ZJ7F2QFjjYJdQ==", "dev": true, "requires": { "concat-stream": "^2.0.0", "conventional-changelog-preset-loader": "^2.3.4", - "conventional-commits-filter": "^2.0.6", - "conventional-commits-parser": "^3.1.0", + "conventional-commits-filter": "^2.0.7", + "conventional-commits-parser": "^3.2.0", "git-raw-commits": "2.0.0", - "git-semver-tags": "^4.1.0", - "meow": "^7.0.0", + "git-semver-tags": "^4.1.1", + "meow": "^8.0.0", "q": "^1.5.1" }, "dependencies": { @@ -6778,27 +6299,19 @@ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, - "camelcase-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", - "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "conventional-commits-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.0.tgz", + "integrity": "sha512-XmJiXPxsF0JhAKyfA2Nn+rZwYKJ60nanlbSWwwkGwLQFbugsc0gv1rzc7VbbUWAzJfR1qR87/pNgv9NgmxtBMQ==", "dev": true, "requires": { - "camelcase": "^4.1.0", - "map-obj": "^2.0.0", - "quick-lru": "^1.0.0" - } - }, - "concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" + "JSONStream": "^1.0.4", + "is-text-path": "^1.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^2.0.0", + "through2": "^4.0.0", + "trim-off-newlines": "^1.0.0" } }, "dargs": { @@ -6832,6 +6345,23 @@ "through2": "^2.0.0" }, "dependencies": { + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, "meow": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", @@ -6848,21 +6378,103 @@ "redent": "^2.0.0", "trim-newlines": "^2.0.0" } + }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true } } }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "hosted-git-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "lru-cache": "^6.0.0" } }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -6873,20 +6485,50 @@ "path-exists": "^3.0.0" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "map-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", "dev": true }, - "minimist-options": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + } + }, + "normalize-package-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz", + "integrity": "sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==", + "dev": true, + "requires": { + "hosted-git-info": "^3.0.6", + "resolve": "^1.17.0", + "semver": "^7.3.2", + "validate-npm-package-license": "^3.0.1" } }, "p-limit": { @@ -6913,6 +6555,12 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", @@ -6943,16 +6591,32 @@ "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "readable-stream": { @@ -6966,32 +6630,46 @@ "util-deprecate": "^1.0.1" } }, - "redent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", - "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", "dev": true, "requires": { - "indent-string": "^3.0.0", - "strip-indent": "^2.0.0" + "lru-cache": "^6.0.0" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, "strip-indent": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", "dev": true }, - "trim-newlines": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", - "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "requires": { + "readable-stream": "3" + } + }, + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true } } @@ -7029,23 +6707,6 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - } } }, "copy-descriptor": { @@ -7055,100 +6716,30 @@ "dev": true }, "copy-webpack-plugin": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.0.3.tgz", - "integrity": "sha512-q5m6Vz4elsuyVEIUXr7wJdIdePWTubsqVbEMvf1WQnHGv0Q+9yPRu7MtYFPt+GBOXRav9lvIINifTQ1vSCs+eA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.1.1.tgz", + "integrity": "sha512-4TlkHFYkrZ3WppLA5XkPmBLI5lnEpFsXvpeqxCf5PzkratZiVklNXsvoQkLhUU43q7ZL3AOXtaHAd9jLNJoU0w==", "dev": true, "requires": { - "cacache": "^15.0.4", + "cacache": "^15.0.5", "fast-glob": "^3.2.4", "find-cache-dir": "^3.3.1", "glob-parent": "^5.1.1", "globby": "^11.0.1", "loader-utils": "^2.0.0", "normalize-path": "^3.0.0", - "p-limit": "^3.0.1", - "schema-utils": "^2.7.0", - "serialize-javascript": "^4.0.0", + "p-limit": "^3.0.2", + "schema-utils": "^2.7.1", + "serialize-javascript": "^5.0.1", "webpack-sources": "^1.4.3" }, "dependencies": { - "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true - }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, - "cacache": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", - "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", - "dev": true, - "requires": { - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.0", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, "find-cache-dir": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", @@ -7160,16 +6751,6 @@ "pkg-dir": "^4.1.0" } }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -7193,12 +6774,6 @@ "slash": "^3.0.0" } }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - }, "loader-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", @@ -7210,24 +6785,6 @@ "json5": "^2.1.2" } }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -7246,41 +6803,6 @@ "p-try": "^2.0.0" } }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - }, - "dependencies": { - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - } - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -7290,62 +6812,11 @@ "find-up": "^4.0.0" } }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - } - }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "ssri": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", - "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } } }, @@ -7364,36 +6835,6 @@ "semver": "7.0.0" }, "dependencies": { - "browserslist": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz", - "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001111", - "electron-to-chromium": "^1.3.523", - "escalade": "^3.0.2", - "node-releases": "^1.1.60" - } - }, - "caniuse-lite": { - "version": "1.0.30001117", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001117.tgz", - "integrity": "sha512-4tY0Fatzdx59kYjQs+bNxUwZB03ZEBgVmJ1UkFPz/Q8OLiUUbjct2EdpnXj0fvFTPej2EkbPIG0w8BWsjAyk1Q==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.544", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.544.tgz", - "integrity": "sha512-jx6H7M1db76Q/dI3MadZC4qwNTvpiq8tdYEJswxexrIm5bH+LKRdg+VAteMF1tJJbBLrcuogE9N3nxT3Dp1gag==", - "dev": true - }, - "node-releases": { - "version": "1.1.60", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", - "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", - "dev": true - }, "semver": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", @@ -7409,33 +6850,16 @@ "dev": true }, "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", "dev": true, "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - }, - "dependencies": { - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" } }, "cp-file": { @@ -7497,24 +6921,14 @@ } }, "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", + "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } } }, "cross-spawn-async": { @@ -7637,6 +7051,25 @@ "postcss-modules-values": "^2.0.0", "postcss-value-parser": "^3.3.0", "schema-utils": "^1.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "css-prefers-color-scheme": { @@ -7649,15 +7082,15 @@ } }, "css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "dev": true, "requires": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" } }, "css-select-base-adapter": { @@ -7684,17 +7117,16 @@ } } }, - "css-unit-converter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz", - "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=", + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", "dev": true }, - "css-what": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz", - "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==", - "dev": true + "css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=" }, "cssdb": { "version": "4.4.0", @@ -7718,6 +7150,46 @@ "cssnano-preset-default": "^4.0.7", "is-resolvable": "^1.0.0", "postcss": "^7.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } } }, "cssnano-preset-default": { @@ -7786,12 +7258,36 @@ "dev": true }, "csso": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.2.tgz", - "integrity": "sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", + "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==", "dev": true, "requires": { - "css-tree": "1.0.0-alpha.37" + "css-tree": "1.0.0-alpha.39" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.39", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", + "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", + "dev": true, + "requires": { + "mdn-data": "2.0.6", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", + "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "currently-unhandled": { @@ -7816,12 +7312,12 @@ "dev": true }, "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", "dev": true, "requires": { - "es5-ext": "^0.10.9" + "es5-ext": "~0.10.2" } }, "dargs": { @@ -7846,9 +7342,9 @@ "dev": true }, "date-format": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", - "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", "dev": true }, "dateformat": { @@ -7967,36 +7463,21 @@ "ast-types": "0.x.x", "escodegen": "1.x.x", "esprima": "3.x.x" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - } } }, "del": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", - "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", "dev": true, "requires": { + "@types/glob": "^7.1.1", "globby": "^6.1.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "p-map": "^1.1.1", - "pify": "^3.0.0", - "rimraf": "^2.2.8" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } + "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": { @@ -8074,29 +7555,12 @@ } }, "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "requires": { - "path-type": "^3.0.0" - }, - "dependencies": { - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } + "path-type": "^4.0.0" } }, "doctrine": { @@ -8140,9 +7604,9 @@ }, "dependencies": { "domelementtype": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", + "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", "dev": true } } @@ -8169,9 +7633,9 @@ } }, "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", "dev": true, "requires": { "dom-serializer": "0", @@ -8179,20 +7643,12 @@ } }, "dot-prop": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", - "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "requires": { "is-obj": "^2.0.0" - }, - "dependencies": { - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - } } }, "dotgitignore": { @@ -8203,6 +7659,42 @@ "requires": { "find-up": "^3.0.0", "minimatch": "^3.0.4" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } } }, "duplexify": { @@ -8234,9 +7726,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.322", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz", - "integrity": "sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA==", + "version": "1.3.572", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.572.tgz", + "integrity": "sha512-TKqdEukCCl7JC20SwEoWTbtnGt4YjfHWAv4tcNky0a9qGo0WdM+Lrd60tps+nkaJCmktKBJjr99fLtEBU1ipWQ==", "dev": true }, "elegant-spinner": { @@ -8269,15 +7761,15 @@ } }, "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true }, "encodeurl": { @@ -8287,9 +7779,9 @@ "dev": true }, "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "requires": { "once": "^1.4.0" @@ -8323,6 +7815,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true + }, + "ws": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "dev": true } } }, @@ -8414,9 +7912,9 @@ "dev": true }, "entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", - "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", "dev": true }, "errno": { @@ -8438,23 +7936,29 @@ } }, "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "version": "1.18.0-next.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", + "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", "dev": true, "requires": { - "es-to-primitive": "^1.2.0", + "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" } }, "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "requires": { "is-callable": "^1.1.4", @@ -8463,14 +7967,14 @@ } }, "es5-ext": { - "version": "0.10.50", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", - "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", "dev": true, "requires": { "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "^1.0.0" + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" } }, "es6-iterator": { @@ -8482,6 +7986,18 @@ "d": "1", "es5-ext": "^0.10.35", "es6-symbol": "^3.1.1" + }, + "dependencies": { + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + } } }, "es6-promise": { @@ -8500,13 +8016,25 @@ } }, "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14" + "d": "^1.0.1", + "ext": "^1.1.2" + }, + "dependencies": { + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + } } }, "es6-weak-map": { @@ -8521,15 +8049,6 @@ "es6-symbol": "~2.0.1" }, "dependencies": { - "d": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", - "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } - }, "es6-iterator": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", @@ -8554,9 +8073,9 @@ } }, "escalade": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", - "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz", + "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==", "dev": true }, "escape-html": { @@ -8572,12 +8091,12 @@ "dev": true }, "escodegen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.1.tgz", - "integrity": "sha512-Q8t2YZ+0e0pc7NRVj3B4tSQ9rim1oi4Fh46k2xhJ2qOiEwhQfdjyEQddWdj7ZFaKmU+5104vn1qrcjEPWq+bgQ==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", "dev": true, "requires": { - "esprima": "^3.1.3", + "esprima": "^4.0.1", "estraverse": "^4.2.0", "esutils": "^2.0.2", "optionator": "^0.8.1", @@ -8585,9 +8104,9 @@ }, "dependencies": { "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, "source-map": { @@ -8649,44 +8168,38 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "semver": { @@ -8717,18 +8230,18 @@ } }, "eslint-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", - "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.0.0" + "eslint-visitor-keys": "^1.1.0" } }, "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true }, "espree": { @@ -8743,39 +8256,55 @@ } }, "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", "dev": true }, "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } } }, "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "requires": { - "estraverse": "^4.1.0" + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } } }, "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, "etag": { @@ -8792,12 +8321,24 @@ "requires": { "d": "1", "es5-ext": "~0.10.14" + }, + "dependencies": { + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + } } }, "eventemitter3": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.5.tgz", - "integrity": "sha512-QR0rh0YiPuxuDQ6+T9GAO/xWTExXpxIes1Nl9RykNGTnE1HJmkuEfxJH9cubjIOQZ/GH4qNBR4u8VSHaKiWs4g==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, "events": { @@ -8817,13 +8358,13 @@ } }, "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", @@ -8913,123 +8454,27 @@ "vary": "~1.1.2" }, "dependencies": { - "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.1", - "http-errors": "~1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "~2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "~1.6.15" - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.4.0", - "unpipe": "~1.0.0" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "dev": true, - "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": ">= 1.3.1 < 2" - } - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true - } - } - }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + } + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", "dev": true } } @@ -9062,9 +8507,9 @@ } }, "external-editor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", - "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, "requires": { "chardet": "^0.7.0", @@ -9072,6 +8517,15 @@ "tmp": "^0.0.33" }, "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -9155,9 +8609,9 @@ "dev": true }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "fast-glob": { @@ -9217,12 +8671,6 @@ "picomatch": "^2.0.5" } }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -9235,9 +8683,9 @@ } }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, "fast-levenshtein": { @@ -9287,74 +8735,6 @@ "requires": { "loader-utils": "^1.4.0", "schema-utils": "^2.5.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", - "dev": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", - "dev": true - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "schema-utils": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz", - "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==", - "dev": true, - "requires": { - "ajv": "^6.12.0", - "ajv-keywords": "^3.4.1" - } - } } }, "file-uri-to-path": { @@ -9388,17 +8768,17 @@ } }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "dev": true, "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", "unpipe": "~1.0.0" } }, @@ -9414,12 +8794,13 @@ } }, "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "findup-sync": { @@ -9443,12 +8824,23 @@ "flatted": "^2.0.0", "rimraf": "2.6.3", "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "flatted": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, "flatten": { @@ -9553,10 +8945,19 @@ "universalify": "^0.1.0" }, "dependencies": { - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true } } @@ -9615,23 +9016,6 @@ "inherits": "~2.0.0", "mkdirp": ">=0.5 0", "rimraf": "2" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - } } }, "function-bind": { @@ -9664,15 +9048,15 @@ "dev": true }, "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-own-enumerable-property-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", - "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", "dev": true }, "get-pkg-repo": { @@ -9729,6 +9113,19 @@ "repeating": "^2.0.0" } }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", @@ -9753,6 +9150,15 @@ "trim-newlines": "^1.0.0" } }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", @@ -9810,6 +9216,15 @@ "strip-indent": "^1.0.1" } }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", @@ -9819,6 +9234,16 @@ "get-stdin": "^4.0.1" } }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", @@ -9828,19 +9253,16 @@ } }, "get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true }, "get-value": { "version": "2.0.6", @@ -9868,24 +9290,6 @@ "meow": "^7.0.0", "split2": "^2.0.0", "through2": "^3.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - } } }, "git-remote-origin-url": { @@ -9907,13 +9311,93 @@ } }, "git-semver-tags": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.0.tgz", - "integrity": "sha512-TcxAGeo03HdErzKzi4fDD+xEL7gi8r2Y5YSxH6N2XYdVSV5UkBwfrt7Gqo1b+uSHCjy/sa9Y6BBBxxFLxfbhTg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", + "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", "dev": true, "requires": { - "meow": "^7.0.0", + "meow": "^8.0.0", "semver": "^6.0.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + } + }, + "normalize-package-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz", + "integrity": "sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==", + "dev": true, + "requires": { + "hosted-git-info": "^3.0.6", + "resolve": "^1.17.0", + "semver": "^7.3.2", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + } } }, "gitconfiglocal": { @@ -10032,9 +9516,9 @@ } }, "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, "handlebars": { @@ -10065,13 +9549,39 @@ "dev": true }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "ajv": "^6.5.5", + "ajv": "^5.1.0", "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + } } }, "hard-rejection": { @@ -10096,6 +9606,14 @@ "dev": true, "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, "has-binary2": { @@ -10128,9 +9646,9 @@ "dev": true }, "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", "dev": true }, "has-value": { @@ -10176,12 +9694,6 @@ "safe-buffer": "^5.2.0" }, "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -10254,9 +9766,9 @@ } }, "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, "hsl-regex": { @@ -10345,6 +9857,12 @@ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", "dev": true }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", @@ -10392,9 +9910,9 @@ "dev": true }, "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -10405,16 +9923,23 @@ } }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "dev": true, "requires": { "depd": "~1.1.2", "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } }, "http-proxy": { @@ -10490,28 +10015,113 @@ "slash": "^3.0.0" }, "dependencies": { - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^2.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, "pkg-dir": { @@ -10532,9 +10142,45 @@ "locate-path": "^5.0.0", "path-exists": "^4.0.0" } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true } } }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -10544,13 +10190,10 @@ } }, "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true }, "icss-replace-symbols": { "version": "1.1.0", @@ -10559,9 +10202,9 @@ "dev": true }, "icss-utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.0.tgz", - "integrity": "sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", "dev": true, "requires": { "postcss": "^7.0.14" @@ -10580,9 +10223,9 @@ "dev": true }, "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "dev": true }, "import-cwd": { @@ -10595,13 +10238,21 @@ } }, "import-fresh": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", - "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } } }, "import-from": { @@ -10638,9 +10289,9 @@ "dev": true }, "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, "indexes-of": { @@ -10672,9 +10323,9 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "ini": { @@ -10684,9 +10335,9 @@ "dev": true }, "inquirer": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", - "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", "dev": true, "requires": { "ansi-escapes": "^3.2.0", @@ -10695,7 +10346,7 @@ "cli-width": "^2.0.0", "external-editor": "^3.0.3", "figures": "^2.0.0", - "lodash": "^4.17.11", + "lodash": "^4.17.12", "mute-stream": "0.0.7", "run-async": "^2.2.0", "rxjs": "^6.4.0", @@ -10705,11 +10356,38 @@ }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -10717,6 +10395,14 @@ "dev": true, "requires": { "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } } } } @@ -10749,9 +10435,9 @@ "dev": true }, "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true }, "is-absolute-url": { @@ -10802,9 +10488,9 @@ "dev": true }, "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", "dev": true }, "is-ci": { @@ -10851,9 +10537,9 @@ } }, "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true }, "is-descriptor": { @@ -10894,18 +10580,15 @@ "dev": true }, "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "is-glob": { @@ -10917,6 +10600,12 @@ "is-extglob": "^2.1.1" } }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -10938,9 +10627,9 @@ } }, "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true }, "is-observable": { @@ -10953,27 +10642,27 @@ } }, "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", "dev": true }, "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", "dev": true, "requires": { - "is-path-inside": "^1.0.0" + "is-path-inside": "^2.1.0" } }, "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", "dev": true, "requires": { - "path-is-inside": "^1.0.1" + "path-is-inside": "^1.0.2" } }, "is-plain-obj": { @@ -10992,18 +10681,18 @@ } }, "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", "dev": true }, "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "dev": true, "requires": { - "has": "^1.0.1" + "has-symbols": "^1.0.1" } }, "is-regexp": { @@ -11034,12 +10723,12 @@ } }, "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "dev": true, "requires": { - "has-symbols": "^1.0.0" + "has-symbols": "^1.0.1" } }, "is-text-path": { @@ -11128,9 +10817,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -11157,6 +10846,14 @@ "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } } }, "jsbn": { @@ -11178,9 +10875,9 @@ "dev": true }, "json-parse-even-better-errors": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.0.tgz", - "integrity": "sha512-o3aP+RsWDJZayj1SbHNQAI8x0v3T3SKiGoZlNYfbUP1S3omJQ6i9CnqADqkSPaOAxwua4/1YWx5CM7oiChJt2Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, "json-schema": { @@ -11214,31 +10911,18 @@ "dev": true, "requires": { "minimist": "^1.2.5" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - } } }, "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", + "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", "dev": true, "requires": { - "graceful-fs": "^4.1.6" + "graceful-fs": "^4.1.6", + "universalify": "^1.0.0" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -11258,24 +10942,23 @@ } }, "karma": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/karma/-/karma-5.1.1.tgz", - "integrity": "sha512-xAlOr5PMqUbiKXSv5PCniHWV3aiwj6wIZ0gUVcwpTCPVQm/qH2WAMFWxtnpM6KJqhkRWrIpovR4Rb0rn8GtJzQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/karma/-/karma-5.2.2.tgz", + "integrity": "sha512-rB3Ua5yDxmIupTj67r3Q8itz7TxJzRE6DmVcOfV20D509Uu9AoBKlVwbZhND4kcm6BqLfbHtv4DZC9QJfrUY+w==", "dev": true, "requires": { "body-parser": "^1.19.0", "braces": "^3.0.2", - "chokidar": "^3.0.0", + "chokidar": "^3.4.2", "colors": "^1.4.0", "connect": "^3.7.0", "di": "^0.0.1", "dom-serialize": "^2.2.1", - "flatted": "^2.0.2", "glob": "^7.1.6", "graceful-fs": "^4.2.4", "http-proxy": "^1.18.1", "isbinaryfile": "^4.0.6", - "lodash": "^4.17.15", + "lodash": "^4.17.19", "log4js": "^6.2.1", "mime": "^2.4.5", "minimatch": "^3.0.4", @@ -11289,22 +10972,6 @@ "yargs": "^15.3.1" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -11321,6 +10988,24 @@ "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "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" + } + }, "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -11330,6 +11015,12 @@ "fill-range": "^7.0.1" } }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, "chokidar": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", @@ -11346,36 +11037,10 @@ "readdirp": "~3.4.0" } }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "date-format": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", + "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", "dev": true }, "fill-range": { @@ -11387,22 +11052,6 @@ "to-regex-range": "^5.0.1" } }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, "fsevents": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", @@ -11410,12 +11059,6 @@ "dev": true, "optional": true }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -11425,10 +11068,32 @@ "is-glob": "^4.0.1" } }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "is-binary-path": { @@ -11440,25 +11105,34 @@ "binary-extensions": "^2.0.0" } }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "log4js": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", + "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "date-format": "^3.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.1", + "rfdc": "^1.1.4", + "streamroller": "^2.2.4" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } } }, "mime": { @@ -11467,21 +11141,30 @@ "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", "dev": true }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, "readdirp": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", @@ -11489,22 +11172,8 @@ "dev": true, "requires": { "picomatch": "^2.2.1" - }, - "dependencies": { - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - } } }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -11514,30 +11183,50 @@ "glob": "^7.1.3" } }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "streamroller": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", + "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "date-format": "^2.1.0", + "debug": "^4.1.1", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "date-format": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "dev": true + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } } }, "tmp": { @@ -11557,46 +11246,6 @@ "requires": { "is-number": "^7.0.0" } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } }, @@ -11726,6 +11375,12 @@ "type-check": "~0.3.2" } }, + "line-reader": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/line-reader/-/line-reader-0.2.4.tgz", + "integrity": "sha1-xDkrWH3qOFgMlnhXDm6OSfzlJiI=", + "dev": true + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -11764,6 +11419,37 @@ "yup": "^0.27.0" }, "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -11773,17 +11459,117 @@ "ms": "^2.1.1" } }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "^6.1.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", + "rimraf": "^2.2.8" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, @@ -11802,14 +11588,6 @@ "listr-verbose-renderer": "^0.5.0", "p-map": "^2.0.0", "rxjs": "^6.3.3" - }, - "dependencies": { - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } } }, "listr-silent-renderer": { @@ -11834,6 +11612,12 @@ "strip-ansi": "^3.0.1" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -11863,6 +11647,12 @@ "object-assign": "^4.1.0" } }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, "log-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", @@ -11872,6 +11662,15 @@ "chalk": "^1.0.0" } }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -11893,31 +11692,31 @@ } }, "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, "dependencies": { "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "^1.2.0" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true } } @@ -11929,13 +11728,13 @@ "dev": true }, "loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", "dev": true, "requires": { "big.js": "^5.2.2", - "emojis-list": "^2.0.0", + "emojis-list": "^3.0.0", "json5": "^1.0.1" }, "dependencies": { @@ -11947,23 +11746,16 @@ "requires": { "minimist": "^1.2.0" } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true } } }, "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^4.1.0" } }, "lodash": { @@ -12083,12 +11875,12 @@ } }, "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", "dev": true, "requires": { - "lodash._reinterpolate": "~3.0.0" + "lodash._reinterpolate": "^3.0.0" } }, "lodash.throttle": { @@ -12120,36 +11912,72 @@ "ansi-escapes": "^3.0.0", "cli-cursor": "^2.0.0", "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + } } }, "log4js": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", - "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.3.tgz", + "integrity": "sha512-M08IQsdodHJGaNMgKb5YqSGiosrngoybVpm1F4Ff0UqcccnNRp92EayInmVawlbjEa9u9ZZVDT9rVNvdnOFiZQ==", "dev": true, "requires": { - "date-format": "^3.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.2.4" + "circular-json": "^0.5.5", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "streamroller": "0.7.0" }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { "ms": "^2.1.1" } }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -12319,6 +12147,15 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, "memoizee": { "version": "0.3.10", "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.10.tgz", @@ -12334,15 +12171,6 @@ "timers-ext": "0.1" }, "dependencies": { - "d": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", - "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } - }, "next-tick": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", @@ -12368,9 +12196,9 @@ "dev": true }, "meow": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.0.tgz", - "integrity": "sha512-kq5F0KVteskZ3JdfyQFivJEj2RaA8NFsS4+r9DaMKLcUHpk5OcHS3Q0XkCXONB1mZRPsu/Y/qImKri0nwSEZog==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.1.tgz", + "integrity": "sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==", "dev": true, "requires": { "@types/minimist": "^1.2.0", @@ -12384,24 +12212,6 @@ "trim-newlines": "^3.0.0", "type-fest": "^0.13.1", "yargs-parser": "^18.1.3" - }, - "dependencies": { - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } } }, "merge-descriptors": { @@ -12480,24 +12290,24 @@ } }, "mime": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.3.tgz", - "integrity": "sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", "dev": true }, "mime-db": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", - "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", "dev": true }, "mime-types": { - "version": "2.1.25", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", - "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", "dev": true, "requires": { - "mime-db": "1.42.0" + "mime-db": "1.44.0" } }, "mimic-fn": { @@ -12522,6 +12332,19 @@ "normalize-url": "1.9.1", "schema-utils": "^1.0.0", "webpack-sources": "^1.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "minimalistic-assert": { @@ -12640,6 +12463,30 @@ "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } } }, "mixin-deep": { @@ -12664,10 +12511,13 @@ } }, "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } }, "modify-values": { "version": "1.0.1", @@ -12676,9 +12526,9 @@ "dev": true }, "moment": { - "version": "2.27.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", - "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz", + "integrity": "sha512-z6IJ5HXYiuxvFTI6eiQ9dm77uE0gyy1yXNApVHqTcnIKfY9tIwEjlzsZ6u1LQXvVgKeTnv9Xm7NDvJ7lso3MtA==" }, "mount-point": { "version": "3.0.0", @@ -12717,23 +12567,6 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.3" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - } } }, "move-file": { @@ -12755,6 +12588,12 @@ "requires": { "semver": "^6.0.0" } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true } } }, @@ -12814,9 +12653,9 @@ "dev": true }, "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, "nested-error-stacks": { @@ -12883,30 +12722,34 @@ "vm-browserify": "^1.0.1" }, "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } } } }, "node-releases": { - "version": "1.1.42", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.42.tgz", - "integrity": "sha512-OQ/ESmUqGawI2PRX+XIRao44qWYBBfN54ImQYdWVTQqUckuejOg76ysSqDBK8NG3zwySRVnX36JwDQ6x+9GxzA==", - "dev": true, - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } + "version": "1.1.61", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", + "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==", + "dev": true }, "node-unzip-2": { "version": "0.2.8", @@ -16101,16 +15944,17 @@ "string.prototype.padend": "^3.0.0" }, "dependencies": { - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, "path-type": { @@ -16139,10 +15983,10 @@ "path-type": "^3.0.0" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true } } @@ -16165,6 +16009,14 @@ "commander": "^2.9.0", "npm-path": "^2.0.2", "which": "^1.2.10" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } } }, "nth-check": { @@ -16190,6 +16042,19 @@ "requires": { "loader-utils": "^1.2.3", "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "num2fraction": { @@ -16205,9 +16070,9 @@ "dev": true }, "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", "dev": true }, "object-assign": { @@ -16254,9 +16119,9 @@ } }, "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", "dev": true }, "object-keys": { @@ -16281,27 +16146,47 @@ } }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", - "function-bind": "^1.1.1", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", + "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "object.getownpropertydescriptors": { @@ -16315,40 +16200,23 @@ }, "dependencies": { "es-abstract": { - "version": "1.17.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz", - "integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==", + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", "object-inspect": "^1.7.0", "object-keys": "^1.1.1", "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.0", - "string.prototype.trimright": "^2.1.0" + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true } } }, @@ -16374,40 +16242,23 @@ }, "dependencies": { "es-abstract": { - "version": "1.17.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0-next.1.tgz", - "integrity": "sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==", + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", "object-inspect": "^1.7.0", "object-keys": "^1.1.1", "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.0", - "string.prototype.trimright": "^2.1.0" + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true } } }, @@ -16439,9 +16290,9 @@ } }, "optimize-css-assets-webpack-plugin": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz", - "integrity": "sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz", + "integrity": "sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A==", "dev": true, "requires": { "cssnano": "^4.1.10", @@ -16449,17 +16300,17 @@ } }, "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", + "fast-levenshtein": "~2.0.6", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "word-wrap": "~1.2.3" } }, "os-browserify": { @@ -16483,49 +16334,6 @@ "execa": "^0.7.0", "lcid": "^1.0.0", "mem": "^1.1.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - } } }, "os-tmpdir": { @@ -16535,9 +16343,9 @@ "dev": true }, "outdent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.7.0.tgz", - "integrity": "sha512-Ue462G+UIFoyQmOzapGIKWS3d/9NHeD/018WGEDZIhN2/VaQpVXbofMcZX0socv1fw4/tmEn7Vd3McOdPZfKzQ==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.7.1.tgz", + "integrity": "sha512-VjIzdUHunL74DdhcwMDt5FhNDQ8NYmTkuW0B+usIV2afS9aWT/1c9z1TsnFW349TP3nxmYeUl7Z++XpJRByvgg==", "dev": true }, "over": { @@ -16553,27 +16361,27 @@ "dev": true }, "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" } }, "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "p-limit": "^2.2.0" } }, "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true }, "p-try": { @@ -16637,13 +16445,15 @@ "dev": true }, "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", "dev": true, "requires": { + "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" } }, "parse-passwd": { @@ -16695,9 +16505,9 @@ "dev": true }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "path-is-absolute": { @@ -16756,15 +16566,15 @@ "dev": true }, "picomatch": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", - "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, "pidtree": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", - "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "dev": true }, "pify": { @@ -16795,12 +16605,48 @@ "dev": true, "requires": { "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } } }, "please-upgrade-node": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz", - "integrity": "sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", "dev": true, "requires": { "semver-compare": "^1.0.0" @@ -16813,9 +16659,9 @@ "dev": true }, "postcss": { - "version": "7.0.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.16.tgz", - "integrity": "sha512-MOo8zNSlIqh22Uaa3drkdIAgUGEL+AD1ESiSdmElLUmE2uVDo1QloiT/IfW9qRw8Gw+Y/w69UVMGwbufMSftxA==", + "version": "7.0.34", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.34.tgz", + "integrity": "sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -16841,63 +16687,24 @@ } }, "postcss-attribute-case-insensitive": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.1.tgz", - "integrity": "sha512-L2YKB3vF4PetdTIthQVeT+7YiSzMoNMLLYxPXXppOOP7NoazEAy45sh2LvJ8leCQjfBcfkYQs8TtCcQjeZTp8A==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz", + "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==", "dev": true, "requires": { "postcss": "^7.0.2", - "postcss-selector-parser": "^5.0.0" - }, - "dependencies": { - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", - "dev": true - }, - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "dev": true, - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } + "postcss-selector-parser": "^6.0.2" } }, "postcss-calc": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.1.tgz", - "integrity": "sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.4.tgz", + "integrity": "sha512-0I79VRAd1UTkaHzY9w83P39YGO/M3bG7/tNLrHGEunBolfoGM0hSjrGvjoeaj0JE/zIw5GsI2KZ0UwDJqv5hjw==", "dev": true, "requires": { - "css-unit-converter": "^1.1.1", - "postcss": "^7.0.5", - "postcss-selector-parser": "^5.0.0-rc.4", - "postcss-value-parser": "^3.3.1" - }, - "dependencies": { - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", - "dev": true - }, - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "dev": true, - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - } + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" } }, "postcss-color-functional-notation": { @@ -16963,6 +16770,14 @@ "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-convert-values": { @@ -16973,6 +16788,14 @@ "requires": { "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-custom-media": { @@ -16992,34 +16815,6 @@ "requires": { "postcss": "^7.0.17", "postcss-values-parser": "^2.0.1" - }, - "dependencies": { - "postcss": { - "version": "7.0.25", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.25.tgz", - "integrity": "sha512-NXXVvWq9icrm/TgQC0O6YVFi4StfJz46M1iNd/h6B26Nvh/HKI+q4YZtFN/EjcInZliEscO/WL10BXnc1E5nwg==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, "postcss-custom-selectors": { @@ -17190,18 +16985,6 @@ "requires": { "lodash.template": "^4.5.0", "postcss": "^7.0.2" - }, - "dependencies": { - "lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - } } }, "postcss-lab-function": { @@ -17216,13 +16999,53 @@ } }, "postcss-load-config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", - "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.1.tgz", + "integrity": "sha512-D2ENobdoZsW0+BHy4x1CAkXtbXtYWYRIxL/JbtRBqrRGOPtJ2zoga/bEZWhV/ShWB5saVxJMzbMdSyA/vv4tXw==", "dev": true, "requires": { "cosmiconfig": "^5.0.0", "import-cwd": "^2.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } } }, "postcss-loader": { @@ -17235,6 +17058,19 @@ "postcss": "^7.0.0", "postcss-load-config": "^2.0.0", "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "postcss-logical": { @@ -17265,6 +17101,14 @@ "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", "stylehacks": "^4.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-merge-rules": { @@ -17281,22 +17125,13 @@ "vendors": "^1.0.0" }, "dependencies": { - "dot-prop": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", - "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, "postcss-selector-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", - "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", "dev": true, "requires": { - "dot-prop": "^4.1.1", + "dot-prop": "^5.2.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } @@ -17311,6 +17146,14 @@ "requires": { "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-minify-gradients": { @@ -17323,6 +17166,14 @@ "is-color-stop": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-minify-params": { @@ -17337,6 +17188,14 @@ "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", "uniqs": "^2.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-minify-selectors": { @@ -17351,22 +17210,13 @@ "postcss-selector-parser": "^3.0.0" }, "dependencies": { - "dot-prop": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", - "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, "postcss-selector-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", - "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", "dev": true, "requires": { - "dot-prop": "^4.1.1", + "dot-prop": "^5.2.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } @@ -17391,12 +17241,20 @@ "postcss": "^7.0.6", "postcss-selector-parser": "^6.0.0", "postcss-value-parser": "^3.3.1" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-modules-scope": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", - "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", "dev": true, "requires": { "postcss": "^7.0.6", @@ -17440,6 +17298,14 @@ "cssnano-util-get-match": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-normalize-positions": { @@ -17452,6 +17318,14 @@ "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-normalize-repeat-style": { @@ -17464,6 +17338,14 @@ "cssnano-util-get-match": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-normalize-string": { @@ -17475,6 +17357,14 @@ "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-normalize-timing-functions": { @@ -17486,6 +17376,14 @@ "cssnano-util-get-match": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-normalize-unicode": { @@ -17497,6 +17395,14 @@ "browserslist": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-normalize-url": { @@ -17516,6 +17422,12 @@ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", "dev": true + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true } } }, @@ -17527,6 +17439,14 @@ "requires": { "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-ordered-values": { @@ -17538,6 +17458,14 @@ "cssnano-util-get-arguments": "^4.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-overflow-shorthand": { @@ -17611,34 +17539,6 @@ "postcss-replace-overflow-wrap": "^3.0.0", "postcss-selector-matches": "^4.0.0", "postcss-selector-not": "^4.0.0" - }, - "dependencies": { - "postcss": { - "version": "7.0.25", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.25.tgz", - "integrity": "sha512-NXXVvWq9icrm/TgQC0O6YVFi4StfJz46M1iNd/h6B26Nvh/HKI+q4YZtFN/EjcInZliEscO/WL10BXnc1E5nwg==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, "postcss-pseudo-class-any-link": { @@ -17692,6 +17592,14 @@ "has": "^1.0.0", "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-replace-overflow-wrap": { @@ -17724,14 +17632,15 @@ } }, "postcss-selector-parser": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", - "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.3.tgz", + "integrity": "sha512-0ClFaY4X1ra21LRqbW6y3rUbWcxnSVkDFG57R7Nxus9J9myPFlv+jYDMohzpkBx0RrjjiqjtycpchQ+PLGmZ9w==", "dev": true, "requires": { "cssesc": "^3.0.0", "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "uniq": "^1.0.1", + "util-deprecate": "^1.0.2" } }, "postcss-svgo": { @@ -17744,6 +17653,14 @@ "postcss": "^7.0.0", "postcss-value-parser": "^3.0.0", "svgo": "^1.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, "postcss-unique-selectors": { @@ -17758,9 +17675,9 @@ } }, "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", "dev": true }, "postcss-values-parser": { @@ -17809,9 +17726,9 @@ "dev": true }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, "progress": { @@ -17833,13 +17750,13 @@ "dev": true }, "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", "dev": true, "requires": { "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" + "ipaddr.js": "1.9.1" } }, "prr": { @@ -17855,9 +17772,9 @@ "dev": true }, "psl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", - "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, "public-encrypt": { @@ -17972,9 +17889,9 @@ "dev": true }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", "dev": true }, "query-string": { @@ -18031,15 +17948,47 @@ "dev": true }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", "dev": true, "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": ">= 1.3.1 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + } } }, "read-pkg": { @@ -18054,17 +18003,11 @@ "type-fest": "^0.6.0" }, "dependencies": { - "parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", - "lines-and-columns": "^1.1.6" - } + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true } } }, @@ -18079,40 +18022,6 @@ "type-fest": "^0.8.1" }, "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -18122,9 +18031,9 @@ } }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -18173,20 +18082,12 @@ "requires": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" - }, - "dependencies": { - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - } } }, "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", + "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", "dev": true }, "regenerate-unicode-properties": { @@ -18199,10 +18100,9 @@ } }, "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, "regenerator-transform": { "version": "0.14.5", @@ -18236,9 +18136,9 @@ "dev": true }, "regexpu-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", - "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", "dev": true, "requires": { "regenerate": "^1.4.0", @@ -18279,37 +18179,21 @@ "dev": true }, "remove-files-webpack-plugin": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/remove-files-webpack-plugin/-/remove-files-webpack-plugin-1.4.3.tgz", - "integrity": "sha512-NOqO5gB4uMeflnnKmouTcRWHPKCI2a3Ft44vQ7Os7avn/N3pK/TEPyCtja3W2A82BlWELXbueRUwPNhc+qNnag==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/remove-files-webpack-plugin/-/remove-files-webpack-plugin-1.4.4.tgz", + "integrity": "sha512-vCtIPQRA9Sf6yn90qepj0A8zEMZK4oHxGH+rTG74ELPprDbhJ9Phe74fj9FM6Jc5I11Q5Ah6EogqJDzSqJ6mEA==", "dev": true, "requires": { - "@types/webpack": "4.41.12", + "@types/webpack": "4.41.22", "trash": "6.1.1" - }, - "dependencies": { - "@types/webpack": { - "version": "4.41.12", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.12.tgz", - "integrity": "sha512-BpCtM4NnBen6W+KEhrL9jKuZCXVtiH6+0b6cxdvNt2EwU949Al334PjQSl2BeAyvAX9mgoNNG21wvjP3xZJJ5w==", - "dev": true, - "requires": { - "@types/anymatch": "*", - "@types/node": "*", - "@types/tapable": "*", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "source-map": "^0.6.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, + "remove-markdown": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/remove-markdown/-/remove-markdown-0.2.2.tgz", + "integrity": "sha1-ZrDO66n7d8qWNrsbAwfOIaMqEqY=", + "dev": true + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -18329,32 +18213,19 @@ "utila": "^0.4.0" }, "dependencies": { - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "ansi-regex": "^2.0.0" } } } @@ -18408,6 +18279,22 @@ "uuid": "^3.3.2" }, "dependencies": { + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", @@ -18454,9 +18341,9 @@ "dev": true }, "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "requires-port": { @@ -18466,9 +18353,9 @@ "dev": true }, "resolve": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", - "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -18515,9 +18402,9 @@ } }, "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, "resolve-global": { @@ -18562,6 +18449,32 @@ "safe-buffer": "~5.1.1" } }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, "postcss": { "version": "7.0.21", "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", @@ -18653,23 +18566,6 @@ "metaparser": "^1.0.7", "mkdirp": "^0.5.0", "node-unzip-2": "^0.2.7" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - } } }, "rgb-regex": { @@ -18685,9 +18581,9 @@ "dev": true }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { "glob": "^7.1.3" @@ -18704,13 +18600,10 @@ } }, "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true }, "run-node": { "version": "1.0.0", @@ -18734,12 +18627,20 @@ } }, "rxjs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", - "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", "dev": true, "requires": { "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + } } }, "safe-buffer": { @@ -18764,9 +18665,9 @@ "dev": true }, "sass": { - "version": "1.26.10", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.10.tgz", - "integrity": "sha512-bzN0uvmzfsTvjz0qwccN1sPm2HxxpNI/Xa+7PlUEMS+nQvbyuEK7Y0qFqxlPHhiNHb1Ze8WQJtU31olMObkAMw==", + "version": "1.26.11", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.11.tgz", + "integrity": "sha512-W1l/+vjGjIamsJ6OnTe0K37U2DBO/dgsv2Z4c89XQ8ZOO6l/VwkqwLSqoYzJeJs6CLuGSTRWc91GbQFL3lvrvw==", "dev": true, "requires": { "chokidar": ">=2.0.0 <4.0.0" @@ -18783,14 +18684,6 @@ "neo-async": "^2.5.0", "pify": "^4.0.1", "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } } }, "sax": { @@ -18800,14 +18693,14 @@ "dev": true }, "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" } }, "semver": { @@ -18841,44 +18734,12 @@ "on-finished": "~2.3.0", "range-parser": "~1.2.0", "statuses": "~1.4.0" - }, - "dependencies": { - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - } } }, "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -18897,26 +18758,6 @@ "http-errors": "~1.6.2", "mime-types": "~2.1.17", "parseurl": "~1.3.2" - }, - "dependencies": { - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - } } }, "serve-static": { @@ -18967,9 +18808,9 @@ "dev": true }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true }, "sha.js": { @@ -19007,16 +18848,10 @@ "dev": true }, "shell-quote": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true, - "requires": { - "array-filter": "~0.0.0", - "array-map": "~0.0.0", - "array-reduce": "~0.0.0", - "jsonify": "~0.0.0" - } + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "dev": true }, "shelljs": { "version": "0.8.4", @@ -19030,27 +18865,27 @@ } }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, "simple-git": { - "version": "1.115.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.115.0.tgz", - "integrity": "sha512-PXcDVDgXifUE7/M2xUfQQ8uG3r73+kYRyPmsbc/iWwUrPbOASHt8p+HEbu85k546qmXixbcSPDg83kegw1vqcA==", + "version": "1.132.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.132.0.tgz", + "integrity": "sha512-xauHm1YqCTom1sC9eOjfq3/9RKiUA9iPnxBbrY2DdL8l4ADMu0jjM5l5lphQP5YWNqAL2aXC/OeuQ76vHtW5fg==", "dev": true, "requires": { "debug": "^4.0.1" }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "ms": { @@ -19101,6 +18936,14 @@ "ansi-styles": "^3.2.0", "astral-regex": "^1.0.0", "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } } }, "slice-stream": { @@ -19434,12 +19277,12 @@ "dev": true }, "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "dev": true, "requires": { - "atob": "^2.1.1", + "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", @@ -19462,9 +19305,9 @@ "dev": true }, "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -19472,15 +19315,15 @@ } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -19488,9 +19331,9 @@ } }, "spdx-license-ids": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", - "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", "dev": true }, "split": { @@ -19518,6 +19361,18 @@ "dev": true, "requires": { "through2": "^2.0.2" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } } }, "sprintf-js": { @@ -19544,12 +19399,12 @@ } }, "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", + "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", "dev": true, "requires": { - "figgy-pudding": "^3.5.1" + "minipass": "^3.1.1" } }, "stable": { @@ -19565,21 +19420,21 @@ "dev": true }, "standard-version": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.0.0.tgz", - "integrity": "sha512-eRR04IscMP3xW9MJTykwz13HFNYs8jS33AGuDiBKgfo5YrO0qX0Nxb4rjupVwT5HDYL/aR+MBEVLjlmVFmFEDQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.1.0.tgz", + "integrity": "sha512-EJcbKUGKBuHjiDSUL5XjPhT1KGVM+UCvv/ti70fHnJwJyJqTSJWl0mWj/Wj0WwsoskyvKWURESzBsZmCCMUZzg==", "dev": true, "requires": { "chalk": "^2.4.2", - "conventional-changelog": "3.1.23", + "conventional-changelog": "3.1.24", "conventional-changelog-config-spec": "2.1.0", - "conventional-changelog-conventionalcommits": "4.4.0", - "conventional-recommended-bump": "6.0.10", + "conventional-changelog-conventionalcommits": "4.5.0", + "conventional-recommended-bump": "6.0.11", "detect-indent": "^6.0.0", "detect-newline": "^3.1.0", "dotgitignore": "^2.1.0", "figures": "^3.1.0", - "find-up": "^4.1.0", + "find-up": "^5.0.0", "fs-access": "^1.0.1", "git-semver-tags": "^4.0.0", "semver": "^7.1.1", @@ -19587,60 +19442,23 @@ "yargs": "^15.3.1" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "conventional-changelog-conventionalcommits": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.5.0.tgz", + "integrity": "sha512-buge9xDvjjOxJlyxUnar/+6i/aVEVGA7EEh4OafBCXPlLUQPGbRUBhBUveWRxzvR8TEjhKEP4BdepnpG2FSZXw==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" } }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "detect-indent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==", "dev": true }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -19651,125 +19469,77 @@ } }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } }, + "standard-version-updater-yaml": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/standard-version-updater-yaml/-/standard-version-updater-yaml-1.0.2.tgz", + "integrity": "sha512-hTaNAnsQ7HznYbt489qVPYs4lvZ5q6pVwZJ7kmPMhYmvNzq7hZnQoImTYvEB9hgkx/moBJkqF38Dp82xy+dqvw==", + "dev": true, + "requires": { + "yaml": "^1.10.0" + } + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -19792,9 +19562,9 @@ } }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", "dev": true }, "stealthy-require": { @@ -19843,26 +19613,21 @@ "dev": true }, "streamroller": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", - "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "fs-extra": "^8.1.0" + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" }, "dependencies": { - "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", - "dev": true - }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { "ms": "^2.1.1" @@ -19889,61 +19654,107 @@ "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "string.prototype.padend": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz", + "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" } } } }, - "string.prototype.padend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", - "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.4.3", - "function-bind": "^1.0.2" - } - }, - "string.prototype.trimleft": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", - "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, - "string.prototype.trimright": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", - "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "string_decoder": { @@ -19964,6 +19775,14 @@ "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", "is-regexp": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + } } }, "stringify-package": { @@ -19973,22 +19792,19 @@ "dev": true }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.0" } }, "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true }, "strip-eof": { "version": "1.0.0", @@ -20019,6 +19835,19 @@ "requires": { "loader-utils": "^1.1.0", "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "stylehacks": { @@ -20032,22 +19861,13 @@ "postcss-selector-parser": "^3.0.0" }, "dependencies": { - "dot-prop": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", - "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, "postcss-selector-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", - "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", "dev": true, "requires": { - "dot-prop": "^4.1.1", + "dot-prop": "^5.2.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } @@ -20084,19 +19904,32 @@ "util.promisify": "~1.0.0" }, "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", "dev": true, "requires": { - "minimist": "^1.2.5" + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-what": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz", + "integrity": "sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg==", + "dev": true + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" } } } @@ -20108,19 +19941,19 @@ "dev": true }, "synchronous-promise": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.9.tgz", - "integrity": "sha512-LO95GIW16x69LuND1nuuwM4pjgFGupg7pZ/4lU86AmchPKrhk0o2tpMU2unXRrqo81iAFe1YJ0nAGEVwsrZAgg==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.13.tgz", + "integrity": "sha512-R9N6uDkVsghHePKh1TEqbnLddO2IY25OcsksyFp/qBe7XYd0PVbKEWxhcdMhpLzE1I6skj5l4aEZ3CRxcbArlA==", "dev": true }, "table": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.0.tgz", - "integrity": "sha512-nHFDrxmbrkU7JAFKqKbDJXfzrX2UBsWmrieXFTGxiI5e4ncg3VqsZeI4EzNmX0ncp4XNGVeoxIWJXfCIXwrsvw==", + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", "dev": true, "requires": { - "ajv": "^6.9.1", - "lodash": "^4.17.11", + "ajv": "^6.10.2", + "lodash": "^4.17.14", "slice-ansi": "^2.1.0", "string-width": "^3.0.0" }, @@ -20131,6 +19964,18 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -20177,10 +20022,10 @@ "yallist": "^4.0.0" }, "dependencies": { - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, "yallist": { @@ -20202,6 +20047,12 @@ "source-map-support": "~0.5.12" }, "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -20237,24 +20088,6 @@ "webpack-sources": "^1.4.3" }, "dependencies": { - "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true - }, "cacache": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", @@ -20281,10 +20114,10 @@ "unique-filename": "^1.1.1" } }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, "find-cache-dir": { @@ -20298,31 +20131,6 @@ "pkg-dir": "^4.1.0" } }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -20341,39 +20149,6 @@ "semver": "^6.0.0" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, "p-map": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", @@ -20383,12 +20158,6 @@ "aggregate-error": "^3.0.0" } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -20398,26 +20167,6 @@ "find-up": "^4.0.0" } }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - } - }, "serialize-javascript": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", @@ -20443,16 +20192,6 @@ "minipass": "^3.1.1" } }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -20480,13 +20219,13 @@ "dev": true }, "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", "dev": true, "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "inherits": "^2.0.4", + "readable-stream": "2 || 3" } }, "thunkify": { @@ -20601,13 +20340,20 @@ "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" }, "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "dev": true, "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } } }, "trash": { @@ -20627,6 +20373,15 @@ "xdg-trashdir": "^2.1.1" }, "dependencies": { + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, "globby": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", @@ -20671,6 +20426,15 @@ "aggregate-error": "^3.0.0" } }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -20710,9 +20474,9 @@ "dev": true }, "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", + "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==", "dev": true }, "tty-browserify": { @@ -20736,6 +20500,12 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -20746,9 +20516,9 @@ } }, "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true }, "type-is": { @@ -20776,7 +20546,8 @@ "typeface-source-code-pro": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/typeface-source-code-pro/-/typeface-source-code-pro-1.1.3.tgz", - "integrity": "sha512-BAQ8I7Xy5zS5+KuG+gjRPNYCdfwL8vSF9jT8q9wzCRiiOG4h7id5zt8wcQx59riGRbRsgycRfs/ubyAm2z/FJQ==" + "integrity": "sha512-BAQ8I7Xy5zS5+KuG+gjRPNYCdfwL8vSF9jT8q9wzCRiiOG4h7id5zt8wcQx59riGRbRsgycRfs/ubyAm2z/FJQ==", + "dev": true }, "typeface-source-sans-pro": { "version": "0.0.75", @@ -20791,16 +20562,16 @@ "dev": true }, "uglify-js": { - "version": "3.10.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.2.tgz", - "integrity": "sha512-GXCYNwqoo0MbLARghYjxVBxDCnU0tLqN7IPLdHHbibCb1NI5zBkU2EPcy/GaVxc0BtTjqyGXJCINe6JMR2Dpow==", + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.7.tgz", + "integrity": "sha512-SIZhkoh+U/wjW+BHGhVwE9nt8tWJspncloBcFapkpGRwNPqcH8pzX36BXe3TPBjzHWPMUZotpCigak/udWNr1Q==", "dev": true, "optional": true }, "underscore": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", - "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.11.0.tgz", + "integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw==", "dev": true }, "unicode-canonical-property-names-ecmascript": { @@ -20874,9 +20645,9 @@ } }, "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", "dev": true }, "unpipe": { @@ -20944,9 +20715,9 @@ "dev": true }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -20998,12 +20769,20 @@ } }, "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { - "inherits": "2.0.3" + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } } }, "util-deprecate": { @@ -21035,9 +20814,9 @@ "dev": true }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, "v8-compile-cache": { @@ -21063,9 +20842,9 @@ "dev": true }, "vendors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.3.tgz", - "integrity": "sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", "dev": true }, "verror": { @@ -21200,15 +20979,6 @@ "optional": true, "requires": { "picomatch": "^2.2.1" - }, - "dependencies": { - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true, - "optional": true - } } }, "to-regex-range": { @@ -21234,9 +21004,9 @@ } }, "webpack": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz", - "integrity": "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==", + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", + "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", "dev": true, "requires": { "@webassemblyjs/ast": "1.9.0", @@ -21264,43 +21034,53 @@ "webpack-sources": "^1.4.1" }, "dependencies": { - "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "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" } }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "requires": { - "minimist": "^1.2.5" + "yallist": "^3.0.2" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, "serialize-javascript": { @@ -21318,6 +21098,15 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, "terser-webpack-plugin": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", @@ -21335,15 +21124,11 @@ "worker-farm": "^1.7.0" } }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true } } }, @@ -21383,48 +21168,69 @@ "wrap-ansi": "^5.1.0" } }, - "emojis-list": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "find-up": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "minimist": "^1.2.0" + "locate-path": "^3.0.0" } }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "require-main-filename": { + "is-fullwidth-code-point": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "string-width": { @@ -21510,6 +21316,14 @@ "range-parser": "^1.0.3", "url-join": "^2.0.2", "webpack-log": "^1.0.1" + }, + "dependencies": { + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + } } }, "webpack-log": { @@ -21546,6 +21360,21 @@ "jsonfile": "^4.0.0", "universalify": "^0.1.0" } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true } } }, @@ -21559,9 +21388,9 @@ } }, "webpack-sources": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", "dev": true, "requires": { "source-list-map": "^2.0.0", @@ -21577,9 +21406,9 @@ } }, "whatwg-fetch": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.4.0.tgz", - "integrity": "sha512-rsum2ulz2iuZH08mJkT0Yi6JnKhwdw4oeyMjokgxd+mmqYSd9cPpOQf01TIWgjxG/U4+QR+AwKq6lSbXVxkyoQ==" + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz", + "integrity": "sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ==" }, "which": { "version": "1.3.1", @@ -21596,6 +21425,12 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -21612,29 +21447,40 @@ } }, "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true } } }, @@ -21651,30 +21497,16 @@ "dev": true, "requires": { "mkdirp": "^0.5.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - } } }, "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", - "dev": true + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.0.0.tgz", + "integrity": "sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } }, "xdg-basedir": { "version": "2.0.0", @@ -21724,9 +21556,9 @@ "integrity": "sha512-zd3ytX2cm+tcSndRU+krm0eL4TMMpZE7evs5hLRAoOy6gviqLfe3qOlkjF3i5SeAkQUCeJk0lJZrEU56kHRfWw==" }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, "y18n": { @@ -21748,51 +21580,32 @@ "dev": true }, "yargs": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.1.tgz", - "integrity": "sha512-B0vRAp1hRX4jgIOWFtjfNjd9OA9RWYZ6tqGA9/I/IrTMsxmKvtWy+ersM+jzpQqbC3YfLzeABPdeTgcJ9eu1qQ==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^2.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^2.0.0", + "string-width": "^4.2.0", "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^10.1.0" - }, - "dependencies": { - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", - "dev": true, - "requires": { - "xregexp": "4.0.0" - } - } + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" } }, "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "requires": { - "camelcase": "^4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - } + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, "yeast": { @@ -21801,6 +21614,12 @@ "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", "dev": true }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + }, "yup": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/yup/-/yup-0.27.0.tgz", diff --git a/package.json b/package.json index 8ae5fcf63..2f8013dd7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "uni2work", - "version": "22.1.0", + "version": "25.10.0", "description": "", "keywords": [], "author": "", @@ -26,7 +26,8 @@ "i18n:test": "./missing-translations.sh", "prerelease": "./is-clean.sh && npm run test", "release": "standard-version -a", - "postrelease": "git push --follow-tags origin master" + "postrelease": "git push --follow-tags origin master", + "parse-changelog": "changelog-parser ./CHANGELOG.md > changelog.json" }, "husky": { "hooks": { @@ -40,15 +41,6 @@ "git add" ] }, - "standard-version": { - "scripts": { - "postbump": "./sync-versions.hs && git add -- package.yaml" - }, - "commitUrlFormat": "https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/{{hash}}", - "compareUrlFormat": "https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/{{previousTag}}...{{currentTag}}", - "issueUrlFormat": "https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/{{id}}", - "userUrlFormat": "https://gitlab2.rz.ifi.lmu.de/{{user}}" - }, "browserslist": [ "defaults" ], @@ -70,6 +62,7 @@ "babel-plugin-transform-decorators-legacy": "^1.3.5", "babel-preset-es2015": "^6.24.1", "cbt_tunnels": "^1.2.2", + "changelog-parser": "^2.8.0", "clean-webpack-plugin": "^3.0.0", "copy-webpack-plugin": "^6.0.3", "css-loader": "^2.1.1", @@ -89,6 +82,7 @@ "karma-mocha-reporter": "^2.2.5", "karma-webpack": "^3.0.5", "lint-staged": "^8.2.1", + "lodash.debounce": "^4.0.8", "mini-css-extract-plugin": "^0.8.2", "npm-run-all": "^4.1.5", "null-loader": "^2.0.0", @@ -103,13 +97,14 @@ "sass": "^1.26.10", "sass-loader": "^7.3.1", "semver": "^6.3.0", - "standard-version": "^9.0.0", + "standard-version": "^9.1.0", + "standard-version-updater-yaml": "^1.0.2", "style-loader": "^0.23.1", "terser-webpack-plugin": "^2.3.8", "tmp": "^0.1.0", "typeface-roboto": "0.0.75", - "typeface-source-sans-pro": "0.0.75", "typeface-source-code-pro": "^1.1.3", + "typeface-source-sans-pro": "0.0.75", "webpack": "^4.44.1", "webpack-cli": "^3.3.12", "webpack-manifest-plugin": "^2.2.0", @@ -119,6 +114,7 @@ "@babel/runtime": "^7.11.2", "@juggle/resize-observer": "^2.5.0", "core-js": "^3.6.5", + "css.escape": "^1.5.1", "js-cookie": "^2.2.1", "lodash.debounce": "^4.0.8", "lodash.defer": "^4.1.0", diff --git a/package.yaml b/package.yaml index 72ffbece2..f6de3f536 100644 --- a/package.yaml +++ b/package.yaml @@ -1,6 +1,5 @@ -name: uniworx -version: 22.1.0 - +name: uniworx +version: 25.10.0 dependencies: - base - yesod @@ -154,14 +153,23 @@ dependencies: - network-ip - data-textual - fastcdc - + - bimap + - list-t + - insert-ordered-containers + - topograph + - network-uri + - psqueues + - nonce + - IntervalMap + - haskell-src-meta + - either + - xlsx other-extensions: - GeneralizedNewtypeDeriving - IncoherentInstances - OverloadedLists - UndecidableInstances - ApplicativeDo - default-extensions: - OverloadedStrings - PartialTypeSignatures @@ -216,7 +224,6 @@ default-extensions: - EmptyDataDeriving - StandaloneKindSignatures - NoStarIsType - ghc-options: - -Wall - -Wmissing-home-modules @@ -229,7 +236,6 @@ ghc-options: - -fno-max-relevant-binds - -j - -freduction-depth=0 - when: - condition: flag(pedantic) ghc-options: @@ -242,18 +248,11 @@ when: - -ddump-splices - -ddump-to-file cpp-options: -DDEVELOPMENT - ghc-prof-options: - - -fprof-auto else: ghc-options: - -O -fllvm - -# The library contains all of our application code. The executable -# defined below is just a thin wrapper. library: source-dirs: src - -# Runnable executable for our application executables: uniworx: main: main.hs @@ -264,7 +263,7 @@ executables: - condition: flag(library-only) buildable: false ghc-options: - - -threaded -rtsopts "-with-rtsopts=-N -T" # Nonblocking GC causes segfaults in production as of 2020-08-19 + - -threaded -rtsopts "-with-rtsopts=-N -T" uniworxdb: main: Database.hs ghc-options: @@ -296,8 +295,20 @@ executables: when: - condition: flag(library-only) buildable: false - -# Test suite + uniworx-wflint: + main: WFLint.hs + ghc-options: + - -main-is WFLint + dependencies: + - base + - uniworx + - bytestring + - yaml + other-modules: [] + source-dirs: wflint + when: + - condition: flag(library-only) + buildable: false tests: yesod: main: Main.hs @@ -315,6 +326,8 @@ tests: - http-types - yesod-persistent - quickcheck-io + - network-arbitrary + - lens-properties ghc-options: - -fno-warn-orphans - -threaded -rtsopts "-with-rtsopts=-N -T" @@ -327,8 +340,6 @@ tests: when: - condition: "!flag(pedantic)" buildable: false - -# Define flags used by "yesod devel" to make compilation faster flags: library-only: description: Build for use with "yesod devel" diff --git a/routes b/routes index 0dffa1063..ab502ea78 100644 --- a/routes +++ b/routes @@ -41,6 +41,8 @@ /metrics MetricsR GET +/err ErrorR GET !free + / NewsR GET !free /users UsersR GET POST -- no tags, i.e. admins only /users/#CryptoUUIDUser AdminUserR GET POST @@ -58,6 +60,36 @@ /admin/tokens AdminTokensR GET POST /admin/crontab AdminCrontabR GET +/admin/workflows/definitions AdminWorkflowDefinitionListR GET +/admin/workflows/definitions/new AdminWorkflowDefinitionNewR GET POST +/admin/workflows/definitions/#WorkflowScope'/#WorkflowDefinitionName AdminWorkflowDefinitionR: + /edit AWDEditR GET POST + /delete AWDDeleteR GET POST + /instantiate AWDInstantiateR GET POST +/admin/workflows/instances AdminWorkflowInstanceListR GET +/admin/workflows/instances/new AdminWorkflowInstanceNewR GET POST +/admin/workflows/instances/#CryptoUUIDWorkflowInstance AdminWorkflowInstanceR: + /edit AWIEditR GET POST +/admin/workflows/workflows AdminWorkflowWorkflowListR GET +/admin/workflows/workflows/new AdminWorkflowWorkflowNewR GET POST + +/global-workflows/instances GlobalWorkflowInstanceListR GET !free +/global-workflows/instances/new GlobalWorkflowInstanceNewR GET POST +/global-workflows/instances/#WorkflowInstanceName GlobalWorkflowInstanceR: + /edit GWIEditR GET POST + /delete GWIDeleteR GET POST + /workflows GWIWorkflowsR GET !¬empty + /initiate GWIInitiateR GET POST !workflow +/global-workflows GlobalWorkflowWorkflowListR GET !free +!/global-workflows/#CryptoFileNameWorkflowWorkflow GlobalWorkflowWorkflowR: + / GWWWorkflowR GET POST !workflow + /files/#WorkflowPayloadLabel/#CryptoUUIDWorkflowStateIndex GWWFilesR GET !workflow + /edit GWWEditR GET POST + /delete GWWDeleteR GET POST + +/workflow-instances TopWorkflowInstanceListR GET !free +/workflows TopWorkflowWorkflowListR GET !free + /health HealthR GET !free /instance InstanceR GET !free /info InfoR GET !free @@ -107,6 +139,20 @@ /school/#SchoolId SchoolR: / SchoolEditR GET POST + /workflows/instances SchoolWorkflowInstanceListR GET !free + /workflows/instances/new SchoolWorkflowInstanceNewR GET POST + /workflows/instances/#WorkflowInstanceName SchoolWorkflowInstanceR: + /edit SWIEditR GET POST + /delete SWIDeleteR GET POST + /workflows SWIWorkflowsR GET !¬empty + /initiate SWIInitiateR GET POST !workflow + /workflows SchoolWorkflowWorkflowListR GET !free + !/workflows/#CryptoFileNameWorkflowWorkflow SchoolWorkflowWorkflowR: + / SWWWorkflowR GET POST !workflow + /files/#WorkflowPayloadLabel/#CryptoUUIDWorkflowStateIndex SWWFilesR GET !workflow + /edit SWWEditR GET POST + /delete SWWDeleteR GET POST + /allocation/ AllocationListR GET !free /allocation/#TermId/#SchoolId/#AllocationShorthand AllocationR: / AShowR GET POST !free @@ -128,7 +174,7 @@ !/course/new CourseNewR GET POST !lecturer /course/#TermId/#SchoolId/#CourseShorthand CourseR !lecturer: / CShowR GET !tutor !corrector !exam-corrector !course-registered !course-time !evaluation !exam-office !allocation-admin - /favourite CFavouriteR POST + /favourite CFavouriteR GET POST !free /schedule-opt/set/#Bool CScheduleOptSetR GET POST !free /schedule-opt/del CScheduleOptDelR GET POST !free /register CRegisterR GET POST !timeANDcapacityANDallocation-timeAND¬course-registeredANDcourse-time !timeANDallocation-timeAND¬exam-resultANDcourse-registered !lecturerANDallocation-time @@ -163,7 +209,7 @@ / SubShowR GET POST !ownerANDtimeANDuser-submissionsANDsubmission-groupANDexam-registeredANDpersonalised-sheet-files !ownerANDread !correctorANDread /delete SubDelR GET POST !ownerANDtimeANDuser-submissionsANDexam-registeredANDpersonalised-sheet-files /assign SubAssignR GET POST !lecturerANDtime - /correction CorrectionR GET POST !corrector !ownerANDreadANDrated + /correction CorrectionR GET POST !corrector !ownerANDreadANDratedANDexam-time /invite SInviteR GET POST !ownerANDtimeANDuser-submissionsANDsubmission-groupANDexam-registeredANDpersonalised-sheet-files !/#SubmissionFileType SubArchiveR GET !owner !corrector !/#SubmissionFileType/*FilePath SubDownloadR GET !owner !corrector diff --git a/src/Application.hs b/src/Application.hs index cd4a9734d..b44459258 100644 --- a/src/Application.hs +++ b/src/Application.hs @@ -17,8 +17,10 @@ module Application ) where import Control.Monad.Logger (liftLoc, LoggingT(..), MonadLoggerIO(..)) -import Database.Persist.Postgresql (createPostgresqlPool, pgConnStr, - pgPoolSize, runSqlPool, ConnectionPool) +import Database.Persist.Postgresql ( openSimpleConn, pgConnStr, connClose, pgPoolIdleTimeout + , pgPoolSize + ) +import qualified Database.PostgreSQL.Simple as PG import Import hiding (cancel, respond) import Language.Haskell.TH.Syntax (qLocation) import Network.Wai (Middleware) @@ -89,6 +91,7 @@ import Control.Concurrent.STM.Delay import Control.Monad.Trans.Cont (runContT, callCC) import qualified Data.Set as Set +import qualified Data.Map as Map import Handler.Utils.Routes (classifyHandler) @@ -103,6 +106,15 @@ import Web.ServerSession.Core (StorageException(..)) import GHC.RTS.Flags (getRTSFlags) +import qualified Prometheus + +import qualified Data.IntervalMap.Strict as IntervalMap + +import qualified Utils.Pool as Custom + +import Utils.Postgresql +import Handler.Utils.Memcached (manageMemcachedLocalInvalidations) + -- Import all relevant handler modules here. -- (HPack takes care to add new modules to our cabal file nowadays.) import Handler.News @@ -129,6 +141,8 @@ import Handler.Metrics import Handler.ExternalExam import Handler.Participants import Handler.StorageKey +import Handler.Workflow +import Handler.Error -- This line actually creates our YesodDispatch instance. It is the second half @@ -141,8 +155,9 @@ mkYesodDispatch "UniWorX" resourcesUniWorX -- the place to put your migrate statements to have automatic database -- migrations handled by Yesod. makeFoundation :: (MonadResource m, MonadUnliftIO m, MonadCatch m) => AppSettings -> m UniWorX -makeFoundation appSettings'@AppSettings{..} = do +makeFoundation appSettings''@AppSettings{..} = do registerGHCMetrics + registerHealthCheckInterval appHealthCheckInterval -- Some basic initializations: HTTP connection manager, logger, and static -- subsite. @@ -178,32 +193,49 @@ makeFoundation appSettings'@AppSettings{..} = do appJobState <- liftIO newEmptyTMVarIO appHealthReport <- liftIO $ newTVarIO Set.empty + appFileSourceARC <- for appFileSourceARCConf $ \ARCConf{..} -> do + ah <- initARCHandle arccMaximumGhost arccMaximumWeight + void . Prometheus.register $ arcMetrics ARCFileSource ah + return ah + appFileSourcePrewarm <- for appFileSourcePrewarmConf $ \PrewarmCacheConf{..} -> do + lh <- initLRUHandle precMaximumWeight + void . Prometheus.register $ lruMetrics LRUFileSourcePrewarm lh + return lh + appFileInjectInhibit <- liftIO $ newTVarIO IntervalMap.empty + for_ (guardOnM (isn't _JobsOffload appJobMode) appInjectFiles) $ \_ -> + void . Prometheus.register $ injectInhibitMetrics appFileInjectInhibit + -- We need a log function to create a connection pool. We need a connection -- pool to create our foundation. And we need our foundation to get a -- logging function. To get out of this loop, we initially create a -- temporary foundation without a real connection pool, get a log function -- from there, and then create the real foundation. - let mkFoundation appConnPool appSmtpPool appLdapPool appCryptoIDKey appSessionStore appSecretBoxKey appWidgetMemcached appJSONWebKeySet appClusterID appMemcached appUploadCache appVerpSecret = UniWorX {..} - -- The UniWorX {..} syntax is an example of record wild cards. For more - -- information, see: - -- https://ocharles.org.uk/blog/posts/2014-12-04-record-wildcards.html - tempFoundation = mkFoundation - (error "connPool forced in tempFoundation") - (error "smtpPool forced in tempFoundation") - (error "ldapPool forced in tempFoundation") - (error "cryptoIDKey forced in tempFoundation") - (error "sessionStore forced in tempFoundation") - (error "secretBoxKey forced in tempFoundation") - (error "widgetMemcached forced in tempFoundation") - (error "JSONWebKeySet forced in tempFoundation") - (error "ClusterID forced in tempFoundation") - (error "memcached forced in tempFoundation") - (error "MinioConn forced in tempFoundation") - (error "VerpSecret forced in tempFoundation") + let + mkFoundation :: _ -> (forall m. MonadIO m => Custom.Pool' m DBConnLabel DBConnUseState SqlBackend) -> _ + mkFoundation appSettings' appConnPool appSmtpPool appLdapPool appCryptoIDKey appSessionStore appSecretBoxKey appWidgetMemcached appJSONWebKeySet appClusterID appMemcached appMemcachedLocal appUploadCache appVerpSecret appAuthKey = UniWorX {..} + -- The UniWorX {..} syntax is an example of record wild cards. For more + -- information, see: + -- https://ocharles.org.uk/blog/posts/2014-12-04-record-wildcards.html + tempFoundation = mkFoundation + (error "appSettings' forced in tempFoundation") + (error "connPool forced in tempFoundation") + (error "smtpPool forced in tempFoundation") + (error "ldapPool forced in tempFoundation") + (error "cryptoIDKey forced in tempFoundation") + (error "sessionStore forced in tempFoundation") + (error "secretBoxKey forced in tempFoundation") + (error "widgetMemcached forced in tempFoundation") + (error "JSONWebKeySet forced in tempFoundation") + (error "ClusterID forced in tempFoundation") + (error "memcached forced in tempFoundation") + (error "memcachedLocal forced in tempFoundation") + (error "MinioConn forced in tempFoundation") + (error "VerpSecret forced in tempFoundation") + (error "AuthKey forced in tempFoundation") runAppLoggingT tempFoundation $ do $logInfoS "InstanceID" $ UUID.toText appInstanceID - $logDebugS "Configuration" $ tshow appSettings' + $logDebugS "Configuration" $ tshow appSettings'' $logDebugS "RTSFlags" . tshow =<< liftIO getRTSFlags smtpPool <- for appSmtpConf $ \c -> do @@ -216,9 +248,24 @@ makeFoundation appSettings'@AppSettings{..} = do -- Create the database connection pool $logDebugS "setup" "PostgreSQL-Pool" - sqlPool <- createPostgresqlPool - (pgConnStr appDatabaseConf) - (pgPoolSize appDatabaseConf) + logFunc <- askLoggerIO + sqlPool' <- + let create = do + $logDebugS "SqlPool" "Opening connection..." + conn <- liftIO . PG.connectPostgreSQL $ pgConnStr appDatabaseConf + backend <- liftIO $ openSimpleConn logFunc conn + observeDatabaseConnectionOpened + $logDebugS "SqlPool" "Opened connection" + return backend + destroy conn = do + $logDebugS "SqlPool" "Closing connection..." + liftIO $ connClose conn + observeDatabaseConnectionClosed + $logDebugS "SqlPool" "Closed connection" + in Custom.createPool' (liftIO . flip runLoggingT logFunc) create destroy ((flip runLoggingT logFunc .) . onUseDBConn) onReleaseDBConn (Just . fromIntegral $ pgPoolIdleTimeout appDatabaseConf) (Just $ pgPoolSize appDatabaseConf) + let sqlPool :: forall m. MonadIO m => Custom.Pool' m DBConnLabel DBConnUseState SqlBackend + sqlPool = Custom.hoistPool (liftIO . flip runLoggingT logFunc) sqlPool' + void . Prometheus.register . poolMetrics PoolDatabaseConnections $ sqlPool @IO ldapPool <- traverse mkFailoverLabeled <=< forOf (traverse . traverse) appLdapConf $ \conf@LdapConf{..} -> do let ldapLabel = case ldapHost of @@ -233,35 +280,52 @@ makeFoundation appSettings'@AppSettings{..} = do if | appAutoDbMigrate -> do $logDebugS "setup" "Migration" - migrateAll `runSqlPool` sqlPool - | otherwise -> whenM (requiresMigration `runSqlPool` sqlPool) $ do + migrateAll `customRunSqlPool` sqlPool + | otherwise -> whenM (requiresMigration `customRunSqlPool` sqlPool) $ do $logErrorS "setup" "Migration required" liftIO . exitWith $ ExitFailure 130 $logDebugS "setup" "Cluster-Config" - appCryptoIDKey <- clusterSetting (Proxy :: Proxy 'ClusterCryptoIDKey) `runSqlPool` sqlPool - appSecretBoxKey <- clusterSetting (Proxy :: Proxy 'ClusterSecretBoxKey) `runSqlPool` sqlPool - appJSONWebKeySet <- clusterSetting (Proxy :: Proxy 'ClusterJSONWebKeySet) `runSqlPool` sqlPool - appClusterID <- clusterSetting (Proxy :: Proxy 'ClusterId) `runSqlPool` sqlPool - appVerpSecret <- clusterSetting (Proxy :: Proxy 'ClusterVerpSecret) `runSqlPool` sqlPool + appCryptoIDKey <- clusterSetting (Proxy :: Proxy 'ClusterCryptoIDKey) `customRunSqlPool` sqlPool + appSecretBoxKey <- clusterSetting (Proxy :: Proxy 'ClusterSecretBoxKey) `customRunSqlPool` sqlPool + appJSONWebKeySet <- clusterSetting (Proxy :: Proxy 'ClusterJSONWebKeySet) `customRunSqlPool` sqlPool + appClusterID <- clusterSetting (Proxy :: Proxy 'ClusterId) `customRunSqlPool` sqlPool + appVerpSecret <- clusterSetting (Proxy :: Proxy 'ClusterVerpSecret) `customRunSqlPool` sqlPool + appAuthKey <- clusterSetting (Proxy :: Proxy 'ClusterAuthKey) `customRunSqlPool` sqlPool + + needsRechunk <- exists [FileContentChunkContentBased !=. True] `customRunSqlPool` sqlPool + let appSettings' = appSettings'' + & _appRechunkFiles %~ guardOnM needsRechunk appMemcached <- for appMemcachedConf $ \memcachedConf -> do $logDebugS "setup" "Memcached" - memcachedKey <- clusterSetting (Proxy :: Proxy 'ClusterMemcachedKey) `runSqlPool` sqlPool - memcached <- createMemcached memcachedConf - return (memcachedKey, memcached) + memcachedKey <- clusterSetting (Proxy :: Proxy 'ClusterMemcachedKey) `customRunSqlPool` sqlPool + memcachedConn <- createMemcached memcachedConf + when appClearCache $ do + $logWarnS "setup" "Clearing memcached" + liftIO $ Memcached.flushAll memcachedConn + return AppMemcached{..} + appMemcachedLocal <- for appMemcachedLocalConf $ \ARCConf{..} -> do + memcachedLocalARC <- initARCHandle arccMaximumGhost arccMaximumWeight + void . Prometheus.register $ arcMetrics ARCMemcachedLocal memcachedLocalARC + memcachedLocalInvalidationQueue <- newTVarIO mempty + memcachedLocalHandleInvalidations <- allocateLinkedAsync . managePostgresqlChannel appDatabaseConf ChannelMemcachedLocalInvalidation $ manageMemcachedLocalInvalidations memcachedLocalARC memcachedLocalInvalidationQueue + return AppMemcachedLocal{..} - appSessionStore <- mkSessionStore appSettings' sqlPool `runSqlPool` sqlPool + appSessionStore <- mkSessionStore appSettings'' sqlPool `customRunSqlPool` sqlPool appUploadCache <- for appUploadCacheConf $ \minioConf -> liftIO $ do conn <- Minio.connect minioConf let isBucketExists Minio.BucketAlreadyOwnedByYou = True isBucketExists _ = False - either throwM return <=< Minio.runMinioWith conn $ + throwLeft <=< Minio.runMinioWith conn $ do handleIf isBucketExists (const $ return ()) $ Minio.makeBucket appUploadCacheBucket Nothing + handleIf isBucketExists (const $ return ()) $ Minio.makeBucket appUploadTmpBucket Nothing return conn - let foundation = mkFoundation sqlPool smtpPool ldapPool appCryptoIDKey appSessionStore appSecretBoxKey appWidgetMemcached appJSONWebKeySet appClusterID appMemcached appUploadCache appVerpSecret + $logDebugS "Runtime configuration" $ tshow appSettings' + + let foundation = mkFoundation appSettings' sqlPool smtpPool ldapPool appCryptoIDKey appSessionStore appSecretBoxKey appWidgetMemcached appJSONWebKeySet appClusterID appMemcached appMemcachedLocal appUploadCache appVerpSecret appAuthKey -- Return the foundation $logDebugS "setup" "Done" @@ -278,7 +342,9 @@ mkSessionStore :: forall m. , MonadThrow m , MonadResource m ) - => AppSettings -> ConnectionPool -> ReaderT SqlBackend m SomeSessionStorage + => AppSettings + -> (forall m'. MonadIO m' => Custom.Pool' m' DBConnLabel DBConnUseState SqlBackend) + -> ReaderT SqlBackend m SomeSessionStorage mkSessionStore AppSettings{..} mcdSqlConnPool | Just mcdConf@MemcachedConf{..} <- appSessionMemcachedConf = do mcdSqlMemcachedKey <- clusterSetting (Proxy :: Proxy 'ClusterServerSessionKey) @@ -536,41 +602,46 @@ appMain = runResourceT $ do Just wInterval | maybe True (== myProcessID) watchdogProcess -> let notifyWatchdog :: forall a m'. ( MonadLogger m', MonadIO m') => m' a - notifyWatchdog = go Nothing - where - go :: Maybe (Set (UTCTime, HealthReport)) -> m' a - go pResults = do - let delay = floor $ wInterval % 4 - d <- liftIO $ newDelay delay + notifyWatchdog = forever' Nothing $ \pResults -> do + let delay = floor $ wInterval % 4 + d <- liftIO $ newDelay delay + + $logDebugS "Notify" $ "Waiting up to " <> tshow delay <> "µs..." + mResults <- atomically $ asum + [ pResults <$ waitDelay d + , do + results <- readTVar $ foundation ^. _appHealthReport + guardOn (pResults /= Just results) $ Just results + ] - $logDebugS "Notify" $ "Waiting up to " <> tshow delay <> "µs..." - mResults <- atomically $ asum - [ pResults <$ waitDelay d - , do - results <- readTVar $ foundation ^. _appHealthReport - guardOn (pResults /= Just results) $ Just results - ] + $logDebugS "Notify" "Checking for status/watchdog..." + mResults <$ do + void . runMaybeT $ do + results <- hoistMaybe mResults - $logDebugS "Notify" "Checking for status/watchdog..." - (*> go mResults) . void . runMaybeT $ do - results <- hoistMaybe mResults + let latestResults = Map.fromListWith (\_ x -> x) $ Set.toAscList results + Min status <- hoistMaybe $ ofoldMap1 (Min . healthReportStatus) <$> fromNullable latestResults + $logInfoS "NotifyStatus" $ toPathPiece status + liftIO . void . Systemd.notifyStatus . unpack $ toPathPiece status - Min status <- hoistMaybe $ ofoldMap1 (Min . healthReportStatus . view _2) <$> fromNullable results - $logInfoS "NotifyStatus" $ toPathPiece status - liftIO . void . Systemd.notifyStatus . unpack $ toPathPiece status + now <- liftIO getCurrentTime + let missing = flip ifoldMap (foundation ^. _appHealthCheckInterval) $ \hc mInterval -> fromMaybe mempty $ do + interval <- mInterval + let lastSuccess = maybeMonoid mResults + & Set.filter (\(_, rep) -> classifyHealthReport rep == hc) + & Set.filter (\(_, rep) -> healthReportStatus rep >= HealthSuccess) + & Set.mapMonotonic (view _1) + & Set.lookupMax - now <- liftIO getCurrentTime - iforM_ (foundation ^. _appHealthCheckInterval) . curry $ \case - (_, Nothing) -> return () - (hc, Just interval) -> do - lastSuccess <- hoistMaybe $ results - & Set.filter (\(_, rep) -> classifyHealthReport rep == hc) - & Set.filter (\(_, rep) -> healthReportStatus rep >= HealthSuccess) - & Set.mapMonotonic (view _1) - & Set.lookupMax - guard $ lastSuccess > addUTCTime (negate interval) now - $logInfoS "NotifyWatchdog" "Notify" - liftIO $ void Systemd.notifyWatchdog + successIsCurrent = lastSuccess > Just (negate interval `addUTCTime` now) + + return . guardMonoid (not successIsCurrent) $ Set.singleton hc + + if | Set.null missing -> do + $logInfoS "NotifyWatchdog" "Notify" + liftIO $ void Systemd.notifyWatchdog + | otherwise -> + $logWarnS "NotifyWatchdog" $ "No notify; missing \n\t " <> tshow (toList missing) <> "\n\tin " <> tshow (toList <$> mResults) in do $logDebugS "Notify" "Spawning notify thread..." void $ allocateLinkedAsync notifyWatchdog @@ -607,11 +678,11 @@ shutdownApp :: (MonadIO m, MonadUnliftIO m) => UniWorX -> m () shutdownApp app = do stopJobCtl app liftIO $ do - destroyAllResources $ appConnPool app + Custom.purgePool $ appConnPool app for_ (appSmtpPool app) destroyAllResources for_ (appLdapPool app) . mapFailover $ views _2 destroyAllResources for_ (appWidgetMemcached app) Memcached.close - for_ (appMemcached app) $ views _2 Memcached.close + for_ (appMemcached app) $ views _memcachedConn Memcached.close release . fst $ appLogger app liftIO $ threadDelay 1e6 diff --git a/src/Audit/Types.hs b/src/Audit/Types.hs index 84fd31336..7d4cfa87d 100644 --- a/src/Audit/Types.hs +++ b/src/Audit/Types.hs @@ -90,12 +90,10 @@ data Transaction } | TransactionSubmissionFileEdit - { transactionSubmissionFile :: SubmissionFileId - , transactionSubmission :: SubmissionId + { transactionSubmissionFile :: Entity SubmissionFile } | TransactionSubmissionFileDelete - { transactionSubmissionFile :: SubmissionFileId - , transactionSubmission :: SubmissionId + { transactionSubmissionFile :: Entity SubmissionFile } | TransactionExamOfficeUserAdd diff --git a/src/Auth/LDAP.hs b/src/Auth/LDAP.hs index 597163cd4..e4fee5cb2 100644 --- a/src/Auth/LDAP.hs +++ b/src/Auth/LDAP.hs @@ -129,14 +129,14 @@ campusUserWith withLdap' pool mode Creds{..} = either (throwM . CampusUserLdapEr _otherwise -> throwE CampusUserAmbiguous campusUserReTest :: (MonadUnliftIO m, MonadMask m, MonadLogger m) => Failover (LdapConf, LdapPool) -> (Nano -> Bool) -> FailoverMode -> Creds site -> m (Ldap.AttrList []) -campusUserReTest pool doTest mode creds = either throwM return =<< campusUserWith (\l -> flip (withLdapFailoverReTest l) doTest) pool mode creds +campusUserReTest pool doTest mode creds = throwLeft =<< campusUserWith (\l -> flip (withLdapFailoverReTest l) doTest) pool mode creds campusUserReTest' :: (MonadMask m, MonadLogger m, MonadUnliftIO m) => Failover (LdapConf, LdapPool) -> (Nano -> Bool) -> FailoverMode -> User -> m (Maybe (Ldap.AttrList [])) campusUserReTest' pool doTest mode User{userIdent} = runMaybeT . catchIfMaybeT (is _CampusUserNoResult) $ campusUserReTest pool doTest mode (Creds apLdap (CI.original userIdent) []) campusUser :: (MonadUnliftIO m, MonadMask m, MonadLogger m) => Failover (LdapConf, LdapPool) -> FailoverMode -> Creds site -> m (Ldap.AttrList []) -campusUser pool mode creds = either throwM return =<< campusUserWith withLdapFailover pool mode creds +campusUser pool mode creds = throwLeft =<< campusUserWith withLdapFailover pool mode creds campusUser' :: (MonadMask m, MonadUnliftIO m, MonadLogger m) => Failover (LdapConf, LdapPool) -> FailoverMode -> User -> m (Maybe (Ldap.AttrList [])) campusUser' pool mode User{userIdent} diff --git a/src/Control/Arrow/Instances.hs b/src/Control/Arrow/Instances.hs new file mode 100644 index 000000000..8bf44e118 --- /dev/null +++ b/src/Control/Arrow/Instances.hs @@ -0,0 +1,15 @@ +{-# OPTIONS_GHC -fno-warn-orphans #-} + +module Control.Arrow.Instances + ( + ) where + +import ClassyPrelude +import Control.Arrow + + +instance (a ~ b, Monad m) => Monoid (Kleisli m a b) where + mempty = Kleisli return + +instance (a ~ b, Monad m) => Semigroup (Kleisli m a b) where + Kleisli f <> Kleisli g = Kleisli $ f <=< g diff --git a/src/Crypto/Hash/Instances.hs b/src/Crypto/Hash/Instances.hs index 0be90af18..c552b0500 100644 --- a/src/Crypto/Hash/Instances.hs +++ b/src/Crypto/Hash/Instances.hs @@ -5,7 +5,7 @@ module Crypto.Hash.Instances import ClassyPrelude -import Crypto.Hash +import Crypto.Hash hiding (hash) import Database.Persist import Database.Persist.Sql @@ -21,6 +21,15 @@ import Control.Monad.Fail import Language.Haskell.TH.Syntax (Lift(liftTyped)) import Instances.TH.Lift () +import Data.Binary +import qualified Data.Binary.Put as Binary +import qualified Data.Binary.Get as Binary + +import qualified Data.ByteString.Base64.URL as Base64 + +import Type.Reflection (typeRep) + + instance HashAlgorithm hash => PersistField (Digest hash) where toPersistValue = PersistByteString . convert fromPersistValue (PersistByteString bs) = maybe (Left "Could not convert Digest from ByteString") Right $ digestFromByteString bs @@ -31,14 +40,14 @@ instance HashAlgorithm hash => PersistFieldSql (Digest hash) where sqlType _ = SqlBlob instance HashAlgorithm hash => PathPiece (Digest hash) where - toPathPiece = showToPathPiece - fromPathPiece = readFromPathPiece + toPathPiece = decodeUtf8 . Base64.encodeUnpadded . convert + fromPathPiece = digestFromByteString <=< either (const Nothing) Just . Base64.decodeUnpadded . encodeUtf8 instance HashAlgorithm hash => ToHttpApiData (Digest hash) where - toUrlPiece = tshow + toUrlPiece = toPathPiece instance HashAlgorithm hash => FromHttpApiData (Digest hash) where - parseUrlPiece = maybe (Left "Could not read Digest") Right . readMay + parseUrlPiece = maybe (Left "Could not read Digest") Right . fromPathPiece instance HashAlgorithm hash => ToJSON (Digest hash) where toJSON = Aeson.String . toUrlPiece @@ -46,8 +55,12 @@ instance HashAlgorithm hash => ToJSON (Digest hash) where instance HashAlgorithm hash => FromJSON (Digest hash) where parseJSON = withText "Digest" $ either (fail . unpack) return . parseUrlPiece -instance Hashable (Digest hash) where - hashWithSalt s = (hashWithSalt s :: ByteString -> Int) . convert +instance Typeable hash => Hashable (Digest hash) where + hashWithSalt s h = s `hashWithSalt` hash (typeRep @hash) `hashWithSalt` hash @ByteString (convert h) instance HashAlgorithm hash => Lift (Digest hash) where liftTyped dgst = [||fromMaybe (error "Lifted digest has wrong length") $ digestFromByteString $$(liftTyped (convert dgst :: ByteString))||] + +instance HashAlgorithm hash => Binary (Digest hash) where + put = Binary.putByteString . convert + get = Binary.getByteString (hashDigestSize (error "hashDigestSize inspected value of type hash" :: hash)) >>= maybe (fail "Could not parse Digest") return . digestFromByteString diff --git a/src/CryptoID.hs b/src/CryptoID.hs index 2c6462321..f16aee18d 100644 --- a/src/CryptoID.hs +++ b/src/CryptoID.hs @@ -3,6 +3,7 @@ module CryptoID ( module CryptoID + , module CryptoID.Cached , module Data.CryptoID.Poly.ImplicitNamespace , module Data.UUID.Cryptographic.ImplicitNamespace , module System.FilePath.Cryptographic.ImplicitNamespace @@ -18,6 +19,7 @@ import qualified Data.CryptoID as E import Data.CryptoID.Poly.ImplicitNamespace hiding (decrypt, encrypt) import Data.UUID.Cryptographic.ImplicitNamespace hiding (decrypt, encrypt) import System.FilePath.Cryptographic.ImplicitNamespace hiding (decrypt, encrypt) +import CryptoID.Cached import qualified Data.Text as Text @@ -28,28 +30,6 @@ import Data.Aeson.Encoding (text) import Text.Blaze (ToMarkup(..)) -import qualified Data.CryptoID.Class.ImplicitNamespace as I - - -encrypt :: forall plaintext ciphertext m. - ( I.HasCryptoID ciphertext plaintext m - , KnownSymbol (CryptoIDNamespace ciphertext plaintext) - , MonadHandler m - , Typeable ciphertext - , PathPiece plaintext - ) - => plaintext -> m (I.CryptoID ciphertext plaintext) -encrypt plain = $cachedHereBinary (toPathPiece plain) $ I.encrypt plain - -decrypt :: forall plaintext ciphertext m. - ( I.HasCryptoID ciphertext plaintext m - , MonadHandler m - , Typeable plaintext - , PathPiece ciphertext - ) - => I.CryptoID ciphertext plaintext -> m plaintext -decrypt cipher = $cachedHereBinary (toPathPiece $ ciphertext cipher) $ I.decrypt cipher - instance {-# OVERLAPPING #-} MonadThrow m => MonadCrypto (ReaderT CryptoIDKey m) where type MonadCryptoKey (ReaderT CryptoIDKey m) = CryptoIDKey @@ -73,9 +53,14 @@ decCryptoIDs [ ''SubmissionId , ''CourseEventId , ''TutorialId , ''ExternalExamId + , ''WorkflowInstanceId + , ''WorkflowWorkflowId , ''MaterialFileId ] +type instance CryptoIDNamespace a WorkflowStateIndex = "WorkflowStateIndex" +type CryptoUUIDWorkflowStateIndex = CryptoUUID WorkflowStateIndex + decCryptoIDKeySize -- CryptoIDNamespace (CI FilePath) SubmissionId ~ "Submission" @@ -113,3 +98,22 @@ instance {-# OVERLAPS #-} FromJSONKey (E.CryptoID "User" (CI FilePath)) where fromJSONKey = FromJSONKeyTextParser $ maybe (fail "Could not parse CryptoFileNameUser") return . fromPathPiece instance {-# OVERLAPS #-} ToMarkup (E.CryptoID "User" (CI FilePath)) where toMarkup = toMarkup . toPathPiece + + +-- CryptoIDNamespace (CI FilePath) WorkflowWorkflowId ~ "WorkflowWorkflow" +instance {-# OVERLAPS #-} PathPiece (E.CryptoID "WorkflowWorkflow" (CI FilePath)) where + fromPathPiece (Text.unpack -> piece) = do + piece' <- (stripPrefix `on` map CI.mk) "uww" piece + return . CryptoID . CI.mk $ map CI.original piece' + toPathPiece = Text.pack . ("uww" <>) . CI.foldedCase . ciphertext + +instance {-# OVERLAPS #-} ToJSON (E.CryptoID "WorkflowWorkflow" (CI FilePath)) where + toJSON = String . toPathPiece +instance {-# OVERLAPS #-} ToJSONKey (E.CryptoID "WorkflowWorkflow" (CI FilePath)) where + toJSONKey = ToJSONKeyText toPathPiece (text . toPathPiece) +instance {-# OVERLAPS #-} FromJSON (E.CryptoID "WorkflowWorkflow" (CI FilePath)) where + parseJSON = withText "CryptoFileNameWorkflowWorkflow" $ maybe (fail "Could not parse CryptoFileNameWorkflowWorkflow") return . fromPathPiece +instance {-# OVERLAPS #-} FromJSONKey (E.CryptoID "WorkflowWorkflow" (CI FilePath)) where + fromJSONKey = FromJSONKeyTextParser $ maybe (fail "Could not parse CryptoFileNameWorkflowWorkflow") return . fromPathPiece +instance {-# OVERLAPS #-} ToMarkup (E.CryptoID "WorkflowWorkflow" (CI FilePath)) where + toMarkup = toMarkup . toPathPiece diff --git a/src/CryptoID/Cached.hs b/src/CryptoID/Cached.hs new file mode 100644 index 000000000..7301e01d3 --- /dev/null +++ b/src/CryptoID/Cached.hs @@ -0,0 +1,51 @@ +module CryptoID.Cached + ( encrypt, decrypt + ) where + +import Import.NoModel + +import qualified Data.Binary as Binary + +import qualified Data.CryptoID.Class.ImplicitNamespace as I + + +newtype CryptoIDDecryption ciphertext plaintext = CryptoIDDecryption plaintext + deriving (Typeable) +newtype CryptoIDEncryption ciphertext plaintext = CryptoIDEncryption ciphertext + deriving (Typeable) + +encrypt :: forall plaintext ciphertext m. + ( I.HasCryptoID ciphertext plaintext (HandlerFor (HandlerSite m)) + , Typeable plaintext, Typeable ciphertext + , Binary plaintext, Binary ciphertext + , MonadHandler m + ) + => plaintext -> m (I.CryptoID ciphertext plaintext) +encrypt plain = liftHandler $ do + (cachedEnc :: Maybe (CryptoIDEncryption ciphertext plaintext)) <- cacheByGet cacheKey + case cachedEnc of + Nothing -> do + cID@(I.CryptoID crypt) <- I.encrypt plain + cacheBySet cacheKey (CryptoIDEncryption crypt :: CryptoIDEncryption ciphertext plaintext) + cacheBySet (toStrict $ Binary.encode crypt) (CryptoIDDecryption plain :: CryptoIDDecryption ciphertext plaintext) + return cID + Just (CryptoIDEncryption crypt) -> return $ I.CryptoID crypt + where cacheKey = toStrict $ Binary.encode plain + +decrypt :: forall plaintext ciphertext m. + ( I.HasCryptoID ciphertext plaintext (HandlerFor (HandlerSite m)) + , Typeable plaintext, Typeable ciphertext + , Binary plaintext, Binary ciphertext + , MonadHandler m + ) + => I.CryptoID ciphertext plaintext -> m plaintext +decrypt cID@(I.CryptoID crypt) = liftHandler $ do + (cachedDec :: Maybe (CryptoIDDecryption ciphertext plaintext)) <- cacheByGet cacheKey + case cachedDec of + Nothing -> do + plain <- I.decrypt cID + cacheBySet (toStrict $ Binary.encode plain) (CryptoIDEncryption crypt :: CryptoIDEncryption ciphertext plaintext) + cacheBySet cacheKey (CryptoIDDecryption plain :: CryptoIDDecryption ciphertext plaintext) + return plain + Just (CryptoIDDecryption plain) -> return plain + where cacheKey = toStrict $ Binary.encode crypt diff --git a/src/Data/CaseInsensitive/Instances.hs b/src/Data/CaseInsensitive/Instances.hs index 512195097..eadbd421b 100644 --- a/src/Data/CaseInsensitive/Instances.hs +++ b/src/Data/CaseInsensitive/Instances.hs @@ -6,7 +6,7 @@ module Data.CaseInsensitive.Instances ( ) where -import ClassyPrelude.Yesod hiding (lift) +import ClassyPrelude.Yesod hiding (lift, Proxy(..)) import Data.CaseInsensitive (CI) import qualified Data.CaseInsensitive as CI @@ -28,16 +28,19 @@ import Web.HttpApiData import qualified Data.Csv as Csv +import Utils.Persist +import Data.Proxy + instance PersistField (CI Text) where - toPersistValue ciText = PersistDbSpecific . Text.encodeUtf8 $ CI.original ciText - fromPersistValue (PersistDbSpecific bs) = Right . CI.mk $ Text.decodeUtf8 bs - fromPersistValue x = Left . pack $ "Expected PersistDbSpecific, received: " ++ show x + toPersistValue ciText = PersistLiteralEscaped . Text.encodeUtf8 $ CI.original ciText + fromPersistValue (PersistLiteralEscaped bs) = Right . CI.mk $ Text.decodeUtf8 bs + fromPersistValue x = Left $ fromPersistValueErrorSql (Proxy @(CI Text)) x instance PersistField (CI String) where - toPersistValue ciText = PersistDbSpecific . Text.encodeUtf8 . pack $ CI.original ciText - fromPersistValue (PersistDbSpecific bs) = Right . CI.mk . unpack $ Text.decodeUtf8 bs - fromPersistValue x = Left . pack $ "Expected PersistDbSpecific, received: " ++ show x + toPersistValue ciText = PersistLiteralEscaped . Text.encodeUtf8 . pack $ CI.original ciText + fromPersistValue (PersistLiteralEscaped bs) = Right . CI.mk . unpack $ Text.decodeUtf8 bs + fromPersistValue x = Left $ fromPersistValueErrorSql (Proxy @(CI String)) x instance PersistFieldSql (CI Text) where sqlType _ = SqlOther "citext" @@ -85,6 +88,10 @@ instance (CI.FoldCase s, PathPiece s) => PathPiece (CI s) where fromPathPiece = fmap CI.mk . fromPathPiece toPathPiece = toPathPiece . CI.original +instance PathPiece [CI Char] where + fromPathPiece = fmap (map CI.mk . (unpack :: Text -> [Char])) . fromPathPiece + toPathPiece = toPathPiece . (pack :: [Char] -> Text) . map CI.original + instance ToHttpApiData s => ToHttpApiData (CI s) where toUrlPiece = toUrlPiece . CI.original toEncodedUrlPiece = toEncodedUrlPiece . CI.original diff --git a/src/Data/Encoding/Instances.hs b/src/Data/Encoding/Instances.hs index d9bf3748d..0d332c1aa 100644 --- a/src/Data/Encoding/Instances.hs +++ b/src/Data/Encoding/Instances.hs @@ -32,3 +32,10 @@ instance Read DynEncoding where instance Ord DynEncoding where compare = comparing show + +instance Hashable DynEncoding where + hashWithSalt s = hashWithSalt s . show + + +instance NFData DynEncoding where + rnf enc = rnf $ show enc diff --git a/src/Data/MultiSet/Instances.hs b/src/Data/MultiSet/Instances.hs new file mode 100644 index 000000000..046daf0ab --- /dev/null +++ b/src/Data/MultiSet/Instances.hs @@ -0,0 +1,14 @@ +{-# OPTIONS_GHC -fno-warn-orphans #-} + +module Data.MultiSet.Instances + ( + ) where + +import ClassyPrelude +import Data.MultiSet + + +type instance Element (MultiSet a) = a + +instance MonoFoldable (MultiSet a) +instance GrowingAppend (MultiSet a) diff --git a/src/Data/Time/Calendar/Instances.hs b/src/Data/Time/Calendar/Instances.hs index 87e74ad1c..d374f9514 100644 --- a/src/Data/Time/Calendar/Instances.hs +++ b/src/Data/Time/Calendar/Instances.hs @@ -18,7 +18,9 @@ deriving instance Lift Day instance Hashable Day where hashWithSalt s (ModifiedJulianDay jDay) = s `hashWithSalt` hash (typeRep @Day) `hashWithSalt` jDay -deriving instance Ord DayOfWeek +-- -- Available since time-1.11 +-- deriving instance Ord DayOfWeek + instance Universe DayOfWeek where universe = [Monday .. Sunday] instance Finite DayOfWeek diff --git a/src/Data/UUID/Instances.hs b/src/Data/UUID/Instances.hs index c75d33ee9..15655fd18 100644 --- a/src/Data/UUID/Instances.hs +++ b/src/Data/UUID/Instances.hs @@ -3,11 +3,13 @@ module Data.UUID.Instances () where -import ClassyPrelude.Yesod +import ClassyPrelude.Yesod hiding (Proxy(..)) import Data.UUID (UUID) import qualified Data.UUID as UUID import Database.Persist.Sql +import Utils.Persist +import Data.Proxy import Text.Blaze (ToMarkup(..)) @@ -17,12 +19,12 @@ instance PathPiece UUID where toPathPiece = pack . UUID.toString instance PersistField UUID where - toPersistValue = PersistDbSpecific . UUID.toASCIIBytes + toPersistValue = PersistLiteralEscaped . UUID.toASCIIBytes - fromPersistValue (PersistText t) = maybe (Left "Failed to parse UUID") Right $ UUID.fromText t - fromPersistValue (PersistByteString bs) = maybe (Left "Failed to parse UUID") Right $ UUID.fromASCIIBytes bs - fromPersistValue (PersistDbSpecific bs) = maybe (Left "Failed to parse UUID") Right $ UUID.fromASCIIBytes bs - fromPersistValue x = Left $ "Expected UUID, received: " <> tshow x + fromPersistValue (PersistText t) = maybe (Left "Failed to parse UUID") Right $ UUID.fromText t + fromPersistValue (PersistByteString bs) = maybe (Left "Failed to parse UUID") Right $ UUID.fromASCIIBytes bs + fromPersistValue (PersistLiteralEscaped bs) = maybe (Left "Failed to parse UUID") Right $ UUID.fromASCIIBytes bs + fromPersistValue x = Left $ fromPersistValueErrorSql (Proxy @UUID) x instance PersistFieldSql UUID where sqlType _ = SqlOther "uuid" diff --git a/src/Data/Universe/Instances/Reverse/JSON.hs b/src/Data/Universe/Instances/Reverse/JSON.hs index 8aed56f14..e4ce07a11 100644 --- a/src/Data/Universe/Instances/Reverse/JSON.hs +++ b/src/Data/Universe/Instances/Reverse/JSON.hs @@ -22,8 +22,11 @@ instance (Eq a, Hashable a, Finite a, ToJSON b, ToJSONKey a) => ToJSON (a -> b) toJSON f = toJSON $ HashMap.fromList [(k, f k) | k <- universeF] instance (Eq a, Hashable a, Finite a, FromJSON b, FromJSONKey a) => FromJSON (a -> b) where - parseJSON val = do - vMap <- parseJSON val :: Parser (HashMap a b) - unless (HashSet.fromMap (HashMap.map (const ()) vMap) == HashSet.fromList universeF) $ - fail "Not all required keys found" - return (vMap !) + parseJSON val = asObject <|> asConst + where + asObject = do + vMap <- parseJSON val :: Parser (HashMap a b) + unless (HashSet.fromMap (HashMap.map (const ()) vMap) == HashSet.fromList universeF) $ + fail "Not all required keys found" + return (vMap !) + asConst = const <$> parseJSON val diff --git a/src/Database/Esqueleto/Utils.hs b/src/Database/Esqueleto/Utils.hs index e73074a91..ad2678036 100644 --- a/src/Database/Esqueleto/Utils.hs +++ b/src/Database/Esqueleto/Utils.hs @@ -20,17 +20,19 @@ module Database.Esqueleto.Utils , selectExists, selectNotExists , SqlHashable , sha256 - , maybe, maybeEq, fromMaybe, unsafeCoalesce + , maybe, maybe2, maybeEq, fromMaybe, guardMaybe, unsafeCoalesce , bool , max, min , abs , SqlProject(..) , (->.), (#>>.) , fromSqlKey + , unKey , selectCountRows , selectMaybe - , day, diffDays + , day, diffDays, diffTimes , exprLift + , explicitUnsafeCoerceSqlExprValue , module Database.Esqueleto.Utils.TH ) where @@ -50,6 +52,12 @@ import qualified Data.ByteString.Lazy as Lazy (ByteString) import Crypto.Hash (Digest, SHA256) +import Data.Coerce (Coercible) + +import Data.Time.Clock (NominalDiffTime) + +import qualified Data.Text.Lazy.Builder as Text.Builder + {-# ANN any ("HLint: ignore Use any" :: String) #-} {-# ANN all ("HLint: ignore Use all" :: String) #-} @@ -124,19 +132,31 @@ substring (E.ERaw p1 f1) (E.ERaw p2 f2) (E.ERaw p3 f3) , strVals <> fromiVals <> foriVals ) substring a b c = substring (construct a) (construct b) (construct c) - where construct :: E.SqlExpr (E.Value a) -> E.SqlExpr (E.Value a) - construct (E.ERaw p f) = E.ERaw E.Parens $ \info -> - let (b1, vals) = f info - build ("?", [E.PersistList vals']) = - (E.uncommas $ replicate (length vals') "?", vals') - build expr = expr - in build (E.parensM p b1, vals) - construct (E.ECompositeKey f) = - E.ERaw E.Parens $ \info -> (E.uncommas $ f info, mempty) - construct (E.EAliasedValue i _) = - E.ERaw E.Never $ E.aliasedValueIdentToRawSql i - construct (E.EValueReference i i') = - E.ERaw E.Never $ E.valueReferenceToRawSql i i' + +explicitUnsafeCoerceSqlExprValue :: forall b a. + Text + -> E.SqlExpr (E.Value a) + -> E.SqlExpr (E.Value b) +explicitUnsafeCoerceSqlExprValue typ (E.ERaw p1 f1) = E.ERaw E.Parens $ \info -> + let (valTLB, valVals) = f1 info + in ( E.parensM p1 valTLB <> " :: " <> Text.Builder.fromText typ + , valVals + ) +explicitUnsafeCoerceSqlExprValue typ val = explicitUnsafeCoerceSqlExprValue typ $ construct val + +construct :: E.SqlExpr (E.Value a) -> E.SqlExpr (E.Value a) +construct (E.ERaw p f) = E.ERaw E.Parens $ \info -> + let (b1, vals) = f info + build ("?", [E.PersistList vals']) = + (E.uncommas $ replicate (length vals') "?", vals') + build expr = expr + in build (E.parensM p b1, vals) +construct (E.ECompositeKey f) = + E.ERaw E.Parens $ \info -> (E.uncommas $ f info, mempty) +construct (E.EAliasedValue i _) = + E.ERaw E.Never $ E.aliasedValueIdentToRawSql i +construct (E.EValueReference i i') = + E.ERaw E.Never $ E.valueReferenceToRawSql i i' and, or :: Foldable f => f (E.SqlExpr (E.Value Bool)) -> E.SqlExpr (E.Value Bool) and = F.foldr (E.&&.) true @@ -302,6 +322,20 @@ maybe onNothing onJust val = E.case_ ] (E.else_ onNothing) +maybe2 :: (PersistField a, PersistField b, PersistField c) + => E.SqlExpr (E.Value c) + -> (E.SqlExpr (E.Value a) -> E.SqlExpr (E.Value b) -> E.SqlExpr (E.Value c)) + -> E.SqlExpr (E.Value (Maybe a)) + -> E.SqlExpr (E.Value (Maybe b)) + -> E.SqlExpr (E.Value c) +maybe2 onNothing onJust val1 val2 = E.case_ + [ E.when_ + (isJust val1 E.&&. isJust val2) + E.then_ + (onJust (E.veryUnsafeCoerceSqlExprValue val1) (E.veryUnsafeCoerceSqlExprValue val2)) + ] + (E.else_ onNothing) + infix 4 `maybeEq` maybeEq :: PersistField a @@ -321,12 +355,20 @@ maybeEq a b = E.case_ ] (E.else_ $ a E.==. b) +-- TODO: replace with guardMaybe in Utils.Schedule fromMaybe :: (PersistField a) => E.SqlExpr (E.Value a) -> E.SqlExpr (E.Value (Maybe a)) -> E.SqlExpr (E.Value a) fromMaybe onNothing = maybe onNothing id +guardMaybe :: PersistField a + => E.SqlExpr (E.Value (Maybe a)) + -> E.SqlQuery (E.SqlExpr (E.Value a)) +guardMaybe mVal = do + E.where_ $ isJust mVal + return $ E.veryUnsafeCoerceSqlExprValue mVal + bool :: PersistField a => E.SqlExpr (E.Value a) -> E.SqlExpr (E.Value a) @@ -356,17 +398,20 @@ unsafeCoalesce :: E.PersistField a => [E.SqlExpr (E.Value (Maybe a))] -> E.SqlEx unsafeCoalesce = E.veryUnsafeCoerceSqlExprValue . E.coalesce -class (PersistEntity entity, PersistField value) => SqlProject entity value entity' value' | entity value entity' -> value', entity value value' -> entity' where +class (PersistEntity entity, PersistField value, PersistField value') => SqlProject entity value entity' value' | entity value entity' -> value', entity value value' -> entity' where sqlProject :: E.SqlExpr entity' -> EntityField entity value -> E.SqlExpr (E.Value value') unSqlProject :: forall p1 p2. p1 entity -> p2 entity' -> value -> value' + unSqlProjectExpr :: forall p1 p2. p1 entity -> p2 entity' -> E.SqlExpr (E.Value value) -> E.SqlExpr (E.Value value') instance (PersistEntity val, PersistField typ) => SqlProject val typ (E.Entity val) typ where sqlProject = (E.^.) unSqlProject _ _ = id + unSqlProjectExpr _ _ = id instance (PersistEntity val, PersistField typ) => SqlProject val typ (Maybe (E.Entity val)) (Maybe typ) where sqlProject = (E.?.) unSqlProject _ _ = Just + unSqlProjectExpr _ _ = E.just infixl 8 ->. @@ -381,6 +426,12 @@ infixl 8 #>>. fromSqlKey :: (ToBackendKey SqlBackend entity, PersistField (Key entity)) => E.SqlExpr (E.Value (Key entity)) -> E.SqlExpr (E.Value Int64) fromSqlKey = E.veryUnsafeCoerceSqlExprValue + +unKey :: ( Coercible (Key entity) a + , PersistField (Key entity), PersistField a + ) + => E.SqlExpr (E.Value (Key entity)) -> E.SqlExpr (E.Value a) +unKey = E.veryUnsafeCoerceSqlExprValue selectCountRows :: (Num a, PersistField a, MonadIO m) => E.SqlQuery ignored -> E.SqlReadT m a @@ -399,11 +450,22 @@ selectMaybe = fmap listToMaybe . E.select . (<* E.limit 1) day :: E.SqlExpr (E.Value UTCTime) -> E.SqlExpr (E.Value Day) day = E.unsafeSqlCastAs "date" -infixl 6 `diffDays` +infixl 6 `diffDays`, `diffTimes` diffDays :: E.SqlExpr (E.Value Day) -> E.SqlExpr (E.Value Day) -> E.SqlExpr (E.Value Int) -- ^ PostgreSQL is weird. diffDays a b = E.veryUnsafeCoerceSqlExprValue $ a E.-. b + +diffTimes :: E.SqlExpr (E.Value UTCTime) -> E.SqlExpr (E.Value UTCTime) -> E.SqlExpr (E.Value NominalDiffTime) +diffTimes a b = unsafeExtract "EPOCH" $ a E.-. b + +unsafeExtract :: String -> E.SqlExpr (E.Value a) -> E.SqlExpr (E.Value b) +unsafeExtract extr (E.ERaw vP vF) = E.ERaw E.Never $ \info -> + let (vTLB, vVals) = vF info + in ( "EXTRACT" <> E.parens (fromString extr <> " FROM " <> E.parensM vP vTLB) + , vVals + ) +unsafeExtract extr v = unsafeExtract extr $ construct v class ExprLift e a | e -> a where diff --git a/src/Database/Esqueleto/Utils/TH.hs b/src/Database/Esqueleto/Utils/TH.hs index 988915aa0..3c21ce597 100644 --- a/src/Database/Esqueleto/Utils/TH.hs +++ b/src/Database/Esqueleto/Utils/TH.hs @@ -10,7 +10,7 @@ module Database.Esqueleto.Utils.TH import ClassyPrelude import qualified Database.Esqueleto as E -import qualified Database.Esqueleto.Internal.Sql as E (SqlSelect) +import qualified Database.Esqueleto.Internal.Internal as E (SqlSelect) import Database.Persist (PersistField) diff --git a/src/Database/Persist/Class/Instances.hs b/src/Database/Persist/Class/Instances.hs index 4a3a7208c..657a86800 100644 --- a/src/Database/Persist/Class/Instances.hs +++ b/src/Database/Persist/Class/Instances.hs @@ -30,9 +30,6 @@ instance PersistEntity record => Binary (Key record) where putList = Binary.putList . map toPersistValue get = either (fail . unpack) return . fromPersistValue =<< Binary.get -instance PersistEntity record => NFData (Key record) where - rnf = rnf . keyToValues - uniqueToMap :: PersistEntity record => Unique record -> Map (HaskellName, DBName) PersistValue uniqueToMap = fmap Map.fromList $ zip <$> persistUniqueToFieldNames <*> persistUniqueToValues diff --git a/src/Database/Persist/Sql/Types/Instances.hs b/src/Database/Persist/Sql/Types/Instances.hs index b7c33572b..4fd50d57a 100644 --- a/src/Database/Persist/Sql/Types/Instances.hs +++ b/src/Database/Persist/Sql/Types/Instances.hs @@ -8,6 +8,8 @@ import ClassyPrelude import Database.Persist.Sql +import Data.Binary (Binary) + instance BackendCompatible SqlWriteBackend SqlWriteBackend where projectBackend = id @@ -20,3 +22,6 @@ instance BackendCompatible SqlReadBackend SqlBackend where instance BackendCompatible SqlWriteBackend SqlBackend where projectBackend = SqlWriteBackend + +deriving newtype instance Binary (BackendKey SqlBackend) +deriving anyclass instance NFData (BackendKey SqlBackend) diff --git a/src/Database/Persist/Types/Instances.hs b/src/Database/Persist/Types/Instances.hs index e7309b6cc..cf05894f2 100644 --- a/src/Database/Persist/Types/Instances.hs +++ b/src/Database/Persist/Types/Instances.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Database.Persist.Types.Instances @@ -22,3 +23,9 @@ deriving instance Typeable PersistValue instance Hashable PersistValue instance Binary PersistValue instance NFData PersistValue + +instance (NFData record, NFData (Key record)) => NFData (Entity record) where + rnf Entity{..} = rnf entityKey `seq` rnf entityVal + +deriving instance Generic Checkmark +deriving anyclass instance NFData Checkmark diff --git a/src/Foundation.hs b/src/Foundation.hs index 6a9988f6c..66c4cd7c3 100644 --- a/src/Foundation.hs +++ b/src/Foundation.hs @@ -10,5 +10,5 @@ import Foundation.Instances as Foundation (ButtonClass(..), unsafeHandler) import Foundation.Authorization as Foundation import Foundation.SiteLayout as Foundation import Foundation.DB as Foundation -import Foundation.Navigation as Foundation (evalAccessCorrector) +import Foundation.Navigation as Foundation (evalAccessCorrector, NavigationCacheKey(..)) import Foundation.Yesod.Middleware as Foundation (updateFavourites) diff --git a/src/Foundation/Authorization.hs b/src/Foundation/Authorization.hs index ad088cbe3..ff547456f 100644 --- a/src/Foundation/Authorization.hs +++ b/src/Foundation/Authorization.hs @@ -1,5 +1,5 @@ -{-# LANGUAGE UndecidableInstances #-} -{-# OPTIONS_GHC -fno-warn-redundant-constraints #-} +{-# LANGUAGE UndecidableInstances, InstanceSigs #-} +{-# OPTIONS_GHC -fno-warn-redundant-constraints -fprof-auto #-} module Foundation.Authorization ( evalAccess, evalAccessFor, evalAccessWith @@ -8,15 +8,20 @@ module Foundation.Authorization , wouldHaveReadAccessTo, wouldHaveWriteAccessTo , wouldHaveReadAccessToIff, wouldHaveWriteAccessToIff , AuthContext(..), getAuthContext - , isDryRun + , isDryRun, isDryRunDB , maybeBearerToken, requireBearerToken , requireCurrentBearerRestrictions, maybeCurrentBearerRestrictions - , BearerAuthSite + , BearerAuthSite, MonadAP , routeAuthTags , orAR, andAR, notAR, trueAR, falseAR + , evalWorkflowRoleFor, evalWorkflowRoleFor' + , hasWorkflowRole + , mayViewWorkflowAction, mayViewWorkflowAction' + , authoritiveApproot + , AuthorizationCacheKey(..) ) where -import Import.NoFoundation +import Import.NoFoundation hiding (Last(..)) import Foundation.Type import Foundation.Routes @@ -26,7 +31,13 @@ import Foundation.DB import Handler.Utils.ExamOffice.Exam import Handler.Utils.ExamOffice.ExternalExam +import Handler.Utils.Workflow.CanonicalRoute +import Handler.Utils.Memcached +import Handler.Utils.I18n +import Handler.Utils.Routes import Utils.Course (courseIsVisible) +import Utils.Workflow +import Utils.Metrics (observeAuthTagEvaluation, AuthTagEvalOutcome(..)) import qualified Data.Set as Set import qualified Data.Aeson as JSON @@ -34,7 +45,8 @@ import qualified Data.HashSet as HashSet import qualified Data.Map as Map import Data.Map ((!?)) import qualified Data.Text as Text -import Data.List (findIndex) +import Data.List (findIndex, inits) +import Data.Semigroup (Last(..)) import qualified Database.Esqueleto as E import qualified Database.Esqueleto.Utils as E @@ -44,6 +56,13 @@ import Control.Monad.Memo.Class (MonadMemo(..), for4) import Data.Aeson.Lens hiding (_Value, key) +import qualified Data.Conduit.Combinators as C + +import qualified Data.Binary as Binary + +import GHC.TypeLits (TypeError) +import qualified GHC.TypeLits as TypeError (ErrorMessage(..)) + type BearerAuthSite site = ( MonadCrypto (HandlerFor site) @@ -78,22 +97,110 @@ type AuthTagsEval m = AuthDNF -> Maybe (AuthId UniWorX) -> Route UniWorX -> Bool data AccessPredicate = APPure (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> Reader MsgRenderer AuthResult) | APHandler (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> HandlerFor UniWorX AuthResult) - | APDB ((forall m. MonadAP m => AuthTagsEval m) -> Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> ReaderT SqlReadBackend (HandlerFor UniWorX) AuthResult) + | APDB (ByteString -> (forall m. MonadAP m => AuthTagsEval m) -> Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> ReaderT SqlReadBackend (HandlerFor UniWorX) AuthResult) + | APBind (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> HandlerFor UniWorX (Either AccessPredicate AuthResult)) + | APBindDB (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> HandlerFor UniWorX (Either (ReaderT SqlReadBackend (HandlerFor UniWorX) (Either AccessPredicate AuthResult)) (Either AccessPredicate AuthResult))) -class (MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX) => MonadAP m where - evalAccessPred :: AccessPredicate -> (forall m'. MonadAP m' => AuthTagsEval m') -> Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> m AuthResult +class (MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX, MonadUnliftIO m) => MonadAP m where + evalAccessPred :: AccessPredicate -> ByteString -> (forall m'. MonadAP m' => AuthTagsEval m') -> Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> m AuthResult -instance {-# INCOHERENT #-} (MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX) => MonadAP m where - evalAccessPred aPred cont aid r w = liftHandler $ case aPred of + apRunDB :: forall a. ReaderT SqlReadBackend (HandlerFor UniWorX) a -> m a + +type family DisabledMonadAPInstance t err :: Constraint where + DisabledMonadAPInstance t err + = TypeError ( 'TypeError.Text "Used dangerous MonadAP instance for: " 'TypeError.:<>: 'TypeError.ShowType t + 'TypeError.:$$: 'TypeError.Text "This instance is currently disabled via TypeError because: " 'TypeError.:<>: err + 'TypeError.:$$: 'TypeError.Text "Please consider removing the usage triggering this error message before re-enabling or removing the instance." + ) + +instance ( BearerAuthSite UniWorX + -- , DisabledMonadAPInstance (HandlerFor UniWorX) ('TypeError.Text "It causes too many database connections") + ) => MonadAP (HandlerFor UniWorX) where + evalAccessPred :: HasCallStack => AccessPredicate -> ByteString -> (forall m'. MonadAP m' => AuthTagsEval m') -> Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> HandlerFor UniWorX AuthResult + evalAccessPred aPred contCtx cont aid r w = case aPred of (APPure p) -> runReader (p aid r w) <$> getMsgRenderer (APHandler p) -> p aid r w - (APDB p) -> runDBRead $ p cont aid r w + (APDB p) -> apRunDB $ p contCtx cont aid r w + (APBind p) -> evalAccessPred (APBindDB $ \aid' r' w' -> Right <$> p aid' r' w') contCtx cont aid r w + (APBindDB p) -> let contAP p' = evalAccessPred p' contCtx cont aid r w + in p aid r w >>= either apRunDB return >>= either contAP return -instance (MonadHandler m, HandlerSite m ~ UniWorX, BackendCompatible SqlReadBackend backend, BearerAuthSite UniWorX) => MonadAP (ReaderT backend m) where - evalAccessPred aPred cont aid r w = mapReaderT liftHandler . withReaderT (projectBackend @SqlReadBackend) $ case aPred of + apRunDB :: forall a. HasCallStack => ReaderT SqlReadBackend (HandlerFor UniWorX) a -> HandlerFor UniWorX a + apRunDB = runDBRead' callStack + +instance BearerAuthSite UniWorX => MonadAP (WidgetFor UniWorX) where + evalAccessPred :: HasCallStack => AccessPredicate -> ByteString -> (forall m'. MonadAP m' => AuthTagsEval m') -> Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> WidgetFor UniWorX AuthResult + evalAccessPred aPred contCtx cont aid r w = liftHandler $ evalAccessPred aPred contCtx cont aid r w + + apRunDB :: forall a. HasCallStack => ReaderT SqlReadBackend (HandlerFor UniWorX) a -> WidgetFor UniWorX a + apRunDB = liftHandler . apRunDB + +instance (MonadHandler m, HandlerSite m ~ UniWorX, BackendCompatible SqlReadBackend backend, BearerAuthSite UniWorX, MonadUnliftIO m) => MonadAP (ReaderT backend m) where + evalAccessPred aPred contCtx cont aid r w = mapReaderT liftHandler . withReaderT (projectBackend @SqlReadBackend) $ case aPred of (APPure p) -> lift $ runReader (p aid r w) <$> getMsgRenderer (APHandler p) -> lift $ p aid r w - (APDB p) -> p cont aid r w + (APDB p) -> p contCtx cont aid r w + (APBind p) -> evalAccessPred (APBindDB $ \aid' r' w' -> Right <$> p aid' r' w') contCtx cont aid r w + (APBindDB p) -> let contAP p' = evalAccessPred p' contCtx cont aid r w + in lift (p aid r w) >>= either id return >>= either contAP return + + apRunDB = hoist liftHandler . withReaderT projectBackend + +-- cacheAP :: ( Binary k +-- , Typeable v, Binary v +-- ) +-- => Maybe Expiry +-- -> k +-- -> HandlerFor UniWorX v +-- -> (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> v -> Either AccessPredicate (HandlerFor UniWorX AuthResult)) +-- -> AccessPredicate +-- cacheAP mExp k mkV cont = APBind $ \mAuthId route isWrite -> either (return . Left) (fmap Right) . cont mAuthId route isWrite =<< memcachedBy mExp k mkV + +cacheAPDB :: ( Binary k + , Typeable v, Binary v, NFData v + ) + => Maybe Expiry + -> k + -> ReaderT SqlReadBackend (HandlerFor UniWorX) v + -> (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> v -> Either AccessPredicate (HandlerFor UniWorX AuthResult)) + -> AccessPredicate +cacheAPDB mExp k mkV cont = APBindDB $ \mAuthId route isWrite -> do + cachedV <- memcachedByGet k + case cachedV of + Just v -> fmap Right . either (return . Left) (fmap Right) $ cont mAuthId route isWrite v + Nothing -> return . Left $ do + v <- mkV + memcachedBySet mExp k v + either (return . Left) (fmap Right . lift) $ cont mAuthId route isWrite v + +-- cacheAP' :: ( Binary k +-- , Typeable v, Binary v +-- ) +-- => Maybe Expiry +-- -> (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> Maybe (k, HandlerFor UniWorX v)) +-- -> (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> Maybe v -> Either AccessPredicate (HandlerFor UniWorX AuthResult)) +-- -> AccessPredicate +-- cacheAP' mExp mkKV cont = APBind $ \mAuthId route isWrite -> case mkKV mAuthId route isWrite of +-- Just (k, mkV) -> either (return . Left) (fmap Right) . cont mAuthId route isWrite . Just =<< memcachedBy mExp k mkV +-- Nothing -> either (return . Left) (fmap Right) $ cont mAuthId route isWrite Nothing + +cacheAPDB' :: ( Binary k + , Typeable v, Binary v, NFData v + ) + => Maybe Expiry + -> (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> Maybe (k, ReaderT SqlReadBackend (HandlerFor UniWorX) v)) + -> (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> Maybe v -> Either AccessPredicate (HandlerFor UniWorX AuthResult)) + -> AccessPredicate +cacheAPDB' mExp mkKV cont = APBindDB $ \mAuthId route isWrite -> case mkKV mAuthId route isWrite of + Just (k, mkV) -> do + cachedV <- memcachedByGet k + case cachedV of + Just v -> fmap Right . either (return . Left) (fmap Right) . cont mAuthId route isWrite $ Just v + Nothing -> return . Left $ do + v <- mkV + memcachedBySet mExp k v + either (return . Left) (fmap Right . lift) . cont mAuthId route isWrite $ Just v + Nothing -> fmap Right . either (return . Left) (fmap Right) $ cont mAuthId route isWrite Nothing orAR, andAR :: MsgRenderer -> AuthResult -> AuthResult -> AuthResult @@ -109,6 +216,21 @@ andAR _ _ reason@(Unauthorized _) = reason andAR _ Authorized other = other andAR _ AuthenticationRequired _ = AuthenticationRequired +_orARI18n, _andARI18n :: MsgRenderer -> I18nAuthResult -> I18nAuthResult -> I18nAuthResult +_orARI18n _ AuthorizedI18n _ = AuthorizedI18n +_orARI18n _ _ AuthorizedI18n = AuthorizedI18n +_orARI18n _ AuthenticationRequiredI18n _ = AuthenticationRequiredI18n +_orARI18n _ _ AuthenticationRequiredI18n = AuthenticationRequiredI18n +_orARI18n mr (UnauthorizedI18n x) (UnauthorizedI18n y) = fmap (Unauthorized . render mr) . MsgUnauthorizedOr <$> x <*> y +_orARI18n mr _ _ = UnauthorizedI18n . opoint $ render mr MsgUnauthorizedI18nMismatch +-- and +_andARI18n mr (UnauthorizedI18n x) (UnauthorizedI18n y) = fmap (Unauthorized . render mr) . MsgUnauthorizedAnd <$> x <*> y +_andARI18n _ reason@(UnauthorizedI18n _) _ = reason +_andARI18n _ _ reason@(UnauthorizedI18n _) = reason +_andARI18n _ AuthorizedI18n other = other +_andARI18n _ AuthenticationRequiredI18n _ = AuthenticationRequiredI18n +_andARI18n mr _ _ = UnauthorizedI18n . opoint $ render mr MsgUnauthorizedI18nMismatch + notAR :: RenderMessage UniWorX msg => MsgRenderer -> msg -> AuthResult -> AuthResult notAR _ _ (Unauthorized _) = Authorized notAR _ _ AuthenticationRequired = AuthenticationRequired @@ -129,9 +251,10 @@ data AuthContext = AuthContext , authActiveTags :: AuthTagActive } deriving (Generic, Typeable) -deriving instance Eq (AuthId UniWorX) => Eq AuthContext -deriving instance (Read (AuthId UniWorX), Eq (AuthId UniWorX), Hashable (AuthId UniWorX)) => Read AuthContext -deriving instance (Show (AuthId UniWorX), Eq (AuthId UniWorX), Hashable (AuthId UniWorX)) => Show AuthContext +deriving stock instance Eq (AuthId UniWorX) => Eq AuthContext +deriving stock instance Ord (AuthId UniWorX) => Ord AuthContext +deriving stock instance (Read (AuthId UniWorX), Eq (AuthId UniWorX), Hashable (AuthId UniWorX)) => Read AuthContext +deriving stock instance (Show (AuthId UniWorX), Eq (AuthId UniWorX), Hashable (AuthId UniWorX)) => Show AuthContext deriving anyclass instance Hashable (AuthId UniWorX) => Hashable AuthContext deriving anyclass instance (Binary (AuthId UniWorX), Eq (AuthId UniWorX), Hashable (AuthId UniWorX)) => Binary AuthContext @@ -142,7 +265,7 @@ getAuthContext :: forall m. => m AuthContext getAuthContext = liftHandler $ do authCtx <- AuthContext - <$> maybeAuthId + <$> defaultMaybeAuthId <*> runMaybeT (exceptTMaybe askBearerUnsafe) <*> (fromMaybe def <$> lookupSessionJson SessionActiveAuthTags) @@ -150,30 +273,42 @@ getAuthContext = liftHandler $ do return authCtx -isDryRun :: forall m. - ( MonadHandler m, HandlerSite m ~ UniWorX +newtype IsDryRun = MkIsDryRun { unIsDryRun :: Bool } + deriving (Eq, Ord, Read, Show, Generic, Typeable) + +isDryRun :: ( HasCallStack , BearerAuthSite UniWorX ) - => m Bool -isDryRun = $cachedHere . liftHandler $ orM + => HandlerFor UniWorX Bool +isDryRun = fmap unIsDryRun . cached . fmap MkIsDryRun $ runDBRead isDryRunDB + +isDryRunDB :: forall m backend. + ( HasCallStack + , MonadAP m, MonadCatch m + , BearerAuthSite UniWorX + , WithRunDB backend (HandlerFor UniWorX) m + , BackendCompatible SqlReadBackend backend + ) + => m Bool +isDryRunDB = fmap unIsDryRun . cached . fmap MkIsDryRun $ orM [ hasGlobalPostParam PostDryRun , hasGlobalGetParam GetDryRun , and2M bearerDryRun bearerRequired ] where bearerDryRun = has (_Just . _Object . ix "dry-run") <$> maybeCurrentBearerRestrictions @Value - bearerRequired = maybeT (return True) . catchIfMaybeT cPred . liftHandler $ do - mAuthId <- maybeAuthId - currentRoute <- maybe (permissionDeniedI MsgUnauthorizedToken404) return =<< getCurrentRoute - isWrite <- isWriteRequest currentRoute + bearerRequired = maybeT (return True) . catchIfMaybeT cPred $ do + mAuthId <- liftHandler defaultMaybeAuthId + currentRoute <- liftHandler $ maybe (permissionDeniedI MsgUnauthorizedToken404) return =<< getCurrentRoute + isWrite <- liftHandler $ isWriteRequest currentRoute let noTokenAuth :: AuthDNF -> AuthDNF noTokenAuth = over _dnfTerms . Set.filter . noneOf (re _nullable . folded) $ (== AuthToken) . plVar - dnf <- either throwM return $ routeAuthTags currentRoute + dnf <- throwLeft $ routeAuthTags currentRoute let eval :: forall m'. MonadAP m' => AuthTagsEval m' eval dnf' mAuthId' route' isWrite' = evalAuthTags 'isDryRun (AuthTagActive $ const True) eval (noTokenAuth dnf') mAuthId' route' isWrite' - in guardAuthResult <=< fmap fst . runWriterT $ eval dnf mAuthId currentRoute isWrite + in guardAuthResult <=< evalWriterT $ eval dnf mAuthId currentRoute isWrite return False @@ -200,25 +335,26 @@ askBearerUnsafe = ExceptT . $cachedHere . liftHandler . runExceptT $ do $logWarnS "AuthToken" $ tshow other throwError =<< unauthorizedI MsgUnauthorizedTokenInvalid -validateBearer :: BearerAuthSite UniWorX +validateBearer :: forall m. + ( HasCallStack + , MonadHandler m, HandlerSite m ~ UniWorX + , MonadCatch m, MonadAP m + , BearerAuthSite UniWorX + ) => Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -- ^ @isWrite@ -> BearerToken UniWorX - -> ReaderT SqlReadBackend (HandlerFor UniWorX) AuthResult + -> m AuthResult validateBearer mAuthId' route' isWrite' token' = $runCachedMemoT $ for4 memo validateBearer' mAuthId' route' isWrite' token' where - validateBearer' :: _ -> _ -> _ -> _ -> CachedMemoT (Maybe (AuthId UniWorX), Route UniWorX, Bool, BearerToken UniWorX) AuthResult (ReaderT SqlReadBackend (HandlerFor UniWorX)) AuthResult + validateBearer' :: _ -> _ -> _ -> _ -> CachedMemoT (Maybe (AuthId UniWorX), Route UniWorX, Bool, BearerToken UniWorX) AuthResult m AuthResult validateBearer' mAuthId route isWrite BearerToken{..} = lift . exceptT return return $ do - guardMExceptT (maybe True (HashSet.member route) bearerRoutes) (unauthorizedI MsgUnauthorizedTokenInvalidRoute) - - bearerAuthority' <- flip foldMapM bearerAuthority $ \case - Left tVal - | JSON.Success groupName <- JSON.fromJSON tVal -> maybeT (throwError =<< unauthorizedI MsgUnauthorizedTokenInvalidAuthorityGroup) . hoist lift $ do - Entity _ UserGroupMember{..} <- MaybeT . getBy $ UniquePrimaryUserGroupMember groupName Active - return $ Set.singleton userGroupMemberUser - | otherwise -> throwError =<< unauthorizedI MsgUnauthorizedTokenInvalidAuthorityValue - Right uid -> return $ Set.singleton uid + iforM_ bearerRoutes $ \case + BearerTokenRouteEval -> \routes -> guardMExceptT (HashSet.member route routes) $ unauthorizedI MsgUnauthorizedTokenInvalidRoute + BearerTokenRouteAccess -> \routes -> maybeTMExceptT (unauthorizedI MsgUnauthorizedTokenInvalidRoute) $ do + cRoute <- MaybeT getCurrentRoute + guard $ HashSet.member cRoute routes let -- Prevent infinite loops @@ -227,186 +363,302 @@ validateBearer mAuthId' route' isWrite' token' = $runCachedMemoT $ for4 memo val eval :: forall m'. MonadAP m' => AuthTagsEval m' eval dnf' mAuthId'' route'' isWrite'' = evalAuthTags 'validateBearer (AuthTagActive $ const True) eval (noTokenAuth dnf') mAuthId'' route'' isWrite'' - guardMExceptT (not $ Set.null bearerAuthority') $ unauthorizedI MsgUnauthorizedTokenInvalidNoAuthority + + bearerAuthority' <- hoist apRunDB $ do + bearerAuthority' <- flip foldMapM bearerAuthority $ \case + Left tVal + | JSON.Success groupName <- JSON.fromJSON tVal -> do + Entity _ primary <- maybeMExceptT (unauthorizedI MsgUnauthorizedTokenInvalidAuthorityGroup) . getBy $ UniquePrimaryUserGroupMember groupName Active + case bearerImpersonate of + Nothing -> return . Set.singleton $ userGroupMemberUser primary + Just iuid | iuid == userGroupMemberUser primary -> return . Set.singleton $ userGroupMemberUser primary + | otherwise -> do + unlessM (lift $ exists [UserGroupMemberUser ==. iuid, UserGroupMemberGroup ==. groupName]) $ + throwError =<< unauthorizedI MsgUnauthorizedTokenInvalidImpersonation + return $ Set.singleton iuid + | otherwise -> throwError =<< unauthorizedI MsgUnauthorizedTokenInvalidAuthorityValue + Right uid -> case bearerImpersonate of + Just iuid | uid == iuid -> return $ Set.singleton uid + | otherwise -> do + cID <- encrypt iuid + unlessM (lift $ is _Authorized <$> evalAccessWithFor [(AuthToken, False)] (Just uid) (AdminHijackUserR cID) True) $ + throwError =<< unauthorizedI MsgUnauthorizedTokenInvalidImpersonation + return $ Set.singleton iuid + Nothing -> return $ Set.singleton uid + + guardMExceptT (not $ Set.null bearerAuthority') $ unauthorizedI MsgUnauthorizedTokenInvalidNoAuthority + + forM_ bearerAuthority' $ \uid -> do + User{userTokensIssuedAfter} <- maybeMExceptT (unauthorizedI MsgUnauthorizedTokenInvalidAuthority) $ get uid + guardMExceptT (Just bearerIssuedAt >= userTokensIssuedAfter) (unauthorizedI MsgUnauthorizedTokenExpired) + + return bearerAuthority' forM_ bearerAuthority' $ \uid -> do - User{userTokensIssuedAfter} <- maybeMExceptT (unauthorizedI MsgUnauthorizedTokenInvalidAuthority) $ get uid - guardMExceptT (Just bearerIssuedAt >= userTokensIssuedAfter) (unauthorizedI MsgUnauthorizedTokenExpired) - authorityVal <- do - dnf <- either throwM return $ routeAuthTags route - fmap fst . runWriterT $ eval (noTokenAuth dnf) (Just uid) route isWrite + dnf <- throwLeft $ routeAuthTags route + lift . evalWriterT $ eval (noTokenAuth dnf) (Just uid) route isWrite guardExceptT (is _Authorized authorityVal) authorityVal whenIsJust bearerAddAuth $ \addDNF -> do $logDebugS "validateToken" $ tshow addDNF - additionalVal <- fmap fst . runWriterT $ eval (noTokenAuth addDNF) mAuthId route isWrite + additionalVal <- lift . evalWriterT $ eval (noTokenAuth addDNF) mAuthId route isWrite guardExceptT (is _Authorized additionalVal) additionalVal return Authorized -maybeBearerToken :: ( MonadHandler m, HandlerSite m ~ UniWorX +maybeBearerToken :: ( HasCallStack + , MonadHandler m, HandlerSite m ~ UniWorX , BearerAuthSite UniWorX + , MonadAP m + , MonadCatch m ) => m (Maybe (BearerToken UniWorX)) -maybeBearerToken = liftHandler . runMaybeT $ catchIfMaybeT cPred requireBearerToken +maybeBearerToken = $cachedHere . runMaybeT $ catchIfMaybeT cPred requireBearerToken where cPred err = any ($ err) [ is $ _HCError . _PermissionDenied , is $ _HCError . _NotAuthenticated ] -requireBearerToken :: ( MonadHandler m, HandlerSite m ~ UniWorX +requireBearerToken :: forall m. + ( HasCallStack + , MonadHandler m, HandlerSite m ~ UniWorX , BearerAuthSite UniWorX + , MonadAP m + , MonadCatch m ) => m (BearerToken UniWorX) -requireBearerToken = liftHandler $ do +requireBearerToken = do bearer <- exceptT (guardAuthResult >=> error "askToken should not throw `Authorized`") return askBearerUnsafe - mAuthId <- maybeAuthId + mAuthId <- defaultMaybeAuthId -- `maybeAuthId` would be an infinite loop; this is equivalent to `maybeAuthId` but ignoring `bearerImpersonate` from any valid token currentRoute <- maybe (permissionDeniedI MsgUnauthorizedToken404) return =<< getCurrentRoute - isWrite <- isWriteRequest currentRoute - guardAuthResult <=< runDBRead $ validateBearer mAuthId currentRoute isWrite bearer + isWrite <- liftHandler $ isWriteRequest currentRoute + guardAuthResult =<< validateBearer mAuthId currentRoute isWrite bearer return bearer requireCurrentBearerRestrictions :: forall a m. - ( MonadHandler m, HandlerSite m ~ UniWorX + ( HasCallStack + , MonadHandler m, HandlerSite m ~ UniWorX , FromJSON a, ToJSON a , BearerAuthSite UniWorX + , MonadAP m + , MonadCatch m ) => m (Maybe a) -requireCurrentBearerRestrictions = liftHandler . runMaybeT $ do - bearer <- requireBearerToken +requireCurrentBearerRestrictions = runMaybeT $ do + bearer <- lift requireBearerToken route <- MaybeT getCurrentRoute hoistMaybe $ bearer ^? _bearerRestrictionIx route maybeCurrentBearerRestrictions :: forall a m. - ( MonadHandler m, HandlerSite m ~ UniWorX + ( HasCallStack + , MonadHandler m, HandlerSite m ~ UniWorX , FromJSON a, ToJSON a , BearerAuthSite UniWorX + , MonadAP m + , MonadCatch m ) => m (Maybe a) -maybeCurrentBearerRestrictions = liftHandler . runMaybeT $ do +maybeCurrentBearerRestrictions = runMaybeT $ do bearer <- MaybeT maybeBearerToken route <- MaybeT getCurrentRoute hoistMaybe $ bearer ^? _bearerRestrictionIx route -tagAccessPredicate :: BearerAuthSite UniWorX +data AuthorizationCacheKey + = AuthCacheWorkflowWorkflowEdgeActors CryptoFileNameWorkflowWorkflow + | AuthCacheWorkflowWorkflowViewers CryptoFileNameWorkflowWorkflow + | AuthCacheWorkflowInstanceInitiators WorkflowInstanceName RouteWorkflowScope + | AuthCacheWorkflowInstanceWorkflowViewers WorkflowInstanceName RouteWorkflowScope + | AuthCacheSchoolFunctionList SchoolFunction | AuthCacheSystemFunctionList SystemFunction + | AuthCacheLecturerList | AuthCacheExternalExamStaffList | AuthCacheCorrectorList | AuthCacheExamCorrectorList | AuthCacheTutorList | AuthCacheSubmissionGroupUserList + | AuthCacheCourseRegisteredList TermId SchoolId CourseShorthand + deriving (Eq, Ord, Read, Show, Generic, Typeable) + deriving anyclass (Hashable, Binary) + +cacheAPSchoolFunction :: BearerAuthSite UniWorX + => SchoolFunction + -> Maybe Expiry + -> (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> Set (AuthId UniWorX) -> Either AccessPredicate (HandlerFor UniWorX AuthResult)) + -> AccessPredicate +cacheAPSchoolFunction f mExp = cacheAPDB mExp (AuthCacheSchoolFunctionList f) mkFunctionList + where + mkFunctionList = fmap (setOf $ folded . _Value) . E.select . E.from $ \userFunction -> do + E.where_ $ userFunction E.^. UserFunctionFunction E.==. E.val f + return $ userFunction E.^. UserFunctionUser + +cacheAPSystemFunction :: BearerAuthSite UniWorX + => SystemFunction + -> Maybe Expiry + -> (Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> Set (AuthId UniWorX) -> Either AccessPredicate (HandlerFor UniWorX AuthResult)) + -> AccessPredicate +cacheAPSystemFunction f mExp = cacheAPDB mExp (AuthCacheSystemFunctionList f) mkFunctionList + where + mkFunctionList = fmap (setOf $ folded . _Value) . E.select . E.from $ \userSystemFunction -> do + E.where_ $ userSystemFunction E.^. UserSystemFunctionFunction E.==. E.val f + E.&&. E.not_ (userSystemFunction E.^. UserSystemFunctionIsOptOut) + return $ userSystemFunction E.^. UserSystemFunctionUser + +tagAccessPredicate :: ( HasCallStack + , BearerAuthSite UniWorX + ) => AuthTag -> AccessPredicate tagAccessPredicate AuthFree = trueAP -tagAccessPredicate AuthAdmin = APDB $ \_ mAuthId route _ -> case route of - -- Courses: access only to school admins - CourseR tid ssh csh _ -> $cachedHereBinary (mAuthId, tid, ssh, csh) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isAdmin <- lift . E.selectExists . E.from $ \(course `E.InnerJoin` userAdmin) -> do - E.on $ course E.^. CourseSchool E.==. userAdmin E.^. UserFunctionSchool - E.where_ $ userAdmin E.^. UserFunctionUser E.==. E.val authId - E.&&. userAdmin E.^. UserFunctionFunction E.==. E.val SchoolAdmin - E.&&. course E.^. CourseTerm E.==. E.val tid - E.&&. course E.^. CourseSchool E.==. E.val ssh - E.&&. course E.^. CourseShorthand E.==. E.val csh - guardMExceptT isAdmin (unauthorizedI MsgUnauthorizedSchoolAdmin) - return Authorized - -- Allocations: access only to school admins - AllocationR tid ssh ash _ -> $cachedHereBinary (mAuthId, tid, ssh, ash) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isAdmin <- lift . E.selectExists . E.from $ \(allocation `E.InnerJoin` userAdmin) -> do - E.on $ allocation E.^. AllocationSchool E.==. userAdmin E.^. UserFunctionSchool - E.where_ $ userAdmin E.^. UserFunctionUser E.==. E.val authId - E.&&. userAdmin E.^. UserFunctionFunction E.==. E.val SchoolAdmin - E.&&. allocation E.^. AllocationTerm E.==. E.val tid - E.&&. allocation E.^. AllocationSchool E.==. E.val ssh - E.&&. allocation E.^. AllocationShorthand E.==. E.val ash - guardMExceptT isAdmin (unauthorizedI MsgUnauthorizedSchoolAdmin) - return Authorized - -- Schools: access only to school admins - SchoolR ssh _ -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isAdmin <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolAdmin] - guardMExceptT isAdmin (unauthorizedI MsgUnauthorizedSchoolAdmin) - return Authorized - -- other routes: access to any admin is granted here - _other -> $cachedHereBinary mAuthId . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - adrights <- lift $ selectFirst [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolAdmin] [] - guardMExceptT (isJust adrights) (unauthorizedI MsgUnauthorizedSiteAdmin) - return Authorized -tagAccessPredicate AuthSystemExamOffice = APDB $ \_ mAuthId _ _ -> $cachedHereBinary mAuthId . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isExamOffice <- lift $ exists [UserSystemFunctionUser ==. authId, UserSystemFunctionFunction ==. SystemExamOffice, UserSystemFunctionIsOptOut ==. False] - guardMExceptT isExamOffice $ unauthorizedI MsgUnauthorizedSystemExamOffice - return Authorized -tagAccessPredicate AuthExamOffice = APDB $ \_ mAuthId route _ -> case route of - CExamR tid ssh csh examn _ -> $cachedHereBinary (mAuthId, tid, ssh, csh, examn) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - hasUsers <- lift . E.selectExists . E.from $ \(course `E.InnerJoin` exam `E.InnerJoin` examResult) -> do - E.on $ examResult E.^. ExamResultExam E.==. exam E.^. ExamId - E.on $ exam E.^. ExamCourse E.==. course E.^. CourseId +tagAccessPredicate AuthAdmin = cacheAPSchoolFunction SchoolAdmin (Just $ Right diffHour) $ \mAuthId' route' _ adminList -> if + | maybe True (`Set.notMember` adminList) mAuthId' -> Right $ case route' of + _ | is _Nothing mAuthId' -> return AuthenticationRequired + CourseR{} -> unauthorizedI MsgUnauthorizedSchoolAdmin + AllocationR{} -> unauthorizedI MsgUnauthorizedSchoolAdmin + SchoolR _ _ -> unauthorizedI MsgUnauthorizedSchoolAdmin + _other -> unauthorizedI MsgUnauthorizedSiteAdmin + | otherwise -> Left $ APDB $ \_ _ mAuthId route _ -> case route of + -- Courses: access only to school admins + CourseR tid ssh csh _ -> $cachedHereBinary (mAuthId, tid, ssh, csh) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isAdmin <- lift . E.selectExists . E.from $ \(course `E.InnerJoin` userAdmin) -> do + E.on $ course E.^. CourseSchool E.==. userAdmin E.^. UserFunctionSchool + E.where_ $ userAdmin E.^. UserFunctionUser E.==. E.val authId + E.&&. userAdmin E.^. UserFunctionFunction E.==. E.val SchoolAdmin + E.&&. course E.^. CourseTerm E.==. E.val tid + E.&&. course E.^. CourseSchool E.==. E.val ssh + E.&&. course E.^. CourseShorthand E.==. E.val csh + guardMExceptT isAdmin $ unauthorizedI MsgUnauthorizedSchoolAdmin + return Authorized + -- Allocations: access only to school admins + AllocationR tid ssh ash _ -> $cachedHereBinary (mAuthId, tid, ssh, ash) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isAdmin <- lift . E.selectExists . E.from $ \(allocation `E.InnerJoin` userAdmin) -> do + E.on $ allocation E.^. AllocationSchool E.==. userAdmin E.^. UserFunctionSchool + E.where_ $ userAdmin E.^. UserFunctionUser E.==. E.val authId + E.&&. userAdmin E.^. UserFunctionFunction E.==. E.val SchoolAdmin + E.&&. allocation E.^. AllocationTerm E.==. E.val tid + E.&&. allocation E.^. AllocationSchool E.==. E.val ssh + E.&&. allocation E.^. AllocationShorthand E.==. E.val ash + guardMExceptT isAdmin (unauthorizedI MsgUnauthorizedSchoolAdmin) + return Authorized + -- Schools: access only to school admins + SchoolR ssh _ -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isAdmin <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolAdmin] + guardMExceptT isAdmin (unauthorizedI MsgUnauthorizedSchoolAdmin) + return Authorized + -- other routes: access to any admin is granted here + _other -> $cachedHereBinary mAuthId . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + adrights <- lift $ selectFirst [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolAdmin] [] + guardMExceptT (isJust adrights) (unauthorizedI MsgUnauthorizedSiteAdmin) + return Authorized +tagAccessPredicate AuthSystemExamOffice = cacheAPSystemFunction SystemExamOffice (Just $ Right diffHour) $ \mAuthId' _ _ examOfficeList -> if + | maybe True (`Set.notMember` examOfficeList) mAuthId' -> Right $ if + | is _Nothing mAuthId' -> return AuthenticationRequired + | otherwise -> unauthorizedI MsgUnauthorizedSystemExamOffice + | otherwise -> Left $ APDB $ \_ _ mAuthId _ _ -> $cachedHereBinary mAuthId . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isExamOffice <- lift $ exists [UserSystemFunctionUser ==. authId, UserSystemFunctionFunction ==. SystemExamOffice, UserSystemFunctionIsOptOut ==. False] + guardMExceptT isExamOffice $ unauthorizedI MsgUnauthorizedSystemExamOffice + return Authorized +tagAccessPredicate AuthStudent = cacheAPSystemFunction SystemStudent (Just $ Right diffHour) $ \mAuthId' _ _ studentList -> if + | maybe True (`Set.notMember` studentList) mAuthId' -> Right $ if + | is _Nothing mAuthId' -> return AuthenticationRequired + | otherwise -> unauthorizedI MsgUnauthorizedStudent + | otherwise -> Left $ APDB $ \_ _ mAuthId _ _ -> $cachedHereBinary mAuthId . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isExamOffice <- lift $ exists [UserSystemFunctionUser ==. authId, UserSystemFunctionFunction ==. SystemStudent, UserSystemFunctionIsOptOut ==. False] + guardMExceptT isExamOffice $ unauthorizedI MsgUnauthorizedStudent + return Authorized +tagAccessPredicate AuthExamOffice = cacheAPSchoolFunction SchoolExamOffice (Just $ Right diffHour) $ \mAuthId' route' _ examOfficeList -> if + | maybe True (`Set.notMember` examOfficeList) mAuthId' -> Right $ case route' of + _ | is _Nothing mAuthId' -> return AuthenticationRequired + CExamR{} -> unauthorizedI MsgUnauthorizedExamExamOffice + EExamR{} -> unauthorizedI MsgUnauthorizedExternalExamExamOffice + CourseR{} -> unauthorizedI MsgUnauthorizedExamExamOffice + SchoolR _ _ -> unauthorizedI MsgUnauthorizedSchoolExamOffice + _other -> unauthorizedI MsgUnauthorizedExamOffice + | otherwise -> Left $ APDB $ \_ _ mAuthId route _ -> case route of + CExamR tid ssh csh examn _ -> $cachedHereBinary (mAuthId, tid, ssh, csh, examn) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + hasUsers <- lift . E.selectExists . E.from $ \(course `E.InnerJoin` exam `E.InnerJoin` examResult) -> do + E.on $ examResult E.^. ExamResultExam E.==. exam E.^. ExamId + E.on $ exam E.^. ExamCourse E.==. course E.^. CourseId - E.where_ $ course E.^. CourseTerm E.==. E.val tid - E.&&. course E.^. CourseSchool E.==. E.val ssh - E.&&. course E.^. CourseShorthand E.==. E.val csh - E.&&. exam E.^. ExamName E.==. E.val examn + E.where_ $ course E.^. CourseTerm E.==. E.val tid + E.&&. course E.^. CourseSchool E.==. E.val ssh + E.&&. course E.^. CourseShorthand E.==. E.val csh + E.&&. exam E.^. ExamName E.==. E.val examn - E.where_ $ examOfficeExamResultAuth (E.val authId) examResult - guardMExceptT hasUsers (unauthorizedI MsgUnauthorizedExamExamOffice) - return Authorized - EExamR tid ssh coursen examn _ -> $cachedHereBinary (mAuthId, tid, ssh, coursen, examn) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - hasUsers <- lift . E.selectExists . E.from $ \(eexam `E.InnerJoin` eexamResult) -> do - E.on $ eexam E.^. ExternalExamId E.==. eexamResult E.^. ExternalExamResultExam + E.where_ $ examOfficeExamResultAuth (E.val authId) examResult + guardMExceptT hasUsers (unauthorizedI MsgUnauthorizedExamExamOffice) + return Authorized + EExamR tid ssh coursen examn _ -> $cachedHereBinary (mAuthId, tid, ssh, coursen, examn) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + hasUsers <- lift . E.selectExists . E.from $ \(eexam `E.InnerJoin` eexamResult) -> do + E.on $ eexam E.^. ExternalExamId E.==. eexamResult E.^. ExternalExamResultExam - E.where_ $ eexam E.^. ExternalExamTerm E.==. E.val tid - E.&&. eexam E.^. ExternalExamSchool E.==. E.val ssh - E.&&. eexam E.^. ExternalExamCourseName E.==. E.val coursen - E.&&. eexam E.^. ExternalExamExamName E.==. E.val examn + E.where_ $ eexam E.^. ExternalExamTerm E.==. E.val tid + E.&&. eexam E.^. ExternalExamSchool E.==. E.val ssh + E.&&. eexam E.^. ExternalExamCourseName E.==. E.val coursen + E.&&. eexam E.^. ExternalExamExamName E.==. E.val examn - E.where_ $ examOfficeExternalExamResultAuth (E.val authId) eexamResult - guardMExceptT hasUsers $ unauthorizedI MsgUnauthorizedExternalExamExamOffice - return Authorized - CourseR _ ssh _ _ -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isExamOffice <- lift . existsBy $ UniqueUserFunction authId ssh SchoolExamOffice - guardMExceptT isExamOffice $ unauthorizedI MsgUnauthorizedExamExamOffice - return Authorized - _other -> $cachedHereBinary mAuthId . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isExamOffice <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolExamOffice] - guardMExceptT isExamOffice (unauthorizedI MsgUnauthorizedExamOffice) - return Authorized -tagAccessPredicate AuthEvaluation = APDB $ \_ mAuthId route _ -> case route of - ParticipantsR _ ssh -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolEvaluation - guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation - return Authorized - CourseR _ ssh _ _ -> $cachedHereBinary(mAuthId, ssh) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolEvaluation - guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation - return Authorized - _other -> $cachedHereBinary mAuthId . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isEvaluation <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolEvaluation] - guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation - return Authorized -tagAccessPredicate AuthAllocationAdmin = APDB $ \_ mAuthId route _ -> case route of - AllocationR _ ssh _ _ -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolAllocation - guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedAllocationAdmin - return Authorized - CourseR _ ssh _ _ -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolAllocation - guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedAllocationAdmin - return Authorized - _other -> $cachedHereBinary mAuthId . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isEvaluation <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolAllocation] - guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedAllocationAdmin - return Authorized -tagAccessPredicate AuthToken = APDB $ \_ mAuthId route isWrite -> exceptT return return $ + E.where_ $ examOfficeExternalExamResultAuth (E.val authId) eexamResult + guardMExceptT hasUsers $ unauthorizedI MsgUnauthorizedExternalExamExamOffice + return Authorized + CourseR _ ssh _ _ -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isExamOffice <- lift . existsBy $ UniqueUserFunction authId ssh SchoolExamOffice + guardMExceptT isExamOffice $ unauthorizedI MsgUnauthorizedExamExamOffice + return Authorized + SchoolR ssh _ -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isAdmin <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolExamOffice] + guardMExceptT isAdmin (unauthorizedI MsgUnauthorizedSchoolExamOffice) + return Authorized + _other -> $cachedHereBinary mAuthId . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isExamOffice <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolExamOffice] + guardMExceptT isExamOffice (unauthorizedI MsgUnauthorizedExamOffice) + return Authorized +tagAccessPredicate AuthEvaluation = cacheAPSchoolFunction SchoolEvaluation (Just $ Right diffHour) $ \mAuthId' _ _ evaluationList -> if + | maybe True (`Set.notMember` evaluationList) mAuthId' -> Right $ if + | is _Nothing mAuthId' -> return AuthenticationRequired + | otherwise -> unauthorizedI MsgUnauthorizedEvaluation + | otherwise -> Left $ APDB $ \_ _ mAuthId route _ -> case route of + ParticipantsR _ ssh -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolEvaluation + guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation + return Authorized + CourseR _ ssh _ _ -> $cachedHereBinary(mAuthId, ssh) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolEvaluation + guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation + return Authorized + _other -> $cachedHereBinary mAuthId . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isEvaluation <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolEvaluation] + guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedEvaluation + return Authorized +tagAccessPredicate AuthAllocationAdmin = cacheAPSchoolFunction SchoolAllocation (Just $ Right diffHour) $ \mAuthId' _ _ allocationList -> if + | maybe True (`Set.notMember` allocationList) mAuthId' -> Right $ if + | is _Nothing mAuthId' -> return AuthenticationRequired + | otherwise -> unauthorizedI MsgUnauthorizedAllocationAdmin + | otherwise -> Left $ APDB $ \_ _ mAuthId route _ -> case route of + AllocationR _ ssh _ _ -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolAllocation + guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedAllocationAdmin + return Authorized + CourseR _ ssh _ _ -> $cachedHereBinary (mAuthId, ssh) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isEvaluation <- lift . existsBy $ UniqueUserFunction authId ssh SchoolAllocation + guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedAllocationAdmin + return Authorized + _other -> $cachedHereBinary mAuthId . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isEvaluation <- lift $ exists [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolAllocation] + guardMExceptT isEvaluation $ unauthorizedI MsgUnauthorizedAllocationAdmin + return Authorized +tagAccessPredicate AuthToken = APDB $ \_ _ mAuthId route isWrite -> exceptT return return $ lift . validateBearer mAuthId route isWrite =<< askBearerUnsafe -tagAccessPredicate AuthNoEscalation = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthNoEscalation = APDB $ \_ _ mAuthId route _ -> case route of AdminHijackUserR cID -> $cachedHereBinary (mAuthId, cID) . exceptT return return $ do myUid <- maybeExceptT AuthenticationRequired $ return mAuthId uid <- decrypt cID @@ -427,140 +679,202 @@ tagAccessPredicate AuthDevelopment = APHandler $ \_ r _ -> do #else return $ Unauthorized "Route under development" #endif -tagAccessPredicate AuthLecturer = APDB $ \_ mAuthId route _ -> case route of - CourseR tid ssh csh _ -> $cachedHereBinary (mAuthId, tid, ssh, csh) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isLecturer <- lift . E.selectExists . E.from $ \(course `E.InnerJoin` lecturer) -> do - E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse - E.where_ $ lecturer E.^. LecturerUser E.==. E.val authId + +tagAccessPredicate AuthLecturer = cacheAPDB' (Just $ Right diffMinute) mkLecturerList $ \mAuthId' route' _ mLecturerList -> if + | Just lecturerList <- mLecturerList + , maybe True (`Set.notMember` lecturerList) mAuthId' -> Right $ case route' of + _ | is _Nothing mAuthId' -> return AuthenticationRequired + CourseR{} -> unauthorizedI MsgUnauthorizedLecturer + AllocationR{} -> unauthorizedI MsgUnauthorizedAllocationLecturer + EExamR{} -> unauthorizedI MsgUnauthorizedExternalExamLecturer + _other -> unauthorizedI MsgUnauthorizedSchoolLecturer + | otherwise -> Left $ APDB $ \_ _ mAuthId route _ -> case route of + CourseR tid ssh csh _ -> $cachedHereBinary (mAuthId, tid, ssh, csh) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isLecturer <- lift . E.selectExists . E.from $ \(course `E.InnerJoin` lecturer) -> do + E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse + E.where_ $ lecturer E.^. LecturerUser E.==. E.val authId + E.&&. course E.^. CourseTerm E.==. E.val tid + E.&&. course E.^. CourseSchool E.==. E.val ssh + E.&&. course E.^. CourseShorthand E.==. E.val csh + guardMExceptT isLecturer (unauthorizedI MsgUnauthorizedLecturer) + return Authorized + AllocationR tid ssh ash _ -> $cachedHereBinary (mAuthId, tid, ssh, ash) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isLecturer <- lift . E.selectExists . E.from $ \(allocation `E.InnerJoin` allocationCourse `E.InnerJoin` course `E.InnerJoin` lecturer) -> do + E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse + E.on $ course E.^. CourseId E.==. allocationCourse E.^. AllocationCourseCourse + E.on $ allocation E.^. AllocationId E.==. allocationCourse E.^. AllocationCourseAllocation + E.where_ $ lecturer E.^. LecturerUser E.==. E.val authId + E.&&. allocation E.^. AllocationTerm E.==. E.val tid + E.&&. allocation E.^. AllocationSchool E.==. E.val ssh + E.&&. allocation E.^. AllocationShorthand E.==. E.val ash + guardMExceptT isLecturer $ unauthorizedI MsgUnauthorizedAllocationLecturer + return Authorized + EExamR tid ssh coursen examn _ -> $cachedHereBinary (mAuthId, tid, ssh, coursen, examn) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isLecturer <- lift . E.selectExists . E.from $ \(eexam `E.InnerJoin` staff) -> do + E.on $ eexam E.^. ExternalExamId E.==. staff E.^. ExternalExamStaffExam + E.where_ $ staff E.^. ExternalExamStaffUser E.==. E.val authId + E.&&. eexam E.^. ExternalExamTerm E.==. E.val tid + E.&&. eexam E.^. ExternalExamSchool E.==. E.val ssh + E.&&. eexam E.^. ExternalExamCourseName E.==. E.val coursen + E.&&. eexam E.^. ExternalExamExamName E.==. E.val examn + guardMExceptT isLecturer $ unauthorizedI MsgUnauthorizedExternalExamLecturer + return Authorized + -- lecturer for any school will do + _ -> $cachedHereBinary mAuthId . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + void . maybeMExceptT (unauthorizedI MsgUnauthorizedSchoolLecturer) $ selectFirst [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolLecturer] [] + return Authorized + where + mkLecturerList _ route _ = case route of + CourseR{} -> cacheLecturerList + AllocationR{} -> cacheLecturerList + EExamR{} -> Just + ( AuthCacheExternalExamStaffList + , fmap (setOf $ folded . _Value) . E.select . E.from $ return . (E.^. ExternalExamStaffUser) + ) + _other -> Just + ( AuthCacheSchoolFunctionList SchoolLecturer + , fmap (setOf $ folded . _Value) . E.select . E.from $ \userFunction -> do + E.where_ $ userFunction E.^. UserFunctionFunction E.==. E.val SchoolLecturer + return $ userFunction E.^. UserFunctionUser + ) + where + cacheLecturerList = Just + ( AuthCacheLecturerList + , fmap (setOf $ folded . _Value) . E.select . E.from $ return . (E.^. LecturerUser) + ) +tagAccessPredicate AuthCorrector = cacheAPDB (Just $ Right diffMinute) AuthCacheCorrectorList mkCorrectorList $ \mAuthId' route' _ correctorList -> if + | maybe True (`Set.notMember` correctorList) mAuthId' -> Right $ case route' of + _ | is _Nothing mAuthId' -> return AuthenticationRequired + CSubmissionR{} -> unauthorizedI MsgUnauthorizedSubmissionCorrector + CSheetR{} -> unauthorizedI MsgUnauthorizedSheetCorrector + CourseR{} -> unauthorizedI MsgUnauthorizedCorrector + _other -> unauthorizedI MsgUnauthorizedCorrectorAny + | otherwise -> Left $ APDB $ \_ _ mAuthId route _ -> exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + case route of + CSubmissionR _ _ _ _ cID _ -> lift . $cachedHereBinary (authId, cID) . maybeT (unauthorizedI MsgUnauthorizedSubmissionCorrector) $ do + sid <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decrypt cID + guardM . lift . E.selectExists . E.from $ \submission -> + E.where_ $ submission E.^. SubmissionId E.==. E.val sid + E.&&. submission E.^. SubmissionRatingBy E.==. E.justVal authId + return Authorized + CSheetR tid ssh csh shn _ -> lift . $cachedHereBinary (authId, tid, ssh, csh, shn) . maybeT (unauthorizedI MsgUnauthorizedSheetCorrector) $ do + guardM . lift . E.selectExists . E.from $ \(course `E.InnerJoin` sheet `E.InnerJoin` sheetCorrector) -> do + E.on $ sheetCorrector E.^. SheetCorrectorSheet E.==. sheet E.^. SheetId + E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId + E.where_ $ sheetCorrector E.^. SheetCorrectorUser E.==. E.val authId + E.where_ $ course E.^. CourseTerm E.==. E.val tid + E.&&. course E.^. CourseSchool E.==. E.val ssh + E.&&. course E.^. CourseShorthand E.==. E.val csh + E.&&. sheet E.^. SheetName E.==. E.val shn + return Authorized + CourseR tid ssh csh _ -> lift . $cachedHereBinary (mAuthId, tid, ssh, csh) . maybeT (unauthorizedI MsgUnauthorizedCorrector) $ do + guardM . lift . E.selectExists . E.from $ \(course `E.InnerJoin` sheet `E.InnerJoin` sheetCorrector) -> do + E.on $ sheetCorrector E.^. SheetCorrectorSheet E.==. sheet E.^. SheetId + E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId + E.where_ $ sheetCorrector E.^. SheetCorrectorUser E.==. E.val authId + E.where_ $ course E.^. CourseTerm E.==. E.val tid + E.&&. course E.^. CourseSchool E.==. E.val ssh + E.&&. course E.^. CourseShorthand E.==. E.val csh + return Authorized + _ -> lift . $cachedHereBinary mAuthId . maybeT (unauthorizedI MsgUnauthorizedCorrectorAny) $ do + guardM . lift . E.selectExists . E.from $ \sheetCorrector -> + E.where_ $ sheetCorrector E.^. SheetCorrectorUser E.==. E.val authId + return Authorized + where + mkCorrectorList = execWriterT $ do + tellM . fmap (setOf $ folded . _Value . _Just) . E.select . E.from $ \submission -> do + E.where_ . E.isJust $ submission E.^. SubmissionRatingBy + return $ submission E.^. SubmissionRatingBy + tellM . fmap (setOf $ folded . _Value) . E.select . E.from $ return . (E.^. SheetCorrectorUser) +tagAccessPredicate AuthExamCorrector = cacheAPDB (Just $ Right diffMinute) AuthCacheExamCorrectorList mkExamCorrectorList $ \mAuthId' route' _ examCorrectorList -> if + | maybe True (`Set.notMember` examCorrectorList) mAuthId' -> Right $ case route' of + _ | is _Nothing mAuthId' -> return AuthenticationRequired + CExamR{} -> unauthorizedI MsgUnauthorizedExamCorrector + CourseR{} -> unauthorizedI MsgUnauthorizedExamCorrector + r -> $unsupportedAuthPredicate AuthExamCorrector r + | otherwise -> Left $ APDB $ \_ _ mAuthId route _ -> case route of + CExamR tid ssh csh examn _ -> $cachedHereBinary (mAuthId, tid, ssh, csh, examn) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isCorrector <- lift . E.selectExists . E.from $ \(course `E.InnerJoin` exam `E.InnerJoin` examCorrector) -> do + E.on $ examCorrector E.^. ExamCorrectorExam E.==. exam E.^. ExamId + E.on $ exam E.^. ExamCourse E.==. course E.^. CourseId + E.where_ $ examCorrector E.^. ExamCorrectorUser E.==. E.val authId E.&&. course E.^. CourseTerm E.==. E.val tid E.&&. course E.^. CourseSchool E.==. E.val ssh E.&&. course E.^. CourseShorthand E.==. E.val csh - guardMExceptT isLecturer (unauthorizedI MsgUnauthorizedLecturer) - return Authorized - AllocationR tid ssh ash _ -> $cachedHereBinary (mAuthId, tid, ssh, ash) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isLecturer <- lift . E.selectExists . E.from $ \(allocation `E.InnerJoin` allocationCourse `E.InnerJoin` course `E.InnerJoin` lecturer) -> do - E.on $ course E.^. CourseId E.==. lecturer E.^. LecturerCourse - E.on $ course E.^. CourseId E.==. allocationCourse E.^. AllocationCourseCourse - E.on $ allocation E.^. AllocationId E.==. allocationCourse E.^. AllocationCourseAllocation - E.where_ $ lecturer E.^. LecturerUser E.==. E.val authId - E.&&. allocation E.^. AllocationTerm E.==. E.val tid - E.&&. allocation E.^. AllocationSchool E.==. E.val ssh - E.&&. allocation E.^. AllocationShorthand E.==. E.val ash - guardMExceptT isLecturer $ unauthorizedI MsgUnauthorizedAllocationLecturer - return Authorized - EExamR tid ssh coursen examn _ -> $cachedHereBinary (mAuthId, tid, ssh, coursen, examn) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isLecturer <- lift . E.selectExists . E.from $ \(eexam `E.InnerJoin` staff) -> do - E.on $ eexam E.^. ExternalExamId E.==. staff E.^. ExternalExamStaffExam - E.where_ $ staff E.^. ExternalExamStaffUser E.==. E.val authId - E.&&. eexam E.^. ExternalExamTerm E.==. E.val tid - E.&&. eexam E.^. ExternalExamSchool E.==. E.val ssh - E.&&. eexam E.^. ExternalExamCourseName E.==. E.val coursen - E.&&. eexam E.^. ExternalExamExamName E.==. E.val examn - guardMExceptT isLecturer $ unauthorizedI MsgUnauthorizedExternalExamLecturer - return Authorized - -- lecturer for any school will do - _ -> $cachedHereBinary mAuthId . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - void . maybeMExceptT (unauthorizedI MsgUnauthorizedSchoolLecturer) $ selectFirst [UserFunctionUser ==. authId, UserFunctionFunction ==. SchoolLecturer] [] - return Authorized -tagAccessPredicate AuthCorrector = APDB $ \_ mAuthId route _ -> exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - resList <- $cachedHereBinary mAuthId . lift . E.select . E.from $ \(course `E.InnerJoin` sheet `E.InnerJoin` sheetCorrector) -> do - E.on $ sheetCorrector E.^. SheetCorrectorSheet E.==. sheet E.^. SheetId - E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId - E.where_ $ sheetCorrector E.^. SheetCorrectorUser E.==. E.val authId - return (course E.^. CourseId, sheet E.^. SheetId) - let - resMap :: Map CourseId (Set SheetId) - resMap = Map.fromListWith Set.union [ (cid, Set.singleton sid) | (E.Value cid, E.Value sid) <- resList ] - case route of - CSubmissionR _ _ _ _ cID _ -> $cachedHereBinary (mAuthId, cID) . maybeT (unauthorizedI MsgUnauthorizedSubmissionCorrector) $ do - sid <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decrypt cID - Submission{..} <- MaybeT . lift $ get sid - guard $ Just authId == submissionRatingBy - return Authorized - CSheetR tid ssh csh shn _ -> $cachedHereBinary (mAuthId, tid, ssh, csh, shn) . maybeT (unauthorizedI MsgUnauthorizedSheetCorrector) $ do - Entity cid _ <- MaybeT . lift . getBy $ TermSchoolCourseShort tid ssh csh - Entity sid _ <- MaybeT . lift . getBy $ CourseSheet cid shn - guard $ sid `Set.member` fromMaybe Set.empty (resMap !? cid) - return Authorized - CourseR tid ssh csh _ -> $cachedHereBinary (mAuthId, tid, ssh, csh) . maybeT (unauthorizedI MsgUnauthorizedCorrector) $ do - Entity cid _ <- MaybeT . lift . getBy $ TermSchoolCourseShort tid ssh csh - guard $ cid `Set.member` Map.keysSet resMap - return Authorized - _ -> do - guardMExceptT (not $ Map.null resMap) (unauthorizedI MsgUnauthorizedCorrectorAny) - return Authorized -tagAccessPredicate AuthExamCorrector = APDB $ \_ mAuthId route _ -> case route of - CExamR tid ssh csh examn _ -> $cachedHereBinary (mAuthId, tid, ssh, csh, examn) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isCorrector <- lift . E.selectExists . E.from $ \(course `E.InnerJoin` exam `E.InnerJoin` examCorrector) -> do - E.on $ examCorrector E.^. ExamCorrectorExam E.==. exam E.^. ExamId - E.on $ exam E.^. ExamCourse E.==. course E.^. CourseId - E.where_ $ examCorrector E.^. ExamCorrectorUser E.==. E.val authId - E.&&. course E.^. CourseTerm E.==. E.val tid - E.&&. course E.^. CourseSchool E.==. E.val ssh - E.&&. course E.^. CourseShorthand E.==. E.val csh - E.&&. exam E.^. ExamName E.==. E.val examn - guardMExceptT isCorrector $ unauthorizedI MsgUnauthorizedExamCorrector - return Authorized - CourseR tid ssh csh _ -> $cachedHereBinary (tid, ssh, csh) . exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isCorrector <- lift . E.selectExists . E.from $ \(course `E.InnerJoin` exam `E.InnerJoin` examCorrector) -> do - E.on $ course E.^. CourseId E.==. exam E.^. ExamCourse - E.on $ exam E.^. ExamId E.==. examCorrector E.^. ExamCorrectorExam - E.where_ $ examCorrector E.^. ExamCorrectorUser E.==. E.val authId - E.&&. course E.^. CourseTerm E.==. E.val tid - E.&&. course E.^. CourseSchool E.==. E.val ssh - E.&&. course E.^. CourseShorthand E.==. E.val csh - guardMExceptT isCorrector $ unauthorizedI MsgUnauthorizedExamCorrector - return Authorized - r -> $unsupportedAuthPredicate AuthExamCorrector r -tagAccessPredicate AuthTutor = APDB $ \_ mAuthId route _ -> exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - resList <- $cachedHereBinary authId . lift . E.select . E.from $ \(course `E.InnerJoin` tutorial `E.InnerJoin` tutor) -> do - E.on $ tutor E.^. TutorTutorial E.==. tutorial E.^. TutorialId - E.on $ tutorial E.^. TutorialCourse E.==. course E.^. CourseId - E.where_ $ tutor E.^. TutorUser E.==. E.val authId - return (course E.^. CourseId, tutorial E.^. TutorialId) - let - resMap :: Map CourseId (Set TutorialId) - resMap = Map.fromListWith Set.union [ (cid, Set.singleton tutid) | (E.Value cid, E.Value tutid) <- resList ] - case route of - CTutorialR tid ssh csh tutn _ -> maybeT (unauthorizedI MsgUnauthorizedTutorialTutor) $ do - Entity cid _ <- $cachedHereBinary (tid, ssh, csh) . MaybeT . lift . getBy $ TermSchoolCourseShort tid ssh csh - Entity tutid _ <- $cachedHereBinary (cid, tutn) . MaybeT . lift . getBy $ UniqueTutorial cid tutn - guard $ tutid `Set.member` fromMaybe Set.empty (resMap !? cid) - return Authorized - CourseR tid ssh csh _ -> maybeT (unauthorizedI MsgUnauthorizedCourseTutor) $ do - Entity cid _ <- $cachedHereBinary (tid, ssh, csh) . MaybeT . lift . getBy $ TermSchoolCourseShort tid ssh csh - guard $ cid `Set.member` Map.keysSet resMap - return Authorized - _ -> do - guardMExceptT (not $ Map.null resMap) (unauthorizedI MsgUnauthorizedTutor) - return Authorized -tagAccessPredicate AuthTutorControl = APDB $ \_ _ route _ -> case route of + E.&&. exam E.^. ExamName E.==. E.val examn + guardMExceptT isCorrector $ unauthorizedI MsgUnauthorizedExamCorrector + return Authorized + CourseR tid ssh csh _ -> $cachedHereBinary (tid, ssh, csh) . exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isCorrector <- lift . E.selectExists . E.from $ \(course `E.InnerJoin` exam `E.InnerJoin` examCorrector) -> do + E.on $ course E.^. CourseId E.==. exam E.^. ExamCourse + E.on $ exam E.^. ExamId E.==. examCorrector E.^. ExamCorrectorExam + E.where_ $ examCorrector E.^. ExamCorrectorUser E.==. E.val authId + E.&&. course E.^. CourseTerm E.==. E.val tid + E.&&. course E.^. CourseSchool E.==. E.val ssh + E.&&. course E.^. CourseShorthand E.==. E.val csh + guardMExceptT isCorrector $ unauthorizedI MsgUnauthorizedExamCorrector + return Authorized + r -> $unsupportedAuthPredicate AuthExamCorrector r + where + mkExamCorrectorList = fmap (setOf $ folded . _Value) . E.select . E.from $ return . (E.^. ExamCorrectorUser) +tagAccessPredicate AuthTutor = cacheAPDB (Just $ Right diffMinute) AuthCacheTutorList mkTutorList $ \mAuthId' route' _ tutorList -> if + | maybe True (`Set.notMember` tutorList) mAuthId' -> Right $ case route' of + _ | is _Nothing mAuthId' -> return AuthenticationRequired + CTutorialR{} -> unauthorizedI MsgUnauthorizedTutorialTutor + CourseR{} -> unauthorizedI MsgUnauthorizedCourseTutor + _other -> unauthorizedI MsgUnauthorizedTutor + | otherwise -> Left $ APDB $ \_ _ mAuthId route _ -> exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + resList <- $cachedHereBinary authId . lift . E.select . E.from $ \(course `E.InnerJoin` tutorial `E.InnerJoin` tutor) -> do + E.on $ tutor E.^. TutorTutorial E.==. tutorial E.^. TutorialId + E.on $ tutorial E.^. TutorialCourse E.==. course E.^. CourseId + E.where_ $ tutor E.^. TutorUser E.==. E.val authId + return (course E.^. CourseId, tutorial E.^. TutorialId) + let + resMap :: Map CourseId (Set TutorialId) + resMap = Map.fromListWith Set.union [ (cid, Set.singleton tutid) | (E.Value cid, E.Value tutid) <- resList ] + case route of + CTutorialR tid ssh csh tutn _ -> maybeT (unauthorizedI MsgUnauthorizedTutorialTutor) $ do + Entity cid _ <- $cachedHereBinary (tid, ssh, csh) . MaybeT . lift . getBy $ TermSchoolCourseShort tid ssh csh + Entity tutid _ <- $cachedHereBinary (cid, tutn) . MaybeT . lift . getBy $ UniqueTutorial cid tutn + guard $ tutid `Set.member` fromMaybe Set.empty (resMap !? cid) + return Authorized + CourseR tid ssh csh _ -> maybeT (unauthorizedI MsgUnauthorizedCourseTutor) $ do + Entity cid _ <- $cachedHereBinary (tid, ssh, csh) . MaybeT . lift . getBy $ TermSchoolCourseShort tid ssh csh + guard $ cid `Set.member` Map.keysSet resMap + return Authorized + _ -> do + guardMExceptT (not $ Map.null resMap) (unauthorizedI MsgUnauthorizedTutor) + return Authorized + where + mkTutorList = fmap (setOf $ folded . _Value) . E.select . E.from $ return . (E.^. TutorUser) +tagAccessPredicate AuthTutorControl = APDB $ \_ _ _ route _ -> case route of CTutorialR tid ssh csh tutn _ -> maybeT (unauthorizedI MsgUnauthorizedTutorialTutorControl) $ do Entity cid _ <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getBy $ TermSchoolCourseShort tid ssh csh Entity _ Tutorial{..} <- $cachedHereBinary (cid, tutn) . MaybeT . getBy $ UniqueTutorial cid tutn guard tutorialTutorControlled return Authorized r -> $unsupportedAuthPredicate AuthTutorControl r -tagAccessPredicate AuthSubmissionGroup = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthSubmissionGroup = APDB $ \_ _ mAuthId route _ -> case route of CSubmissionR tid ssh csh shn cID _ -> maybeT (unauthorizedI MsgUnauthorizedSubmissionSubmissionGroup) $ do - course <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getKeyBy $ TermSchoolCourseShort tid ssh csh - Entity _ Sheet{..} <- $cachedHereBinary (course, shn) . MaybeT . getBy $ CourseSheet course shn - smId <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decrypt cID - groups <- $cachedHereBinary cID . lift . fmap (Set.fromList . fmap E.unValue) . E.select . E.from $ \(submissionGroupUser `E.InnerJoin` submissionUser) -> do - E.on $ submissionGroupUser E.^. SubmissionGroupUserUser E.==. submissionUser E.^. SubmissionUserUser - E.where_ $ submissionUser E.^. SubmissionUserSubmission E.==. E.val smId - return $ submissionGroupUser E.^. SubmissionGroupUserSubmissionGroup - unless (Set.null groups || isn't _RegisteredGroups sheetGrouping) $ do - uid <- hoistMaybe mAuthId - guardM . lift $ exists [SubmissionGroupUserUser ==. uid, SubmissionGroupUserSubmissionGroup <-. Set.toList groups] + course <- MaybeT . $cachedHereBinary (tid, ssh, csh) . getKeyBy $ TermSchoolCourseShort tid ssh csh + Entity _ Sheet{..} <- MaybeT . $cachedHereBinary (course, shn) . getBy $ CourseSheet course shn + when (is _RegisteredGroups sheetGrouping) $ do + smId <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decrypt cID + groups <- $cachedHereBinary cID . lift . fmap (Set.fromList . fmap E.unValue) . E.select . E.from $ \(submissionGroupUser `E.InnerJoin` submissionUser) -> do + E.on $ submissionGroupUser E.^. SubmissionGroupUserUser E.==. submissionUser E.^. SubmissionUserUser + E.where_ $ submissionUser E.^. SubmissionUserSubmission E.==. E.val smId + return $ submissionGroupUser E.^. SubmissionGroupUserSubmissionGroup + unless (Set.null groups) $ do + uid <- hoistMaybe mAuthId + guardM . lift $ exists [SubmissionGroupUserUser ==. uid, SubmissionGroupUserSubmissionGroup <-. Set.toList groups] return Authorized CSheetR tid ssh csh sheetn _ -> maybeT (unauthorizedI MsgUnauthorizedSheetSubmissionGroup) $ do course <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getKeyBy $ TermSchoolCourseShort tid ssh csh @@ -574,7 +888,7 @@ tagAccessPredicate AuthSubmissionGroup = APDB $ \_ mAuthId route _ -> case route return Authorized r -> $unsupportedAuthPredicate AuthSubmissionGroup r -tagAccessPredicate AuthTime = APDB $ \(runTACont -> cont) mAuthId route isWrite -> case route of +tagAccessPredicate AuthTime = APDB $ \_ (runTACont -> cont) mAuthId route isWrite -> case route of CExamR tid ssh csh examn subRoute -> maybeT (unauthorizedI MsgUnauthorizedExamTime) $ do course <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getKeyBy $ TermSchoolCourseShort tid ssh csh Entity eId Exam{..} <- $cachedHereBinary (course, examn) . MaybeT . getBy $ UniqueExam course examn @@ -754,7 +1068,7 @@ tagAccessPredicate AuthTime = APDB $ \(runTACont -> cont) mAuthId route isWrite return Authorized r -> $unsupportedAuthPredicate AuthTime r -tagAccessPredicate AuthStaffTime = APDB $ \_ _ route isWrite -> case route of +tagAccessPredicate AuthStaffTime = APDB $ \_ _ _ route isWrite -> case route of CApplicationR tid ssh csh _ _ -> maybeT (unauthorizedI MsgUnauthorizedApplicationTime) $ do course <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getKeyBy $ TermSchoolCourseShort tid ssh csh allocationCourse <- $cachedHereBinary course . lift . getBy $ UniqueAllocationCourse course @@ -779,7 +1093,7 @@ tagAccessPredicate AuthStaffTime = APDB $ \_ _ route isWrite -> case route of return Authorized r -> $unsupportedAuthPredicate AuthStaffTime r -tagAccessPredicate AuthAllocationTime = APDB $ \(runTACont -> cont) mAuthId route isWrite -> case route of +tagAccessPredicate AuthAllocationTime = APDB $ \_ (runTACont -> cont) mAuthId route isWrite -> case route of CourseR tid ssh csh CRegisterR -> do now <- liftIO getCurrentTime mba <- mbAllocation tid ssh csh @@ -823,7 +1137,7 @@ tagAccessPredicate AuthAllocationTime = APDB $ \(runTACont -> cont) mAuthId rout cid <- MaybeT . getKeyBy $ TermSchoolCourseShort tid ssh csh Entity _ AllocationCourse{..} <- MaybeT . getBy $ UniqueAllocationCourse cid (cid,) <$> MaybeT (get allocationCourseAllocation) -tagAccessPredicate AuthCourseTime = APDB $ \_ _mAuthId route _ -> case route of +tagAccessPredicate AuthCourseTime = APDB $ \_ _ _mAuthId route _ -> case route of CourseR tid ssh csh _ -> exceptT return return $ do now <- liftIO getCurrentTime courseVisible <- $cachedHereBinary (tid, ssh, csh) . lift . E.selectExists . E.from $ \course -> do @@ -834,20 +1148,50 @@ tagAccessPredicate AuthCourseTime = APDB $ \_ _mAuthId route _ -> case route of guardMExceptT courseVisible (unauthorizedI MsgUnauthorizedCourseTime) return Authorized r -> $unsupportedAuthPredicate AuthCourseTime r -tagAccessPredicate AuthCourseRegistered = APDB $ \_ mAuthId route _ -> case route of - CourseR tid ssh csh _ -> exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - isRegistered <- $cachedHereBinary (authId, tid, ssh, csh) . lift . E.selectExists . E.from $ \(course `E.InnerJoin` courseParticipant) -> do - E.on $ course E.^. CourseId E.==. courseParticipant E.^. CourseParticipantCourse - E.where_ $ courseParticipant E.^. CourseParticipantUser E.==. E.val authId - E.&&. courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive - E.&&. course E.^. CourseTerm E.==. E.val tid - E.&&. course E.^. CourseSchool E.==. E.val ssh - E.&&. course E.^. CourseShorthand E.==. E.val csh - guardMExceptT isRegistered (unauthorizedI MsgUnauthorizedRegistered) +tagAccessPredicate AuthExamTime = APDB $ \_ _ _ route _ -> case route of + CSubmissionR tid ssh csh shn _cID CorrectionR -> maybeT (unauthorizedI MsgUnauthorizedCorrectionExamTime) $ do + cid <- MaybeT . $cachedHereBinary (tid, ssh, csh) . getKeyBy $ TermSchoolCourseShort tid ssh csh + Entity _sid Sheet{..} <- MaybeT . $cachedHereBinary (cid, shn) . getBy $ CourseSheet cid shn + whenIsJust (sheetType ^? _examPart . from _SqlKey) $ \epId -> do + ExamPart{examPartExam} <- MaybeT . $cachedHereBinary epId $ get epId + Exam{..} <- MaybeT . $cachedHereBinary examPartExam $ get examPartExam + now <- liftIO getCurrentTime + guard $ NTop (Just now) >= NTop examFinished return Authorized - r -> $unsupportedAuthPredicate AuthCourseRegistered r -tagAccessPredicate AuthTutorialRegistered = APDB $ \_ mAuthId route _ -> case route of + r -> $unsupportedAuthPredicate AuthExamTime r +tagAccessPredicate AuthCourseRegistered = cacheAPDB' (Just $ Right diffMinute) mkAuthCacheCourseRegisteredList $ \mAuthId' route' _ mCourseRegisteredList -> if + | Just courseRegisteredList <- mCourseRegisteredList + , maybe True (`Set.notMember` courseRegisteredList) mAuthId' -> Right $ case route' of + _ | is _Nothing mAuthId' -> return AuthenticationRequired + CourseR{} -> unauthorizedI MsgUnauthorizedRegistered + r -> $unsupportedAuthPredicate AuthCourseRegistered r + | otherwise -> Left $ APDB $ \_ _ mAuthId route _ -> case route of + CourseR tid ssh csh _ -> exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + isRegistered <- $cachedHereBinary (authId, tid, ssh, csh) . lift . E.selectExists . E.from $ \(course `E.InnerJoin` courseParticipant) -> do + E.on $ course E.^. CourseId E.==. courseParticipant E.^. CourseParticipantCourse + E.where_ $ courseParticipant E.^. CourseParticipantUser E.==. E.val authId + E.&&. courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive + E.&&. course E.^. CourseTerm E.==. E.val tid + E.&&. course E.^. CourseSchool E.==. E.val ssh + E.&&. course E.^. CourseShorthand E.==. E.val csh + guardMExceptT isRegistered (unauthorizedI MsgUnauthorizedRegistered) + return Authorized + r -> $unsupportedAuthPredicate AuthCourseRegistered r + where + mkAuthCacheCourseRegisteredList _ route _ = case route of + CourseR tid ssh csh _ -> Just + ( AuthCacheCourseRegisteredList tid ssh csh + , fmap (setOf $ folded . _Value) . E.select . E.from $ \(course `E.InnerJoin` courseParticipant) -> do + E.on $ course E.^. CourseId E.==. courseParticipant E.^. CourseParticipantCourse + E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive + E.&&. course E.^. CourseTerm E.==. E.val tid + E.&&. course E.^. CourseSchool E.==. E.val ssh + E.&&. course E.^. CourseShorthand E.==. E.val csh + return $ courseParticipant E.^. CourseParticipantUser + ) + _other -> Nothing +tagAccessPredicate AuthTutorialRegistered = APDB $ \_ _ mAuthId route _ -> case route of CTutorialR tid ssh csh tutn _ -> exceptT return return $ do authId <- maybeExceptT AuthenticationRequired $ return mAuthId isRegistered <- $cachedHereBinary (authId, tid, ssh, csh, tutn) . lift . E.selectExists . E.from $ \(course `E.InnerJoin` tutorial `E.InnerJoin` tutorialParticipant) -> do @@ -872,7 +1216,7 @@ tagAccessPredicate AuthTutorialRegistered = APDB $ \_ mAuthId route _ -> case ro guardMExceptT isRegistered (unauthorizedI MsgUnauthorizedRegistered) return Authorized r -> $unsupportedAuthPredicate AuthTutorialRegistered r -tagAccessPredicate AuthExamOccurrenceRegistration = APDB $ \_ _ route _ -> case route of +tagAccessPredicate AuthExamOccurrenceRegistration = APDB $ \_ _ _ route _ -> case route of CExamR tid ssh csh examn _ -> exceptT return return $ do isOccurrenceRegistration <- $cachedHereBinary (tid, ssh, csh, examn) . lift . E.selectExists . E.from $ \(course `E.InnerJoin` exam) -> do E.on $ course E.^. CourseId E.==. exam E.^. ExamCourse @@ -884,7 +1228,7 @@ tagAccessPredicate AuthExamOccurrenceRegistration = APDB $ \_ _ route _ -> case guardMExceptT isOccurrenceRegistration (unauthorizedI MsgUnauthorizedExamOccurrenceRegistration) return Authorized r -> $unsupportedAuthPredicate AuthExamOccurrenceRegistration r -tagAccessPredicate AuthExamOccurrenceRegistered = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthExamOccurrenceRegistered = APDB $ \_ _ mAuthId route _ -> case route of CExamR tid ssh csh examn (ERegisterOccR occn) -> exceptT return return $ do authId <- maybeExceptT AuthenticationRequired $ return mAuthId hasRegistration <- $cachedHereBinary (authId, tid, ssh, csh, examn, occn) . lift . E.selectExists . E.from $ \(course `E.InnerJoin` exam `E.InnerJoin` examRegistration `E.InnerJoin` examOccurrence) -> do @@ -925,7 +1269,7 @@ tagAccessPredicate AuthExamOccurrenceRegistered = APDB $ \_ mAuthId route _ -> c guardMExceptT hasRegistration (unauthorizedI MsgUnauthorizedRegistered) return Authorized r -> $unsupportedAuthPredicate AuthExamOccurrenceRegistered r -tagAccessPredicate AuthExamRegistered = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthExamRegistered = APDB $ \_ _ mAuthId route _ -> case route of CExamR tid ssh csh examn _ -> exceptT return return $ do authId <- maybeExceptT AuthenticationRequired $ return mAuthId hasRegistration <- $cachedHereBinary (authId, tid, ssh, csh, examn) . lift . E.selectExists . E.from $ \(course `E.InnerJoin` exam `E.InnerJoin` examRegistration) -> do @@ -966,7 +1310,7 @@ tagAccessPredicate AuthExamRegistered = APDB $ \_ mAuthId route _ -> case route guardMExceptT hasRegistration $ unauthorizedI MsgUnauthorizedRegisteredAnyExam return Authorized r -> $unsupportedAuthPredicate AuthExamRegistered r -tagAccessPredicate AuthExamResult = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthExamResult = APDB $ \_ _ mAuthId route _ -> case route of CExamR tid ssh csh examn _ -> exceptT return return $ do authId <- maybeExceptT AuthenticationRequired $ return mAuthId hasResult <- $cachedHereBinary (authId, tid, ssh, csh, examn) . lift . E.selectExists . E.from $ \(course `E.InnerJoin` exam `E.InnerJoin` examResult) -> do @@ -1019,14 +1363,14 @@ tagAccessPredicate AuthExamResult = APDB $ \_ mAuthId route _ -> case route of guardMExceptT (hasResult || hasPartResult) (unauthorizedI MsgUnauthorizedExamResult) return Authorized r -> $unsupportedAuthPredicate AuthExamRegistered r -tagAccessPredicate AuthAllocationRegistered = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthAllocationRegistered = APDB $ \_ _ mAuthId route _ -> case route of AllocationR tid ssh ash _ -> maybeT (unauthorizedI MsgUnauthorizedAllocationRegistered) $ do uid <- hoistMaybe mAuthId aId <- MaybeT . $cachedHereBinary (tid, ssh, ash) . getKeyBy $ TermSchoolAllocationShort tid ssh ash void . MaybeT . $cachedHereBinary (uid, aId) . getKeyBy $ UniqueAllocationUser aId uid return Authorized r -> $unsupportedAuthPredicate AuthAllocationRegistered r -tagAccessPredicate AuthParticipant = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthParticipant = APDB $ \_ _ mAuthId route _ -> case route of CNewsR tid ssh csh cID _ -> maybeT (unauthorizedI MsgUnauthorizedParticipantSelf) $ do nId <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decrypt cID CourseNews{courseNewsParticipantsOnly} <- $cachedHereBinary nId . MaybeT $ get nId @@ -1134,7 +1478,7 @@ tagAccessPredicate AuthParticipant = APDB $ \_ mAuthId route _ -> case route of E.&&. course E.^. CourseTerm E.==. E.val tid E.&&. course E.^. CourseSchool E.==. E.val ssh E.&&. course E.^. CourseShorthand E.==. E.val csh -tagAccessPredicate AuthApplicant = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthApplicant = APDB $ \_ _ mAuthId route _ -> case route of CourseR tid ssh csh (CUserR cID) -> maybeT (unauthorizedI MsgUnauthorizedApplicant) $ do uid <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decrypt cID isApplicant <- isCourseApplicant tid ssh csh uid @@ -1155,13 +1499,15 @@ tagAccessPredicate AuthApplicant = APDB $ \_ mAuthId route _ -> case route of E.&&. course E.^. CourseTerm E.==. E.val tid E.&&. course E.^. CourseSchool E.==. E.val ssh E.&&. course E.^. CourseShorthand E.==. E.val csh -tagAccessPredicate AuthCapacity = APDB $ \_ _ route _ -> case route of +tagAccessPredicate AuthCapacity = APDB $ \_ _ _ route _ -> case route of CExamR tid ssh csh examn (ERegisterOccR occn) -> maybeT (unauthorizedI MsgExamOccurrenceNoCapacity) $ do cid <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getKeyBy $ TermSchoolCourseShort tid ssh csh eid <- $cachedHereBinary (cid, examn) . MaybeT . getKeyBy $ UniqueExam cid examn Entity occId ExamOccurrence{..} <- $cachedHereBinary (eid, occn) . MaybeT . getBy $ UniqueExamOccurrence eid occn - registered <- $cachedHereBinary occId . lift $ fromIntegral <$> count [ ExamRegistrationOccurrence ==. Just occId, ExamRegistrationExam ==. eid ] - guard $ examOccurrenceCapacity > registered + -- Nothing means unlimited size + whenIsJust examOccurrenceCapacity $ \capacity -> do + registered <- $cachedHereBinary occId . lift $ fromIntegral <$> count [ ExamRegistrationOccurrence ==. Just occId, ExamRegistrationExam ==. eid ] + guard $ capacity > registered return Authorized CTutorialR tid ssh csh tutn _ -> maybeT (unauthorizedI MsgTutorialNoCapacity) $ do cid <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getKeyBy $ TermSchoolCourseShort tid ssh csh @@ -1175,7 +1521,7 @@ tagAccessPredicate AuthCapacity = APDB $ \_ _ route _ -> case route of guard $ NTop courseCapacity > NTop (Just registered) return Authorized r -> $unsupportedAuthPredicate AuthCapacity r -tagAccessPredicate AuthRegisterGroup = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthRegisterGroup = APDB $ \_ _ mAuthId route _ -> case route of CTutorialR tid ssh csh tutn _ -> maybeT (unauthorizedI MsgUnauthorizedTutorialRegisterGroup) $ do cid <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getKeyBy $ TermSchoolCourseShort tid ssh csh Entity _ Tutorial{..} <- $cachedHereBinary (cid, tutn) . MaybeT . getBy $ UniqueTutorial cid tutn @@ -1191,41 +1537,83 @@ tagAccessPredicate AuthRegisterGroup = APDB $ \_ mAuthId route _ -> case route o guard $ not hasOther return Authorized r -> $unsupportedAuthPredicate AuthRegisterGroup r -tagAccessPredicate AuthEmpty = APDB $ \_ mAuthId route _ -> case route of - EExamListR -> exceptT return return $ do - authId <- maybeExceptT AuthenticationRequired $ return mAuthId - hasExternalExams <- $cachedHereBinary authId . lift . E.selectExists . E.from $ \(eexam `E.InnerJoin` eexamStaff) -> do - E.on $ eexam E.^. ExternalExamId E.==. eexamStaff E.^. ExternalExamStaffExam - E.where_ $ eexamStaff E.^. ExternalExamStaffUser E.==. E.val authId - E.||. E.exists (E.from $ \externalExamResult -> - E.where_ $ externalExamResult E.^. ExternalExamResultExam E.==. eexam E.^. ExternalExamId - E.&&. externalExamResult E.^. ExternalExamResultUser E.==. E.val authId - ) - guardMExceptT (not hasExternalExams) $ unauthorizedI MsgUnauthorizedExternalExamListNotEmpty - return Authorized - CourseR tid ssh csh _ -> maybeT (unauthorizedI MsgCourseNotEmpty) $ do - -- Entity cid Course{..} <- MaybeT . getBy $ TermSchoolCourseShort tid ssh csh - cid <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getKeyBy $ TermSchoolCourseShort tid ssh csh - assertM_ (<= 0) . $cachedHereBinary cid . lift $ count [ CourseParticipantCourse ==. cid ] - assertM_ not . $cachedHereBinary cid . lift $ E.selectExists . E.from $ \(sheet `E.InnerJoin` submission) -> do - E.on $ sheet E.^. SheetId E.==. submission E.^. SubmissionSheet - E.where_ $ sheet E.^. SheetCourse E.==. E.val cid - return Authorized - r -> $unsupportedAuthPredicate AuthEmpty r -tagAccessPredicate AuthMaterials = APDB $ \_ _ route _ -> case route of +tagAccessPredicate AuthEmpty = APDB $ \evalCtx eval' mAuthId route _ -> do + mr <- getMsgRenderer + let orAR', _andAR' :: forall m'. Monad m' => m' AuthResult -> m' AuthResult -> m' AuthResult + orAR' = shortCircuitM (is _Authorized) (orAR mr) + _andAR' = shortCircuitM (is _Unauthorized) (andAR mr) + + workflowInstanceWorkflowsEmpty rScope win = selectLanguageI18n <=< $cachedHereBinary (evalCtx, mAuthId, route) . maybeT (unauthorizedI18n MsgUnauthorizedWorkflowWorkflowsNotEmpty) $ do + roles <- memcacheAuth' (Right diffDay) (AuthCacheWorkflowInstanceWorkflowViewers win rScope) $ do + scope <- fromRouteWorkflowScope rScope + let dbScope = scope ^. _DBWorkflowScope + getWorkflowWorkflows = E.selectSource . E.from $ \(workflowWorkflow `E.InnerJoin` workflowInstance) -> do + E.on $ workflowWorkflow E.^. WorkflowWorkflowInstance E.==. E.just (workflowInstance E.^. WorkflowInstanceId) + E.where_ $ workflowInstance E.^. WorkflowInstanceName E.==. E.val win + E.&&. workflowInstance E.^. WorkflowInstanceScope E.==. E.val dbScope + return workflowWorkflow + workflowRoles (Entity wwId WorkflowWorkflow{..}) = do + wwGraph <- getSharedIdWorkflowGraph workflowWorkflowGraph + let + nodeViewers = do + WorkflowAction{..} <- otoList workflowWorkflowState + (node, WGN{..}) <- itoListOf (_wgNodes . ifolded) wwGraph + guard $ node == wpTo + WorkflowNodeView{..} <- hoistMaybe wgnViewers + return $ toNullable wnvViewers + payloadViewers = do + (prevActs, act) <- zip (inits $ otoList workflowWorkflowState) $ otoList workflowWorkflowState + prevAct <- hoistMaybe $ prevActs ^? _last + payload <- Map.keys $ wpPayload act + guard $ Map.lookup payload (workflowStateCurrentPayloads prevActs) /= Map.lookup payload (wpPayload act) + fmap (toNullable . wpvViewers) . hoistMaybe $ Map.lookup payload . wgnPayloadView =<< Map.lookup (wpTo prevAct) (wgNodes wwGraph) + return . Set.mapMonotonic ((workflowWorkflowScope, wwId), ) $ fold nodeViewers <> fold payloadViewers + lift . runConduit $ getWorkflowWorkflows .| C.foldMapM workflowRoles + let + evalRole ((wwScope, wwId), role) = do + rScope' <- toRouteWorkflowScope $ _DBWorkflowScope # wwScope + cID <- encrypt wwId + let route' = _WorkflowScopeRoute # (rScope', WorkflowWorkflowR cID WWWorkflowR) + lift . evalWriterT $ evalWorkflowRoleFor' eval' mAuthId (Just wwId) role route' False + guardM . fmap (isn't _Authorized) $ ofoldl1' orAR' . mapNonNull evalRole =<< hoistMaybe (fromNullable $ otoList roles) + return AuthorizedI18n + in case route of + r | Just (rScope, WorkflowInstanceR win WIWorkflowsR) <- r ^? _WorkflowScopeRoute + -> workflowInstanceWorkflowsEmpty rScope win + EExamListR -> exceptT return return $ do + authId <- maybeExceptT AuthenticationRequired $ return mAuthId + hasExternalExams <- $cachedHereBinary authId . lift . E.selectExists . E.from $ \(eexam `E.InnerJoin` eexamStaff) -> do + E.on $ eexam E.^. ExternalExamId E.==. eexamStaff E.^. ExternalExamStaffExam + E.where_ $ eexamStaff E.^. ExternalExamStaffUser E.==. E.val authId + E.||. E.exists (E.from $ \externalExamResult -> + E.where_ $ externalExamResult E.^. ExternalExamResultExam E.==. eexam E.^. ExternalExamId + E.&&. externalExamResult E.^. ExternalExamResultUser E.==. E.val authId + ) + guardMExceptT (not hasExternalExams) $ unauthorizedI MsgUnauthorizedExternalExamListNotEmpty + return Authorized + CourseR tid ssh csh _ -> maybeT (unauthorizedI MsgCourseNotEmpty) $ do + -- Entity cid Course{..} <- MaybeT . getBy $ TermSchoolCourseShort tid ssh csh + cid <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getKeyBy $ TermSchoolCourseShort tid ssh csh + assertM_ (<= 0) . $cachedHereBinary cid . lift $ count [ CourseParticipantCourse ==. cid ] + assertM_ not . $cachedHereBinary cid . lift $ E.selectExists . E.from $ \(sheet `E.InnerJoin` submission) -> do + E.on $ sheet E.^. SheetId E.==. submission E.^. SubmissionSheet + E.where_ $ sheet E.^. SheetCourse E.==. E.val cid + return Authorized + r -> $unsupportedAuthPredicate AuthEmpty r +tagAccessPredicate AuthMaterials = APDB $ \_ _ _ route _ -> case route of CourseR tid ssh csh _ -> maybeT (unauthorizedI MsgUnfreeMaterials) $ do Entity _ Course{..} <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getBy $ TermSchoolCourseShort tid ssh csh guard courseMaterialFree return Authorized r -> $unsupportedAuthPredicate AuthMaterials r -tagAccessPredicate AuthOwner = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthOwner = APDB $ \_ _ mAuthId route _ -> case route of CSubmissionR _ _ _ _ cID _ -> $cachedHereBinary (mAuthId, cID) . exceptT return return $ do sid <- catchIfMExceptT (const $ unauthorizedI MsgUnauthorizedSubmissionOwner) (const True :: CryptoIDError -> Bool) $ decrypt cID authId <- maybeExceptT AuthenticationRequired $ return mAuthId void . maybeMExceptT (unauthorizedI MsgUnauthorizedSubmissionOwner) . getBy $ UniqueSubmissionUser authId sid return Authorized r -> $unsupportedAuthPredicate AuthOwner r -tagAccessPredicate AuthPersonalisedSheetFiles = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthPersonalisedSheetFiles = APDB $ \_ _ mAuthId route _ -> case route of CSheetR tid ssh csh shn _ -> $cachedHereBinary (mAuthId, tid, ssh, csh, shn) . exceptT return return $ do Entity shId Sheet{..} <- maybeTMExceptT (unauthorizedI MsgUnauthorizedSubmissionPersonalisedSheetFiles) $ do cid <- MaybeT . $cachedHereBinary (tid, ssh, csh) . getKeyBy $ TermSchoolCourseShort tid ssh csh @@ -1240,28 +1628,28 @@ tagAccessPredicate AuthPersonalisedSheetFiles = APDB $ \_ mAuthId route _ -> cas E.&&. E.not_ (E.isNothing $ psFile E.^. PersonalisedSheetFileContent) -- directories don't count return Authorized r -> $unsupportedAuthPredicate AuthPersonalisedSheetFiles r -tagAccessPredicate AuthRated = APDB $ \_ _ route _ -> case route of +tagAccessPredicate AuthRated = APDB $ \_ _ _ route _ -> case route of CSubmissionR _ _ _ _ cID _ -> $cachedHereBinary cID . maybeT (unauthorizedI MsgUnauthorizedSubmissionRated) $ do sid <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decrypt cID sub <- MaybeT $ get sid guard $ submissionRatingDone sub return Authorized r -> $unsupportedAuthPredicate AuthRated r -tagAccessPredicate AuthUserSubmissions = APDB $ \_ _ route _ -> case route of +tagAccessPredicate AuthUserSubmissions = APDB $ \_ _ _ route _ -> case route of CSheetR tid ssh csh shn _ -> $cachedHereBinary (tid, ssh, csh, shn) . maybeT (unauthorizedI MsgUnauthorizedUserSubmission) $ do Entity cid _ <- MaybeT . getBy $ TermSchoolCourseShort tid ssh csh Entity _ Sheet{ sheetSubmissionMode = SubmissionMode{..} } <- MaybeT . getBy $ CourseSheet cid shn guard $ is _Just submissionModeUser return Authorized r -> $unsupportedAuthPredicate AuthUserSubmissions r -tagAccessPredicate AuthCorrectorSubmissions = APDB $ \_ _ route _ -> case route of +tagAccessPredicate AuthCorrectorSubmissions = APDB $ \_ _ _ route _ -> case route of CSheetR tid ssh csh shn _ -> maybeT (unauthorizedI MsgUnauthorizedCorrectorSubmission) $ do Entity cid _ <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getBy $ TermSchoolCourseShort tid ssh csh Entity _ Sheet{ sheetSubmissionMode = SubmissionMode{..} } <- $cachedHereBinary (cid, shn) . MaybeT . getBy $ CourseSheet cid shn guard submissionModeCorrector return Authorized r -> $unsupportedAuthPredicate AuthCorrectorSubmissions r -tagAccessPredicate AuthSelf = APDB $ \_ mAuthId route _ -> exceptT return return $ do +tagAccessPredicate AuthSelf = APDB $ \_ _ mAuthId route _ -> exceptT return return $ do referencedUser' <- case route of AdminUserR cID -> return $ Left cID AdminUserDeleteR cID -> return $ Left cID @@ -1282,7 +1670,7 @@ tagAccessPredicate AuthSelf = APDB $ \_ mAuthId route _ -> exceptT return return | uid == referencedUser -> return Authorized Nothing -> return AuthenticationRequired _other -> unauthorizedI MsgUnauthorizedSelf -tagAccessPredicate AuthIsLDAP = APDB $ \_ _ route _ -> exceptT return return $ do +tagAccessPredicate AuthIsLDAP = APDB $ \_ _ _ route _ -> exceptT return return $ do referencedUser <- case route of AdminUserR cID -> return cID AdminUserDeleteR cID -> return cID @@ -1296,7 +1684,7 @@ tagAccessPredicate AuthIsLDAP = APDB $ \_ _ route _ -> exceptT return return $ d User{..} <- MaybeT $ get referencedUser' guard $ userAuthentication == AuthLDAP return Authorized -tagAccessPredicate AuthIsPWHash = APDB $ \_ _ route _ -> exceptT return return $ do +tagAccessPredicate AuthIsPWHash = APDB $ \_ _ _ route _ -> exceptT return return $ do referencedUser <- case route of AdminUserR cID -> return cID AdminUserDeleteR cID -> return cID @@ -1310,7 +1698,7 @@ tagAccessPredicate AuthIsPWHash = APDB $ \_ _ route _ -> exceptT return return $ User{..} <- MaybeT $ get referencedUser' guard $ is _AuthPWHash userAuthentication return Authorized -tagAccessPredicate AuthAuthentication = APDB $ \_ mAuthId route _ -> case route of +tagAccessPredicate AuthAuthentication = APDB $ \_ _ mAuthId route _ -> case route of MessageR cID -> maybeT (unauthorizedI MsgUnauthorizedSystemMessageAuth) $ do smId <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decrypt cID SystemMessage{..} <- $cachedHereBinary smId . MaybeT $ get smId @@ -1324,6 +1712,91 @@ tagAccessPredicate AuthAuthentication = APDB $ \_ mAuthId route _ -> case route guard $ not systemMessageAuthenticatedOnly || isAuthenticated return Authorized r -> $unsupportedAuthPredicate AuthAuthentication r +tagAccessPredicate AuthWorkflow = APDB $ \evalCtx eval' mAuthId route isWrite -> do + mr <- getMsgRenderer + let orAR', _andAR' :: forall m'. Monad m' => m' AuthResult -> m' AuthResult -> m' AuthResult + orAR' = shortCircuitM (is _Authorized) (orAR mr) + _andAR' = shortCircuitM (is _Unauthorized) (andAR mr) + + + wInitiate win rScope = selectLanguageI18n <=< $memcacheAuthHere' (Right diffDay) (evalCtx, route, mAuthId) . maybeT (unauthorizedI18n MsgUnauthorizedWorkflowInitiate) $ do -- @isWrite@ not included since it should make no difference regarding initiation (in the end that will always be a write) + roles <- memcacheAuth' (Right diffDay) (AuthCacheWorkflowInstanceInitiators win rScope) $ do + scope <- MaybeT . $cachedHereBinary rScope . runMaybeT $ fromRouteWorkflowScope rScope + Entity _ WorkflowInstance{..} <- $cachedHereBinary (win, scope) . MaybeT . getBy . UniqueWorkflowInstance win $ scope ^. _DBWorkflowScope + wiGraph <- lift $ getSharedIdWorkflowGraph workflowInstanceGraph + return . fold $ do + WGN{..} <- wiGraph ^.. _wgNodes . folded + WorkflowGraphEdgeInitial{..} <- wgnEdges ^.. folded + return wgeActors + let evalRole role = lift . evalWriterT $ evalWorkflowRoleFor' eval' mAuthId Nothing role route isWrite + guardM . fmap (is _Authorized) $ ofoldl1' orAR' . mapNonNull evalRole =<< hoistMaybe (fromNullable $ toList roles) + return AuthorizedI18n + + wWorkflow isWrite' cID + | isWrite' = maybeT (unauthorizedI MsgUnauthorizedWorkflowWrite) $ do + (wwId, edges) <- memcacheAuth' (Right diffDay) (AuthCacheWorkflowWorkflowEdgeActors cID) $ do + wwId <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decrypt cID + WorkflowWorkflow{..} <- MaybeT . $cachedHereBinary wwId $ get wwId + wwGraph <- lift $ getSharedIdWorkflowGraph workflowWorkflowGraph + + let + wwNode = wpTo $ last workflowWorkflowState + + return . (wwId, ) . (Set.fromList :: _ -> Set (WorkflowRole UserId)) . foldMap toNullable $ do + WGN{..} <- wwGraph ^.. _wgNodes . folded + WorkflowGraphEdgeManual{..} <- wgnEdges ^.. folded + guard $ wgeSource == wwNode + hoistMaybe . fromNullable $ wgeActors ^.. folded + + let + evalRole role = lift . evalWriterT $ evalWorkflowRoleFor' eval' mAuthId (Just wwId) role route isWrite + guardM . fmap (is _Authorized) $ ofoldl1' orAR' . mapNonNull evalRole =<< hoistMaybe (fromNullable $ otoList edges) + return Authorized + | otherwise = flip orAR' (wWorkflow True cID) . maybeT (unauthorizedI MsgUnauthorizedWorkflowRead) $ do + (wwId, roles) <- memcacheAuth' (Right diffDay) (AuthCacheWorkflowWorkflowViewers cID) $ do + wwId <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decrypt cID + WorkflowWorkflow{..} <- MaybeT . $cachedHereBinary wwId $ get wwId + wwGraph <- lift $ getSharedIdWorkflowGraph workflowWorkflowGraph + + let + nodeViewers = do + WorkflowAction{..} <- otoList workflowWorkflowState + (node, WGN{..}) <- itoListOf (_wgNodes . ifolded) wwGraph + guard $ node == wpTo + WorkflowNodeView{..} <- hoistMaybe wgnViewers + return $ toNullable wnvViewers + payloadViewers = do + (prevActs, act) <- zip (inits $ otoList workflowWorkflowState) $ otoList workflowWorkflowState + prevAct <- hoistMaybe $ prevActs ^? _last + payload <- Map.keys $ wpPayload act + guard $ Map.lookup payload (workflowStateCurrentPayloads prevActs) /= Map.lookup payload (wpPayload act) + fmap (toNullable . wpvViewers) . hoistMaybe $ Map.lookup payload . wgnPayloadView =<< Map.lookup (wpTo prevAct) (wgNodes wwGraph) + + return (wwId, fold nodeViewers <> fold payloadViewers :: (Set (WorkflowRole UserId))) + + let + evalRole role = lift . evalWriterT $ evalWorkflowRoleFor' eval' mAuthId (Just wwId) role route isWrite + guardM . fmap (is _Authorized) $ ofoldl1' orAR' . mapNonNull evalRole =<< hoistMaybe (fromNullable $ otoList roles) + return Authorized + wFiles wwCID wpl stCID = maybeT (unauthorizedI MsgUnauthorizedWorkflowFiles) $ do + wwId <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decrypt wwCID + WorkflowWorkflow{..} <- MaybeT . $cachedHereBinary wwId $ get wwId + stIx <- catchIfMaybeT (const True :: CryptoIDError -> Bool) $ decryptWorkflowStateIndex wwId stCID + wwGraph <- lift $ getSharedIdWorkflowGraph workflowWorkflowGraph + act <- workflowStateIndex stIx $ _DBWorkflowState # workflowWorkflowState + let + cState = wpTo act + payloadViewers = Map.findWithDefault Set.empty wpl $ toNullable . wpvViewers <$> Map.findWithDefault Map.empty cState (wgnPayloadView <$> wgNodes wwGraph) + evalRole role = lift . evalWriterT $ evalWorkflowRoleFor' eval' mAuthId (Just wwId) role route isWrite + guardM . anyM (otoList payloadViewers) $ fmap (is _Authorized) . evalRole + guardM . lift . evalWriterT $ mayViewWorkflowAction' eval' mAuthId wwId act + return Authorized + + case route of + _ | Just (rScope, WorkflowInstanceR win WIInitiateR) <- route ^? _WorkflowScopeRoute -> wInitiate win rScope + _ | Just (_, WorkflowWorkflowR cID WWWorkflowR) <- route ^? _WorkflowScopeRoute -> wWorkflow isWrite cID + _ | Just (_, WorkflowWorkflowR wwCID (WWFilesR wpl stCID)) <- route ^? _WorkflowScopeRoute -> wFiles wwCID wpl stCID + r -> $unsupportedAuthPredicate AuthWorkflow r tagAccessPredicate AuthRead = APPure $ \_ _ isWrite -> do MsgRenderer mr <- ask return $ bool Authorized (Unauthorized $ mr MsgUnauthorizedWrite) isWrite @@ -1334,7 +1807,7 @@ tagAccessPredicate AuthWrite = APPure $ \_ _ isWrite -> do runTACont :: forall m. MonadAP m => (forall m'. MonadAP m' => AuthTagsEval m') -> AuthDNF -> Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> m Bool -runTACont cont dnf mAuthId route isWrite = is _Authorized . fst <$> runWriterT (cont dnf mAuthId route isWrite) +runTACont cont dnf mAuthId route isWrite = is _Authorized <$> evalWriterT (cont dnf mAuthId route isWrite) authTagSpecificity :: AuthTag -> AuthTag -> Ordering @@ -1353,36 +1826,24 @@ authTagSpecificity = comparing $ NTop . flip findIndex eqClasses . elem ] defaultAuthDNF :: AuthDNF -defaultAuthDNF = PredDNF $ Set.fromList - [ impureNonNull . Set.singleton $ PLVariable AuthAdmin - , impureNonNull . Set.singleton $ PLVariable AuthToken - ] +defaultAuthDNF = predDNFVar AuthAdmin `predDNFOr` predDNFVar AuthToken routeAuthTags :: Route UniWorX -> Either InvalidAuthTag AuthDNF --- ^ DNF up to entailment: --- --- > (A_1 && A_2 && ...) OR' B OR' ... --- --- > A OR' B := ((A |- B) ==> A) && (A || B) -routeAuthTags = fmap (PredDNF . Set.mapMonotonic impureNonNull) . ofoldM partition' (Set.mapMonotonic toNullable $ dnfTerms defaultAuthDNF) . routeAttrs +-- ^ DNF up to entailment, see `predDNFEntail` +routeAuthTags = fmap predDNFEntail . ofoldM parse defaultAuthDNF . routeAttrs where - partition' :: Set (Set AuthLiteral) -> Text -> Either InvalidAuthTag (Set (Set AuthLiteral)) - partition' prev t - | Just (Set.fromList . toNullable -> authTags) <- fromNullable =<< mapM fromPathPiece (Text.splitOn "AND" t) - = if - | oany (authTags `Set.isSubsetOf`) prev - -> Right prev - | otherwise - -> Right . Set.insert authTags $ Set.filter (not . (`Set.isSubsetOf` authTags)) prev - | otherwise - = Left $ InvalidAuthTag t + parse :: AuthDNF -> Text -> Either InvalidAuthTag AuthDNF + parse prev t = case fromNullable . Set.fromList =<< mapM fromPathPiece (Text.splitOn "AND" t) of + Just t' -> Right . predDNFOr prev . PredDNF $ Set.singleton t' + Nothing -> Left $ InvalidAuthTag t -evalAuthTags :: forall ctx m. (Binary ctx, MonadAP m) => ctx -> AuthTagActive -> (forall m'. MonadAP m' => AuthTagsEval m') -> AuthTagsEval m +evalAuthTags :: forall ctx m. (HasCallStack, Binary ctx, MonadAP m) => ctx -> AuthTagActive -> (forall m'. MonadAP m' => AuthTagsEval m') -> AuthTagsEval m -- ^ `tell`s disabled predicates, identified as pivots -evalAuthTags ctx AuthTagActive{..} cont (map (Set.toList . toNullable) . Set.toList . dnfTerms -> authDNF') mAuthId route isWrite +evalAuthTags ctx authActive@AuthTagActive{..} cont (map (Set.toList . toNullable) . Set.toList . dnfTerms -> authDNF') mAuthId route isWrite = do mr <- getMsgRenderer let + contCtx = toStrict $ Binary.encode (ctx, authActive) authVarSpecificity = authTagSpecificity `on` plVar authDNF = sortBy (authVarSpecificity `on` maximumBy authVarSpecificity . impureNonNull) $ map (sortBy authVarSpecificity) authDNF' @@ -1393,7 +1854,12 @@ evalAuthTags ctx AuthTagActive{..} cont (map (Set.toList . toNullable) . Set.toL where evalAccessPred' authTag' mAuthId' route' isWrite' = lift $ do $logDebugS "evalAccessPred" $ tshow (authTag', mAuthId', route', isWrite') - evalAccessPred (tagAccessPredicate authTag') cont mAuthId' route' isWrite' + observeAuthTagEvaluation authTag' (classifyHandler route') $ do + res <- evalAccessPred (tagAccessPredicate authTag') contCtx cont mAuthId' route' isWrite' + return . (res, ) $ case res of + Authorized -> OutcomeAuthorized + Unauthorized _ -> OutcomeUnauthorized + AuthenticationRequired -> OutcomeAuthenticationRequired evalAuthLiteral :: AuthLiteral -> WriterT (Set AuthTag) m AuthResult evalAuthLiteral PLVariable{..} = evalAuthTag plVar @@ -1422,55 +1888,60 @@ evalAuthTags ctx AuthTagActive{..} cont (map (Set.toList . toNullable) . Set.toL return result -evalAccessFor :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX) => Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> m AuthResult -evalAccessFor mAuthId route isWrite = do - dnf <- either throwM return $ routeAuthTags route - let eval :: forall m'. MonadAP m' => AuthTagsEval m' - eval dnf' mAuthId' route' isWrite' = evalAuthTags 'evalAccessFor (AuthTagActive $ const True) eval dnf' mAuthId' route' isWrite' - in fmap fst . runWriterT $ eval dnf mAuthId route isWrite - -evalAccessForDB :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX, BackendCompatible SqlReadBackend backend) => Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> ReaderT backend m AuthResult -evalAccessForDB = evalAccessFor - -evalAccessWith :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX) => [(AuthTag, Bool)] -> Route UniWorX -> Bool -> m AuthResult -evalAccessWith assumptions route isWrite = do - mAuthId <- liftHandler maybeAuthId - (tagActive :: AuthTagActive) <- fromMaybe def <$> lookupSessionJson SessionActiveAuthTags - dnf <- either throwM return $ routeAuthTags route +evalAccessWithFor :: (HasCallStack, MonadThrow m, MonadAP m) => [(AuthTag, Bool)] -> Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> m AuthResult +evalAccessWithFor assumptions mAuthId route isWrite = do + isSelf <- (== mAuthId) <$> liftHandler defaultMaybeAuthId + tagActive <- if + | isSelf -> fromMaybe def <$> lookupSessionJson SessionActiveAuthTags + | otherwise -> return . AuthTagActive $ const True + dnf <- throwLeft $ routeAuthTags route let adjDNF = ala Endo foldMap (map ((=<<) . uncurry dnfAssumeValue) assumptions) . Just evalAdj :: forall m'. MonadAP m' => AuthTagsEval m' evalAdj (adjDNF -> dnf') mAuthId' route' isWrite' = case dnf' of Nothing -> return Authorized - Just dnf'' -> evalAuthTags ('evalAccessWith, assumptions) tagActive evalAdj dnf'' mAuthId' route' isWrite' + Just dnf'' -> evalAuthTags ('evalAccessWithFor, assumptions) tagActive evalAdj dnf'' mAuthId' route' isWrite' in do (result, deactivated) <- runWriterT $ evalAdj dnf mAuthId route isWrite - result <$ tellSessionJson SessionInactiveAuthTags deactivated + when isSelf $ + tellSessionJson SessionInactiveAuthTags deactivated + return result + +evalAccessFor :: (HasCallStack, MonadThrow m, MonadAP m) => Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> m AuthResult +evalAccessFor = evalAccessWithFor [] + +evalAccessForDB :: (HasCallStack, MonadThrow m, MonadAP m, BackendCompatible SqlReadBackend backend) => Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> ReaderT backend m AuthResult +evalAccessForDB = evalAccessFor + +evalAccessWith :: (HasCallStack, MonadThrow m, MonadAP m) => [(AuthTag, Bool)] -> Route UniWorX -> Bool -> m AuthResult +evalAccessWith assumptions route isWrite = do + mAuthId <- liftHandler maybeAuthId + evalAccessWithFor assumptions mAuthId route isWrite -evalAccessWithDB :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX, BackendCompatible SqlReadBackend backend) => [(AuthTag, Bool)] -> Route UniWorX -> Bool -> ReaderT backend m AuthResult +evalAccessWithDB :: (HasCallStack, MonadThrow m, MonadAP m, BackendCompatible SqlReadBackend backend) => [(AuthTag, Bool)] -> Route UniWorX -> Bool -> ReaderT backend m AuthResult evalAccessWithDB = evalAccessWith -evalAccess :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX) => Route UniWorX -> Bool -> m AuthResult +evalAccess :: (HasCallStack, MonadThrow m, MonadAP m) => Route UniWorX -> Bool -> m AuthResult evalAccess = evalAccessWith [] -evalAccessDB :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX, BackendCompatible SqlReadBackend backend) => Route UniWorX -> Bool -> ReaderT backend m AuthResult +evalAccessDB :: (HasCallStack, MonadThrow m, MonadAP m, BackendCompatible SqlReadBackend backend) => Route UniWorX -> Bool -> ReaderT backend m AuthResult evalAccessDB = evalAccess -- | Check whether the current user is authorized by `evalAccess` for the given route -- Convenience function for a commonly used code fragment -hasAccessTo :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX) => Route UniWorX -> Bool -> m Bool +hasAccessTo :: (HasCallStack, MonadThrow m, MonadAP m) => Route UniWorX -> Bool -> m Bool hasAccessTo route isWrite = (== Authorized) <$> evalAccess route isWrite -- | Check whether the current user is authorized by `evalAccess` to read from the given route -- Convenience function for a commonly used code fragment -hasReadAccessTo :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX) => Route UniWorX -> m Bool +hasReadAccessTo :: (HasCallStack, MonadThrow m, MonadAP m) => Route UniWorX -> m Bool hasReadAccessTo = flip hasAccessTo False -- | Check whether the current user is authorized by `evalAccess` to rwrite to the given route -- Convenience function for a commonly used code fragment -hasWriteAccessTo :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX) => Route UniWorX -> m Bool +hasWriteAccessTo :: (HasCallStack, MonadThrow m, MonadAP m) => Route UniWorX -> m Bool hasWriteAccessTo = flip hasAccessTo True -wouldHaveAccessTo :: ( MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX ) +wouldHaveAccessTo :: (HasCallStack, MonadThrow m, MonadAP m) => [(AuthTag, Bool)] -- ^ Assumptions -> Route UniWorX -> Bool @@ -1478,7 +1949,7 @@ wouldHaveAccessTo :: ( MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, Be wouldHaveAccessTo assumptions route isWrite = (== Authorized) <$> evalAccessWith assumptions route isWrite wouldHaveReadAccessTo, wouldHaveWriteAccessTo - :: ( MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX ) + :: (HasCallStack, MonadThrow m, MonadAP m) => [(AuthTag, Bool)] -- ^ Assumptions -> Route UniWorX -> m Bool @@ -1486,9 +1957,175 @@ wouldHaveReadAccessTo assumptions route = wouldHaveAccessTo assumptions route Fa wouldHaveWriteAccessTo assumptions route = wouldHaveAccessTo assumptions route True wouldHaveReadAccessToIff, wouldHaveWriteAccessToIff - :: ( MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX ) + :: (HasCallStack, MonadThrow m, MonadAP m) => [(AuthTag, Bool)] -- ^ Assumptions -> Route UniWorX -> m Bool wouldHaveReadAccessToIff assumptions route = and2M (not <$> hasReadAccessTo route) $ wouldHaveReadAccessTo assumptions route wouldHaveWriteAccessToIff assumptions route = and2M (not <$> hasWriteAccessTo route) $ wouldHaveWriteAccessTo assumptions route + + +evalWorkflowRoleFor' :: forall m backend. + ( HasCallStack + , MonadHandler m, HandlerSite m ~ UniWorX + , MonadAP (ReaderT backend m), MonadIO m + , MonadThrow m + , BackendCompatible SqlReadBackend backend + ) + => (forall m'. MonadAP m' => AuthTagsEval m') + -> Maybe UserId + -> Maybe WorkflowWorkflowId + -> WorkflowRole UserId + -> Route UniWorX + -> Bool + -> WriterT (Set AuthTag) (ReaderT backend m) AuthResult +evalWorkflowRoleFor' eval mAuthId mwwId wRole route isWrite = do + mr <- getMsgRenderer + + let + orAR' :: forall m'. Monad m' => m' AuthResult -> m' AuthResult -> m' AuthResult + orAR' = shortCircuitM (is _Authorized) (orAR mr) + + orDefault = orAR' $ eval defaultAuthDNF mAuthId route isWrite + + case wRole of + WorkflowRoleUser{..} -> orDefault . lift . exceptT return return $ do + uid <- maybeExceptT AuthenticationRequired $ return mAuthId + unless (uid == workflowRoleUser) $ + throwE =<< unauthorizedI MsgWorkflowRoleUserMismatch + return Authorized + -- `WorkflowRoleInitiator` now means "during initiation". + -- The old meaning can be emulated via `WorkflowRolePayloadReference`. + WorkflowRoleInitiator{} -> orDefault $ if + | is _Nothing mwwId -> return Authorized + | otherwise -> unauthorizedI MsgWorkflowRoleAlreadyInitiated + -- WorkflowRoleInitiator{} -> exceptT return return $ do + -- wwId <- maybeMExceptT (unauthorizedI MsgWorkflowRoleNoInitiator) $ return mwwId + -- WorkflowWorkflow{..} <- maybeMExceptT (unauthorizedI MsgWorkflowRoleNoSuchWorkflowWorkflow) . lift . withReaderT (projectBackend @SqlReadBackend) $ get wwId + -- let WorkflowAction{..} = head workflowWorkflowState + -- wpUser' <- maybeMExceptT (unauthorizedI MsgWorkflowRoleNoInitiator) . return $ review _SqlKey <$> join wpUser + -- lift $ evalWorkflowRoleFor' tagActive mAuthId mwwId (WorkflowRoleUser wpUser') route isWrite + WorkflowRolePayloadReference{..} -> orDefault . exceptT return return $ do + uid <- maybeExceptT AuthenticationRequired $ return mAuthId + wwId <- maybeMExceptT (unauthorizedI MsgWorkflowRoleNoPayload) $ return mwwId + Entity _ WorkflowWorkflow{..} <- maybeMExceptT (unauthorizedI MsgWorkflowRoleNoSuchWorkflowWorkflow) . lift $ getWorkflowWorkflowState wwId + -- WorkflowWorkflow{..} <- maybeMExceptT (unauthorizedI MsgWorkflowRoleNoSuchWorkflowWorkflow) . lift . withReaderT (projectBackend @SqlReadBackend) $ get wwId + let uids = maybe Set.empty getLast . foldMap (fmap Last) . workflowStatePayload workflowRolePayloadLabel $ _DBWorkflowState # workflowWorkflowState + unless (uid `Set.member` uids) $ + throwE =<< unauthorizedI MsgWorkflowRoleUserMismatch + return Authorized + WorkflowRoleAuthorized{..} -> eval (predDNFEntail $ workflowRoleAuthorized `predDNFOr` defaultAuthDNF) mAuthId route isWrite + +evalWorkflowRoleFor :: ( HasCallStack + , MonadAP (ReaderT backend m), MonadIO m + , MonadHandler m, HandlerSite m ~ UniWorX + , MonadThrow m + , BackendCompatible SqlReadBackend backend + ) + => Maybe UserId + -> Maybe WorkflowWorkflowId + -> WorkflowRole UserId + -> Route UniWorX + -> Bool + -> ReaderT backend m AuthResult +evalWorkflowRoleFor mAuthId mwwId wRole route isWrite = do + isSelf <- (== mAuthId) <$> liftHandler defaultMaybeAuthId + tagActive <- if + | isSelf -> fromMaybe def <$> lookupSessionJson SessionActiveAuthTags + | otherwise -> return . AuthTagActive $ const True + (result, deactivated) <- + let eval :: forall m'. MonadAP m' => AuthTagsEval m' + eval dnf' mAuthId' route' isWrite' = evalAuthTags 'evalWorkflowRoleFor tagActive eval dnf' mAuthId' route' isWrite' + in runWriterT $ evalWorkflowRoleFor' eval mAuthId mwwId wRole route isWrite + when isSelf $ + tellSessionJson SessionInactiveAuthTags deactivated + return result + +hasWorkflowRole :: ( HasCallStack + , MonadAP (ReaderT backend m) + , MonadHandler m, HandlerSite m ~ UniWorX + , MonadThrow m + , BackendCompatible SqlReadBackend backend + ) + => Maybe WorkflowWorkflowId + -> WorkflowRole UserId + -> Route UniWorX + -> Bool + -> ReaderT backend m AuthResult +hasWorkflowRole mwwId wRole route isWrite = do + mAuthId <- maybeAuthId + evalWorkflowRoleFor mAuthId mwwId wRole route isWrite + +mayViewWorkflowAction' :: forall backend m fileid. + ( HasCallStack + , MonadAP (ReaderT backend m) + , BackendCompatible SqlReadBackend backend + , MonadCrypto m, MonadCryptoKey m ~ CryptoIDKey + , MonadCatch m + , MonadHandler m, HandlerSite m ~ UniWorX + , MonadUnliftIO m + ) + => (forall m'. MonadAP m' => AuthTagsEval m') + -> Maybe UserId + -> WorkflowWorkflowId + -> WorkflowAction fileid UserId + -> WriterT (Set AuthTag) (ReaderT backend m) Bool +mayViewWorkflowAction' eval mAuthId wwId WorkflowAction{..} = hoist (withReaderT $ projectBackend @SqlReadBackend) . maybeT (return False) $ do + Entity _ WorkflowWorkflow{..} <- MaybeT . lift $ getWorkflowWorkflowState wwId + rScope <- hoist lift . toRouteWorkflowScope $ _DBWorkflowScope # workflowWorkflowScope + cID <- catchMaybeT (Proxy @CryptoIDError) . lift . lift $ encrypt wwId + WorkflowGraph{..} <- lift . lift $ getSharedIdWorkflowGraph workflowWorkflowGraph + let canonRoute = _WorkflowScopeRoute # (rScope, WorkflowWorkflowR cID WWWorkflowR) + evalWorkflowRole'' role = lift $ is _Authorized <$> evalWorkflowRoleFor' eval mAuthId (Just wwId) role canonRoute False + WorkflowNodeView{..} <- hoistMaybe $ Map.lookup wpTo wgNodes >>= wgnViewers + guardM $ orM + [ return $ is _Just mAuthId && wpUser == Just mAuthId + , anyM wnvViewers evalWorkflowRole'' + , anyM (Map.keys wpPayload) $ \payloadLbl -> lift . maybeT (return False) $ do + WorkflowPayloadView{..} <- hoistMaybe . Map.lookup payloadLbl $ Map.findWithDefault Map.empty wpTo (wgnPayloadView <$> wgNodes) + anyM wpvViewers evalWorkflowRole'' + ] + return True + +mayViewWorkflowAction :: forall backend m fileid. + ( HasCallStack + , MonadAP (ReaderT backend m) + , BackendCompatible SqlReadBackend backend + , MonadCrypto m, MonadCryptoKey m ~ CryptoIDKey + , MonadCatch m + , MonadHandler m, HandlerSite m ~ UniWorX + , MonadUnliftIO m + ) + => Maybe UserId + -> WorkflowWorkflowId + -> WorkflowAction fileid UserId + -> ReaderT backend m Bool +mayViewWorkflowAction mAuthId wwId act = do + isSelf <- (== mAuthId) <$> liftHandler defaultMaybeAuthId + tagActive <- if + | isSelf -> fromMaybe def <$> lookupSessionJson SessionActiveAuthTags + | otherwise -> return . AuthTagActive $ const True + (result, deactivated) <- + let eval :: forall m'. MonadAP m' => AuthTagsEval m' + eval dnf' mAuthId' route' isWrite' = evalAuthTags 'mayViewWorkflowAction tagActive eval dnf' mAuthId' route' isWrite' + in runWriterT $ mayViewWorkflowAction' eval mAuthId wwId act + when isSelf $ + tellSessionJson SessionInactiveAuthTags deactivated + return result + + +authoritiveApproot :: Route UniWorX -> ApprootScope +authoritiveApproot = \case + CourseR _ _ _ (MaterialR _ (MFileR _)) -> ApprootUserGenerated + CourseR _ _ _ (MaterialR _ MArchiveR) -> ApprootUserGenerated + CourseR _ _ _ (SheetR _ (SFileR _ _)) -> ApprootUserGenerated + CourseR _ _ _ (SheetR _ (SZipR _)) -> ApprootUserGenerated + CourseR _ _ _ (SheetR _ (SubmissionR _ (SubDownloadR _ _))) -> ApprootUserGenerated + CourseR _ _ _ (SheetR _ (SubmissionR _ (SubArchiveR _))) -> ApprootUserGenerated + CourseR _ _ _ (CourseNewsR _ (CNFileR _)) -> ApprootUserGenerated + CourseR _ _ _ (CourseNewsR _ CNArchiveR) -> ApprootUserGenerated + CourseR _ _ _ CRegisterTemplateR -> ApprootUserGenerated + CourseR _ _ _ CAppsFilesR -> ApprootUserGenerated + CourseR _ _ _ (CourseApplicationR _ CAFilesR) -> ApprootUserGenerated + route | Just (_, WorkflowWorkflowR _ (WWFilesR _ _)) <- route ^? _WorkflowScopeRoute -> ApprootUserGenerated + _other -> ApprootDefault diff --git a/src/Foundation/DB.hs b/src/Foundation/DB.hs index 5261af6a2..87f93a952 100644 --- a/src/Foundation/DB.hs +++ b/src/Foundation/DB.hs @@ -1,6 +1,7 @@ module Foundation.DB - ( runDBRead - , runSqlPoolRetry + ( runDBRead, runDBRead' + , runSqlPoolRetry, runSqlPoolRetry' + , dbPoolPressured ) where import Import.NoFoundation hiding (runDB, getDBRunner) @@ -10,17 +11,31 @@ import Foundation.Type import qualified Control.Retry as Retry import GHC.IO.Exception (IOErrorType(OtherError)) -import Database.Persist.Sql (runSqlPool, SqlReadBackend(..)) +import Database.Persist.Sql (SqlReadBackend(..)) +import Database.Persist.Sql.Raw.QQ (executeQQ) + +import qualified Utils.Pool as Custom -runSqlPoolRetry :: forall m a backend. - ( MonadUnliftIO m, BackendCompatible SqlBackend backend +runSqlPoolRetry :: forall m a backend c. + ( HasCallStack + , MonadUnliftIO m, BackendCompatible SqlBackend backend , MonadLogger m, MonadMask m ) => ReaderT backend m a - -> Pool backend + -> Custom.Pool' m DBConnLabel c backend -> m a -runSqlPoolRetry action pool = do +runSqlPoolRetry action pool = runSqlPoolRetry' action pool callStack + +runSqlPoolRetry' :: forall m a backend c. + ( MonadUnliftIO m, BackendCompatible SqlBackend backend + , MonadLogger m, MonadMask m + ) + => ReaderT backend m a + -> Custom.Pool' m DBConnLabel c backend + -> CallStack + -> m a +runSqlPoolRetry' action pool lbl = do let policy = Retry.fullJitterBackoff 1e3 & Retry.limitRetriesByCumulativeDelay 10e6 handlers = Retry.skipAsyncExceptions `snoc` Retry.logRetries suggestRetry logRetry where suggestRetry :: IOException -> m Bool @@ -38,9 +53,22 @@ runSqlPoolRetry action pool = do Retry.recovering policy handlers $ \Retry.RetryStatus{..} -> do $logDebugS "runSqlPoolRetry" $ "rsIterNumber = " <> tshow rsIterNumber - runSqlPool action pool + customRunSqlPool' action pool lbl -runDBRead :: ReaderT SqlReadBackend (HandlerFor UniWorX) a -> (HandlerFor UniWorX) a -runDBRead action = do +runDBRead :: HasCallStack => ReaderT SqlReadBackend (HandlerFor UniWorX) a -> (HandlerFor UniWorX) a +runDBRead = runDBRead' callStack + +runDBRead' :: CallStack -> ReaderT SqlReadBackend (HandlerFor UniWorX) a -> (HandlerFor UniWorX) a +runDBRead' lbl action = do $logDebugS "YesodPersist" "runDBRead" - runSqlPoolRetry (withReaderT SqlReadBackend action) . appConnPool =<< getYesod + flip (runSqlPoolRetry' . withReaderT SqlReadBackend $ [executeQQ|SET TRANSACTION READ ONLY|] *> action) lbl . appConnPool =<< getYesod + +dbPoolPressured :: ( MonadHandler m + , HandlerSite m ~ UniWorX + ) + => m Bool +dbPoolPressured = do + connPool <- getsYesod @_ @(Custom.Pool' IO _ _ _) appConnPool + case Custom.getPoolMaxAvailable connPool of + Nothing -> return False + Just lim -> atomically $ (>= lim) <$> Custom.getPoolInUseCount connPool diff --git a/src/Foundation/I18n.hs b/src/Foundation/I18n.hs index b8cee3c41..c6d56cf86 100644 --- a/src/Foundation/I18n.hs +++ b/src/Foundation/I18n.hs @@ -1,13 +1,14 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# OPTIONS_GHC -fno-warn-orphans #-} + module Foundation.I18n ( appLanguages, appLanguagesOpts - , UniWorXMessage(..) + , UniWorXMessage(..), UniWorXTestMessage(..) , ShortTermIdentifier(..) , MsgLanguage(..) , ShortSex(..) , ShortWeekDay(..) - , SheetTypeHeader(..) + , SheetType'(..), classifySheetType , SheetArchiveFileTypeDirectory(..) , ShortStudyDegree(..) , ShortStudyTerms(..) @@ -15,14 +16,15 @@ module Foundation.I18n , ShortStudyFieldType(..) , StudyDegreeTermType(..) , ErrorResponseTitle(..) + , WorkflowPayloadBool(..) , UniWorXMessages(..) , uniworxMessages , unRenderMessage, unRenderMessage', unRenderMessageLenient + , module Foundation.I18n.TH ) where import Foundation.Type - import Import.NoFoundation import Auth.LDAP @@ -47,6 +49,12 @@ import Data.Text.Lens (packed) import Data.List ((!!)) +import qualified Data.Scientific as Scientific + +import Utils.Workflow (RouteWorkflowScope) + +import Foundation.I18n.TH + pluralDE :: (Eq a, Num a) => a -- ^ Count @@ -118,21 +126,19 @@ ordinalEN (toMessage -> numStr) = case lastChar of lastChar = last <$> fromNullable numStr --- Convenience Type for Messages, since Yesod messages cannot deal with compound type identifiers -type IntMaybe = Maybe Int - -- | Convenience function for i18n messages definitions maybeToMessage :: ToMessage m => Text -> Maybe m -> Text -> Text maybeToMessage _ Nothing _ = mempty maybeToMessage before (Just x) after = before <> toMessage x <> after -- Messages creates type UniWorXMessage and RenderMessage UniWorX instance -mkMessage "UniWorX" "messages/uniworx" "de-de-formal" -mkMessageVariant "UniWorX" "Campus" "messages/campus" "de" -mkMessageVariant "UniWorX" "Dummy" "messages/dummy" "de" -mkMessageVariant "UniWorX" "PWHash" "messages/pw-hash" "de" -mkMessageVariant "UniWorX" "Button" "messages/button" "de" -mkMessageVariant "UniWorX" "Frontend" "messages/frontend" "de-de-formal" +mkMessage ''UniWorX "messages/uniworx/misc" "de-de-formal" +mkMessageAddition ''UniWorX "Test" "messages/uniworx/test" "de-de-formal" +mkMessageVariant ''UniWorX ''CampusMessage "messages/campus" "de" +mkMessageVariant ''UniWorX ''DummyMessage "messages/dummy" "de" +mkMessageVariant ''UniWorX ''PWHashMessage "messages/pw-hash" "de" +mkMessageVariant ''UniWorX ''ButtonMessage "messages/button" "de" +mkMessageVariant ''UniWorX ''FrontendMessage "messages/frontend" "de-de-formal" instance RenderMessage UniWorX TermIdentifier where renderMessage foundation ls TermIdentifier{..} = case season of @@ -160,6 +166,8 @@ instance RenderMessage UniWorX Integer where renderMessage f ls = renderMessage f ls . tshow instance RenderMessage UniWorX Natural where renderMessage f ls = renderMessage f ls . tshow +instance RenderMessage UniWorX Word64 where + renderMessage f ls = renderMessage f ls . tshow instance HasResolution a => RenderMessage UniWorX (Fixed a) where renderMessage f ls = renderMessage f ls . showFixed True @@ -219,6 +227,7 @@ embedRenderMessage ''UniWorX ''SchoolFunction id embedRenderMessage ''UniWorX ''SystemFunction id embedRenderMessage ''UniWorX ''CsvPreset id embedRenderMessage ''UniWorX ''Quoting ("Csv" <>) +embedRenderMessage ''UniWorX ''CsvFormat ("Csv" <>) embedRenderMessage ''UniWorX ''FavouriteReason id embedRenderMessage ''UniWorX ''Sex id embedRenderMessage ''UniWorX ''ExamGradingMode id @@ -227,32 +236,41 @@ embedRenderMessage ''UniWorX ''ExamOnlinePreset id embedRenderMessage ''UniWorX ''ExamSynchronicityPreset id embedRenderMessage ''UniWorX ''ExamRequiredEquipmentPreset id embedRenderMessage ''UniWorX ''ChangelogItemKind id +embedRenderMessage ''UniWorX ''WorkflowScope' $ ("WorkflowScopeKind" <>) . concat . drop 1 . splitCamel . fromMaybe (error "Expected WorkflowScope' to have '") . stripSuffix "'" +embedRenderMessage ''UniWorX ''RoomReference' $ dropSuffix "'" embedRenderMessage ''UniWorX ''AuthenticationMode id embedRenderMessage ''UniWorX ''RatingValidityException id +embedRenderMessage ''UniWorX ''UrlFieldMessage id + embedRenderMessageVariant ''UniWorX ''ADInvalidCredentials ("InvalidCredentials" <>) newtype ShortSex = ShortSex Sex embedRenderMessageVariant ''UniWorX ''ShortSex ("Short" <>) -newtype SheetTypeHeader = SheetTypeHeader SheetType -embedRenderMessageVariant ''UniWorX ''SheetTypeHeader ("SheetType" <>) +data SheetType' + = NotGraded' | Normal' | Bonus' | Informational' | ExamPartPoints' + deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, Typeable) + deriving (Universe, Finite) + +classifySheetType :: SheetType a -> SheetType' +classifySheetType = \case + NotGraded -> NotGraded' + Normal{} -> Normal' + Bonus{} -> Bonus' + Informational{} -> Informational' + ExamPartPoints{} -> ExamPartPoints' + +nullaryPathPiece ''SheetType' (camelToPathPiece . dropSuffix "'") +embedRenderMessage ''UniWorX ''SheetType' $ ("SheetType" <>) . fromMaybe (error "Expected SheetType' to have '") . stripSuffix "'" newtype SheetArchiveFileTypeDirectory = SheetArchiveFileTypeDirectory SheetFileType deriving (Eq, Ord, Read, Show, Generic, Typeable) deriving newtype (Enum, Bounded, Universe, Finite) embedRenderMessageVariant ''UniWorX ''SheetArchiveFileTypeDirectory $ ("SheetArchiveFileTypeDirectory" <>) . concat . drop 1 . splitCamel -instance RenderMessage UniWorX SheetType where - renderMessage foundation ls sheetType = case sheetType of - NotGraded -> mr $ SheetTypeHeader NotGraded - other -> mr (grading other) <> ", " <> mr (SheetTypeHeader other) - where - mr :: RenderMessage UniWorX msg => msg -> Text - mr = renderMessage foundation ls - instance RenderMessage UniWorX StudyDegree where renderMessage _found _ls StudyDegree{..} = fromMaybe (tshow studyDegreeKey) (studyDegreeName <|> studyDegreeShorthand) @@ -330,7 +348,17 @@ instance RenderMessage UniWorX ScheduleView where mr :: RenderMessage UniWorX msg => msg -> Text mr = renderMessage foundation ls +instance RenderMessage UniWorX ExamCloseMode where + renderMessage foundation ls = \case + ExamCloseSeparate -> mr MsgExamCloseModeSeparate + ExamCloseOnFinished False -> mr MsgExamCloseModeOnFinished + ExamCloseOnFinished True -> mr MsgExamCloseModeOnFinishedHidden + where + mr :: RenderMessage UniWorX msg => msg -> Text + mr = renderMessage foundation ls + -- ToMessage instances for converting raw numbers to Text (no internationalization) +-- FIXME: Use RenderMessage always instance ToMessage Int where toMessage = tshow @@ -340,6 +368,8 @@ instance ToMessage Integer where toMessage = tshow instance ToMessage Natural where toMessage = tshow +instance ToMessage Word64 where + toMessage = tshow instance HasResolution a => ToMessage (Fixed a) where toMessage = toMessage . showFixed True @@ -353,6 +383,10 @@ instance HasResolution a => ToMessage (Fixed a) where newtype ErrorResponseTitle = ErrorResponseTitle ErrorResponse embedRenderMessageVariant ''UniWorX ''ErrorResponseTitle ("ErrorResponseTitle" <>) +newtype WorkflowPayloadBool = WorkflowPayloadBool { unWorkflowPayloadBool :: Bool } +embedRenderMessageVariant ''UniWorX ''WorkflowPayloadBool ("WorkflowPayloadBool" <>) + + newtype UniWorXMessages = UniWorXMessages [SomeMessage UniWorX] deriving stock (Generic, Typeable) deriving newtype (Semigroup, Monoid) @@ -409,6 +443,17 @@ instance RenderMessage UniWorX ShortWeekDay where embedRenderMessage ''UniWorX ''ButtonSubmit id +instance RenderMessage UniWorX RouteWorkflowScope where + renderMessage foundation ls = \case + WSGlobal -> mr MsgWorkflowScopeGlobal + WSTerm{..} -> mr . ShortTermIdentifier $ unTermKey wisTerm + WSSchool{..} -> mr $ unSchoolKey wisSchool + WSTermSchool{..} -> mr $ MsgWorkflowScopeTermSchool wisTerm wisSchool + WSCourse{ wisCourse = (tid, ssh, csh) } -> mr $ MsgWorkflowScopeCourse tid ssh csh + where + mr :: forall msg. RenderMessage UniWorX msg => msg -> Text + mr = renderMessage foundation ls + unRenderMessage' :: (Eq a, Finite a, RenderMessage master a) => (Text -> Text -> Bool) -> master -> Text -> [a] unRenderMessage' cmp foundation inp = nub $ do diff --git a/src/Foundation/I18n/TH.hs b/src/Foundation/I18n/TH.hs new file mode 100644 index 000000000..991d43e5d --- /dev/null +++ b/src/Foundation/I18n/TH.hs @@ -0,0 +1,324 @@ +{-# LANGUAGE UndecidableInstances #-} + +module Foundation.I18n.TH + ( mkMessage, mkMessageFor, mkMessageVariant, mkMessageAddition + ) where + +import Import.NoFoundation +import qualified Language.Haskell.TH.Lib as TH +import qualified Language.Haskell.TH.Syntax as TH + +import qualified System.Directory.Tree as DirTree + +import Data.HashMap.Strict.InsOrd (InsOrdHashMap) +import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap +import Data.HashSet.InsOrd (InsOrdHashSet) +import qualified Data.HashSet.InsOrd as InsOrdHashSet +import qualified Data.Foldable as F +import qualified Data.HashMap.Strict as HashMap +import qualified Data.HashSet as HashSet +import qualified Data.Map.Strict as Map + +import qualified Text.Parsec as P +import qualified Text.Parsec.Text.Lazy as P + +import qualified Language.Haskell.Meta.Parse as Meta + +import qualified Data.List.NonEmpty as NonEmpty + +import qualified Data.Text as Text + +import Utils.TH.AlphaConversion (alphaConvE) + + +newtype MsgFile f g = MsgFile + { msgFileContent :: InsOrdHashMap String (f (MsgDef f g)) + } deriving (Generic, Typeable) + +deriving stock instance Eq (f (MsgDef f g)) => Eq (MsgFile f g) +deriving stock instance Show (f (MsgDef f g)) => Show (MsgFile f g) + +instance Semigroup (f (MsgDef f g)) => Monoid (MsgFile f g) where + mempty = MsgFile InsOrdHashMap.empty +instance Semigroup (f (MsgDef f g)) => Semigroup (MsgFile f g) where + MsgFile a <> MsgFile b = MsgFile $ InsOrdHashMap.unionWith (<>) a b + +data MsgDef f g = MsgDef + { msgDefVars :: InsOrdHashMap String (f (g TH.Type)) + , msgDefContent :: [MsgDefContent] + } deriving (Generic, Typeable) + +deriving stock instance Eq (f (g TH.Type)) => Eq (MsgDef f g) +deriving stock instance Show (f (g TH.Type)) => Show (MsgDef f g) + +data MsgDefContent = MsgDefContentLiteral String + | MsgDefContentSplice Bool {- Recurse? -} TH.Exp + deriving (Eq, Ord, Show, Generic, Typeable) + + +disambiguateMsgFile :: MsgFile NonEmpty Maybe -> Either (InsOrdHashSet String, InsOrdHashMap String (InsOrdHashSet String)) (MsgFile Identity Maybe) +disambiguateMsgFile MsgFile{..} + | not (InsOrdHashSet.null duplicateDefs) || not (InsOrdHashMap.null duplicateVars) + = Left (duplicateDefs, duplicateVars) + | otherwise + = Right $ MsgFile{ msgFileContent = fmap msgDefToSingletons <$> toSingletons msgFileContent, .. } + where + toDuplicates :: forall k v. (Eq k, Hashable k) => InsOrdHashMap k (NonEmpty v) -> InsOrdHashSet k + toDuplicates = InsOrdHashSet.fromList . InsOrdHashMap.keys . InsOrdHashMap.filter (minLength 2) + duplicateDefs = toDuplicates msgFileContent + duplicateVars = InsOrdHashMap.mapMaybe (assertM' (not . InsOrdHashSet.null) . toDuplicates . msgDefVars . NonEmpty.head) msgFileContent + + toSingletons :: forall k v. InsOrdHashMap k (NonEmpty v) -> InsOrdHashMap k (Identity v) + toSingletons = InsOrdHashMap.map $ \case + x NonEmpty.:| [] -> Identity x + xs -> error $ "toSingletons: Expected length 1, but got: " <> show (NonEmpty.length xs) + msgDefToSingletons :: MsgDef NonEmpty Maybe -> MsgDef Identity Maybe + msgDefToSingletons MsgDef{..} = MsgDef + { msgDefVars = toSingletons msgDefVars + , .. + } + +ensureTypesMsgFile :: MsgFile Identity Maybe -> Either (InsOrdHashMap String (InsOrdHashSet String)) (MsgFile Identity Identity) +ensureTypesMsgFile MsgFile{..} + | not $ InsOrdHashMap.null untyped + = Left untyped + | otherwise + = Right $ MsgFile{ msgFileContent = over _Wrapped msgDefToTyped <$> msgFileContent, .. } + where + untyped = InsOrdHashMap.mapMaybe (assertM' (not . InsOrdHashSet.null) . InsOrdHashSet.fromList . InsOrdHashMap.keys . InsOrdHashMap.filter (is _Nothing . runIdentity) . msgDefVars . runIdentity) msgFileContent + + msgDefToTyped MsgDef{..} = MsgDef + { msgDefVars = flip InsOrdHashMap.map msgDefVars $ \case + Identity (Just x) -> Identity $ Identity x + _other -> error "msgDefToTyped got Nothing" + , .. + } + + +accumInsOrdHashMap :: (Foldable f, Eq k, Hashable k) + => f (k, v) + -> InsOrdHashMap k (NonEmpty v) +accumInsOrdHashMap = F.foldl' (\acc (k, v) -> InsOrdHashMap.insertWith (<>) k (pure v) acc) InsOrdHashMap.empty + +unionsInsOrdHashMap :: (Foldable f, Eq k, Hashable k) + => f (InsOrdHashMap k (NonEmpty v)) + -> InsOrdHashMap k (NonEmpty v) +unionsInsOrdHashMap = F.foldl' (InsOrdHashMap.unionWith (<>)) InsOrdHashMap.empty + +insOrdHashMapKeysSet :: InsOrdHashMap k v -> HashSet k +insOrdHashMapKeysSet = HashMap.keysSet . InsOrdHashMap.toHashMap + + +mkMessage :: TH.Name -- ^ Foundation type + -> FilePath -- ^ Base directory of translation files + -> Lang -- ^ Default translation language + -> TH.DecsQ +mkMessage dt = mkMessageCommon True "Msg" dt . TH.mkName $ TH.nameBase dt <> "Message" + +mkMessageFor :: TH.Name -- ^ Foundation type + -> TH.Name -- ^ Existing type to add translations for + -> FilePath -- ^ Base directory of translation files + -> Lang -- ^ Default translation language + -> TH.DecsQ +mkMessageFor = mkMessageCommon False "" + +mkMessageVariant :: TH.Name -- ^ Foundation type + -> TH.Name -- ^ Existing type to add translations for + -> FilePath -- ^ Base directory of translation files + -> Lang -- ^ Default translation language + -> TH.DecsQ +mkMessageVariant = mkMessageCommon False "Msg" + +mkMessageAddition :: TH.Name -- ^ Foundation type + -> String -- ^ Qualifier to insert into name of message type + -> FilePath -- ^ Base directory of translation files + -> Lang -- ^ Default translation language + -> TH.DecsQ +mkMessageAddition master qual = mkMessageCommon True "Msg" master . TH.mkName $ TH.nameBase master <> qual <> "Message" + +mkMessageCommon :: Bool -- ^ Generate new datatype + -> String -- ^ String to prepend to constructor names + -> TH.Name -- ^ Name of master datatype + -> TH.Name -- ^ Name of translation datatype + -> FilePath -- ^ Base directory of translation files + -> Lang -- ^ Default translation language + -> TH.DecsQ +mkMessageCommon genType prefix master datName folder defLang = do + files <- fmap DirTree.zipPaths . liftIO $ DirTree.readDirectoryWith (runExceptT . parseMsgFile) folder + forMOf_ (folded . _1) files TH.addDependentFile + + let (errors, successes) = flip (foldMapOf $ folded . _2) files $ \case + Left err -> ([err], mempty) + Right (lang, x) -> (mempty, MergeHashMap $ HashMap.singleton lang x) + unless (null errors) . fail $ "Errors occurred while parsing message files:\n" <> indent 2 (unlines $ map show errors) + + let (ambiguous, disambiguated) = flip ifoldMap successes $ \lang x -> case disambiguateMsgFile x of + Left errs -> ([(lang, errs)], mempty) + Right x' -> (mempty, HashMap.singleton lang x') + ambiguousError (lang, (ambigDefs, ambigVars)) = "Language " <> unpack lang <> ":\n" <> unlines errs + where + errs = bool (pure $ "Duplicate message definitions:\n" <> indent 1 (unlines ambigDefsErrs)) [] (InsOrdHashSet.null ambigDefs) + ++ bool (pure $ "Duplicate variable names:\n" <> indent 1 (unlines ambigVarsErrs)) [] (InsOrdHashMap.null ambigVars) + ambigDefsErrs = InsOrdHashSet.toList ambigDefs + ambigVarsErrs = map (\(defn, InsOrdHashSet.toList -> vars) -> defn <> ": " <> intercalate ", " vars) $ InsOrdHashMap.toList ambigVars + unless (null ambiguous) . fail . indent' 2 . unlines $ map ambiguousError ambiguous + + defMsgFile <- case HashMap.lookup defLang disambiguated of + Nothing -> fail $ "Default language (" <> unpack defLang <> ") not found; found instead: " <> intercalate ", " (unpack <$> HashMap.keys disambiguated) + Just x -> return x + + let allDefns = insOrdHashMapKeysSet $ msgFileContent defMsgFile + extraDefns = flip HashMap.mapMaybe disambiguated $ \MsgFile{..} -> assertM' (not . HashSet.null) $ insOrdHashMapKeysSet msgFileContent `HashSet.difference` allDefns + extraDefnsErrs = flip map (HashMap.toList extraDefns) $ \(lang, extra) -> "Language " <> unpack lang <> ":\n" <> indent 1 (intercalate ", " $ HashSet.toList extra) + unless (null extraDefns) . fail $ "Extraneous message definitions:\n" <> indent 2 (unlines extraDefnsErrs) + + let defnName defn = TH.mkName $ prefix <> defn + + execWriterT @_ @[TH.Dec] $ do + when genType $ do + typedDefMsgFile <- case ensureTypesMsgFile defMsgFile of + Left untypedVars -> fail $ "Default language (" <> unpack defLang <> ") contains untyped variables:\n" <> indent 2 (unlines . flip map (InsOrdHashMap.toList $ InsOrdHashSet.toList <$> untypedVars) $ \(defn, vs) -> defn <> ": " <> intercalate ", " vs) + Right x -> return x + + let + datCons :: [TH.ConQ] + datCons = flip foldMap (InsOrdHashMap.toList $ msgFileContent typedDefMsgFile) $ \(defn, Identity MsgDef{ msgDefVars }) -> + pure . TH.normalC (defnName defn) . flip foldMap (InsOrdHashMap.toList msgDefVars) $ \(_, Identity (Identity varT)) -> + pure . TH.bangType (TH.bang TH.noSourceUnpackedness TH.sourceStrict) $ return varT + + tellMPoint $ TH.dataD (TH.cxt []) datName [] Nothing datCons [] + + renderLangs <- iforM disambiguated $ \lang MsgFile{..} -> do + let missing = allDefns `HashSet.difference` insOrdHashMapKeysSet msgFileContent + complete = HashSet.null missing + unless complete $ + lift . TH.reportWarning $ "Language " <> unpack lang <> " is not complete, missing:\n" <> indent 2 (unlines $ HashSet.toList missing) + funName <- lift $ newUniqueName "renderLang" + tellMPoint $ TH.sigD funName [t| $(TH.conT master) -> [Lang] -> $(TH.conT datName) -> $(bool [t|Maybe Text|] [t|Text|] complete) |] + masterN <- lift $ TH.newName "_master" + langsN <- lift $ TH.newName "_langs" + let + lamExp :: TH.ExpQ + lamExp = TH.lamCaseE $ bool (++ [TH.match TH.wildP (TH.normalB [e|Nothing|]) []]) id complete matches + where matches :: [TH.MatchQ] + matches = flip map (InsOrdHashMap.toList msgFileContent) $ \(defn, Identity MsgDef{..}) -> do + varns <- flip foldMapM (InsOrdHashMap.toList msgDefVars) $ \(varn, Identity mType) -> InsOrdHashMap.singleton varn . (, mType) <$> TH.newName ("_" <> varn) + let transE :: TH.ExpQ + transE + | Just (x NonEmpty.:| xs) <- NonEmpty.nonEmpty msgDefContent = go x xs + | otherwise = [e|Text.empty|] + where + go' (MsgDefContentLiteral (pack -> t)) = TH.lift (t :: Text) + go' (MsgDefContentSplice isRec spliceE) + | isRec = [e|renderMessage $(TH.varE masterN) $(TH.varE langsN) $(return $ alphaConv spliceE)|] + | otherwise = [e|toMessage $(return $ alphaConv spliceE)|] + + go c [] = go' c + go (MsgDefContentLiteral t1) (MsgDefContentLiteral t2 : cs) = go (MsgDefContentLiteral $ t1 <> t2) cs + go c1 (c2:cs) = [e|$(go' c1) `Text.append` $(go c2 cs)|] + + alphaConv = alphaConvE . Map.fromList . map ((,) <$> views _1 TH.mkName <*> view (_2 . _1)) $ InsOrdHashMap.toList varns + + defnP :: TH.PatQ + defnP = TH.conP (defnName defn) . map varP $ F.toList varns + where varP (varn, Nothing) = TH.varP varn + varP (varn, Just typ) = TH.sigP (varP (varn, Nothing)) $ return typ + TH.match defnP (TH.normalB $ bool [e|Just $(transE)|] transE complete) [] + tellMPoint . TH.funD funName . pure $ TH.clause [TH.varP masterN, TH.varP langsN] (TH.normalB lamExp) [] + tellMPoint $ TH.pragInlD funName TH.Inlinable TH.FunLike TH.AllPhases + return (complete, funName) + + allRenderers <- lift $ newUniqueName "langRendereres" + tellMPoint $ TH.sigD allRenderers [t|HashMap Lang (Either ($(TH.conT master) -> [Lang] -> $(TH.conT datName) -> Maybe Text) ($(TH.conT master) -> [Lang] -> $(TH.conT datName) -> Text))|] + let allRenderers' = TH.listE . flip map (HashMap.toList renderLangs) $ \(lang, (complete, funName)) -> [e|($(TH.lift lang), $(bool [e|Left|] [e|Right|] complete) $(TH.varE funName))|] + in tellMPoint . TH.funD allRenderers . pure $ TH.clause [] (TH.normalB [e|HashMap.fromList $(allRenderers')|]) [] + tellMPoint $ TH.pragInlD allRenderers TH.NoInline TH.FunLike TH.AllPhases + + let defRender = views _2 TH.varE $ HashMap.findWithDefault (error "could not find default language in renderLangs") defLang renderLangs + in tellMPoint . TH.instanceD (TH.cxt []) [t|RenderMessage $(TH.conT master) $(TH.conT datName)|] . pure $ + TH.funD 'renderMessage . pure $ + TH.clause [] (TH.normalB [e|renderMessageDispatch $(TH.lift defLang) $(defRender) $(TH.varE allRenderers)|]) [] + where + indent, indent' :: Int -> String -> String + indent n = unlines . map (replicate (4 * n) ' ' <>) . lines + indent' n = unlines . over (_tail . traverse) (replicate (4 * n) ' ' <>) . lines + +parseMsgFile :: FilePath -> ExceptT P.ParseError IO (Lang, MsgFile NonEmpty Maybe) +parseMsgFile fPath = do + let msgFileLang = pack $ takeBaseName fPath + msgFileContent <- either throwE return <=< liftIO $ P.parseFromFile (pMsgFile <* P.eof) fPath + return (msgFileLang, MsgFile{..}) + +pMsgFile, pMsgLine :: P.Parser (InsOrdHashMap String (NonEmpty (MsgDef NonEmpty Maybe))) +pMsgFile = flip P.label ".msg file" . fmap unionsInsOrdHashMap $ pMsgLine `P.sepEndBy` P.try (P.many1 P.endOfLine) +pMsgLine = flip P.label ".msg line" $ do + spaces + P.choice + [ flip P.label "comment line" $ InsOrdHashMap.empty <$ P.char '#' <* P.manyTill P.anyChar (P.lookAhead . P.try $ void P.endOfLine <|> P.eof) + , flip P.label "empty line" $ InsOrdHashMap.empty <$ P.try P.endOfLine + , flip P.label "message line" $ do + constrBase <- (:) <$> P.upper <*> P.many (P.upper <|> P.lower <|> P.digit <|> P.char '\'') + msgDefVars <- P.option InsOrdHashMap.empty $ do + P.skipMany1 P.space + accumInsOrdHashMap <$> P.sepEndBy pMsgDefVar (P.many1 P.space) + spaces + void $ P.char ':' + spaces + msgDefContent <- P.manyTill pMsgDefContent . P.lookAhead . P.try $ void P.endOfLine <|> P.eof + return . InsOrdHashMap.singleton constrBase $ (NonEmpty.:| []) MsgDef{..} + ] + +pMsgDefVar :: P.Parser (String, Maybe TH.Type) +pMsgDefVar = do + varBase <- (:) <$> P.lower <*> P.many (P.upper <|> P.lower <|> P.digit <|> P.char '\'') + varTyp <- P.optionMaybe $ + P.char '@' + *> parseToSeparator Meta.parseType (fmap pure $ P.char ':' <|> P.space) + return (varBase, varTyp) + +pMsgDefContent :: P.Parser MsgDefContent +pMsgDefContent = flip P.label "message definition content" $ choice + [ MsgDefContentLiteral . pure <$ P.char '\\' <*> (P.char '_' <|> P.char '#' <|> P.char '\\') + , do + isRecurse <- P.try $ + (True <$ P.string "_{") + <|> (False <$ P.string "#{") + spliceExp <- parseToSeparator Meta.parseExp (pure <$> P.char '}') + void $ P.char '}' + return $ MsgDefContentSplice isRecurse spliceExp + , MsgDefContentLiteral <$> many1Till P.anyChar (P.lookAhead . P.try $ void (P.char '_') <|> void (P.char '#') <|> void P.endOfLine <|> P.eof) + ] + +parseToSeparator :: (String -> Either String a) -> P.Parser String -> P.Parser a +parseToSeparator innerP sepP = do + w <- many1Till P.anyChar $ P.lookAhead endOfWord + let cont mErrStr = do + endStr <- endOfWord + case endStr of + Nothing -> maybe mzero fail mErrStr + Just sepStr -> parseToSeparator (innerP . ((w <> sepStr) <>)) sepP + case innerP w of + Right res -> return res + <|> cont Nothing + Left errStr -> cont $ Just errStr + where + endOfWord = (Just <$> P.try sepP ) + <|> (Nothing <$ P.try P.endOfLine) + + +many1Till :: P.Stream s m t => P.ParsecT s u m a -> P.ParsecT s u m end -> P.ParsecT s u m [a] +many1Till p end = (:) <$> p <*> P.manyTill p end + +notLookAhead :: P.Stream s m t => P.ParsecT s u m a -> P.ParsecT s u m not -> P.ParsecT s u m a +notLookAhead p n = do + followingNot <- (True <$ P.lookAhead n) <|> pure False + bool p mzero followingNot + +spaces :: P.Parser () +spaces = P.skipMany $ notLookAhead P.space P.endOfLine + +-- | Stolen from Richard Eisenberg: +newUniqueName :: TH.Quasi q => String -> q TH.Name +newUniqueName str = do + n <- TH.qNewName str + TH.qNewName $ show n diff --git a/src/Foundation/Instances.hs b/src/Foundation/Instances.hs index 3c476665c..730d0ad29 100644 --- a/src/Foundation/Instances.hs +++ b/src/Foundation/Instances.hs @@ -1,4 +1,5 @@ {-# LANGUAGE UndecidableInstances #-} -- for `MonadCrypto` and `MonadSecretBox` +{-# LANGUAGE InstanceSigs #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Foundation.Instances @@ -9,7 +10,6 @@ module Foundation.Instances import Import.NoFoundation import qualified Data.Text as Text -import qualified Data.List as List import Data.List (inits) import qualified Yesod.Core.Unsafe as Unsafe @@ -27,6 +27,7 @@ import qualified Foundation.Yesod.StaticContent as UniWorX import qualified Foundation.Yesod.Persist as UniWorX import qualified Foundation.Yesod.Auth as UniWorX +import Foundation.Instances.ButtonClass import Foundation.SiteLayout import Foundation.Type import Foundation.I18n @@ -50,37 +51,13 @@ import qualified Data.CaseInsensitive as CI import qualified Database.Esqueleto as E -data instance ButtonClass UniWorX - = BCIsButton - | BCDefault - | BCPrimary - | BCSuccess - | BCInfo - | BCWarning - | BCDanger - | BCLink - | BCMassInputAdd | BCMassInputDelete - | BCScheduleView | BCScheduleOffset - deriving (Enum, Eq, Ord, Bounded, Read, Show, Generic, Typeable) - deriving anyclass (Universe, Finite) - -instance PathPiece (ButtonClass UniWorX) where - toPathPiece BCIsButton = "btn" - toPathPiece bClass = ("btn-" <>) . camelToPathPiece' 1 $ tshow bClass - fromPathPiece = flip List.lookup $ map (toPathPiece &&& id) universeF - -instance Button UniWorX ButtonSubmit where - btnClasses BtnSubmit = [BCIsButton, BCPrimary] - - - -- Please see the documentation for the Yesod typeclass. There are a number -- of settings which can be configured by overriding methods here. instance Yesod UniWorX where -- Controls the base of generated URLs. For more information on modifying, -- see: https://github.com/yesodweb/yesod/wiki/Overriding-approot approot = ApprootRequest $ \app req -> - case app ^. _appRoot of + case app ^. _appRoot . to ($ ApprootDefault) of Nothing -> getApprootText guessApproot app req Just root -> root @@ -107,7 +84,8 @@ instance Yesod UniWorX where -- The page to be redirected to when authentication is required. authRoute _ = Just $ AuthR LoginR - isAuthorized = evalAccess + isAuthorized :: HasCallStack => Route UniWorX -> Bool -> HandlerFor UniWorX AuthResult + isAuthorized r w = runDBRead $ evalAccess r w addStaticContent = UniWorX.addStaticContent @@ -129,11 +107,13 @@ unsafeHandler f h = do -- How to run database actions. instance YesodPersist UniWorX where - type YesodPersistBackend UniWorX = SqlBackend - runDB = UniWorX.runDB + type YesodPersistBackend UniWorX = SqlBackend + runDB :: HasCallStack => YesodDB UniWorX a -> HandlerFor UniWorX a + runDB = UniWorX.runDB' callStack instance YesodPersistRunner UniWorX where - getDBRunner = UniWorX.getDBRunner + getDBRunner :: HasCallStack => HandlerFor UniWorX (DBRunner UniWorX, HandlerFor UniWorX ()) + getDBRunner = UniWorX.getDBRunner' callStack instance YesodAuth UniWorX where @@ -182,7 +162,14 @@ instance YesodAuth UniWorX where _other -> Auth.germanMessage where lang = Text.splitOn "-" $ selectLanguage' appLanguages ls + maybeAuthId :: (HasCallStack, MonadHandler m, HandlerSite m ~ UniWorX) => m (Maybe (AuthId UniWorX)) + maybeAuthId = $cachedHere . runMaybeT $ authIdFromBearer <|> MaybeT defaultMaybeAuthId + where authIdFromBearer = do + BearerToken{..} <- MaybeT . liftHandler $ runDBRead maybeBearerToken + hoistMaybe bearerImpersonate + instance YesodAuthPersist UniWorX where + getAuthEntity :: (HasCallStack, MonadHandler m, HandlerSite m ~ UniWorX) => UserId -> m (Maybe User) getAuthEntity = liftHandler . runDBRead . get @@ -291,3 +278,6 @@ instance (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX) => MonadCrypto instance {-# OVERLAPPING #-} (Monad m, MonadHandler m, HandlerSite m ~ UniWorX) => MonadSecretBox m where secretBoxKey = getsYesod appSecretBoxKey + +instance {-# OVERLAPPING #-} (Monad m, MonadHandler m, HandlerSite m ~ UniWorX) => MonadAuth m where + authKey = getsYesod appAuthKey diff --git a/src/Foundation/Instances/ButtonClass.hs b/src/Foundation/Instances/ButtonClass.hs new file mode 100644 index 000000000..fc90bf95e --- /dev/null +++ b/src/Foundation/Instances/ButtonClass.hs @@ -0,0 +1,34 @@ +{-# OPTIONS_GHC -fno-warn-orphans #-} +module Foundation.Instances.ButtonClass (ButtonClass(..)) where + +import Import.NoFoundation + +import Utils.Form +import Foundation.Type +import qualified Data.List as List + +-- instance RenderMessage UniWorX ButtonSubmit +import Foundation.I18n () + + +data instance ButtonClass UniWorX + = BCIsButton + | BCDefault + | BCPrimary + | BCSuccess + | BCInfo + | BCWarning + | BCDanger + | BCLink + | BCMassInputAdd | BCMassInputDelete + | BCScheduleView | BCScheduleOffset + deriving (Enum, Eq, Ord, Bounded, Read, Show, Generic, Typeable) + deriving anyclass (Universe, Finite) + +instance PathPiece (ButtonClass UniWorX) where + toPathPiece BCIsButton = "btn" + toPathPiece bClass = ("btn-" <>) . camelToPathPiece' 1 $ tshow bClass + fromPathPiece = flip List.lookup $ map (toPathPiece &&& id) universeF + +instance Button UniWorX ButtonSubmit where + btnClasses BtnSubmit = [BCIsButton, BCPrimary] diff --git a/src/Foundation/Navigation.hs b/src/Foundation/Navigation.hs index 3fce22496..53c0128db 100644 --- a/src/Foundation/Navigation.hs +++ b/src/Foundation/Navigation.hs @@ -7,21 +7,23 @@ module Foundation.Navigation ( NavQuickView(..), NavType(..), NavLevel(..), NavHeaderRole(..), NavLink(..), Nav(..), NavChildren , _navModal, _navMethod, _navData, _navLabel, _navType, _navForceActive, _navHeaderRole, _navIcon, _navLink, _navChildren , _NavHeader, _NavHeaderContainer, _NavPageActionPrimary, _NavPageActionSecondary, _NavFooter + , NavigationCacheKey(..) + , navBaseRoute, navLinkRoute , pageActions , pageQuickActions , defaultLinks , navAccess , navQuick , evalAccessCorrector + , breadcrumb ) where -import Import.NoFoundation +import Import.NoFoundation hiding (runDB) import Foundation.Type import Foundation.Routes import Foundation.I18n import Foundation.Authorization -import Foundation.DB import Handler.Utils.Memcached import Handler.Utils.ExamOffice.Course @@ -35,12 +37,25 @@ import Control.Monad.Trans.State (execStateT) import Yesod.Core.Types (HandlerContents) +import qualified Data.Conduit.Combinators as C +import Utils.Workflow +import Handler.Utils.Workflow.CanonicalRoute + +import qualified Data.Map.Strict as Map +import qualified Data.Set as Set + +import Data.List (inits) + + +type Breadcrumb = (Text, Maybe (Route UniWorX)) + -- Define breadcrumbs. -i18nCrumb :: (RenderMessage (HandlerSite m) msg, MonadHandler m) +i18nCrumb :: forall msg m. + (RenderMessage UniWorX msg, MonadHandler m, HandlerSite m ~ UniWorX) => msg - -> Maybe (Route (HandlerSite m)) - -> m (Text, Maybe (Route (HandlerSite m))) + -> Maybe (Route UniWorX) + -> m Breadcrumb i18nCrumb msg mbR = do mr <- getMessageRender return (mr msg, mbR) @@ -53,295 +68,374 @@ i18nCrumb msg mbR = do -- Keep in mind that Breadcrumbs are also shown by the 403-Handler, -- i.e. information might be leaked by not performing permission checks if the -- breadcrumb value depends on sensitive content (like an user's name). -instance BearerAuthSite UniWorX => YesodBreadcrumbs UniWorX where - breadcrumb (AuthR _) = i18nCrumb MsgMenuLogin $ Just NewsR - breadcrumb (StaticR _) = i18nCrumb MsgBreadcrumbStatic Nothing - breadcrumb (WellKnownR _) = i18nCrumb MsgBreadcrumbWellKnown Nothing - breadcrumb MetricsR = i18nCrumb MsgBreadcrumbMetrics Nothing +breadcrumb :: ( BearerAuthSite UniWorX + , WithRunDB SqlReadBackend (HandlerFor UniWorX) m + , MonadHandler m, HandlerSite m ~ UniWorX + ) + => Route UniWorX + -> m Breadcrumb +breadcrumb (AuthR _) = i18nCrumb MsgMenuLogin $ Just NewsR +breadcrumb (StaticR _) = i18nCrumb MsgBreadcrumbStatic Nothing +breadcrumb (WellKnownR _) = i18nCrumb MsgBreadcrumbWellKnown Nothing +breadcrumb MetricsR = i18nCrumb MsgBreadcrumbMetrics Nothing +breadcrumb ErrorR = i18nCrumb MsgBreadcrumbError Nothing - breadcrumb NewsR = i18nCrumb MsgMenuNews Nothing - breadcrumb UsersR = i18nCrumb MsgMenuUsers $ Just AdminR - breadcrumb AdminUserAddR = i18nCrumb MsgMenuUserAdd $ Just UsersR - breadcrumb (AdminUserR cID) = maybeT (i18nCrumb MsgBreadcrumbUser $ Just UsersR) $ do - guardM . hasReadAccessTo $ AdminUserR cID - uid <- decrypt cID - User{..} <- MaybeT . runDBRead $ get uid - return (userDisplayName, Just UsersR) - breadcrumb (AdminUserDeleteR cID) = i18nCrumb MsgBreadcrumbUserDelete . Just $ AdminUserR cID - breadcrumb (AdminHijackUserR cID) = i18nCrumb MsgBreadcrumbUserHijack . Just $ AdminUserR cID - breadcrumb (UserNotificationR cID) = do - mayList <- hasReadAccessTo UsersR - if - | mayList - -> i18nCrumb MsgMenuUserNotifications . Just $ AdminUserR cID - | otherwise - -> i18nCrumb MsgMenuUserNotifications $ Just ProfileR - breadcrumb (UserPasswordR cID) = do - mayList <- hasReadAccessTo UsersR - if - | mayList - -> i18nCrumb MsgMenuUserPassword . Just $ AdminUserR cID - | otherwise - -> i18nCrumb MsgMenuUserPassword $ Just ProfileR - breadcrumb AdminNewFunctionaryInviteR = i18nCrumb MsgMenuLecturerInvite $ Just UsersR - breadcrumb AdminFunctionaryInviteR = i18nCrumb MsgBreadcrumbFunctionaryInvite Nothing +breadcrumb NewsR = i18nCrumb MsgMenuNews Nothing +breadcrumb UsersR = i18nCrumb MsgMenuUsers $ Just AdminR +breadcrumb AdminUserAddR = i18nCrumb MsgMenuUserAdd $ Just UsersR +breadcrumb (AdminUserR cID) = useRunDB . maybeT (i18nCrumb MsgBreadcrumbUser $ Just UsersR) $ do + guardM . lift . hasReadAccessTo $ AdminUserR cID + uid <- decrypt cID + User{..} <- MaybeT $ get uid + return (userDisplayName, Just UsersR) +breadcrumb (AdminUserDeleteR cID) = i18nCrumb MsgBreadcrumbUserDelete . Just $ AdminUserR cID +breadcrumb (AdminHijackUserR cID) = i18nCrumb MsgBreadcrumbUserHijack . Just $ AdminUserR cID +breadcrumb (UserNotificationR cID) = useRunDB $ do + mayList <- hasReadAccessTo UsersR + if + | mayList + -> i18nCrumb MsgMenuUserNotifications . Just $ AdminUserR cID + | otherwise + -> i18nCrumb MsgMenuUserNotifications $ Just ProfileR +breadcrumb (UserPasswordR cID) = useRunDB $ do + mayList <- hasReadAccessTo UsersR + if + | mayList + -> i18nCrumb MsgMenuUserPassword . Just $ AdminUserR cID + | otherwise + -> i18nCrumb MsgMenuUserPassword $ Just ProfileR +breadcrumb AdminNewFunctionaryInviteR = i18nCrumb MsgMenuLecturerInvite $ Just UsersR +breadcrumb AdminFunctionaryInviteR = i18nCrumb MsgBreadcrumbFunctionaryInvite Nothing - breadcrumb AdminR = i18nCrumb MsgAdminHeading Nothing - breadcrumb AdminFeaturesR = i18nCrumb MsgAdminFeaturesHeading $ Just AdminR - breadcrumb AdminTestR = i18nCrumb MsgMenuAdminTest $ Just AdminR - breadcrumb AdminErrMsgR = i18nCrumb MsgMenuAdminErrMsg $ Just AdminR - breadcrumb AdminTokensR = i18nCrumb MsgMenuAdminTokens $ Just AdminR - breadcrumb AdminCrontabR = i18nCrumb MsgBreadcrumbAdminCrontab $ Just AdminR +breadcrumb AdminR = i18nCrumb MsgAdminHeading Nothing +breadcrumb AdminFeaturesR = i18nCrumb MsgAdminFeaturesHeading $ Just AdminR +breadcrumb AdminTestR = i18nCrumb MsgMenuAdminTest $ Just AdminR +breadcrumb AdminErrMsgR = i18nCrumb MsgMenuAdminErrMsg $ Just AdminR +breadcrumb AdminTokensR = i18nCrumb MsgMenuAdminTokens $ Just AdminR +breadcrumb AdminCrontabR = i18nCrumb MsgBreadcrumbAdminCrontab $ Just AdminR - breadcrumb SchoolListR = i18nCrumb MsgMenuSchoolList $ Just AdminR - breadcrumb (SchoolR ssh SchoolEditR) = maybeT (i18nCrumb MsgBreadcrumbSchool $ Just SchoolListR) $ do - School{..} <- MaybeT . runDBRead $ get ssh - return (CI.original schoolName, Just SchoolListR) - breadcrumb SchoolNewR = i18nCrumb MsgMenuSchoolNew $ Just SchoolListR +breadcrumb SchoolListR = i18nCrumb MsgMenuSchoolList $ Just AdminR +breadcrumb (SchoolR ssh sRoute) = case sRoute of + SchoolEditR -> useRunDB . maybeT (i18nCrumb MsgBreadcrumbSchool $ Just SchoolListR) $ do + School{..} <- MaybeT $ get ssh + isAdmin <- lift $ hasReadAccessTo SchoolListR + return (CI.original schoolName, bool Nothing (Just SchoolListR) isAdmin) - breadcrumb (ExamOfficeR EOExamsR) = i18nCrumb MsgMenuExamOfficeExams Nothing - breadcrumb (ExamOfficeR EOFieldsR) = i18nCrumb MsgMenuExamOfficeFields . Just $ ExamOfficeR EOExamsR - breadcrumb (ExamOfficeR EOUsersR) = i18nCrumb MsgMenuExamOfficeUsers . Just $ ExamOfficeR EOExamsR - breadcrumb (ExamOfficeR EOUsersInviteR) = i18nCrumb MsgBreadcrumbExamOfficeUserInvite Nothing + SchoolWorkflowInstanceListR -> i18nCrumb MsgBreadcrumbWorkflowInstanceList . Just $ SchoolR ssh SchoolEditR + SchoolWorkflowInstanceNewR -> i18nCrumb MsgBreadcrumbWorkflowInstanceNew . Just $ SchoolR ssh SchoolWorkflowInstanceListR + SchoolWorkflowInstanceR win sRoute' -> case sRoute' of + SWIEditR -> do + desc <- useRunDB . runMaybeT $ do + guardM . lift . hasReadAccessTo . SchoolR ssh $ SchoolWorkflowInstanceR win SWIWorkflowsR + wiId <- MaybeT . getKeyBy . UniqueWorkflowInstance win . WSSchool $ unSchoolKey ssh + MaybeT $ selectWorkflowInstanceDescription wiId + let bRoute = SchoolR ssh SchoolWorkflowInstanceListR + case desc of + Nothing -> i18nCrumb (MsgBreadcrumbWorkflowInstanceEdit win) $ Just bRoute + Just (Entity _ WorkflowInstanceDescription{..}) -> i18nCrumb workflowInstanceDescriptionTitle $ Just bRoute + SWIDeleteR -> i18nCrumb MsgBreadcrumbWorkflowInstanceDelete . Just . SchoolR ssh $ SchoolWorkflowInstanceR win SWIEditR + SWIWorkflowsR -> i18nCrumb MsgBreadcrumbWorkflowInstanceWorkflowList . Just . SchoolR ssh $ SchoolWorkflowInstanceR win SWIEditR + SWIInitiateR -> useRunDB $ do + mayEdit <- hasReadAccessTo . SchoolR ssh $ SchoolWorkflowInstanceR win SWIEditR + i18nCrumb MsgBreadcrumbWorkflowInstanceInitiate . Just . SchoolR ssh $ if + | mayEdit -> SchoolWorkflowInstanceR win SWIEditR + | otherwise -> SchoolWorkflowInstanceListR + SchoolWorkflowWorkflowListR -> i18nCrumb MsgBreadcrumbWorkflowWorkflowList . Just $ SchoolR ssh SchoolWorkflowInstanceListR + SchoolWorkflowWorkflowR cID sRoute' -> case sRoute' of + SWWWorkflowR -> i18nCrumb (MsgBreadcrumbWorkflowWorkflow cID) . Just $ SchoolR ssh SchoolWorkflowWorkflowListR + SWWFilesR _ _ -> i18nCrumb MsgBreadcrumbWorkflowWorkflowFiles . Just . SchoolR ssh $ SchoolWorkflowWorkflowR cID SWWWorkflowR + SWWEditR -> i18nCrumb MsgBreadcrumbWorkflowWorkflowEdit . Just . SchoolR ssh $ SchoolWorkflowWorkflowR cID SWWWorkflowR + SWWDeleteR -> i18nCrumb MsgBreadcrumbWorkflowWorkflowDelete . Just . SchoolR ssh $ SchoolWorkflowWorkflowR cID SWWWorkflowR +breadcrumb SchoolNewR = i18nCrumb MsgMenuSchoolNew $ Just SchoolListR - breadcrumb InfoR = i18nCrumb MsgMenuInformation Nothing - breadcrumb InfoLecturerR = i18nCrumb MsgInfoLecturerTitle $ Just InfoR - breadcrumb LegalR = i18nCrumb MsgMenuLegal $ Just InfoR - breadcrumb InfoAllocationR = i18nCrumb MsgBreadcrumbAllocationInfo $ Just InfoR - breadcrumb VersionR = i18nCrumb MsgMenuVersion $ Just InfoR - breadcrumb FaqR = i18nCrumb MsgBreadcrumbFaq $ Just InfoR +breadcrumb (ExamOfficeR EOExamsR) = i18nCrumb MsgMenuExamOfficeExams Nothing +breadcrumb (ExamOfficeR EOFieldsR) = i18nCrumb MsgMenuExamOfficeFields . Just $ ExamOfficeR EOExamsR +breadcrumb (ExamOfficeR EOUsersR) = i18nCrumb MsgMenuExamOfficeUsers . Just $ ExamOfficeR EOExamsR +breadcrumb (ExamOfficeR EOUsersInviteR) = i18nCrumb MsgBreadcrumbExamOfficeUserInvite Nothing + +breadcrumb InfoR = i18nCrumb MsgMenuInformation Nothing +breadcrumb InfoLecturerR = i18nCrumb MsgInfoLecturerTitle $ Just InfoR +breadcrumb LegalR = i18nCrumb MsgMenuLegal $ Just InfoR +breadcrumb InfoAllocationR = i18nCrumb MsgBreadcrumbAllocationInfo $ Just InfoR +breadcrumb VersionR = i18nCrumb MsgMenuVersion $ Just InfoR +breadcrumb FaqR = i18nCrumb MsgBreadcrumbFaq $ Just InfoR - breadcrumb HelpR = i18nCrumb MsgMenuHelp Nothing +breadcrumb HelpR = i18nCrumb MsgMenuHelp Nothing - breadcrumb HealthR = i18nCrumb MsgMenuHealth Nothing - breadcrumb InstanceR = i18nCrumb MsgMenuInstance Nothing +breadcrumb HealthR = i18nCrumb MsgMenuHealth Nothing +breadcrumb InstanceR = i18nCrumb MsgMenuInstance Nothing - breadcrumb ProfileR = i18nCrumb MsgBreadcrumbProfile Nothing - breadcrumb SetDisplayEmailR = i18nCrumb MsgUserDisplayEmail $ Just ProfileR - breadcrumb ProfileDataR = i18nCrumb MsgMenuProfileData $ Just ProfileR - breadcrumb AuthPredsR = i18nCrumb MsgMenuAuthPreds $ Just ProfileR - breadcrumb CsvOptionsR = i18nCrumb MsgCsvOptions $ Just ProfileR - breadcrumb LangR = i18nCrumb MsgMenuLanguage $ Just ProfileR +breadcrumb ProfileR = i18nCrumb MsgBreadcrumbProfile Nothing +breadcrumb SetDisplayEmailR = i18nCrumb MsgUserDisplayEmail $ Just ProfileR +breadcrumb ProfileDataR = i18nCrumb MsgMenuProfileData $ Just ProfileR +breadcrumb AuthPredsR = i18nCrumb MsgMenuAuthPreds $ Just ProfileR +breadcrumb CsvOptionsR = i18nCrumb MsgCsvOptions $ Just ProfileR +breadcrumb LangR = i18nCrumb MsgMenuLanguage $ Just ProfileR - breadcrumb StorageKeyR = i18nCrumb MsgBreadcrumbStorageKey Nothing +breadcrumb StorageKeyR = i18nCrumb MsgBreadcrumbStorageKey Nothing - breadcrumb TermShowR = i18nCrumb MsgMenuTermShow $ Just NewsR - breadcrumb TermCurrentR = i18nCrumb MsgMenuTermCurrent $ Just TermShowR - breadcrumb TermEditR = i18nCrumb MsgMenuTermCreate $ Just TermShowR - breadcrumb (TermEditExistR tid) = i18nCrumb MsgMenuTermEdit . Just $ TermCourseListR tid - breadcrumb (TermCourseListR tid) = maybeT (i18nCrumb MsgBreadcrumbTerm $ Just CourseListR) $ do -- redirect only, used in other breadcrumbs - guardM . lift . runDBRead $ isJust <$> get tid - i18nCrumb (ShortTermIdentifier $ unTermKey tid) $ Just CourseListR +breadcrumb TermShowR = i18nCrumb MsgMenuTermShow $ Just NewsR +breadcrumb TermCurrentR = i18nCrumb MsgMenuTermCurrent $ Just TermShowR +breadcrumb TermEditR = i18nCrumb MsgMenuTermCreate $ Just TermShowR +breadcrumb (TermEditExistR tid) = i18nCrumb MsgMenuTermEdit . Just $ TermCourseListR tid +breadcrumb (TermCourseListR tid) = useRunDB . maybeT (i18nCrumb MsgBreadcrumbTerm $ Just CourseListR) $ do -- redirect only, used in other breadcrumbs + guardM . lift $ isJust <$> get tid + i18nCrumb (ShortTermIdentifier $ unTermKey tid) $ Just CourseListR - breadcrumb (TermSchoolCourseListR tid ssh) = maybeT (i18nCrumb MsgBreadcrumbSchool . Just $ TermCourseListR tid) $ do -- redirect only, used in other breadcrumbs - guardM . lift . runDBRead $ - (&&) <$> fmap isJust (get ssh) - <*> fmap isJust (get tid) - return (CI.original $ unSchoolKey ssh, Just $ TermCourseListR tid) +breadcrumb (TermSchoolCourseListR tid ssh) = useRunDB . maybeT (i18nCrumb MsgBreadcrumbSchool . Just $ TermCourseListR tid) $ do -- redirect only, used in other breadcrumbs + guardM . lift $ + (&&) <$> fmap isJust (get ssh) + <*> fmap isJust (get tid) + return (CI.original $ unSchoolKey ssh, Just $ TermCourseListR tid) - breadcrumb AllocationListR = i18nCrumb MsgAllocationListTitle $ Just NewsR - breadcrumb (AllocationR tid ssh ash sRoute) = case sRoute of - AShowR -> maybeT (i18nCrumb MsgBreadcrumbAllocation $ Just AllocationListR) $ do - mr <- getMessageRender - Entity _ Allocation{allocationName} <- MaybeT . runDBRead . getBy $ TermSchoolAllocationShort tid ssh ash - return ([st|#{allocationName} (#{mr (ShortTermIdentifier (unTermKey tid))}, #{CI.original (unSchoolKey ssh)})|], Just AllocationListR) - ARegisterR -> i18nCrumb MsgBreadcrumbAllocationRegister . Just $ AllocationR tid ssh ash AShowR - AApplyR cID -> maybeT (i18nCrumb MsgBreadcrumbCourse . Just $ AllocationR tid ssh ash AShowR) $ do - cid <- decrypt cID - Course{..} <- hoist runDBRead $ do - aid <- MaybeT . getKeyBy $ TermSchoolAllocationShort tid ssh ash - guardM . lift $ exists [ AllocationCourseAllocation ==. aid, AllocationCourseCourse ==. cid ] - MaybeT $ get cid - return (CI.original courseName, Just $ AllocationR tid ssh ash AShowR) - AUsersR -> i18nCrumb MsgBreadcrumbAllocationUsers . Just $ AllocationR tid ssh ash AShowR - APriosR -> i18nCrumb MsgBreadcrumbAllocationPriorities . Just $ AllocationR tid ssh ash AUsersR - AComputeR -> i18nCrumb MsgBreadcrumbAllocationCompute . Just $ AllocationR tid ssh ash AUsersR - AAcceptR -> i18nCrumb MsgBreadcrumbAllocationAccept . Just $ AllocationR tid ssh ash AUsersR - AAddUserR -> i18nCrumb MsgBreadcrumbAllocationAddUser . Just $ AllocationR tid ssh ash AUsersR +breadcrumb AllocationListR = i18nCrumb MsgAllocationListTitle $ Just NewsR +breadcrumb (AllocationR tid ssh ash sRoute) = case sRoute of + AShowR -> useRunDB . maybeT (i18nCrumb MsgBreadcrumbAllocation $ Just AllocationListR) $ do + mr <- getMessageRender + Entity _ Allocation{allocationName} <- MaybeT . getBy $ TermSchoolAllocationShort tid ssh ash + return ([st|#{allocationName} (#{mr (ShortTermIdentifier (unTermKey tid))}, #{CI.original (unSchoolKey ssh)})|], Just AllocationListR) + ARegisterR -> i18nCrumb MsgBreadcrumbAllocationRegister . Just $ AllocationR tid ssh ash AShowR + AApplyR cID -> useRunDB . maybeT (i18nCrumb MsgBreadcrumbCourse . Just $ AllocationR tid ssh ash AShowR) $ do + cid <- decrypt cID + Course{..} <- do + aid <- MaybeT . getKeyBy $ TermSchoolAllocationShort tid ssh ash + guardM . lift $ exists [ AllocationCourseAllocation ==. aid, AllocationCourseCourse ==. cid ] + MaybeT $ get cid + return (CI.original courseName, Just $ AllocationR tid ssh ash AShowR) + AUsersR -> i18nCrumb MsgBreadcrumbAllocationUsers . Just $ AllocationR tid ssh ash AShowR + APriosR -> i18nCrumb MsgBreadcrumbAllocationPriorities . Just $ AllocationR tid ssh ash AUsersR + AComputeR -> i18nCrumb MsgBreadcrumbAllocationCompute . Just $ AllocationR tid ssh ash AUsersR + AAcceptR -> i18nCrumb MsgBreadcrumbAllocationAccept . Just $ AllocationR tid ssh ash AUsersR + AAddUserR -> i18nCrumb MsgBreadcrumbAllocationAddUser . Just $ AllocationR tid ssh ash AUsersR - breadcrumb ParticipantsListR = i18nCrumb MsgBreadcrumbParticipantsList $ Just CourseListR - breadcrumb (ParticipantsR _ _) = i18nCrumb MsgBreadcrumbParticipants $ Just ParticipantsListR - breadcrumb ParticipantsIntersectR = i18nCrumb MsgMenuParticipantsIntersect $ Just ParticipantsListR +breadcrumb ParticipantsListR = i18nCrumb MsgBreadcrumbParticipantsList $ Just CourseListR +breadcrumb (ParticipantsR _ _) = i18nCrumb MsgBreadcrumbParticipants $ Just ParticipantsListR +breadcrumb ParticipantsIntersectR = i18nCrumb MsgMenuParticipantsIntersect $ Just ParticipantsListR - breadcrumb CourseListR = i18nCrumb MsgMenuCourseList Nothing - breadcrumb CourseNewR = i18nCrumb MsgMenuCourseNew $ Just CourseListR - breadcrumb (CourseR tid ssh csh CShowR) = maybeT (i18nCrumb MsgBreadcrumbCourse . Just $ TermSchoolCourseListR tid ssh) $ do - guardM . lift . runDBRead . existsBy $ TermSchoolCourseShort tid ssh csh - return (CI.original csh, Just $ TermSchoolCourseListR tid ssh) - breadcrumb (CourseR tid ssh csh CEditR) = i18nCrumb MsgMenuCourseEdit . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CUsersR) = i18nCrumb MsgMenuCourseMembers . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CAddUserR) = i18nCrumb MsgMenuCourseAddMembers . Just $ CourseR tid ssh csh CUsersR - breadcrumb (CourseR tid ssh csh CInviteR) = i18nCrumb MsgBreadcrumbCourseParticipantInvitation . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CExamOfficeR) = i18nCrumb MsgMenuCourseExamOffice . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh (CUserR cID)) = maybeT (i18nCrumb MsgBreadcrumbUser . Just $ CourseR tid ssh csh CUsersR) $ do - guardM . hasReadAccessTo . CourseR tid ssh csh $ CUserR cID - uid <- decrypt cID - User{userDisplayName} <- MaybeT . runDBRead $ get uid - return (userDisplayName, Just $ CourseR tid ssh csh CUsersR) - breadcrumb (CourseR tid ssh csh CCorrectionsR) = i18nCrumb MsgMenuSubmissions . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CAssignR) = i18nCrumb MsgMenuCorrectionsAssign . Just $ CourseR tid ssh csh CCorrectionsR - breadcrumb (CourseR tid ssh csh SheetListR) = i18nCrumb MsgMenuSheetList . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh SheetNewR ) = i18nCrumb MsgMenuSheetNew . Just $ CourseR tid ssh csh SheetListR - breadcrumb (CourseR tid ssh csh SheetCurrentR) = i18nCrumb MsgMenuSheetCurrent . Just $ CourseR tid ssh csh SheetListR - breadcrumb (CourseR tid ssh csh SheetOldUnassignedR) = i18nCrumb MsgMenuSheetOldUnassigned . Just $ CourseR tid ssh csh SheetListR - breadcrumb (CourseR tid ssh csh CCommR ) = i18nCrumb MsgMenuCourseCommunication . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CTutorialListR) = i18nCrumb MsgMenuTutorialList . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CTutorialNewR) = i18nCrumb MsgMenuTutorialNew . Just $ CourseR tid ssh csh CTutorialListR - breadcrumb (CourseR tid ssh csh CFavouriteR) = i18nCrumb MsgBreadcrumbCourseFavourite . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CRegisterR) = i18nCrumb MsgBreadcrumbCourseRegister . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CRegisterTemplateR) = i18nCrumb MsgBreadcrumbCourseRegisterTemplate . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CLecInviteR) = i18nCrumb MsgBreadcrumbLecturerInvite . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CDeleteR) = i18nCrumb MsgMenuCourseDelete . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CHiWisR) = i18nCrumb MsgBreadcrumbHiWis . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CNotesR) = i18nCrumb MsgBreadcrumbCourseNotes . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh (CScheduleOptSetR _opt)) = i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CScheduleOptDelR) = i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CShowR +breadcrumb CourseListR = i18nCrumb MsgMenuCourseList Nothing +breadcrumb CourseNewR = i18nCrumb MsgMenuCourseNew $ Just CourseListR +breadcrumb (CourseR tid ssh csh CShowR) = useRunDB . maybeT (i18nCrumb MsgBreadcrumbCourse . Just $ TermSchoolCourseListR tid ssh) $ do + guardM . lift . existsBy $ TermSchoolCourseShort tid ssh csh + return (CI.original csh, Just $ TermSchoolCourseListR tid ssh) +breadcrumb (CourseR tid ssh csh CEditR) = i18nCrumb MsgMenuCourseEdit . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CUsersR) = i18nCrumb MsgMenuCourseMembers . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CAddUserR) = i18nCrumb MsgMenuCourseAddMembers . Just $ CourseR tid ssh csh CUsersR +breadcrumb (CourseR tid ssh csh CInviteR) = i18nCrumb MsgBreadcrumbCourseParticipantInvitation . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CExamOfficeR) = i18nCrumb MsgMenuCourseExamOffice . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh (CUserR cID)) = useRunDB . maybeT (i18nCrumb MsgBreadcrumbUser . Just $ CourseR tid ssh csh CUsersR) $ do + guardM . lift . hasReadAccessTo . CourseR tid ssh csh $ CUserR cID + uid <- decrypt cID + User{userDisplayName} <- MaybeT $ get uid + return (userDisplayName, Just $ CourseR tid ssh csh CUsersR) +breadcrumb (CourseR tid ssh csh CCorrectionsR) = i18nCrumb MsgMenuSubmissions . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CAssignR) = i18nCrumb MsgMenuCorrectionsAssign . Just $ CourseR tid ssh csh CCorrectionsR +breadcrumb (CourseR tid ssh csh SheetListR) = i18nCrumb MsgMenuSheetList . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh SheetNewR ) = i18nCrumb MsgMenuSheetNew . Just $ CourseR tid ssh csh SheetListR +breadcrumb (CourseR tid ssh csh SheetCurrentR) = i18nCrumb MsgMenuSheetCurrent . Just $ CourseR tid ssh csh SheetListR +breadcrumb (CourseR tid ssh csh SheetOldUnassignedR) = i18nCrumb MsgMenuSheetOldUnassigned . Just $ CourseR tid ssh csh SheetListR +breadcrumb (CourseR tid ssh csh CCommR ) = i18nCrumb MsgMenuCourseCommunication . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CTutorialListR) = i18nCrumb MsgMenuTutorialList . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CTutorialNewR) = i18nCrumb MsgMenuTutorialNew . Just $ CourseR tid ssh csh CTutorialListR +breadcrumb (CourseR tid ssh csh CFavouriteR) = i18nCrumb MsgBreadcrumbCourseFavourite . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CRegisterR) = i18nCrumb MsgBreadcrumbCourseRegister . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CRegisterTemplateR) = i18nCrumb MsgBreadcrumbCourseRegisterTemplate . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CLecInviteR) = i18nCrumb MsgBreadcrumbLecturerInvite . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CDeleteR) = i18nCrumb MsgMenuCourseDelete . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CHiWisR) = i18nCrumb MsgBreadcrumbHiWis . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CNotesR) = i18nCrumb MsgBreadcrumbCourseNotes . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh (CScheduleOptSetR _opt)) = i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CScheduleOptDelR) = i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CNewsNewR) = i18nCrumb MsgMenuCourseNewsNew . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh (CourseNewsR cID sRoute)) = case sRoute of - CNShowR -> i18nCrumb MsgBreadcrumbCourseNews . Just $ CourseR tid ssh csh CShowR - CNEditR -> i18nCrumb MsgMenuCourseNewsEdit . Just $ CNewsR tid ssh csh cID CNShowR - CNDeleteR -> i18nCrumb MsgBreadcrumbCourseNewsDelete . Just $ CNewsR tid ssh csh cID CNShowR - CNArchiveR -> i18nCrumb MsgBreadcrumbCourseNewsArchive . Just $ CNewsR tid ssh csh cID CNShowR - CNFileR _ -> i18nCrumb MsgBreadcrumbCourseNewsFile . Just $ CNewsR tid ssh csh cID CNShowR +breadcrumb (CourseR tid ssh csh CNewsNewR) = i18nCrumb MsgMenuCourseNewsNew . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh (CourseNewsR cID sRoute)) = case sRoute of + CNShowR -> i18nCrumb MsgBreadcrumbCourseNews . Just $ CourseR tid ssh csh CShowR + CNEditR -> i18nCrumb MsgMenuCourseNewsEdit . Just $ CNewsR tid ssh csh cID CNShowR + CNDeleteR -> i18nCrumb MsgBreadcrumbCourseNewsDelete . Just $ CNewsR tid ssh csh cID CNShowR + CNArchiveR -> i18nCrumb MsgBreadcrumbCourseNewsArchive . Just $ CNewsR tid ssh csh cID CNShowR + CNFileR _ -> i18nCrumb MsgBreadcrumbCourseNewsFile . Just $ CNewsR tid ssh csh cID CNShowR - breadcrumb (CourseR tid ssh csh CEventsNewR) = i18nCrumb MsgMenuCourseEventNew . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh (CourseEventR _cID sRoute)) = case sRoute of - CEvScheduleOptSetR _ -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CShowR - CEvScheduleOptDelR -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CShowR - CEvEditR -> i18nCrumb MsgMenuCourseEventEdit . Just $ CourseR tid ssh csh CShowR - CEvDeleteR -> i18nCrumb MsgBreadcrumbCourseEventDelete . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CEventsNewR) = i18nCrumb MsgMenuCourseEventNew . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh (CourseEventR _cID sRoute)) = case sRoute of + CEvScheduleOptSetR _ -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CShowR + CEvScheduleOptDelR -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CShowR + CEvEditR -> i18nCrumb MsgMenuCourseEventEdit . Just $ CourseR tid ssh csh CShowR + CEvDeleteR -> i18nCrumb MsgBreadcrumbCourseEventDelete . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CExamListR) = i18nCrumb MsgMenuExamList . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CExamNewR) = i18nCrumb MsgMenuExamNew . Just $ CourseR tid ssh csh CExamListR +breadcrumb (CourseR tid ssh csh CExamListR) = i18nCrumb MsgMenuExamList . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CExamNewR) = i18nCrumb MsgMenuExamNew . Just $ CourseR tid ssh csh CExamListR - breadcrumb (CourseR tid ssh csh CApplicationsR) = i18nCrumb MsgMenuCourseApplications . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh CAppsFilesR) = i18nCrumb MsgBreadcrumbCourseAppsFiles . Just $ CourseR tid ssh csh CApplicationsR +breadcrumb (CourseR tid ssh csh CApplicationsR) = i18nCrumb MsgMenuCourseApplications . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CAppsFilesR) = i18nCrumb MsgBreadcrumbCourseAppsFiles . Just $ CourseR tid ssh csh CApplicationsR - breadcrumb (CourseR tid ssh csh (CourseApplicationR cID sRoute)) = case sRoute of - CAEditR -> maybeT (i18nCrumb MsgBreadcrumbApplicant . Just $ CourseR tid ssh csh CApplicationsR) $ do - guardM . hasReadAccessTo $ CApplicationR tid ssh csh cID CAEditR - appId <- decrypt cID - User{..} <- hoist runDBRead $ MaybeT (get appId) >>= MaybeT . get . courseApplicationUser - return (userDisplayName, Just $ CourseR tid ssh csh CApplicationsR) - CAFilesR -> i18nCrumb MsgBreadcrumbApplicationFiles . Just $ CApplicationR tid ssh csh cID CAEditR +breadcrumb (CourseR tid ssh csh (CourseApplicationR cID sRoute)) = case sRoute of + CAEditR -> useRunDB . maybeT (i18nCrumb MsgBreadcrumbApplicant . Just $ CourseR tid ssh csh CApplicationsR) $ do + guardM . lift . hasReadAccessTo $ CApplicationR tid ssh csh cID CAEditR + appId <- decrypt cID + User{..} <- MaybeT (get appId) >>= MaybeT . get . courseApplicationUser + return (userDisplayName, Just $ CourseR tid ssh csh CApplicationsR) + CAFilesR -> i18nCrumb MsgBreadcrumbApplicationFiles . Just $ CApplicationR tid ssh csh cID CAEditR - breadcrumb (CourseR tid ssh csh (ExamR examn sRoute)) = case sRoute of - EShowR -> maybeT (i18nCrumb MsgBreadcrumbExam . Just $ CourseR tid ssh csh CExamListR) $ do - guardM . hasReadAccessTo $ CExamR tid ssh csh examn EShowR - return (CI.original examn, Just $ CourseR tid ssh csh CExamListR) - EEditR -> i18nCrumb MsgMenuExamEdit . Just $ CExamR tid ssh csh examn EShowR - EUsersR -> i18nCrumb MsgMenuExamUsers . Just $ CExamR tid ssh csh examn EShowR - EAddUserR -> i18nCrumb MsgMenuExamAddMembers . Just $ CExamR tid ssh csh examn EUsersR - EGradesR -> i18nCrumb MsgMenuExamGrades . Just $ CExamR tid ssh csh examn EShowR - ECInviteR -> i18nCrumb MsgBreadcrumbExamCorrectorInvite . Just $ CExamR tid ssh csh examn EShowR - EInviteR -> i18nCrumb MsgBreadcrumbExamParticipantInvite . Just $ CExamR tid ssh csh examn EShowR - ERegisterR -> i18nCrumb MsgBreadcrumbExamRegister . Just $ CExamR tid ssh csh examn EShowR - ERegisterOccR _occn -> i18nCrumb MsgBreadcrumbExamRegister . Just $ CExamR tid ssh csh examn EShowR - EAutoOccurrenceR -> i18nCrumb MsgBreadcrumbExamAutoOccurrence . Just $ CExamR tid ssh csh examn EUsersR - ECorrectR -> i18nCrumb MsgMenuExamCorrect . Just $ CExamR tid ssh csh examn EShowR - EScheduleOptSetR _eoname _opt -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CExamR tid ssh csh examn EShowR - EScheduleOptDelR _eoname -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CExamR tid ssh csh examn EShowR +breadcrumb (CourseR tid ssh csh (ExamR examn sRoute)) = case sRoute of + EShowR -> useRunDB . maybeT (i18nCrumb MsgBreadcrumbExam . Just $ CourseR tid ssh csh CExamListR) $ do + guardM . lift . hasReadAccessTo $ CExamR tid ssh csh examn EShowR + return (CI.original examn, Just $ CourseR tid ssh csh CExamListR) + EEditR -> i18nCrumb MsgMenuExamEdit . Just $ CExamR tid ssh csh examn EShowR + EUsersR -> i18nCrumb MsgMenuExamUsers . Just $ CExamR tid ssh csh examn EShowR + EAddUserR -> i18nCrumb MsgMenuExamAddMembers . Just $ CExamR tid ssh csh examn EUsersR + EGradesR -> i18nCrumb MsgMenuExamGrades . Just $ CExamR tid ssh csh examn EShowR + ECInviteR -> i18nCrumb MsgBreadcrumbExamCorrectorInvite . Just $ CExamR tid ssh csh examn EShowR + EInviteR -> i18nCrumb MsgBreadcrumbExamParticipantInvite . Just $ CExamR tid ssh csh examn EShowR + ERegisterR -> i18nCrumb MsgBreadcrumbExamRegister . Just $ CExamR tid ssh csh examn EShowR + ERegisterOccR _occn -> i18nCrumb MsgBreadcrumbExamRegister . Just $ CExamR tid ssh csh examn EShowR + EAutoOccurrenceR -> i18nCrumb MsgBreadcrumbExamAutoOccurrence . Just $ CExamR tid ssh csh examn EUsersR + ECorrectR -> i18nCrumb MsgMenuExamCorrect . Just $ CExamR tid ssh csh examn EShowR + EScheduleOptSetR _eoname _opt -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CExamR tid ssh csh examn EShowR + EScheduleOptDelR _eoname -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CExamR tid ssh csh examn EShowR - breadcrumb (CourseR tid ssh csh (TutorialR tutn sRoute)) = case sRoute of - TUsersR -> maybeT (i18nCrumb MsgBreadcrumbTutorial . Just $ CourseR tid ssh csh CTutorialListR) $ do - guardM . hasReadAccessTo $ CTutorialR tid ssh csh tutn TUsersR - return (CI.original tutn, Just $ CourseR tid ssh csh CTutorialListR) - TEditR -> i18nCrumb MsgMenuTutorialEdit . Just $ CTutorialR tid ssh csh tutn TUsersR - TDeleteR -> i18nCrumb MsgMenuTutorialDelete . Just $ CTutorialR tid ssh csh tutn TUsersR - TCommR -> i18nCrumb MsgMenuTutorialComm . Just $ CTutorialR tid ssh csh tutn TUsersR - TRegisterR -> i18nCrumb MsgBreadcrumbTutorialRegister . Just $ CourseR tid ssh csh CShowR - TInviteR -> i18nCrumb MsgBreadcrumbTutorInvite . Just $ CTutorialR tid ssh csh tutn TUsersR - (TScheduleOptSetR _) -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CTutorialListR - TScheduleOptDelR -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CTutorialListR +breadcrumb (CourseR tid ssh csh (TutorialR tutn sRoute)) = case sRoute of + TUsersR -> useRunDB . maybeT (i18nCrumb MsgBreadcrumbTutorial . Just $ CourseR tid ssh csh CTutorialListR) $ do + guardM . lift . hasReadAccessTo $ CTutorialR tid ssh csh tutn TUsersR + return (CI.original tutn, Just $ CourseR tid ssh csh CTutorialListR) + TEditR -> i18nCrumb MsgMenuTutorialEdit . Just $ CTutorialR tid ssh csh tutn TUsersR + TDeleteR -> i18nCrumb MsgMenuTutorialDelete . Just $ CTutorialR tid ssh csh tutn TUsersR + TCommR -> i18nCrumb MsgMenuTutorialComm . Just $ CTutorialR tid ssh csh tutn TUsersR + TRegisterR -> i18nCrumb MsgBreadcrumbTutorialRegister . Just $ CourseR tid ssh csh CShowR + TInviteR -> i18nCrumb MsgBreadcrumbTutorInvite . Just $ CTutorialR tid ssh csh tutn TUsersR + (TScheduleOptSetR _) -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CTutorialListR + TScheduleOptDelR -> i18nCrumb MsgBreadcrumbScheduleOpt . Just $ CourseR tid ssh csh CTutorialListR - breadcrumb (CourseR tid ssh csh (SheetR shn sRoute)) = case sRoute of - SShowR -> maybeT (i18nCrumb MsgBreadcrumbSheet . Just $ CourseR tid ssh csh SheetListR) $ do - guardM . hasReadAccessTo $ CSheetR tid ssh csh shn SShowR - return (CI.original shn, Just $ CourseR tid ssh csh SheetListR) - SEditR -> i18nCrumb MsgMenuSheetEdit . Just $ CSheetR tid ssh csh shn SShowR - SDelR -> i18nCrumb MsgMenuSheetDelete . Just $ CSheetR tid ssh csh shn SShowR - SSubsR -> i18nCrumb MsgMenuSubmissions . Just $ CSheetR tid ssh csh shn SShowR - SAssignR -> i18nCrumb MsgMenuCorrectionsAssign . Just $ CSheetR tid ssh csh shn SSubsR - SubmissionNewR -> i18nCrumb MsgMenuSubmissionNew . Just $ CSheetR tid ssh csh shn SShowR - SubmissionOwnR -> i18nCrumb MsgMenuSubmissionOwn . Just $ CSheetR tid ssh csh shn SShowR - SubmissionR cid sRoute' -> case sRoute' of - SubShowR -> do - mayList <- hasReadAccessTo $ CSheetR tid ssh csh shn SSubsR - if - | mayList - -> i18nCrumb MsgBreadcrumbSubmission . Just $ CSheetR tid ssh csh shn SSubsR - | otherwise - -> i18nCrumb MsgBreadcrumbSubmission . Just $ CSheetR tid ssh csh shn SShowR - CorrectionR -> i18nCrumb MsgMenuCorrection . Just $ CSubmissionR tid ssh csh shn cid SubShowR - SubDelR -> i18nCrumb MsgMenuSubmissionDelete . Just $ CSubmissionR tid ssh csh shn cid SubShowR - SubAssignR -> i18nCrumb MsgCorrectorAssignTitle . Just $ CSubmissionR tid ssh csh shn cid SubShowR - SInviteR -> i18nCrumb MsgBreadcrumbSubmissionUserInvite . Just $ CSubmissionR tid ssh csh shn cid SubShowR - SubArchiveR sft -> i18nCrumb sft . Just $ CSubmissionR tid ssh csh shn cid SubShowR - SubDownloadR _ _ -> i18nCrumb MsgBreadcrumbSubmissionFile . Just $ CSubmissionR tid ssh csh shn cid SubShowR - SArchiveR -> i18nCrumb MsgBreadcrumbSheetArchive . Just $ CSheetR tid ssh csh shn SShowR - SIsCorrR -> i18nCrumb MsgBreadcrumbSheetIsCorrector . Just $ CSheetR tid ssh csh shn SShowR - SPseudonymR -> i18nCrumb MsgBreadcrumbSheetPseudonym . Just $ CSheetR tid ssh csh shn SShowR - SCorrInviteR -> i18nCrumb MsgBreadcrumbSheetCorrectorInvite . Just $ CSheetR tid ssh csh shn SShowR - SZipR sft -> i18nCrumb sft . Just $ CSheetR tid ssh csh shn SShowR - SFileR _ _ -> i18nCrumb MsgBreadcrumbSheetFile . Just $ CSheetR tid ssh csh shn SShowR - SPersonalFilesR -> i18nCrumb MsgBreadcrumbSheetPersonalisedFiles . Just $ CSheetR tid ssh csh shn SShowR +breadcrumb (CourseR tid ssh csh (SheetR shn sRoute)) = case sRoute of + SShowR -> useRunDB . maybeT (i18nCrumb MsgBreadcrumbSheet . Just $ CourseR tid ssh csh SheetListR) $ do + guardM . lift . hasReadAccessTo $ CSheetR tid ssh csh shn SShowR + return (CI.original shn, Just $ CourseR tid ssh csh SheetListR) + SEditR -> i18nCrumb MsgMenuSheetEdit . Just $ CSheetR tid ssh csh shn SShowR + SDelR -> i18nCrumb MsgMenuSheetDelete . Just $ CSheetR tid ssh csh shn SShowR + SSubsR -> i18nCrumb MsgMenuSubmissions . Just $ CSheetR tid ssh csh shn SShowR + SAssignR -> i18nCrumb MsgMenuCorrectionsAssign . Just $ CSheetR tid ssh csh shn SSubsR + SubmissionNewR -> i18nCrumb MsgMenuSubmissionNew . Just $ CSheetR tid ssh csh shn SShowR + SubmissionOwnR -> i18nCrumb MsgMenuSubmissionOwn . Just $ CSheetR tid ssh csh shn SShowR + SubmissionR cid sRoute' -> case sRoute' of + SubShowR -> useRunDB $ do + mayList <- hasReadAccessTo $ CSheetR tid ssh csh shn SSubsR + if + | mayList + -> i18nCrumb MsgBreadcrumbSubmission . Just $ CSheetR tid ssh csh shn SSubsR + | otherwise + -> i18nCrumb MsgBreadcrumbSubmission . Just $ CSheetR tid ssh csh shn SShowR + CorrectionR -> i18nCrumb MsgMenuCorrection . Just $ CSubmissionR tid ssh csh shn cid SubShowR + SubDelR -> i18nCrumb MsgMenuSubmissionDelete . Just $ CSubmissionR tid ssh csh shn cid SubShowR + SubAssignR -> i18nCrumb MsgCorrectorAssignTitle . Just $ CSubmissionR tid ssh csh shn cid SubShowR + SInviteR -> i18nCrumb MsgBreadcrumbSubmissionUserInvite . Just $ CSubmissionR tid ssh csh shn cid SubShowR + SubArchiveR sft -> i18nCrumb sft . Just $ CSubmissionR tid ssh csh shn cid SubShowR + SubDownloadR _ _ -> i18nCrumb MsgBreadcrumbSubmissionFile . Just $ CSubmissionR tid ssh csh shn cid SubShowR + SArchiveR -> i18nCrumb MsgBreadcrumbSheetArchive . Just $ CSheetR tid ssh csh shn SShowR + SIsCorrR -> i18nCrumb MsgBreadcrumbSheetIsCorrector . Just $ CSheetR tid ssh csh shn SShowR + SPseudonymR -> i18nCrumb MsgBreadcrumbSheetPseudonym . Just $ CSheetR tid ssh csh shn SShowR + SCorrInviteR -> i18nCrumb MsgBreadcrumbSheetCorrectorInvite . Just $ CSheetR tid ssh csh shn SShowR + SZipR sft -> i18nCrumb sft . Just $ CSheetR tid ssh csh shn SShowR + SFileR _ _ -> i18nCrumb MsgBreadcrumbSheetFile . Just $ CSheetR tid ssh csh shn SShowR + SPersonalFilesR -> i18nCrumb MsgBreadcrumbSheetPersonalisedFiles . Just $ CSheetR tid ssh csh shn SShowR - breadcrumb (CourseR tid ssh csh MaterialListR) = i18nCrumb MsgMenuMaterialList . Just $ CourseR tid ssh csh CShowR - breadcrumb (CourseR tid ssh csh MaterialNewR ) = i18nCrumb MsgMenuMaterialNew . Just $ CourseR tid ssh csh MaterialListR - breadcrumb (CourseR tid ssh csh (MaterialR mnm sRoute)) = case sRoute of - MShowR -> maybeT (i18nCrumb MsgBreadcrumbMaterial . Just $ CourseR tid ssh csh MaterialListR) $ do - guardM . hasReadAccessTo $ CMaterialR tid ssh csh mnm MShowR - return (CI.original mnm, Just $ CourseR tid ssh csh MaterialListR) - MEditR -> i18nCrumb MsgMenuMaterialEdit . Just $ CMaterialR tid ssh csh mnm MShowR - MDelR -> i18nCrumb MsgMenuMaterialDelete . Just $ CMaterialR tid ssh csh mnm MShowR - MArchiveR -> i18nCrumb MsgBreadcrumbMaterialArchive . Just $ CMaterialR tid ssh csh mnm MShowR - MFileR _ -> i18nCrumb MsgBreadcrumbMaterialFile . Just $ CMaterialR tid ssh csh mnm MShowR - MVideoR _ -> i18nCrumb MsgBreadcrumbMaterialVideo . Just $ CMaterialR tid ssh csh mnm MShowR +breadcrumb (CourseR tid ssh csh MaterialListR) = i18nCrumb MsgMenuMaterialList . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh MaterialNewR ) = i18nCrumb MsgMenuMaterialNew . Just $ CourseR tid ssh csh MaterialListR +breadcrumb (CourseR tid ssh csh (MaterialR mnm sRoute)) = case sRoute of + MShowR -> useRunDB . maybeT (i18nCrumb MsgBreadcrumbMaterial . Just $ CourseR tid ssh csh MaterialListR) $ do + guardM . lift . hasReadAccessTo $ CMaterialR tid ssh csh mnm MShowR + return (CI.original mnm, Just $ CourseR tid ssh csh MaterialListR) + MEditR -> i18nCrumb MsgMenuMaterialEdit . Just $ CMaterialR tid ssh csh mnm MShowR + MDelR -> i18nCrumb MsgMenuMaterialDelete . Just $ CMaterialR tid ssh csh mnm MShowR + MArchiveR -> i18nCrumb MsgBreadcrumbMaterialArchive . Just $ CMaterialR tid ssh csh mnm MShowR + MFileR _ -> i18nCrumb MsgBreadcrumbMaterialFile . Just $ CMaterialR tid ssh csh mnm MShowR + MVideoR _ -> i18nCrumb MsgBreadcrumbMaterialVideo . Just $ CMaterialR tid ssh csh mnm MShowR - breadcrumb (CourseR tid ssh csh CPersonalFilesR) = i18nCrumb MsgBreadcrumbCourseSheetPersonalisedFiles . Just $ CourseR tid ssh csh CShowR +breadcrumb (CourseR tid ssh csh CPersonalFilesR) = i18nCrumb MsgBreadcrumbCourseSheetPersonalisedFiles . Just $ CourseR tid ssh csh CShowR - breadcrumb CorrectionsR = i18nCrumb MsgMenuCorrections Nothing - breadcrumb CorrectionsUploadR = i18nCrumb MsgMenuCorrectionsUpload $ Just CorrectionsR - breadcrumb CorrectionsCreateR = i18nCrumb MsgMenuCorrectionsCreate $ Just CorrectionsR - breadcrumb CorrectionsGradeR = i18nCrumb MsgMenuCorrectionsGrade $ Just CorrectionsR - breadcrumb CorrectionsDownloadR = i18nCrumb MsgMenuCorrectionsDownload $ Just CorrectionsR +breadcrumb CorrectionsR = i18nCrumb MsgMenuCorrections Nothing +breadcrumb CorrectionsUploadR = i18nCrumb MsgMenuCorrectionsUpload $ Just CorrectionsR +breadcrumb CorrectionsCreateR = i18nCrumb MsgMenuCorrectionsCreate $ Just CorrectionsR +breadcrumb CorrectionsGradeR = i18nCrumb MsgMenuCorrectionsGrade $ Just CorrectionsR +breadcrumb CorrectionsDownloadR = i18nCrumb MsgMenuCorrectionsDownload $ Just CorrectionsR - breadcrumb (CryptoUUIDDispatchR _) = i18nCrumb MsgBreadcrumbCryptoIDDispatch Nothing +breadcrumb (CryptoUUIDDispatchR _) = i18nCrumb MsgBreadcrumbCryptoIDDispatch Nothing - breadcrumb (MessageR _) = do - mayList <- (== Authorized) <$> evalAccess MessageListR False - if - | mayList -> i18nCrumb MsgBreadcrumbSystemMessage $ Just MessageListR - | otherwise -> i18nCrumb MsgBreadcrumbSystemMessage $ Just NewsR - breadcrumb MessageListR = i18nCrumb MsgMenuMessageList $ Just AdminR - breadcrumb (MessageHideR cID) = i18nCrumb MsgBreadcrumbMessageHide . Just $ MessageR cID +breadcrumb (MessageR _) = do + mayList <- useRunDB $ hasReadAccessTo MessageListR + if + | mayList -> i18nCrumb MsgBreadcrumbSystemMessage $ Just MessageListR + | otherwise -> i18nCrumb MsgBreadcrumbSystemMessage $ Just NewsR +breadcrumb MessageListR = i18nCrumb MsgMenuMessageList $ Just AdminR +breadcrumb (MessageHideR cID) = i18nCrumb MsgBreadcrumbMessageHide . Just $ MessageR cID - breadcrumb ScheduleR = i18nCrumb MsgMenuSchedule Nothing +breadcrumb ScheduleR = i18nCrumb MsgMenuSchedule Nothing - breadcrumb GlossaryR = i18nCrumb MsgMenuGlossary $ Just InfoR +breadcrumb GlossaryR = i18nCrumb MsgMenuGlossary $ Just InfoR - breadcrumb EExamListR = i18nCrumb MsgMenuExternalExamList Nothing - breadcrumb EExamNewR = do - isEO <- hasReadAccessTo $ ExamOfficeR EOExamsR - i18nCrumb MsgBreadcrumbExternalExamNew . Just $ if - | isEO -> ExamOfficeR EOExamsR - | otherwise -> EExamListR - breadcrumb (EExamR tid ssh coursen examn sRoute) = case sRoute of - EEShowR -> do - isEO <- hasReadAccessTo $ ExamOfficeR EOExamsR - maybeT (i18nCrumb MsgBreadcrumbExternalExam . Just $ bool EExamListR (ExamOfficeR EOExamsR) isEO) $ do - guardM . hasReadAccessTo $ EExamR tid ssh coursen examn EEShowR - i18nCrumb (MsgBreadcrumbExternalExamShow coursen examn) . Just $ if - | isEO -> ExamOfficeR EOExamsR - | otherwise -> EExamListR - EEEditR -> i18nCrumb MsgBreadcrumbExternalExamEdit . Just $ EExamR tid ssh coursen examn EEShowR - EEUsersR -> i18nCrumb MsgBreadcrumbExternalExamUsers . Just $ EExamR tid ssh coursen examn EEShowR - EEGradesR -> i18nCrumb MsgBreadcrumbExternalExamGrades . Just $ EExamR tid ssh coursen examn EEShowR - EEStaffInviteR -> i18nCrumb MsgBreadcrumbExternalExamStaffInvite . Just $ EExamR tid ssh coursen examn EEShowR - EECorrectR -> i18nCrumb MsgBreadcrumbExternalExamCorrect . Just $ EExamR tid ssh coursen examn EEShowR +breadcrumb EExamListR = i18nCrumb MsgMenuExternalExamList Nothing +breadcrumb EExamNewR = do + isEO <- useRunDB . hasReadAccessTo $ ExamOfficeR EOExamsR + i18nCrumb MsgBreadcrumbExternalExamNew . Just $ if + | isEO -> ExamOfficeR EOExamsR + | otherwise -> EExamListR +breadcrumb (EExamR tid ssh coursen examn sRoute) = case sRoute of + EEShowR -> do + (isEO, mayShow) <- useRunDB $ (,) + <$> hasReadAccessTo (ExamOfficeR EOExamsR) + <*> hasReadAccessTo (EExamR tid ssh coursen examn EEShowR) + maybeT (i18nCrumb MsgBreadcrumbExternalExam . Just $ bool EExamListR (ExamOfficeR EOExamsR) isEO) $ do + guard mayShow + i18nCrumb (MsgBreadcrumbExternalExamShow coursen examn) . Just $ if + | isEO -> ExamOfficeR EOExamsR + | otherwise -> EExamListR + EEEditR -> i18nCrumb MsgBreadcrumbExternalExamEdit . Just $ EExamR tid ssh coursen examn EEShowR + EEUsersR -> i18nCrumb MsgBreadcrumbExternalExamUsers . Just $ EExamR tid ssh coursen examn EEShowR + EEGradesR -> i18nCrumb MsgBreadcrumbExternalExamGrades . Just $ EExamR tid ssh coursen examn EEShowR + EEStaffInviteR -> i18nCrumb MsgBreadcrumbExternalExamStaffInvite . Just $ EExamR tid ssh coursen examn EEShowR + EECorrectR -> i18nCrumb MsgBreadcrumbExternalExamCorrect . Just $ EExamR tid ssh coursen examn EEShowR + +breadcrumb AdminWorkflowDefinitionListR = i18nCrumb MsgBreadcrumbAdminWorkflowDefinitionList $ Just AdminR +breadcrumb AdminWorkflowDefinitionNewR = i18nCrumb MsgBreadcrumbAdminWorkflowDefinitionNew $ Just AdminWorkflowDefinitionListR +breadcrumb (AdminWorkflowDefinitionR wfdScope wfdName sRoute) = case sRoute of + AWDEditR -> do + MsgRenderer mr <- getMsgRenderer + i18nCrumb (MsgBreadcrumbAdminWorkflowDefinitionEdit (mr wfdScope) wfdName) $ Just AdminWorkflowDefinitionListR + AWDDeleteR -> i18nCrumb MsgBreadcrumbAdminWorkflowDefinitionDelete . Just $ AdminWorkflowDefinitionR wfdScope wfdName AWDEditR + AWDInstantiateR -> i18nCrumb MsgBreadcrumbAdminWorkflowDefinitionInstantiate . Just $ AdminWorkflowDefinitionR wfdScope wfdName AWDEditR +breadcrumb AdminWorkflowInstanceListR = i18nCrumb MsgBreadcrumbAdminWorkflowInstanceList $ Just AdminWorkflowDefinitionListR +breadcrumb AdminWorkflowInstanceNewR = i18nCrumb MsgBreadcrumbAdminWorkflowInstanceNew $ Just AdminWorkflowInstanceListR +breadcrumb (AdminWorkflowInstanceR _cID sRoute) = case sRoute of + AWIEditR -> i18nCrumb MsgBreadcrumbAdminWorkflowInstanceEdit $ Just AdminWorkflowInstanceListR +breadcrumb AdminWorkflowWorkflowListR = i18nCrumb MsgBreadcrumbAdminWorkflowWorkflowList $ Just AdminWorkflowInstanceListR +breadcrumb AdminWorkflowWorkflowNewR = i18nCrumb MsgBreadcrumbAdminWorkflowWorkflowNew $ Just AdminWorkflowWorkflowListR + +breadcrumb GlobalWorkflowInstanceListR = i18nCrumb MsgBreadcrumbGlobalWorkflowInstanceList Nothing +breadcrumb GlobalWorkflowInstanceNewR = i18nCrumb MsgBreadcrumbWorkflowInstanceNew $ Just GlobalWorkflowInstanceListR +breadcrumb (GlobalWorkflowInstanceR win sRoute) = case sRoute of + GWIEditR -> do + desc <- useRunDB . runMaybeT $ do + guardM . lift . hasReadAccessTo $ GlobalWorkflowInstanceR win GWIWorkflowsR + wiId <- MaybeT . getKeyBy $ UniqueWorkflowInstance win WSGlobal + MaybeT $ selectWorkflowInstanceDescription wiId + case desc of + Nothing -> i18nCrumb (MsgBreadcrumbWorkflowInstanceEdit win) $ Just GlobalWorkflowInstanceListR + Just (Entity _ WorkflowInstanceDescription{..}) -> i18nCrumb workflowInstanceDescriptionTitle $ Just GlobalWorkflowInstanceListR + GWIDeleteR -> i18nCrumb MsgBreadcrumbWorkflowInstanceDelete . Just $ GlobalWorkflowInstanceR win GWIEditR + GWIWorkflowsR -> i18nCrumb MsgBreadcrumbWorkflowInstanceWorkflowList . Just $ GlobalWorkflowInstanceR win GWIEditR + GWIInitiateR -> do + mayEdit <- useRunDB . hasReadAccessTo $ GlobalWorkflowInstanceR win GWIEditR + i18nCrumb MsgBreadcrumbWorkflowInstanceInitiate . Just $ if + | mayEdit -> GlobalWorkflowInstanceR win GWIEditR + | otherwise -> GlobalWorkflowInstanceListR +breadcrumb GlobalWorkflowWorkflowListR = i18nCrumb MsgBreadcrumbWorkflowWorkflowList $ Just GlobalWorkflowInstanceListR +breadcrumb (GlobalWorkflowWorkflowR cID sRoute) = case sRoute of + GWWWorkflowR -> i18nCrumb (MsgBreadcrumbWorkflowWorkflow cID) $ Just GlobalWorkflowWorkflowListR + GWWFilesR _ _ -> i18nCrumb MsgBreadcrumbWorkflowWorkflowFiles . Just $ GlobalWorkflowWorkflowR cID GWWWorkflowR + GWWEditR -> i18nCrumb MsgBreadcrumbWorkflowWorkflowEdit . Just $ GlobalWorkflowWorkflowR cID GWWWorkflowR + GWWDeleteR -> i18nCrumb MsgBreadcrumbWorkflowWorkflowDelete . Just $ GlobalWorkflowWorkflowR cID GWWWorkflowR + +breadcrumb TopWorkflowInstanceListR = i18nCrumb MsgBreadcrumbTopWorkflowInstanceList Nothing +breadcrumb TopWorkflowWorkflowListR = i18nCrumb MsgBreadcrumbTopWorkflowWorkflowList $ Just TopWorkflowInstanceListR data NavQuickView @@ -362,7 +456,7 @@ data NavType , navData :: [(Text, Text)] } deriving (Eq, Ord, Read, Show, Generic, Typeable) - deriving anyclass (Binary) + deriving anyclass (Hashable, Binary) makeLenses_ ''NavType makePrisms ''NavType @@ -373,10 +467,14 @@ data NavLevel = NavLevelTop | NavLevelInner data NavHeaderRole = NavHeaderPrimary | NavHeaderSecondary deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable) +data NavAccess = NavAccessDB (ReaderT SqlReadBackend Handler Bool) + | NavAccessHandler (Handler Bool) + | NavAccessTrue + data NavLink = forall msg route. (RenderMessage UniWorX msg, HasRoute UniWorX route, RedirectUrl UniWorX route) => NavLink { navLabel :: msg , navRoute :: route - , navAccess' :: Handler Bool + , navAccess' :: NavAccess , navType :: NavType , navQuick' :: NavQuickView -> Any , navForceActive :: Bool @@ -384,13 +482,20 @@ data NavLink = forall msg route. (RenderMessage UniWorX msg, HasRoute UniWorX ro makeLenses_ ''NavLink -instance HasRoute UniWorX NavLink where - urlRoute NavLink{..} = urlRoute navRoute -instance RedirectUrl UniWorX NavLink where - toTextUrl NavLink{..} = toTextUrl navRoute +-- instance HasRoute UniWorX NavLink where +-- urlRoute NavLink{..} = urlRoute navRoute +-- instance RedirectUrl UniWorX NavLink where +-- toTextUrl NavLink{..} = toTextUrl navRoute instance RenderMessage UniWorX NavLink where renderMessage app ls NavLink{..} = renderMessage app ls navLabel +navBaseRoute :: NavLink -> Route UniWorX +navBaseRoute NavLink{navRoute} = urlRoute navRoute + +navLinkRoute :: Applicative m + => NavLink -> m (SomeRoute UniWorX) +navLinkRoute NavLink{..} = pure $ SomeRoute navRoute + data Nav = NavHeader { navHeaderRole :: NavHeaderRole @@ -424,27 +529,50 @@ type family ChildrenNavChildren a where ChildrenNavChildren a = Children ChGeneric a -navAccess :: (MonadHandler m, HandlerSite m ~ UniWorX, MonadCatch m, BearerAuthSite UniWorX) => Nav -> MaybeT m Nav -navAccess = execStateT $ do - guardM $ preuse _navLink >>= maybe (return True) navLinkAccess +data NavigationCacheKey + = NavCacheRouteAccess AuthContext NavType (Route UniWorX) + | NavCacheHaveWorkflowWorkflowsRoles RouteWorkflowScope + | NavCacheHaveTopWorkflowInstancesRoles | NavCacheHaveTopWorkflowWorkflowsRoles + | NavCacheHaveTopWorkflowsInstances AuthContext + deriving (Generic, Typeable) - _navChildren <~ (filterM navLinkAccess =<< use _navChildren) +deriving stock instance Eq (AuthId UniWorX) => Eq NavigationCacheKey +deriving stock instance Ord (AuthId UniWorX) => Ord NavigationCacheKey +deriving stock instance (Read (AuthId UniWorX), Eq (AuthId UniWorX), Hashable (AuthId UniWorX)) => Read NavigationCacheKey +deriving stock instance (Show (AuthId UniWorX), Eq (AuthId UniWorX), Hashable (AuthId UniWorX)) => Show NavigationCacheKey +deriving anyclass instance Hashable (AuthId UniWorX) => Hashable NavigationCacheKey +deriving anyclass instance (Binary (AuthId UniWorX), Eq (AuthId UniWorX), Hashable (AuthId UniWorX)) => Binary NavigationCacheKey + + +navAccess :: (MonadHandler m, HandlerSite m ~ UniWorX, MonadCatch m, WithRunDB SqlReadBackend (HandlerFor UniWorX) m, BearerAuthSite UniWorX) => Nav -> MaybeT m Nav +navAccess = execStateT $ do + guardM $ preuse _navLink >>= lift . lift . maybe (return True) navLinkAccess + + _navChildren <~ (filterM (lift . lift . navLinkAccess) =<< use _navChildren) whenM (hasn't _navLink <$> use id) $ guardM $ not . null <$> use _navChildren -navLinkAccess :: forall m. (MonadHandler m, HandlerSite m ~ UniWorX, MonadCatch m, BearerAuthSite UniWorX) => NavLink -> m Bool -navLinkAccess NavLink{..} = handle shortCircuit $ liftHandler navAccess' `and2M` accessCheck navType navRoute +navLinkAccess :: forall m. (MonadHandler m, HandlerSite m ~ UniWorX, MonadCatch m, WithRunDB SqlReadBackend (HandlerFor UniWorX) m, BearerAuthSite UniWorX) => NavLink -> m Bool +navLinkAccess NavLink{..} = case navAccess' of + NavAccessHandler naNoDb -> handle shortCircuit $ liftHandler naNoDb `and2M` accessCheck navType navRoute + NavAccessDB naDb -> handle shortCircuit . useRunDB $ naDb `and2M` accessCheck navType navRoute + NavAccessTrue -> accessCheck navType navRoute where shortCircuit :: HandlerContents -> m Bool shortCircuit _ = return False - accessCheck :: HasRoute UniWorX route => NavType -> route -> m Bool + accessCheck :: forall m' route. (MonadHandler m', HandlerSite m' ~ UniWorX, MonadThrow m', WithRunDB SqlReadBackend (HandlerFor UniWorX) m', HasRoute UniWorX route) => NavType -> route -> m' Bool accessCheck nt (urlRoute -> route) = do authCtx <- getAuthContext - $memcachedByHere (Just $ Right 120) (authCtx, nt, route) $ + memcachedBy (Just . Right $ 2 * diffMinute) (NavCacheRouteAccess authCtx nt route) . useRunDB $ bool hasWriteAccessTo hasReadAccessTo (is _NavTypeLink nt) route -defaultLinks :: (MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX) => m [Nav] +defaultLinks :: ( MonadHandler m + , HandlerSite m ~ UniWorX + , MonadThrow m + , WithRunDB SqlReadBackend (HandlerFor UniWorX) m + , BearerAuthSite UniWorX + ) => m [Nav] defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the header. [ return NavHeader { navHeaderRole = NavHeaderSecondary @@ -452,7 +580,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , navLink = NavLink { navLabel = MsgMenuLogout , navRoute = AuthR LogoutR - , navAccess' = is _Just <$> maybeAuthId + , navAccess' = NavAccessHandler $ is _Just <$> maybeAuthId , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -464,7 +592,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , navLink = NavLink { navLabel = MsgMenuLogin , navRoute = AuthR LoginR - , navAccess' = is _Nothing <$> maybeAuthId + , navAccess' = NavAccessHandler $ is _Nothing <$> maybeAuthId , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -476,7 +604,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , navLink = NavLink { navLabel = MsgMenuProfile , navRoute = ProfileR - , navAccess' = is _Just <$> maybeAuthId + , navAccess' = NavAccessHandler $ is _Just <$> maybeAuthId , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -490,7 +618,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the let navChildren = flip map (toList appLanguages) $ \lang -> NavLink { navLabel = MsgLanguage lang , navRoute = (LangR, [(toPathPiece GetReferer, toPathPiece currentRoute) | currentRoute <- hoistMaybe mCurrentRoute ]) - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeButton { navMethod = POST , navData = [(toPathPiece PostLanguage, lang)] @@ -516,7 +644,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , navLink = NavLink { navLabel = MsgMenuHelp , navRoute = (HelpR, [(toPathPiece GetReferer, toPathPiece currentRoute) | currentRoute <- hoistMaybe mCurrentRoute ]) - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -525,7 +653,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , return $ NavFooter NavLink { navLabel = MsgMenuDataProt , navRoute = LegalR :#: ("data-protection" :: Text) - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -533,7 +661,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , return $ NavFooter NavLink { navLabel = MsgMenuTermsUse , navRoute = LegalR :#: ("terms-of-use" :: Text) - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -541,7 +669,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , return $ NavFooter NavLink { navLabel = MsgMenuCopyright , navRoute = LegalR :#: ("copyright" :: Text) - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -549,7 +677,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , return $ NavFooter NavLink { navLabel = MsgMenuImprint , navRoute = LegalR :#: ("imprint" :: Text) - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -557,7 +685,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , return $ NavFooter NavLink { navLabel = MsgMenuInformation , navRoute = InfoR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -565,7 +693,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , return $ NavFooter NavLink { navLabel = MsgMenuFaq , navRoute = FaqR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -573,7 +701,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , return $ NavFooter NavLink { navLabel = MsgMenuGlossary , navRoute = GlossaryR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -584,7 +712,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , navLink = NavLink { navLabel = MsgMenuNews , navRoute = NewsR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -596,7 +724,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , navLink = NavLink { navLabel = MsgMenuCourseList , navRoute = CourseListR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -608,7 +736,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , navLink = NavLink { navLabel = MsgMenuCorrections , navRoute = CorrectionsR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -620,12 +748,43 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , navLink = NavLink { navLabel = MsgMenuExamOfficeExams , navRoute = ExamOfficeR EOExamsR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False } } + , do + authCtx <- getAuthContext + (haveInstances, haveWorkflows) <- lift . memcachedBy (Just . Right $ 2 * diffMinute) (NavCacheHaveTopWorkflowsInstances authCtx) . useRunDB $ (,) + <$> haveTopWorkflowInstances + <*> haveTopWorkflowWorkflows + + if | haveInstances -> return NavHeader + { navHeaderRole = NavHeaderPrimary + , navIcon = IconMenuWorkflows + , navLink = NavLink + { navLabel = MsgMenuTopWorkflowInstanceList + , navRoute = TopWorkflowInstanceListR + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + } + | haveWorkflows -> return NavHeader + { navHeaderRole = NavHeaderPrimary + , navIcon = IconMenuWorkflows + , navLink = NavLink + { navLabel = MsgMenuTopWorkflowWorkflowListHeader + , navRoute = TopWorkflowWorkflowListR + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + } + | otherwise -> mzero , return NavHeaderContainer { navHeaderRole = NavHeaderPrimary , navLabel = SomeMessage MsgAdminHeading @@ -634,7 +793,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the [ NavLink { navLabel = MsgMenuUsers , navRoute = UsersR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -642,7 +801,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , NavLink { navLabel = MsgMenuSchoolList , navRoute = SchoolListR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -650,7 +809,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , NavLink { navLabel = MsgAdminFeaturesHeading , navRoute = AdminFeaturesR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -658,7 +817,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , NavLink { navLabel = MsgMenuMessageList , navRoute = MessageListR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -666,7 +825,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , NavLink { navLabel = MsgMenuAdminErrMsg , navRoute = AdminErrMsgR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -674,7 +833,15 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , NavLink { navLabel = MsgMenuAdminTokens , navRoute = AdminTokensR - , navAccess' = return True + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + , NavLink + { navLabel = MsgMenuAdminWorkflowDefinitionList + , navRoute = AdminWorkflowDefinitionListR + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -682,7 +849,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , NavLink { navLabel = MsgMenuAdminCrontab , navRoute = AdminCrontabR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -690,7 +857,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , NavLink { navLabel = MsgMenuAdminTest , navRoute = AdminTestR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -705,7 +872,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the [ NavLink { navLabel = MsgMenuCourseNew , navRoute = CourseNewR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -713,7 +880,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , NavLink { navLabel = MsgMenuExternalExamList , navRoute = EExamListR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -721,7 +888,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , NavLink { navLabel = MsgMenuTermShow , navRoute = TermShowR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -729,7 +896,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , NavLink { navLabel = MsgMenuAllocationList , navRoute = AllocationListR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -737,7 +904,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , NavLink { navLabel = MsgInfoLecturerTitle , navRoute = InfoLecturerR - , navAccess' = hasWriteAccessTo CourseNewR + , navAccess' = NavAccessDB $ hasWriteAccessTo CourseNewR , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -749,7 +916,9 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the pageActions :: ( MonadHandler m , HandlerSite m ~ UniWorX , MonadCatch m + , WithRunDB SqlReadBackend (HandlerFor UniWorX) m , BearerAuthSite UniWorX + , MonadUnliftIO m ) => Route UniWorX -> m [Nav] pageActions NewsR = return @@ -757,7 +926,7 @@ pageActions NewsR = return { navLink = NavLink { navLabel = MsgMenuOpenCourses , navRoute = (CourseListR, [("courses-openregistration", toPathPiece True)]) - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -768,7 +937,7 @@ pageActions NewsR = return { navLink = NavLink { navLabel = MsgMenuOpenAllocations , navRoute = (AllocationListR, [("allocations-active", toPathPiece True)]) - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -785,7 +954,7 @@ pageActions (CourseR tid ssh csh CShowR) = do let examListBound :: Num a => a examListBound = 4 -- guaranteed random; chosen by fair dice roll - examListExams <- liftHandler . runDBRead $ do + examListExams <- useRunDB $ do examNames <- E.select . E.from $ \(course `E.InnerJoin` exam) -> do E.on $ exam E.^. ExamCourse E.==. course E.^. CourseId E.where_ $ course E.^. CourseTerm E.==. E.val tid @@ -798,7 +967,7 @@ pageActions (CourseR tid ssh csh CShowR) = do return NavLink { navLabel = examn , navRoute = CExamR tid ssh csh examn EShowR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewFavourite , navForceActive = False @@ -810,7 +979,7 @@ pageActions (CourseR tid ssh csh CShowR) = do { navLink = NavLink { navLabel = MsgMenuCourseMembers , navRoute = CourseR tid ssh csh CUsersR - , navAccess' = + , navAccess' = NavAccessDB $ let courseWhere course = course <$ do E.where_ $ course E.^. CourseTerm E.==. E.val tid E.&&. course E.^. CourseSchool E.==. E.val ssh @@ -820,7 +989,7 @@ pageActions (CourseR tid ssh csh CShowR) = do E.where_ $ courseParticipant E.^. CourseParticipantState E.==. E.val CourseParticipantActive void $ courseWhere course mayRegister = hasWriteAccessTo $ CourseR tid ssh csh CAddUserR - in runDBRead $ mayRegister `or2M` hasParticipants + in mayRegister `or2M` hasParticipants , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewFavourite , navForceActive = False @@ -834,7 +1003,7 @@ pageActions (CourseR tid ssh csh CShowR) = do { navLink = NavLink { navLabel = MsgMenuMaterialList , navRoute = CourseR tid ssh csh MaterialListR - , navAccess' = + , navAccess' = NavAccessDB $ let lecturerAccess = hasWriteAccessTo $ CourseR tid ssh csh MaterialNewR -- Always show for lecturers to create new material materialAccess mnm = hasReadAccessTo $ CMaterialR tid ssh csh mnm MShowR -- otherwise show only if the user can see at least one of the contents existsVisible = do @@ -845,7 +1014,7 @@ pageActions (CourseR tid ssh csh CShowR) = do E.&&. course E.^. CourseShorthand E.==. E.val csh return $ material E.^. MaterialName anyM matNames (materialAccess . E.unValue) - in runDBRead $ lecturerAccess `or2M` existsVisible + in lecturerAccess `or2M` existsVisible , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewFavourite , navForceActive = False @@ -856,7 +1025,7 @@ pageActions (CourseR tid ssh csh CShowR) = do { navLink = NavLink { navLabel = MsgMenuSheetList , navRoute = CourseR tid ssh csh SheetListR - , navAccess' = + , navAccess' = NavAccessDB $ let lecturerAccess = hasWriteAccessTo $ CourseR tid ssh csh SheetNewR -- Always show for lecturers to create new sheets sheetAccess shn = hasReadAccessTo $ CSheetR tid ssh csh shn SShowR -- othwerwise show only if the user can see at least one of the contents existsVisible = do @@ -867,7 +1036,7 @@ pageActions (CourseR tid ssh csh CShowR) = do E.&&. course E.^. CourseShorthand E.==. E.val csh return $ sheet E.^. SheetName anyM sheetNames $ sheetAccess . E.unValue - in runDBRead $ lecturerAccess `or2M` existsVisible + in lecturerAccess `or2M` existsVisible , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewFavourite , navForceActive = False @@ -878,7 +1047,7 @@ pageActions (CourseR tid ssh csh CShowR) = do { navLink = NavLink { navLabel = MsgMenuTutorialList , navRoute = CourseR tid ssh csh CTutorialListR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewFavourite , navForceActive = False @@ -889,7 +1058,7 @@ pageActions (CourseR tid ssh csh CShowR) = do { navLink = NavLink { navLabel = MsgMenuExamList , navRoute = CourseR tid ssh csh CExamListR - , navAccess' = + , navAccess' = NavAccessDB $ let lecturerAccess = hasWriteAccessTo $ CourseR tid ssh csh CExamNewR examAccess examn = hasReadAccessTo $ CExamR tid ssh csh examn EShowR existsVisible = do @@ -900,7 +1069,7 @@ pageActions (CourseR tid ssh csh CShowR) = do E.&&. course E.^. CourseShorthand E.==. E.val csh return $ exam E.^. ExamName anyM examNames $ examAccess . E.unValue - in runDBRead $ lecturerAccess `or2M` existsVisible + in lecturerAccess `or2M` existsVisible , navType = NavTypeLink { navModal = False } , navQuick' = bool (navQuick NavQuickViewFavourite) mempty showExamList , navForceActive = False @@ -913,7 +1082,7 @@ pageActions (CourseR tid ssh csh CShowR) = do { navLink = NavLink { navLabel = MsgMenuCourseCommunication , navRoute = CourseR tid ssh csh CCommR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewFavourite , navForceActive = False @@ -924,13 +1093,12 @@ pageActions (CourseR tid ssh csh CShowR) = do { navLink = NavLink { navLabel = MsgMenuCourseExamOffice , navRoute = CourseR tid ssh csh CExamOfficeR - , navAccess' = do + , navAccess' = NavAccessDB $ do uid <- requireAuthId - runDBRead $ do - cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh - E.selectExists $ do - (_school, isForced) <- courseExamOfficeSchools (E.val uid) (E.val cid) - E.where_ $ E.not_ isForced + cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh + E.selectExists $ do + (_school, isForced) <- courseExamOfficeSchools (E.val uid) (E.val cid) + E.where_ $ E.not_ isForced , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -940,7 +1108,7 @@ pageActions (CourseR tid ssh csh CShowR) = do { navLink = NavLink { navLabel = MsgMenuCourseEdit , navRoute = CourseR tid ssh csh CEditR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -952,7 +1120,7 @@ pageActions (CourseR tid ssh csh CShowR) = do , navRoute = ( CourseNewR , [("tid", toPathPiece tid), ("ssh", toPathPiece ssh), ("csh", toPathPiece csh)] ) - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -962,7 +1130,7 @@ pageActions (CourseR tid ssh csh CShowR) = do { navLink = NavLink { navLabel = MsgMenuCourseDelete , navRoute = CourseR tid ssh csh CDeleteR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -974,7 +1142,7 @@ pageActions (ExamOfficeR EOExamsR) = return { navLink = NavLink { navLabel = MsgMenuExamOfficeFields , navRoute = ExamOfficeR EOFieldsR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -985,7 +1153,7 @@ pageActions (ExamOfficeR EOExamsR) = return { navLink = NavLink { navLabel = MsgMenuExamOfficeUsers , navRoute = ExamOfficeR EOUsersR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -998,7 +1166,7 @@ pageActions SchoolListR = return { navLink = NavLink { navLabel = MsgMenuSchoolNew , navRoute = SchoolNewR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1011,7 +1179,7 @@ pageActions UsersR = return { navLink = NavLink { navLabel = MsgMenuLecturerInvite , navRoute = AdminNewFunctionaryInviteR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -1022,7 +1190,7 @@ pageActions UsersR = return { navLink = NavLink { navLabel = MsgMenuUserAdd , navRoute = AdminUserAddR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -1035,7 +1203,7 @@ pageActions (AdminUserR cID) = return { navLink = NavLink { navLabel = MsgMenuUserNotifications , navRoute = UserNotificationR cID - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -1046,9 +1214,9 @@ pageActions (AdminUserR cID) = return { navLink = NavLink { navLabel = MsgMenuUserPassword , navRoute = UserPasswordR cID - , navAccess' = do + , navAccess' = NavAccessDB $ do uid <- decrypt cID - User{userAuthentication} <- runDBRead $ get404 uid + User{userAuthentication} <- get404 uid return $ is _AuthPWHash userAuthentication , navType = NavTypeLink { navModal = True } , navQuick' = mempty @@ -1062,7 +1230,7 @@ pageActions InfoR = return { navLink = NavLink { navLabel = MsgInfoLecturerTitle , navRoute = InfoLecturerR - , navAccess' = hasWriteAccessTo CourseNewR + , navAccess' = NavAccessDB $ hasWriteAccessTo CourseNewR , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1073,7 +1241,7 @@ pageActions InfoR = return { navLink = NavLink { navLabel = MsgMenuLegal , navRoute = LegalR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1084,7 +1252,7 @@ pageActions InfoR = return { navLink = NavLink { navLabel = MsgMenuFaq , navRoute = FaqR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1095,7 +1263,7 @@ pageActions InfoR = return { navLink = NavLink { navLabel = MsgMenuGlossary , navRoute = GlossaryR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1108,7 +1276,7 @@ pageActions VersionR = return { navLink = NavLink { navLabel = MsgInfoLecturerTitle , navRoute = InfoLecturerR - , navAccess' = hasWriteAccessTo CourseNewR + , navAccess' = NavAccessDB $ hasWriteAccessTo CourseNewR , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1119,7 +1287,7 @@ pageActions VersionR = return { navLink = NavLink { navLabel = MsgMenuLegal , navRoute = LegalR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1130,7 +1298,7 @@ pageActions VersionR = return { navLink = NavLink { navLabel = MsgMenuFaq , navRoute = FaqR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1141,7 +1309,7 @@ pageActions VersionR = return { navLink = NavLink { navLabel = MsgMenuGlossary , navRoute = GlossaryR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1154,7 +1322,7 @@ pageActions HealthR = return { navLink = NavLink { navLabel = MsgMenuInstance , navRoute = InstanceR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1167,7 +1335,7 @@ pageActions InstanceR = return { navLink = NavLink { navLabel = MsgMenuHealth , navRoute = HealthR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1180,7 +1348,7 @@ pageActions HelpR = return { navLink = NavLink { navLabel = MsgMenuFaq , navRoute = FaqR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1191,7 +1359,7 @@ pageActions HelpR = return { navLink = NavLink { navLabel = MsgInfoLecturerTitle , navRoute = InfoLecturerR - , navAccess' = hasWriteAccessTo CourseNewR + , navAccess' = NavAccessDB $ hasWriteAccessTo CourseNewR , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1207,7 +1375,7 @@ pageActions HelpR = return return NavLink { navLabel , navRoute = InfoLecturerR :#: section - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1217,7 +1385,7 @@ pageActions HelpR = return { navLink = NavLink { navLabel = MsgMenuGlossary , navRoute = GlossaryR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1230,7 +1398,7 @@ pageActions ProfileR = return { navLink = NavLink { navLabel = MsgMenuProfileData , navRoute = ProfileDataR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1241,7 +1409,7 @@ pageActions ProfileR = return { navLink = NavLink { navLabel = MsgMenuAuthPreds , navRoute = AuthPredsR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -1252,7 +1420,7 @@ pageActions ProfileR = return { navLink = NavLink { navLabel = MsgCsvOptions , navRoute = CsvOptionsR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -1267,7 +1435,7 @@ pageActions TermShowR = do { navLink = NavLink { navLabel = MsgMenuTermCreate , navRoute = TermEditR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1278,7 +1446,7 @@ pageActions TermShowR = do { navLink = NavLink { navLabel = MsgMenuParticipantsList , navRoute = ParticipantsListR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1291,7 +1459,7 @@ pageActions (AllocationR tid ssh ash AShowR) = return { navLink = NavLink { navLabel = MsgMenuAllocationInfo , navRoute = InfoAllocationR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -1302,7 +1470,7 @@ pageActions (AllocationR tid ssh ash AShowR) = return { navLink = NavLink { navLabel = MsgMenuAllocationUsers , navRoute = AllocationR tid ssh ash AUsersR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1313,7 +1481,7 @@ pageActions (AllocationR tid ssh ash AShowR) = return { navLink = NavLink { navLabel = MsgMenuAllocationCompute , navRoute = AllocationR tid ssh ash AComputeR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1326,7 +1494,7 @@ pageActions (AllocationR tid ssh ash AUsersR) = return { navLink = NavLink { navLabel = MsgMenuAllocationPriorities , navRoute = AllocationR tid ssh ash APriosR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1337,7 +1505,7 @@ pageActions (AllocationR tid ssh ash AUsersR) = return { navLink = NavLink { navLabel = MsgMenuAllocationCompute , navRoute = AllocationR tid ssh ash AComputeR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1348,7 +1516,7 @@ pageActions (AllocationR tid ssh ash AUsersR) = return { navLink = NavLink { navLabel = MsgMenuAllocationAddUser , navRoute = AllocationR tid ssh ash AAddUserR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1363,7 +1531,7 @@ pageActions CourseListR = do { navLink = NavLink { navLabel = MsgMenuCourseNew , navRoute = CourseNewR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1374,7 +1542,7 @@ pageActions CourseListR = do { navLink = NavLink { navLabel = MsgMenuAllocationList , navRoute = AllocationListR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1385,7 +1553,7 @@ pageActions CourseListR = do { navLink = NavLink { navLabel = MsgMenuParticipantsList , navRoute = ParticipantsListR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1398,7 +1566,7 @@ pageActions CourseNewR = return { navLink = NavLink { navLabel = MsgInfoLecturerTitle , navRoute = InfoLecturerR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1411,7 +1579,7 @@ pageActions (CourseR tid ssh csh CCorrectionsR) = return { navLink = NavLink { navLabel = MsgMenuCorrectionsAssign , navRoute = CourseR tid ssh csh CAssignR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite , navForceActive = False @@ -1427,12 +1595,12 @@ pageActions (CourseR tid ssh csh CCorrectionsR) = return , ("corrections-course", toPathPiece csh) ] ) - , navAccess' = do + , navAccess' = NavAccessDB $ do muid <- maybeAuthId case muid of Nothing -> return False (Just uid) -> do - runDBRead . E.selectExists . E.from $ \(course `E.InnerJoin` sheet `E.InnerJoin` submission) -> do + E.selectExists . E.from $ \(course `E.InnerJoin` sheet `E.InnerJoin` submission) -> do E.on $ submission E.^. SubmissionSheet E.==. sheet E.^. SheetId E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId E.where_ $ submission E.^. SubmissionRatingBy E.==. E.just (E.val uid) @@ -1454,7 +1622,7 @@ pageActions (CourseR tid ssh csh SheetListR) = do { navLink = NavLink { navLabel = MsgMenuSubmissions , navRoute = CourseR tid ssh csh CCorrectionsR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite , navForceActive = False @@ -1468,10 +1636,9 @@ pageActions (CourseR tid ssh csh SheetListR) = do { navLink = NavLink { navLabel = MsgMenuSheetCurrent , navRoute = CourseR tid ssh csh SheetCurrentR - , navAccess' = - runDBRead . maybeT (return False) $ do - void . MaybeT $ sheetCurrent tid ssh csh - return True + , navAccess' = NavAccessDB . maybeT (return False) $ do + void . MaybeT $ sheetCurrent tid ssh csh + return True , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite , navForceActive = False @@ -1482,10 +1649,9 @@ pageActions (CourseR tid ssh csh SheetListR) = do { navLink = NavLink { navLabel = MsgMenuSheetOldUnassigned , navRoute = CourseR tid ssh csh SheetOldUnassignedR - , navAccess' = - runDBRead . maybeT (return False) $ do - void . MaybeT $ sheetOldUnassigned tid ssh csh - return True + , navAccess' = NavAccessDB . maybeT (return False) $ do + void . MaybeT $ sheetOldUnassigned tid ssh csh + return True , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite , navForceActive = False @@ -1498,7 +1664,7 @@ pageActions (CourseR tid ssh csh SheetListR) = do { navLink = NavLink { navLabel = MsgMenuSheetNew , navRoute = CourseR tid ssh csh SheetNewR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite , navForceActive = False @@ -1511,7 +1677,7 @@ pageActions (CourseR tid ssh csh CUsersR) = return { navLink = NavLink { navLabel = MsgMenuCourseAddMembers , navRoute = CourseR tid ssh csh CAddUserR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -1522,7 +1688,7 @@ pageActions (CourseR tid ssh csh CUsersR) = return { navLink = NavLink { navLabel = MsgMenuCourseApplications , navRoute = CourseR tid ssh csh CApplicationsR - , navAccess' = + , navAccess' = NavAccessDB $ let courseWhere course = course <$ do E.where_ $ course E.^. CourseTerm E.==. E.val tid E.&&. course E.^. CourseSchool E.==. E.val ssh @@ -1536,7 +1702,7 @@ pageActions (CourseR tid ssh csh CUsersR) = return courseAllocation = E.selectExists . E.from $ \(course `E.InnerJoin` allocationCourse) -> do E.on $ course E.^. CourseId E.==. allocationCourse E.^. AllocationCourseCourse void $ courseWhere course - in runDBRead $ courseAllocation `or2M` courseApplications `or2M` existsApplications + in courseAllocation `or2M` courseApplications `or2M` existsApplications , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary <> navQuick NavQuickViewFavourite , navForceActive = False @@ -1549,7 +1715,7 @@ pageActions (CourseR tid ssh csh MaterialListR) = return { navLink = NavLink { navLabel = MsgMenuMaterialNew , navRoute = CourseR tid ssh csh MaterialNewR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -1562,7 +1728,7 @@ pageActions (CMaterialR tid ssh csh mnm MShowR) = return { navLink = NavLink { navLabel = MsgMenuMaterialEdit , navRoute = CMaterialR tid ssh csh mnm MEditR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1573,7 +1739,7 @@ pageActions (CMaterialR tid ssh csh mnm MShowR) = return { navLink = NavLink { navLabel = MsgMenuMaterialDelete , navRoute = CMaterialR tid ssh csh mnm MDelR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -1585,7 +1751,7 @@ pageActions (CourseR tid ssh csh CTutorialListR) = return { navLink = NavLink { navLabel = MsgMenuTutorialNew , navRoute = CourseR tid ssh csh CTutorialNewR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -1598,7 +1764,7 @@ pageActions (CTutorialR tid ssh csh tutn TEditR) = return { navLink = NavLink { navLabel = MsgMenuTutorialDelete , navRoute = CTutorialR tid ssh csh tutn TDeleteR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1610,7 +1776,7 @@ pageActions (CTutorialR tid ssh csh tutn TUsersR) = return { navLink = NavLink { navLabel = MsgMenuTutorialComm , navRoute = CTutorialR tid ssh csh tutn TCommR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1621,7 +1787,7 @@ pageActions (CTutorialR tid ssh csh tutn TUsersR) = return { navLink = NavLink { navLabel = MsgMenuTutorialEdit , navRoute = CTutorialR tid ssh csh tutn TEditR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1632,7 +1798,7 @@ pageActions (CTutorialR tid ssh csh tutn TUsersR) = return { navLink = NavLink { navLabel = MsgMenuTutorialDelete , navRoute = CTutorialR tid ssh csh tutn TDeleteR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1644,7 +1810,7 @@ pageActions (CourseR tid ssh csh CExamListR) = return { navLink = NavLink { navLabel = MsgMenuExamNew , navRoute = CourseR tid ssh csh CExamNewR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -1660,7 +1826,7 @@ pageActions (CExamR tid ssh csh examn EShowR) = do { navLink = NavLink { navLabel = MsgMenuExamEdit , navRoute = CExamR tid ssh csh examn EEditR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1671,7 +1837,7 @@ pageActions (CExamR tid ssh csh examn EShowR) = do { navLink = NavLink { navLabel = MsgMenuExamUsers , navRoute = CExamR tid ssh csh examn EUsersR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1682,7 +1848,7 @@ pageActions (CExamR tid ssh csh examn EShowR) = do { navLink = NavLink { navLabel = MsgMenuExamGrades , navRoute = CExamR tid ssh csh examn EGradesR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1693,7 +1859,7 @@ pageActions (CExamR tid ssh csh examn EShowR) = do { navLink = NavLink { navLabel = MsgMenuExamCorrect , navRoute = CExamR tid ssh csh examn ECorrectR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1706,7 +1872,7 @@ pageActions (CExamR tid ssh csh examn ECorrectR) = return { navLink = NavLink { navLabel = MsgMenuExamUsers , navRoute = CExamR tid ssh csh examn EUsersR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1717,7 +1883,7 @@ pageActions (CExamR tid ssh csh examn ECorrectR) = return { navLink = NavLink { navLabel = MsgMenuExamGrades , navRoute = CExamR tid ssh csh examn EGradesR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1728,7 +1894,7 @@ pageActions (CExamR tid ssh csh examn ECorrectR) = return { navLink = NavLink { navLabel = MsgMenuExamEdit , navRoute = CExamR tid ssh csh examn EEditR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1740,7 +1906,7 @@ pageActions (CExamR tid ssh csh examn EUsersR) = return { navLink = NavLink { navLabel = MsgMenuExamAddMembers , navRoute = CExamR tid ssh csh examn EAddUserR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -1751,7 +1917,7 @@ pageActions (CExamR tid ssh csh examn EUsersR) = return { navLink = NavLink { navLabel = MsgMenuExamGrades , navRoute = CExamR tid ssh csh examn EGradesR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1762,7 +1928,7 @@ pageActions (CExamR tid ssh csh examn EUsersR) = return { navLink = NavLink { navLabel = MsgMenuExamCorrect , navRoute = CExamR tid ssh csh examn ECorrectR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1775,7 +1941,7 @@ pageActions (CExamR tid ssh csh examn EGradesR) = return { navLink = NavLink { navLabel = MsgMenuExamUsers , navRoute = CExamR tid ssh csh examn EUsersR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -1786,7 +1952,7 @@ pageActions (CExamR tid ssh csh examn EGradesR) = return { navLink = NavLink { navLabel = MsgMenuExamCorrect , navRoute = CExamR tid ssh csh examn ECorrectR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1801,7 +1967,7 @@ pageActions (CSheetR tid ssh csh shn SShowR) = do { navLink = NavLink { navLabel = MsgMenuSubmissions , navRoute = CSheetR tid ssh csh shn SSubsR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1815,12 +1981,11 @@ pageActions (CSheetR tid ssh csh shn SShowR) = do { navLink = NavLink { navLabel = MsgMenuSubmissionOwn , navRoute = CSheetR tid ssh csh shn SubmissionOwnR - , navAccess' = - runDBRead . maybeT (return False) $ do - uid <- MaybeT $ liftHandler maybeAuthId - submissions <- lift $ submissionList tid csh shn uid - guard . not $ null submissions - return True + , navAccess' = NavAccessDB . maybeT (return False) $ do + uid <- MaybeT $ liftHandler maybeAuthId + submissions <- lift $ submissionList tid csh shn uid + guard . not $ null submissions + return True , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1833,7 +1998,7 @@ pageActions (CSheetR tid ssh csh shn SShowR) = do { navLink = NavLink { navLabel = MsgMenuSheetPersonalisedFiles , navRoute = CSheetR tid ssh csh shn SPersonalFilesR - , navAccess' = + , navAccess' = NavAccessDB $ let onlyPersonalised = fmap (maybe False $ not . E.unValue) . E.selectMaybe . E.from $ \(sheet `E.InnerJoin` course) -> do E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId E.where_$ sheet E.^. SheetName E.==. E.val shn @@ -1848,7 +2013,7 @@ pageActions (CSheetR tid ssh csh shn SShowR) = do E.&&. course E.^. CourseTerm E.==. E.val tid E.&&. course E.^. CourseSchool E.==. E.val ssh E.&&. course E.^. CourseShorthand E.==. E.val csh - in runDBRead $ or2M onlyPersonalised hasPersonalised + in or2M onlyPersonalised hasPersonalised , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -1859,7 +2024,7 @@ pageActions (CSheetR tid ssh csh shn SShowR) = do { navLink = NavLink { navLabel = MsgMenuSheetEdit , navRoute = CSheetR tid ssh csh shn SEditR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1870,7 +2035,7 @@ pageActions (CSheetR tid ssh csh shn SShowR) = do { navLink = NavLink { navLabel = MsgMenuSheetClone , navRoute = (CourseR tid ssh csh SheetNewR, [("shn", toPathPiece shn)]) - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1880,7 +2045,7 @@ pageActions (CSheetR tid ssh csh shn SShowR) = do { navLink = NavLink { navLabel = MsgMenuSheetDelete , navRoute = CSheetR tid ssh csh shn SDelR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1892,14 +2057,14 @@ pageActions (CSheetR tid ssh csh shn SSubsR) = return { navLink = NavLink { navLabel = MsgMenuSubmissionNew , navRoute = CSheetR tid ssh csh shn SubmissionNewR - , navAccess' = + , navAccess' = NavAccessDB $ let submissionAccess = hasWriteAccessTo $ CSheetR tid ssh csh shn SSubsR hasNoSubmission = maybeT (return False) $ do uid <- MaybeT $ liftHandler maybeAuthId submissions <- lift $ submissionList tid csh shn uid guard $ null submissions return True - in runDBRead $ hasNoSubmission `or2M` submissionAccess + in hasNoSubmission `or2M` submissionAccess , navType = NavTypeLink { navModal = True } , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -1916,7 +2081,7 @@ pageActions (CSheetR tid ssh csh shn SSubsR) = return , ("corrections-sheet", toPathPiece shn) ] ) - , navAccess' = (== Authorized) <$> evalAccessCorrector tid ssh csh + , navAccess' = NavAccessDB $ (== Authorized) <$> evalAccessCorrector tid ssh csh , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -1927,7 +2092,7 @@ pageActions (CSheetR tid ssh csh shn SSubsR) = return { navLink = NavLink { navLabel = MsgMenuCorrectionsAssign , navRoute = CSheetR tid ssh csh shn SAssignR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -1940,7 +2105,7 @@ pageActions (CSubmissionR tid ssh csh shn cid SubShowR) = return { navLink = NavLink { navLabel = MsgMenuCorrection , navRoute = CSubmissionR tid ssh csh shn cid CorrectionR - , navAccess' = hasWriteAccessTo $ CSubmissionR tid ssh csh shn cid CorrectionR + , navAccess' = NavAccessDB . hasWriteAccessTo $ CSubmissionR tid ssh csh shn cid CorrectionR , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1951,7 +2116,7 @@ pageActions (CSubmissionR tid ssh csh shn cid SubShowR) = return { navLink = NavLink { navLabel = MsgCorrectorAssignTitle , navRoute = CSubmissionR tid ssh csh shn cid SubAssignR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -1962,7 +2127,7 @@ pageActions (CSubmissionR tid ssh csh shn cid SubShowR) = return { navLink = NavLink { navLabel = MsgMenuSubmissionDelete , navRoute = CSubmissionR tid ssh csh shn cid SubDelR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1974,7 +2139,7 @@ pageActions (CSubmissionR tid ssh csh shn cid CorrectionR) = return { navLink = NavLink { navLabel = MsgCorrectorAssignTitle , navRoute = CSubmissionR tid ssh csh shn cid SubAssignR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -1985,7 +2150,7 @@ pageActions (CSubmissionR tid ssh csh shn cid CorrectionR) = return { navLink = NavLink { navLabel = MsgMenuSubmissionDelete , navRoute = CSubmissionR tid ssh csh shn cid SubDelR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -1997,7 +2162,7 @@ pageActions (CourseR tid ssh csh CApplicationsR) = return { navLink = NavLink { navLabel = MsgMenuCourseApplicationsFiles , navRoute = CourseR tid ssh csh CAppsFilesR - , navAccess' = + , navAccess' = NavAccessDB $ let appAccess (E.Value appId) = do cID <- encrypt appId hasReadAccessTo $ CApplicationR tid ssh csh cID CAFilesR @@ -2009,7 +2174,7 @@ pageActions (CourseR tid ssh csh CApplicationsR) = return E.where_ . E.exists . E.from $ \courseApplicationFile -> E.where_ $ courseApplicationFile E.^. CourseApplicationFileApplication E.==. courseApplication E.^. CourseApplicationId return $ courseApplication E.^. CourseApplicationId - in runDBRead . runConduit $ appSource .| anyMC appAccess + in runConduit $ appSource .| anyMC appAccess , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2020,10 +2185,9 @@ pageActions (CourseR tid ssh csh CApplicationsR) = return { navLink = NavLink { navLabel = MsgMenuCourseMembers , navRoute = CourseR tid ssh csh CUsersR - , navAccess' = - runDBRead $ do - cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh - exists [ CourseParticipantCourse ==. cid ] + , navAccess' = NavAccessDB $ do + cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh + exists [ CourseParticipantCourse ==. cid ] , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2036,7 +2200,7 @@ pageActions CorrectionsR = return { navLink = NavLink { navLabel = MsgMenuCorrectionsDownload , navRoute = CorrectionsDownloadR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -2047,7 +2211,7 @@ pageActions CorrectionsR = return { navLink = NavLink { navLabel = MsgMenuCorrectionsUpload , navRoute = CorrectionsUploadR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -2058,7 +2222,7 @@ pageActions CorrectionsR = return { navLink = NavLink { navLabel = MsgMenuCorrectionsCreate , navRoute = CorrectionsCreateR - , navAccess' = runDBRead . maybeT (return False) $ do + , navAccess' = NavAccessDB . maybeT (return False) $ do uid <- MaybeT $ liftHandler maybeAuthId sheets <- lift . E.select . E.from $ \(course `E.InnerJoin` sheet) -> do E.on $ course E.^. CourseId E.==. sheet E.^. SheetCourse @@ -2082,7 +2246,7 @@ pageActions CorrectionsR = return { navLink = NavLink { navLabel = MsgMenuCorrectionsGrade , navRoute = CorrectionsGradeR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2097,7 +2261,7 @@ pageActions CorrectionsGradeR = do { navLink = NavLink { navLabel = MsgMenuCorrections , navRoute = CorrectionsR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2110,7 +2274,7 @@ pageActions EExamListR = return { navLink = NavLink { navLabel = MsgMenuExternalExamNew , navRoute = EExamNewR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2123,7 +2287,7 @@ pageActions (EExamR tid ssh coursen examn EEShowR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamEdit , navRoute = EExamR tid ssh coursen examn EEEditR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2134,7 +2298,7 @@ pageActions (EExamR tid ssh coursen examn EEShowR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamUsers , navRoute = EExamR tid ssh coursen examn EEUsersR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2145,7 +2309,7 @@ pageActions (EExamR tid ssh coursen examn EEShowR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamGrades , navRoute = EExamR tid ssh coursen examn EEGradesR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2156,7 +2320,7 @@ pageActions (EExamR tid ssh coursen examn EEShowR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamCorrect , navRoute = EExamR tid ssh coursen examn EECorrectR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2169,7 +2333,7 @@ pageActions (EExamR tid ssh coursen examn EEGradesR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamCorrect , navRoute = EExamR tid ssh coursen examn EECorrectR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2180,7 +2344,7 @@ pageActions (EExamR tid ssh coursen examn EEGradesR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamUsers , navRoute = EExamR tid ssh coursen examn EEUsersR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2191,7 +2355,7 @@ pageActions (EExamR tid ssh coursen examn EEGradesR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamEdit , navRoute = EExamR tid ssh coursen examn EEEditR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2204,7 +2368,7 @@ pageActions (EExamR tid ssh coursen examn EECorrectR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamGrades , navRoute = EExamR tid ssh coursen examn EEGradesR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2215,7 +2379,7 @@ pageActions (EExamR tid ssh coursen examn EECorrectR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamUsers , navRoute = EExamR tid ssh coursen examn EEUsersR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2226,7 +2390,7 @@ pageActions (EExamR tid ssh coursen examn EECorrectR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamEdit , navRoute = EExamR tid ssh coursen examn EEEditR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2239,7 +2403,7 @@ pageActions (EExamR tid ssh coursen examn EEUsersR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamGrades , navRoute = EExamR tid ssh coursen examn EEGradesR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2250,7 +2414,7 @@ pageActions (EExamR tid ssh coursen examn EEUsersR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamCorrect , navRoute = EExamR tid ssh coursen examn EECorrectR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2261,7 +2425,7 @@ pageActions (EExamR tid ssh coursen examn EEUsersR) = return { navLink = NavLink { navLabel = MsgMenuExternalExamEdit , navRoute = EExamR tid ssh coursen examn EEEditR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } , navQuick' = mempty , navForceActive = False @@ -2274,7 +2438,7 @@ pageActions ParticipantsListR = return { navLink = NavLink { navLabel = MsgCsvOptions , navRoute = CsvOptionsR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = True } , navQuick' = mempty , navForceActive = False @@ -2286,7 +2450,7 @@ pageActions ParticipantsListR = return { navLink = NavLink { navLabel = MsgMenuParticipantsIntersect , navRoute = ParticipantsIntersectR - , navAccess' = return True + , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False} , navQuick' = navQuick NavQuickViewPageActionSecondary , navForceActive = False @@ -2294,6 +2458,148 @@ pageActions ParticipantsListR = return , navChildren = [] } ] +pageActions AdminWorkflowDefinitionListR = return + [ NavPageActionPrimary + { navLink = NavLink + { navLabel = MsgMenuAdminWorkflowDefinitionNew + , navRoute = AdminWorkflowDefinitionNewR + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + , navChildren = [] + } + , NavPageActionPrimary + { navLink = NavLink + { navLabel = MsgMenuAdminWorkflowInstanceList + , navRoute = AdminWorkflowInstanceListR + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + , navChildren = [] + } + ] +pageActions (AdminWorkflowDefinitionR wds wdn AWDEditR) = return + [ NavPageActionSecondary + { navLink = NavLink + { navLabel = MsgMenuAdminWorkflowDefinitionDelete + , navRoute = AdminWorkflowDefinitionR wds wdn AWDDeleteR + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = True } + , navQuick' = mempty + , navForceActive = False + } + } + , NavPageActionPrimary + { navLink = NavLink + { navLabel = MsgMenuAdminWorkflowDefinitionInstantiate + , navRoute = AdminWorkflowDefinitionR wds wdn AWDInstantiateR + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = True } + , navQuick' = mempty + , navForceActive = False + } + , navChildren = [] + } + ] +pageActions AdminWorkflowInstanceListR = return + [ NavPageActionPrimary + { navLink = NavLink + { navLabel = MsgMenuAdminWorkflowInstanceNew + , navRoute = AdminWorkflowInstanceNewR + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + , navChildren = [] + } + ] +pageActions route | Just (rScope, WorkflowInstanceListR) <- route ^? _WorkflowScopeRoute = return + [ NavPageActionPrimary + { navLink = NavLink + { navLabel = MsgMenuWorkflowWorkflowList + , navRoute = _WorkflowScopeRoute # (rScope, WorkflowWorkflowListR) + , navAccess' = NavAccessDB $ haveWorkflowWorkflows rScope + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + , navChildren = [] + } + ] +pageActions route | Just (rScope, WorkflowInstanceR win WIEditR) <- route ^? _WorkflowScopeRoute = return + [ NavPageActionSecondary + { navLink = NavLink + { navLabel = MsgMenuWorkflowInstanceDelete + , navRoute = _WorkflowScopeRoute # (rScope, WorkflowInstanceR win WIDeleteR) + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + } + , NavPageActionPrimary + { navLink = NavLink + { navLabel = MsgMenuWorkflowInstanceWorkflows + , navRoute = _WorkflowScopeRoute # (rScope, WorkflowInstanceR win WIWorkflowsR) + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + , navChildren = [] + } + , NavPageActionPrimary + { navLink = NavLink + { navLabel = MsgMenuWorkflowInstanceInitiate + , navRoute = _WorkflowScopeRoute # (rScope, WorkflowInstanceR win WIInitiateR) + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + , navChildren = [] + } + ] +pageActions route | Just (rScope, WorkflowWorkflowR cID WWWorkflowR) <- route ^? _WorkflowScopeRoute = return + [ NavPageActionSecondary + { navLink = NavLink + { navLabel = MsgMenuWorkflowWorkflowEdit + , navRoute = _WorkflowScopeRoute # (rScope, WorkflowWorkflowR cID WWEditR) + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + } + , NavPageActionSecondary + { navLink = NavLink + { navLabel = MsgMenuWorkflowWorkflowDelete + , navRoute = _WorkflowScopeRoute # (rScope, WorkflowWorkflowR cID WWDeleteR) + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + } + ] +pageActions TopWorkflowInstanceListR = return + [ NavPageActionPrimary + { navLink = NavLink + { navLabel = MsgMenuTopWorkflowWorkflowList + , navRoute = TopWorkflowWorkflowListR + , navAccess' = NavAccessDB haveTopWorkflowWorkflows + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + , navChildren = [] + } + ] pageActions _ = return [] submissionList :: ( MonadIO m @@ -2313,9 +2619,10 @@ submissionList tid csh shn uid = withReaderT (projectBackend @SqlReadBackend) . return $ submission E.^. SubmissionId -pageQuickActions :: ( MonadCatch m +pageQuickActions :: ( MonadCatch m, MonadUnliftIO m , MonadHandler m , HandlerSite m ~ UniWorX + , WithRunDB SqlReadBackend (HandlerFor UniWorX) m , BearerAuthSite UniWorX ) => NavQuickView -> Route UniWorX -> m [NavLink] @@ -2325,7 +2632,112 @@ pageQuickActions qView route = do filterM navLinkAccess $ items' ^.. typesUsing @NavChildren @NavLink . filtered (getAny . ($ qView) . navQuick') -- | Verify that the currently logged in user is lecturer or corrector for at least one sheet for the given course -evalAccessCorrector - :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BearerAuthSite UniWorX) - => TermId -> SchoolId -> CourseShorthand -> m AuthResult +evalAccessCorrector :: (MonadAP m, MonadThrow m) => TermId -> SchoolId -> CourseShorthand -> m AuthResult evalAccessCorrector tid ssh csh = evalAccess (CourseR tid ssh csh CNotesR) False + + +haveWorkflowWorkflows + :: ( MonadHandler m, HandlerSite m ~ UniWorX + , BackendCompatible SqlReadBackend backend + , BearerAuthSite UniWorX + ) + => RouteWorkflowScope + -> ReaderT backend m Bool +haveWorkflowWorkflows rScope = hoist liftHandler . withReaderT (projectBackend @SqlReadBackend) . $cachedHereBinary rScope . maybeT (return False) $ do + roles <- memcachedBy (Just $ Right diffDay) (NavCacheHaveWorkflowWorkflowsRoles rScope) $ do + scope <- fromRouteWorkflowScope rScope + + let + getWorkflows = E.selectSource . E.from $ \workflowWorkflow -> do + E.where_ $ workflowWorkflow E.^. WorkflowWorkflowScope E.==. E.val (scope ^. _DBWorkflowScope) + return workflowWorkflow + workflowRoles (Entity wwId WorkflowWorkflow{..}) = do + wwGraph <- lift $ getSharedIdWorkflowGraph workflowWorkflowGraph + let + nodeViewers = do + WorkflowAction{..} <- otoList workflowWorkflowState + (node, WGN{..}) <- itoListOf (_wgNodes . ifolded) wwGraph + guard $ node == wpTo + WorkflowNodeView{..} <- hoistMaybe wgnViewers + return $ toNullable wnvViewers + payloadViewers = do + (prevActs, act) <- zip (inits $ otoList workflowWorkflowState) $ otoList workflowWorkflowState + prevAct <- hoistMaybe $ prevActs ^? _last + payload <- Map.keys $ wpPayload act + guard $ Map.lookup payload (workflowStateCurrentPayloads prevActs) /= Map.lookup payload (wpPayload act) + fmap (toNullable . wpvViewers) . hoistMaybe $ Map.lookup payload . wgnPayloadView =<< Map.lookup (wpTo prevAct) (wgNodes wwGraph) + + cID <- encrypt wwId + return . Set.mapMonotonic ((wwId, cID), ) $ fold nodeViewers <> fold payloadViewers + + runConduit $ transPipe lift getWorkflows .| C.foldMapM workflowRoles + + let + evalRole ((wwId, cID), role) = do + let route = _WorkflowScopeRoute # (rScope, WorkflowWorkflowR cID WWWorkflowR) + is _Authorized <$> hasWorkflowRole (Just wwId) role route False + + lift $ anyM roles evalRole + +haveTopWorkflowInstances, haveTopWorkflowWorkflows + :: ( MonadHandler m, HandlerSite m ~ UniWorX + , BackendCompatible SqlReadBackend backend + , BearerAuthSite UniWorX + ) + => ReaderT backend m Bool +haveTopWorkflowInstances = hoist liftHandler . withReaderT (projectBackend @SqlReadBackend) . $cachedHere . maybeT (return False) $ do + roles <- memcachedBy (Just $ Right diffDay) NavCacheHaveTopWorkflowInstancesRoles $ do + let + getInstances = E.selectSource . E.from $ \workflowInstance -> do + E.where_ . isTopWorkflowScopeSql $ workflowInstance E.^. WorkflowInstanceScope + return workflowInstance + instanceRoles (Entity _ WorkflowInstance{..}) = do + rScope <- toRouteWorkflowScope $ _DBWorkflowScope # workflowInstanceScope + wiGraph <- lift $ getSharedIdWorkflowGraph workflowInstanceGraph + return . Set.mapMonotonic ((rScope, workflowInstanceName), ) . fold $ do + WGN{..} <- wiGraph ^.. _wgNodes . folded + WorkflowGraphEdgeInitial{..} <- wgnEdges ^.. folded + return wgeActors + runConduit $ transPipe lift getInstances .| C.foldMapM instanceRoles + + let + evalRole :: _ -> ReaderT SqlReadBackend (HandlerFor UniWorX) Bool + evalRole ((rScope, win), role) = do + let route = _WorkflowScopeRoute # (rScope, WorkflowInstanceR win WIInitiateR) + is _Authorized <$> hasWorkflowRole Nothing role route False + + lift $ anyM roles evalRole +haveTopWorkflowWorkflows = hoist liftHandler . withReaderT (projectBackend @SqlReadBackend) . $cachedHere . maybeT (return False) $ do + roles <- memcachedBy (Just $ Right diffDay) NavCacheHaveTopWorkflowWorkflowsRoles $ do + let + getWorkflows = E.selectSource . E.from $ \workflowWorkflow -> do + E.where_ . isTopWorkflowScopeSql $ workflowWorkflow E.^. WorkflowWorkflowScope + return workflowWorkflow + workflowRoles (Entity wwId WorkflowWorkflow{..}) = do + wwGraph <- lift $ getSharedIdWorkflowGraph workflowWorkflowGraph + rScope <- toRouteWorkflowScope $ _DBWorkflowScope # workflowWorkflowScope + let + nodeViewers = do + WorkflowAction{..} <- otoList workflowWorkflowState + (node, WGN{..}) <- itoListOf (_wgNodes . ifolded) wwGraph + guard $ node == wpTo + WorkflowNodeView{..} <- hoistMaybe wgnViewers + return $ toNullable wnvViewers + payloadViewers = do + (prevActs, act) <- zip (inits $ otoList workflowWorkflowState) $ otoList workflowWorkflowState + prevAct <- hoistMaybe $ prevActs ^? _last + payload <- Map.keys $ wpPayload act + guard $ Map.lookup payload (workflowStateCurrentPayloads prevActs) /= Map.lookup payload (wpPayload act) + fmap (toNullable . wpvViewers) . hoistMaybe $ Map.lookup payload . wgnPayloadView =<< Map.lookup (wpTo prevAct) (wgNodes wwGraph) + + cID <- encrypt wwId + return . Set.mapMonotonic ((wwId, cID, rScope), ) $ fold nodeViewers <> fold payloadViewers + runConduit $ transPipe lift getWorkflows .| C.foldMapM workflowRoles + + let + evalRole :: _ -> ReaderT SqlReadBackend (HandlerFor UniWorX) Bool + evalRole ((wwId, cID, rScope), role) = do + let route = _WorkflowScopeRoute # (rScope, WorkflowWorkflowR cID WWWorkflowR) + is _Authorized <$> hasWorkflowRole (Just wwId) role route False + + lift $ anyM roles evalRole diff --git a/src/Foundation/Routes.hs b/src/Foundation/Routes.hs index d2dc89459..bb5dc51eb 100644 --- a/src/Foundation/Routes.hs +++ b/src/Foundation/Routes.hs @@ -38,6 +38,12 @@ deriving instance Generic SchoolR deriving instance Generic ExamOfficeR deriving instance Generic CourseNewsR deriving instance Generic CourseEventR +deriving instance Generic AdminWorkflowDefinitionR +deriving instance Generic AdminWorkflowInstanceR +deriving instance Generic GlobalWorkflowInstanceR +deriving instance Generic GlobalWorkflowWorkflowR +deriving instance Generic SchoolWorkflowInstanceR +deriving instance Generic SchoolWorkflowWorkflowR deriving instance Generic (Route UniWorX) instance Ord (Route Auth) where @@ -58,6 +64,12 @@ deriving instance Ord SchoolR deriving instance Ord ExamOfficeR deriving instance Ord CourseNewsR deriving instance Ord CourseEventR +deriving instance Ord AdminWorkflowDefinitionR +deriving instance Ord AdminWorkflowInstanceR +deriving instance Ord GlobalWorkflowInstanceR +deriving instance Ord GlobalWorkflowWorkflowR +deriving instance Ord SchoolWorkflowInstanceR +deriving instance Ord SchoolWorkflowWorkflowR deriving instance Ord (Route UniWorX) data RouteChildren diff --git a/src/Foundation/SiteLayout.hs b/src/Foundation/SiteLayout.hs index 9f151bca7..255a131db 100644 --- a/src/Foundation/SiteLayout.hs +++ b/src/Foundation/SiteLayout.hs @@ -1,19 +1,22 @@ {-# LANGUAGE UndecidableInstances #-} -- for `MemcachedKeyFavourites` +{-# OPTIONS_GHC -fprof-auto #-} module Foundation.SiteLayout ( siteLayout', siteLayout , siteLayoutMsg', siteLayoutMsg , getSystemMessageState + , storedFavouriteReason ) where -import Import.NoFoundation hiding (embedFile) +import Import.NoFoundation hiding (embedFile, runDB) import Foundation.Type import Foundation.Authorization import Foundation.Routes import Foundation.Navigation import Foundation.I18n -import Foundation.DB +import Foundation.Yesod.Persist +import Foundation.Instances.ButtonClass import Utils.SystemMessage import Utils.Form @@ -36,9 +39,64 @@ import Text.Cassius (cassiusFile) import Text.Hamlet (hamletFile) import Data.FileEmbed (embedFile) +data CourseFavouriteToggleButton + = BtnCourseFavouriteToggleManual + | BtnCourseFavouriteToggleAutomatic + | BtnCourseFavouriteToggleOff + deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, Typeable) + deriving anyclass (Universe, Finite) + +nullaryPathPiece ''CourseFavouriteToggleButton $ camelToPathPiece' 4 + +instance Button UniWorX CourseFavouriteToggleButton where + btnLabel BtnCourseFavouriteToggleManual + = toWidget $ iconFixed IconCourseFavouriteManual + btnLabel BtnCourseFavouriteToggleAutomatic + = toWidget $ iconFixed IconCourseFavouriteAutomatic + btnLabel BtnCourseFavouriteToggleOff + = toWidget $ iconStacked IconCourseFavouriteManual IconCourseFavouriteOff + + btnClasses _ = [BCIsButton, BCLink] + +-- inspired by examAutoOccurrenceIgnoreRoomsForm +courseFavouriteToggleForm :: Maybe FavouriteReason -> Form () +courseFavouriteToggleForm currentReason html + = over _1 void <$> identifyForm FIDCourseFavouriteToggle (buttonForm' [btn]) html + where + btn :: CourseFavouriteToggleButton + btn = case currentReason of + Nothing -> BtnCourseFavouriteToggleOff + (Just FavouriteVisited) -> BtnCourseFavouriteToggleAutomatic + (Just FavouriteParticipant) -> BtnCourseFavouriteToggleAutomatic + (Just FavouriteManual) -> BtnCourseFavouriteToggleManual + (Just FavouriteCurrent) -> BtnCourseFavouriteToggleAutomatic + +-- (storedReason, isBlacklist) +-- Will never return FavouriteCurrent +-- Nothing if no entry for current user (e.g. not logged in) +storedFavouriteReason :: (MonadIO m, BearerAuthSite UniWorX) => TermId -> SchoolId -> CourseShorthand -> Maybe (AuthId UniWorX, AuthEntity UniWorX) + -> ReaderT SqlBackend m (Maybe (Maybe FavouriteReason, Bool)) +storedFavouriteReason tid ssh csh muid = fmap unValueFirst . E.select . E.from $ \(course `E.LeftOuterJoin` courseFavourite) -> do + E.on $ E.just (course E.^. CourseId) E.==. courseFavourite E.?. CourseFavouriteCourse + E.&&. courseFavourite E.?. CourseFavouriteUser E.==. E.val (view _1 <$> muid) + E.where_ $ course E.^. CourseTerm E.==. E.val tid + E.&&. course E.^. CourseSchool E.==. E.val ssh + E.&&. course E.^. CourseShorthand E.==. E.val csh + E.limit 1 -- we know that there is at most one match, but we tell the DB this info too + let isBlacklist = E.exists . E.from $ \courseNoFavourite -> + E.where_ $ E.just (courseNoFavourite E.^. CourseNoFavouriteUser) E.==. E.val (view _1 <$> muid) + E.&&. courseNoFavourite E.^. CourseNoFavouriteCourse E.==. course E.^. CourseId + reason :: (E.SqlExpr (E.Value (Maybe FavouriteReason)), E.SqlExpr (E.Value Bool)) + reason = (courseFavourite E.?. CourseFavouriteReason, isBlacklist) + pure reason + where + unValueFirst :: [(E.Value (Maybe a), E.Value Bool)] -> Maybe (Maybe a, Bool) + -- `over each E.unValue` doesn't work here, since E.unValue is monomorphised + unValueFirst = fmap (bimap E.unValue E.unValue) . listToMaybe + data MemcachedKeyFavourites - = MemcachedKeyFavouriteQuickActions CourseId AuthContext (NonEmpty Lang) + = MemcachedKeyFavouriteQuickActions (TermId, SchoolId, CourseShorthand) AuthContext (NonEmpty Lang) deriving (Generic, Typeable) deriving instance Eq AuthContext => Eq MemcachedKeyFavourites @@ -53,24 +111,22 @@ data MemcachedLimitKeyFavourites deriving anyclass (Hashable, Binary) -siteLayoutMsg :: (RenderMessage site msg, site ~ UniWorX, BearerAuthSite UniWorX, BackendCompatible SqlBackend (YesodPersistBackend UniWorX), Button UniWorX ButtonSubmit) => msg -> WidgetFor UniWorX () -> HandlerFor UniWorX Html +siteLayoutMsg :: (RenderMessage site msg, site ~ UniWorX, BearerAuthSite UniWorX, YesodPersistBackend UniWorX ~ SqlBackend) => msg -> WidgetFor UniWorX () -> HandlerFor UniWorX Html siteLayoutMsg = siteLayout . i18n {-# DEPRECATED siteLayoutMsg' "Use siteLayoutMsg" #-} -siteLayoutMsg' :: (RenderMessage site msg, site ~ UniWorX, BearerAuthSite UniWorX, BackendCompatible SqlBackend (YesodPersistBackend UniWorX), Button UniWorX ButtonSubmit) => msg -> WidgetFor UniWorX () -> HandlerFor UniWorX Html +siteLayoutMsg' :: (RenderMessage site msg, site ~ UniWorX, BearerAuthSite UniWorX, YesodPersistBackend UniWorX ~ SqlBackend) => msg -> WidgetFor UniWorX () -> HandlerFor UniWorX Html siteLayoutMsg' = siteLayoutMsg siteLayout :: ( BearerAuthSite UniWorX - , BackendCompatible SqlBackend (YesodPersistBackend UniWorX) - , Button UniWorX ButtonSubmit + , YesodPersistBackend UniWorX ~ SqlBackend ) => WidgetFor UniWorX () -- ^ `pageHeading` -> WidgetFor UniWorX () -> HandlerFor UniWorX Html siteLayout = siteLayout' . Just siteLayout' :: ( BearerAuthSite UniWorX - , BackendCompatible SqlBackend (YesodPersistBackend UniWorX) - , Button UniWorX ButtonSubmit + , YesodPersistBackend UniWorX ~ SqlBackend ) => Maybe (WidgetFor UniWorX ()) -- ^ `pageHeading` -> WidgetFor UniWorX () -> HandlerFor UniWorX Html @@ -86,24 +142,6 @@ siteLayout' overrideHeading widget = do currentApproot' <- siteApproot <$> getYesod <*> (reqWaiRequest <$> getRequest) - -- Get the breadcrumbs, as defined in the YesodBreadcrumbs instance. - let - breadcrumbs' mcRoute = do - mr <- getMessageRender - case mcRoute of - Nothing -> return (mr MsgErrorResponseTitleNotFound, []) - Just cRoute -> do - (title, next) <- breadcrumb cRoute - crumbs <- go [] next - return (title, crumbs) - where - go crumbs Nothing = return crumbs - go crumbs (Just cRoute) = do - hasAccess <- hasReadAccessTo cRoute - (title, next) <- breadcrumb cRoute - go ((cRoute, title, hasAccess) : crumbs) next - (title, parents) <- breadcrumbs' mcurrentRoute - -- let isParent :: Route UniWorX -> Bool -- isParent r = r == (fst parents) @@ -111,11 +149,12 @@ siteLayout' overrideHeading widget = do now <- liftIO getCurrentTime - -- Lookup Favourites & Theme if possible - (favourites', maxFavouriteTerms, currentTheme) <- do - muid <- maybeAuthPair + muid <- maybeAuthPair + -- Lookup Favourites, Breadcrumbs, Headline, & Theme if possible + (favourites', (title, parents), nav', contentHeadline, mmsgs, maxFavouriteTerms, currentTheme, storedReasonAndToggleRoute) <- do - favCourses'' <- runDBRead . E.select . E.from $ \(course `E.LeftOuterJoin` courseFavourite) -> do + (favCourses, breadcrumbs'', nav', contentHeadline, mmsgs, storedReasonAndToggleRoute) <- runDB $ do + favCourses'' <- withReaderT (projectBackend @SqlReadBackend) . E.select . E.from $ \(course `E.LeftOuterJoin` courseFavourite) -> do E.on $ E.just (course E.^. CourseId) E.==. courseFavourite E.?. CourseFavouriteCourse E.&&. courseFavourite E.?. CourseFavouriteUser E.==. E.val (view _1 <$> muid) @@ -155,62 +194,130 @@ siteLayout' overrideHeading widget = do E.where_ $ ((isFavourite E.||. isAssociated) E.&&. notBlacklist) E.||. isCurrent - return (course, reason, courseVisible) + return ( ( course E.^. CourseName + , course E.^. CourseTerm + , course E.^. CourseSchool + , course E.^. CourseShorthand + ) + , reason + , courseVisible + ) - favCourses' <- forM favCourses'' $ \(course@(Entity _ Course{..}), reason, E.Value courseVisible) -> do - mayView <- hasReadAccessTo $ CourseR courseTerm courseSchool courseShorthand CShowR - mayEdit <- hasWriteAccessTo $ CourseR courseTerm courseSchool courseShorthand CEditR - return (course, reason, courseVisible, mayView, mayEdit) + favCourses' <- withReaderT (projectBackend @SqlReadBackend) . forM favCourses'' $ \((E.Value cName, E.Value tid, E.Value ssh, E.Value csh), reason, E.Value courseVisible) -> do + mayView <- hasReadAccessTo $ CourseR tid ssh csh CShowR + mayEdit <- hasWriteAccessTo $ CourseR tid ssh csh CEditR + return ((cName, tid, ssh, csh), reason, courseVisible, mayView, mayEdit) let favCourses = favCourses' & filter (\(_, _, _, mayView, _) -> mayView) - return ( favCourses - , maybe userDefaultMaxFavouriteTerms userMaxFavouriteTerms $ view _2 <$> muid - , maybe userDefaultTheme userTheme $ view _2 <$> muid - ) + breadcrumbs'' + <- let breadcrumbs' mcRoute = do + mr <- getMessageRender + case mcRoute of + Nothing -> return (mr MsgErrorResponseTitleNotFound, []) + Just cRoute -> do + (title, next) <- breadcrumb cRoute + crumbs <- go [] next + return (title, crumbs) + where + go crumbs Nothing = return crumbs + go crumbs (Just cRoute) = do + hasAccess <- hasReadAccessTo cRoute + (title, next) <- breadcrumb cRoute + go ((cRoute, title, hasAccess) : crumbs) next + in withReaderT (projectBackend @SqlReadBackend) $ breadcrumbs' mcurrentRoute + + nav'' <- withReaderT (projectBackend @SqlReadBackend) $ mconcat <$> sequence + [ defaultLinks + , maybe (return []) pageActions mcurrentRoute + ] + nav' <- withReaderT (projectBackend @SqlReadBackend) $ catMaybes <$> mapM (runMaybeT . navAccess) nav'' + + -- contentHeadline :: Maybe (WidgetFor UniWorX ()) + contentHeadline <- withReaderT (projectBackend @SqlReadBackend) . runMaybeT $ hoistMaybe overrideHeading <|> (pageHeading =<< hoistMaybe mcurrentRoute) + + mmsgs <- if + | isModal -> return mempty + | otherwise -> do + applySystemMessages + authTagPivots <- fromMaybe Set.empty <$> takeSessionJson SessionInactiveAuthTags + forM_ authTagPivots $ + \authTag -> addMessageWidget Info $ msgModal [whamlet|_{MsgUnauthorizedDisabledTag authTag}|] (Left $ SomeRoute (AuthPredsR, catMaybes [(toPathPiece GetReferer, ) . toPathPiece <$> mcurrentRoute])) + getMessages + + storedReasonAndToggleRoute <- case mcurrentRoute of + (Just (CourseR tid ssh csh _)) -> (, Just . SomeRoute $ CourseR tid ssh csh CFavouriteR) <$> storedFavouriteReason tid ssh csh muid + _otherwise -> pure (Nothing, Nothing) + + return (favCourses, breadcrumbs'', nav', contentHeadline, mmsgs, storedReasonAndToggleRoute) + + return ( favCourses + , breadcrumbs'' + , nav' + , contentHeadline + , mmsgs + , maybe userDefaultMaxFavouriteTerms userMaxFavouriteTerms $ view _2 <$> muid + , maybe userDefaultTheme userTheme $ view _2 <$> muid + , storedReasonAndToggleRoute + ) + + let (currentReason', maybeRoute) = storedReasonAndToggleRoute + currentReason = case currentReason' of + -- (reason, blacklist) + (Just (_reason, True)) -> Nothing + (Just (Just reason, False)) -> Just reason + (Just (Nothing, False)) -> Just FavouriteCurrent + Nothing -> Just FavouriteCurrent + showFavToggle :: FavouriteReason -> Bool + showFavToggle FavouriteCurrent = isJust muid + showFavToggle _favouriteReason = False + favouriteToggleRes <- runFormPost $ courseFavouriteToggleForm currentReason + let favouriteToggleWgt = favouriteToggleRes & \((_, favouriteToggleView), favouriteToggleEncoding) -> + wrapForm favouriteToggleView def + { formAction = maybeRoute + , formEncoding = favouriteToggleEncoding + , formSubmit = FormNoSubmit + , formAttrs = [("class", "buttongroup buttongroup--inline")] + } let favouriteTerms :: [TermIdentifier] - favouriteTerms = take maxFavouriteTerms . Set.toDescList $ foldMap (\(Entity _ Course{..}, _, _, _, _) -> Set.singleton $ unTermKey courseTerm) favourites' + favouriteTerms = Set.toDescList . prune $ toTermKeySet favourites' + where + prune ts = currentTerms `Set.union` setTakeEnd (maxFavouriteTerms - Set.size currentTerms) (ts `Set.difference` currentTerms) + setTakeEnd n ts + | n <= 0 = Set.empty + | otherwise = Set.drop (Set.size ts - n) ts + currentTerms = toTermKeySet $ filter (views (_2 . _Value) . maybe True $ is _FavouriteCurrent) favourites' + toTermKeySet = setOf $ folded . _1 . _2 . to unTermKey - favourites <- fmap catMaybes . forM favourites' $ \(Entity cId c@Course{..}, E.Value mFavourite, courseVisible, mayView, mayEdit) - -> let courseRoute = CourseR courseTerm courseSchool courseShorthand CShowR + favourites <- fmap catMaybes . forM favourites' $ \(c@(_, tid, ssh, csh), E.Value mFavourite, courseVisible, mayView, mayEdit) + -> let courseRoute = CourseR tid ssh csh CShowR favouriteReason = fromMaybe FavouriteCurrent mFavourite - in runMaybeT . guardOnM (unTermKey courseTerm `elem` favouriteTerms) . lift $ do + in runMaybeT . guardOnM (unTermKey tid `elem` favouriteTerms) . lift $ do ctx <- getAuthContext MsgRenderer mr <- getMsgRenderer langs <- selectLanguages appLanguages <$> languages - let cK = MemcachedKeyFavouriteQuickActions cId ctx langs + let cK = MemcachedKeyFavouriteQuickActions (tid, ssh, csh) ctx langs $logDebugS "FavouriteQuickActions" $ tshow cK <> " Checking..." - items <- memcachedLimitedKeyTimeoutBy - MemcachedLimitKeyFavourites appFavouritesQuickActionsBurstsize appFavouritesQuickActionsAvgInverseRate 1 - (Right <$> appFavouritesQuickActionsCacheTTL) - appFavouritesQuickActionsTimeout - cK - cK - . observeFavouritesQuickActionsDuration $ do - $logDebugS "FavouriteQuickActions" $ tshow cK <> " Starting..." - items' <- pageQuickActions NavQuickViewFavourite courseRoute - items <- forM items' $ \n@NavLink{navLabel} -> (mr navLabel,) <$> toTextUrl n - $logDebugS "FavouriteQuickActions" $ tshow cK <> " Done." - return items + poolIsPressured <- dbPoolPressured + items <- if + | poolIsPressured -> Nothing <$ observeFavouritesSkippedDueToDBLoad + | otherwise -> memcachedLimitedKeyTimeoutBy + MemcachedLimitKeyFavourites appFavouritesQuickActionsBurstsize appFavouritesQuickActionsAvgInverseRate 1 + (Right <$> appFavouritesQuickActionsCacheTTL) + appFavouritesQuickActionsTimeout + cK + cK + . observeFavouritesQuickActionsDuration . runDBRead $ do + $logDebugS "FavouriteQuickActions" $ tshow cK <> " Starting..." + items' <- pageQuickActions NavQuickViewFavourite courseRoute + items <- forM items' $ \n@NavLink{navLabel} -> fmap (mr navLabel,) $ toTextUrl =<< navLinkRoute n + $logDebugS "FavouriteQuickActions" $ tshow cK <> " Done." + return items $logDebugS "FavouriteQuickActions" $ tshow cK <> " returning " <> tshow (is _Just items) return (c, courseRoute, items, favouriteReason, courseVisible, mayView, mayEdit) - nav'' <- mconcat <$> sequence - [ defaultLinks - , maybe (return []) pageActions mcurrentRoute - ] - nav' <- catMaybes <$> mapM (runMaybeT . navAccess) nav'' - nav <- forM nav' $ \n -> (n,,,) <$> newIdent <*> traverse toTextUrl (n ^? _navLink) <*> traverse (\nc -> (nc,, ) <$> newIdent <*> toTextUrl nc) (n ^. _navChildren) - - mmsgs <- if - | isModal -> return mempty - | otherwise -> do - applySystemMessages - authTagPivots <- fromMaybe Set.empty <$> takeSessionJson SessionInactiveAuthTags - forM_ authTagPivots $ - \authTag -> addMessageWidget Info $ msgModal [whamlet|_{MsgUnauthorizedDisabledTag authTag}|] (Left $ SomeRoute (AuthPredsR, catMaybes [(toPathPiece GetReferer, ) . toPathPiece <$> mcurrentRoute])) - getMessages + nav <- forM nav' $ \n -> (n,,,) <$> newIdent <*> traverse (toTextUrl <=< navLinkRoute) (n ^? _navLink) <*> traverse (\nc -> (nc,, ) <$> newIdent <*> (toTextUrl <=< navLinkRoute) nc) (n ^. _navChildren) -- (langFormView, langFormEnctype) <- generateFormPost $ identifyForm FIDLanguage langForm -- let langFormView' = wrapForm langFormView def @@ -223,13 +330,15 @@ siteLayout' overrideHeading widget = do -- ^ highlight last route in breadcrumbs, favorites taking priority highlight = (highR ==) . Just . urlRoute where crumbs = mcons mcurrentRoute $ view _1 <$> reverse parents - navItems = map (view _2) favourites ++ toListOf (folded . typesUsing @NavChildren @NavLink . to urlRoute) nav + navItems = map (view _2) favourites ++ toListOf (folded . typesUsing @NavChildren @NavLink . to navBaseRoute) nav highR = find (`elem` navItems) . uncurry (++) $ partition (`elem` map (view _2) favourites) crumbs - highlightNav = (||) <$> navForceActive <*> highlight - favouriteTermReason :: TermIdentifier -> FavouriteReason -> [(Course, Route UniWorX, Maybe [(Text, Text)], FavouriteReason, Bool, Bool, Bool)] + highlightNav = (||) <$> navForceActive <*> (highlight . navBaseRoute) + favouriteTermReason :: TermIdentifier -> FavouriteReason -> [((CourseName, TermId, SchoolId, CourseShorthand), Route UniWorX, Maybe [(Text, Text)], FavouriteReason, Bool, Bool, Bool)] favouriteTermReason tid favReason' = favourites - & filter (\(Course{..}, _, _, favReason, _, _, _) -> unTermKey courseTerm == tid && favReason == favReason') - & sortOn (\(Course{..}, _, _, _, _, _, _) -> courseName) + & filter (\((_, tid', _, _), _, _, favReason, _, _, _) -> unTermKey tid' == tid && favReason == favReason') + & sortOn (\((cName, _, _, _), _, _, _, _, _, _) -> cName) + anyFavToggle = flip any ((,) <$> universeF <*> favouriteTerms) $ \(reason, term) -> + showFavToggle reason && not (null $ favouriteTermReason term reason) -- We break up the default layout into two components: -- default-layout is the contents of the body tag, and @@ -241,15 +350,16 @@ siteLayout' overrideHeading widget = do navWidget (n, navIdent, navRoute', navChildren') = case n of NavHeader{ navLink = navLink@NavLink{..}, .. } | NavTypeLink{..} <- navType - , navModal - -> customModal Modal - { modalTriggerId = Just navIdent - , modalId = Nothing - , modalTrigger = \mroute ident -> case mroute of - Just route -> $(widgetFile "widgets/navbar/item") - Nothing -> error "navWidget with non-link modal" - , modalContent = Left $ SomeRoute navLink - } + , navModal -> do + modalContent <- liftHandler $ Left <$> navLinkRoute navLink + customModal Modal + { modalTriggerId = Just navIdent + , modalId = Nothing + , modalTrigger = \mroute ident -> case mroute of + Just route -> $(widgetFile "widgets/navbar/item") + Nothing -> error "navWidget with non-link modal" + , modalContent + } | NavTypeLink{} <- navType -> let route = navRoute' ident = navIdent @@ -257,14 +367,15 @@ siteLayout' overrideHeading widget = do NavPageActionPrimary{ navLink = navLink@NavLink{..} } -> let pWidget | NavTypeLink{..} <- navType - , navModal - = customModal Modal + , navModal = do + modalContent <- liftHandler $ Left <$> navLinkRoute navLink + customModal Modal { modalTriggerId = Just navIdent , modalId = Nothing , modalTrigger = \mroute ident -> case mroute of Just route -> $(widgetFile "widgets/pageaction/primary") Nothing -> error "navWidget with non-link modal" - , modalContent = Left $ SomeRoute navLink + , modalContent } | NavTypeLink{} <- navType = let route = navRoute' @@ -277,15 +388,16 @@ siteLayout' overrideHeading widget = do in $(widgetFile "widgets/pageaction/primary-wrapper") NavPageActionSecondary{ navLink = navLink@NavLink{..} } | NavTypeLink{..} <- navType - , navModal - -> customModal Modal - { modalTriggerId = Just navIdent - , modalId = Nothing - , modalTrigger = \mroute ident -> case mroute of - Just route -> $(widgetFile "widgets/pageaction/secondary") - Nothing -> error "navWidget with non-link modal" - , modalContent = Left $ SomeRoute navLink - } + , navModal -> do + modalContent <- liftHandler $ Left <$> navLinkRoute navLink + customModal Modal + { modalTriggerId = Just navIdent + , modalId = Nothing + , modalTrigger = \mroute ident -> case mroute of + Just route -> $(widgetFile "widgets/pageaction/secondary") + Nothing -> error "navWidget with non-link modal" + , modalContent + } | NavTypeLink{} <- navType -> let route = navRoute' ident = navIdent @@ -305,25 +417,27 @@ siteLayout' overrideHeading widget = do navContainerItemWidget (n, _navIdent, _navRoute', _navChildren') (iN@NavLink{..}, iNavIdent, iNavRoute) = case n of NavHeaderContainer{} | NavTypeLink{..} <- navType - , navModal - -> customModal Modal - { modalTriggerId = Just iNavIdent - , modalId = Nothing - , modalTrigger = \mroute ident -> case mroute of - Just route -> $(widgetFile "widgets/navbar/navbar-container-item--link") - Nothing -> error "navWidget with non-link modal" - , modalContent = Left $ SomeRoute iN - } + , navModal -> do + modalContent <- liftHandler $ Left <$> navLinkRoute iN + customModal Modal + { modalTriggerId = Just iNavIdent + , modalId = Nothing + , modalTrigger = \mroute ident -> case mroute of + Just route -> $(widgetFile "widgets/navbar/navbar-container-item--link") + Nothing -> error "navWidget with non-link modal" + , modalContent + } | NavTypeLink{} <- navType -> let route = iNavRoute ident = iNavIdent in $(widgetFile "widgets/navbar/navbar-container-item--link") | NavTypeButton{..} <- navType -> do csrfToken <- reqToken <$> getRequest + formAction <- liftHandler $ Just <$> navLinkRoute iN wrapForm $(widgetFile "widgets/navbar/navbar-container-item--button") def { formMethod = navMethod , formSubmit = FormNoSubmit - , formAction = Just $ SomeRoute iN + , formAction } _other -> error "not implemented" @@ -343,8 +457,6 @@ siteLayout' overrideHeading widget = do where isNavFooter = has $ _1 . _NavFooter alerts :: WidgetFor UniWorX () alerts = $(widgetFile "widgets/alerts/alerts") - contentHeadline :: Maybe (WidgetFor UniWorX ()) - contentHeadline = overrideHeading <|> (pageHeading =<< mcurrentRoute) breadcrumbsWgt :: WidgetFor UniWorX () breadcrumbsWgt = $(widgetFile "widgets/breadcrumbs/breadcrumbs") pageaction :: WidgetFor UniWorX () @@ -402,19 +514,25 @@ getSystemMessageState smId = liftHandler $ do where foldSt (Entity _ SystemMessageHidden{..}) = MergeHashMap . HashMap.singleton systemMessageHiddenMessage $ mempty { userSystemMessageHidden = Just systemMessageHiddenTime } -applySystemMessages :: (MonadHandler m, HandlerSite m ~ UniWorX, BackendCompatible SqlBackend (YesodPersistBackend UniWorX), BearerAuthSite UniWorX) => m () -applySystemMessages = liftHandler . maybeT_ . catchMPlus (Proxy @CryptoIDError) $ do +applySystemMessages :: forall m. + ( MonadHandler m, HandlerSite m ~ UniWorX + , YesodPersistBackend UniWorX ~ SqlBackend + , BearerAuthSite UniWorX + , WithRunDB SqlBackend (HandlerFor UniWorX) m + , MonadCatch m + ) => m () +applySystemMessages = maybeT_ . catchMPlus (Proxy @CryptoIDError) $ do lift $ maybeAuthId >>= traverse_ syncSystemMessageHidden - cRoute <- lift getCurrentRoute + cRoute <- getCurrentRoute guard $ cRoute /= Just NewsR - lift . runDBRead . runConduit $ selectSource [] [Asc SystemMessageManualPriority] .| C.mapM_ applyMessage + lift . useRunDB . runConduit $ selectSource [] [Asc SystemMessageManualPriority] .| C.mapM_ applyMessage where - syncSystemMessageHidden :: UserId -> HandlerFor UniWorX () - syncSystemMessageHidden uid = runDB . withReaderT projectBackend $ do - smSt <- lookupRegisteredCookiesJson id CookieSystemMessageState :: SqlPersistT (HandlerFor UniWorX) (MergeHashMap CryptoUUIDSystemMessage UserSystemMessageState) - iforM_ smSt $ \cID UserSystemMessageState{..} -> do + syncSystemMessageHidden :: UserId -> m () + syncSystemMessageHidden uid = do + smSt <- lookupRegisteredCookiesJson id CookieSystemMessageState :: m (MergeHashMap CryptoUUIDSystemMessage UserSystemMessageState) + iforM_ smSt $ \cID UserSystemMessageState{..} -> useRunDB $ do smId <- decrypt cID whenIsJust userSystemMessageHidden $ \systemMessageHiddenTime -> void $ upsert SystemMessageHidden @@ -431,12 +549,12 @@ applySystemMessages = liftHandler . maybeT_ . catchMPlus (Proxy @CryptoIDError) -> fmap MergeHashMap . assertM' (/= mempty) $ HashMap.update (\smSt' -> assertM' (/= mempty) $ smSt' { userSystemMessageHidden = Nothing, userSystemMessageUnhidden = Nothing }) cID hm - applyMessage :: Entity SystemMessage -> ReaderT SqlReadBackend (HandlerFor UniWorX) () + applyMessage :: Entity SystemMessage -> ReaderT SqlBackend (HandlerFor UniWorX) () applyMessage (Entity smId SystemMessage{..}) = maybeT_ $ do guard $ not systemMessageNewsOnly - cID <- encrypt smId - void . assertM (== Authorized) . lift $ evalAccessDB (MessageR cID) False + cID <- lift $ encrypt smId + guardM . lift . hasReadAccessTo $ MessageR cID now <- liftIO getCurrentTime guard $ NTop systemMessageFrom <= NTop (Just now) @@ -467,103 +585,102 @@ applySystemMessages = liftHandler . maybeT_ . catchMPlus (Proxy @CryptoIDError) -- All handlers whose code is under our control should use -- `siteLayout` instead; `pageHeading` is only a fallback solution for -- e.g. subsites like `AuthR` -pageHeading :: ( YesodPersist UniWorX - , BackendCompatible SqlBackend (YesodPersistBackend UniWorX) - ) => Route UniWorX -> Maybe Widget +pageHeading :: ( YesodPersistBackend UniWorX ~ SqlBackend + , WithRunDB SqlReadBackend (HandlerFor UniWorX) m + , MonadHandler m + ) => Route UniWorX -> MaybeT m Widget pageHeading (AuthR _) - = Just $ i18n MsgLoginHeading + = return $ i18n MsgLoginHeading pageHeading NewsR - = Just $ i18n MsgNewsHeading + = return $ i18n MsgNewsHeading pageHeading UsersR - = Just $ i18n MsgUsers + = return $ i18n MsgUsers pageHeading (AdminUserR _) - = Just $ i18n MsgAdminUserHeading + = return $ i18n MsgAdminUserHeading pageHeading AdminTestR - = Just [whamlet|Internal Code Demonstration Page|] + = return [whamlet|Internal Code Demonstration Page|] pageHeading AdminErrMsgR - = Just $ i18n MsgErrMsgHeading + = return $ i18n MsgErrMsgHeading pageHeading InfoR - = Just $ i18n MsgInfoHeading + = return $ i18n MsgInfoHeading pageHeading LegalR - = Just $ i18n MsgLegalHeading + = return $ i18n MsgLegalHeading pageHeading VersionR - = Just $ i18n MsgVersionHeading + = return $ i18n MsgVersionHeading pageHeading HelpR - = Just $ i18n MsgHelpRequest + = return $ i18n MsgHelpRequest pageHeading ProfileR - = Just $ i18n MsgProfileHeading + = return $ i18n MsgProfileHeading pageHeading ProfileDataR - = Just $ i18n MsgProfileDataHeading + = return $ i18n MsgProfileDataHeading pageHeading TermShowR - = Just $ i18n MsgTermsHeading + = return $ i18n MsgTermsHeading pageHeading TermCurrentR - = Just $ i18n MsgTermCurrent + = return $ i18n MsgTermCurrent pageHeading TermEditR - = Just $ i18n MsgTermEditHeading + = return $ i18n MsgTermEditHeading pageHeading (TermEditExistR tid) - = Just $ i18n $ MsgTermEditTid tid + = return $ i18n $ MsgTermEditTid tid pageHeading (TermCourseListR tid) - = Just . i18n . MsgTermCourseListHeading $ tid -pageHeading (TermSchoolCourseListR tid ssh) - = Just $ do - School{schoolName=school} <- handlerToWidget . runDB . withReaderT (projectBackend @SqlBackend) $ get404 ssh - i18n $ MsgTermSchoolCourseListHeading tid school + = return . i18n . MsgTermCourseListHeading $ tid +pageHeading (TermSchoolCourseListR tid ssh) = do + School{schoolName=school} <- MaybeT . useRunDB $ get ssh + return . i18n $ MsgTermSchoolCourseListHeading tid school pageHeading CourseListR - = Just $ i18n MsgCourseListTitle + = return $ i18n MsgCourseListTitle pageHeading CourseNewR - = Just $ i18n MsgCourseNewHeading -pageHeading (CourseR tid ssh csh CShowR) - = Just $ do - Entity _ Course{..} <- handlerToWidget . runDB . withReaderT (projectBackend @SqlBackend) . getBy404 $ TermSchoolCourseShort tid ssh csh - toWidget courseName + = return $ i18n MsgCourseNewHeading +pageHeading (CourseR tid ssh csh CShowR) = do + Entity _ Course{..} <- MaybeT . useRunDB . getBy $ TermSchoolCourseShort tid ssh csh + return $ toWidget courseName -- (CourseR tid csh CRegisterR) -- just for POST pageHeading (CourseR tid ssh csh CEditR) - = Just $ i18n $ MsgCourseEditHeading tid ssh csh + = return $ i18n $ MsgCourseEditHeading tid ssh csh pageHeading (CourseR tid ssh csh CCorrectionsR) - = Just $ i18n $ MsgSubmissionsCourse tid ssh csh + = return $ i18n $ MsgSubmissionsCourse tid ssh csh pageHeading (CourseR tid ssh csh SheetListR) - = Just $ i18n $ MsgSheetList tid ssh csh + = return $ i18n $ MsgSheetList tid ssh csh pageHeading (CourseR tid ssh csh SheetNewR) - = Just $ i18n $ MsgSheetNewHeading tid ssh csh + = return $ i18n $ MsgSheetNewHeading tid ssh csh pageHeading (CSheetR tid ssh csh shn SShowR) - = Just $ i18n $ MsgSheetTitle tid ssh csh shn - -- = Just $ i18n $ prependCourseTitle tid ssh csh $ SomeMessage shn -- TODO: for consistency use prependCourseTitle throughout ERROR: circularity + = return $ i18n $ MsgSheetTitle tid ssh csh shn + -- = return $ i18n $ prependCourseTitle tid ssh csh $ SomeMessage shn -- TODO: for consistency use prependCourseTitle throughout ERROR: circularity pageHeading (CSheetR tid ssh csh shn SEditR) - = Just $ i18n $ MsgSheetEditHead tid ssh csh shn + = return $ i18n $ MsgSheetEditHead tid ssh csh shn pageHeading (CSheetR tid ssh csh shn SDelR) - = Just $ i18n $ MsgSheetDelHead tid ssh csh shn + = return $ i18n $ MsgSheetDelHead tid ssh csh shn pageHeading (CSheetR _tid _ssh _csh shn SSubsR) - = Just $ i18n $ MsgSubmissionsSheet shn + = return $ i18n $ MsgSubmissionsSheet shn pageHeading (CSheetR tid ssh csh shn SubmissionNewR) - = Just $ i18n $ MsgSubmissionEditHead tid ssh csh shn + = return $ i18n $ MsgSubmissionEditHead tid ssh csh shn pageHeading (CSheetR tid ssh csh shn SubmissionOwnR) - = Just $ i18n $ MsgSubmissionEditHead tid ssh csh shn + = return $ i18n $ MsgSubmissionEditHead tid ssh csh shn pageHeading (CSubmissionR tid ssh csh shn _ SubShowR) -- TODO: Rethink this one! - = Just $ i18n $ MsgSubmissionEditHead tid ssh csh shn + = return $ i18n $ MsgSubmissionEditHead tid ssh csh shn -- (CSubmissionR tid csh shn cid SubArchiveR) -- just a download pageHeading (CSubmissionR tid ssh csh shn cid CorrectionR) - = Just $ i18n $ MsgCorrectionHead tid ssh csh shn cid + = return $ i18n $ MsgCorrectionHead tid ssh csh shn cid -- (CSubmissionR tid csh shn cid SubDownloadR) -- just a download -- (CSheetR tid ssh csh shn SFileR) -- just for Downloads pageHeading CorrectionsR - = Just $ i18n MsgCorrectionsTitle + = return $ i18n MsgCorrectionsTitle pageHeading CorrectionsUploadR - = Just $ i18n MsgCorrUpload + = return $ i18n MsgCorrUpload pageHeading CorrectionsCreateR - = Just $ i18n MsgCorrCreate + = return $ i18n MsgCorrCreate pageHeading CorrectionsGradeR - = Just $ i18n MsgCorrGrade + = return $ i18n MsgCorrGrade pageHeading (MessageR _) - = Just $ i18n MsgSystemMessageHeading + = return $ i18n MsgSystemMessageHeading pageHeading MessageListR - = Just $ i18n MsgSystemMessageListHeading + = return $ i18n MsgSystemMessageListHeading -- TODO: add headings for more single course- and single term-pages pageHeading _ - = Nothing + = mzero diff --git a/src/Foundation/Type.hs b/src/Foundation/Type.hs index 9ca763f3f..3b7494d3c 100644 --- a/src/Foundation/Type.hs +++ b/src/Foundation/Type.hs @@ -5,13 +5,16 @@ module Foundation.Type ( UniWorX(..) , SomeSessionStorage(..) , _SessionStorageMemcachedSql, _SessionStorageAcid + , AppMemcached(..) + , _memcachedKey, _memcachedConn + , AppMemcachedLocal(..) + , _memcachedLocalARC , SMTPPool - , _appSettings', _appStatic, _appConnPool, _appSmtpPool, _appLdapPool, _appWidgetMemcached, _appHttpManager, _appLogger, _appLogSettings, _appCryptoIDKey, _appClusterID, _appInstanceID, _appJobState, _appSessionStore, _appSecretBoxKey, _appJSONWebKeySet, _appHealthReport + , _appSettings', _appStatic, _appConnPool, _appSmtpPool, _appLdapPool, _appWidgetMemcached, _appHttpManager, _appLogger, _appLogSettings, _appCryptoIDKey, _appClusterID, _appInstanceID, _appJobState, _appSessionStore, _appSecretBoxKey, _appJSONWebKeySet, _appHealthReport, _appMemcached, _appUploadCache, _appVerpSecret, _appAuthKey , DB, Form, MsgRenderer, MailM, DBFile ) where import Import.NoFoundation -import Database.Persist.Sql (ConnectionPool) import Jobs.Types @@ -19,46 +22,78 @@ import Yesod.Core.Types (Logger) import qualified Crypto.Saltine.Core.SecretBox as SecretBox import qualified Crypto.Saltine.Core.AEAD as AEAD +import qualified Crypto.Saltine.Core.Auth as Auth import qualified Jose.Jwk as Jose import qualified Database.Memcached.Binary.IO as Memcached import Network.Minio (MinioConn) +import Data.IntervalMap.Strict (IntervalMap) + +import qualified Utils.Pool as Custom + +import Utils.Metrics (DBConnUseState) + +import qualified Data.ByteString.Lazy as Lazy +import Data.Time.Clock.POSIX (POSIXTime) +import GHC.Fingerprint (Fingerprint) + type SMTPPool = Pool SMTPConnection data SomeSessionStorage = SessionStorageMemcachedSql { sessionStorageMemcachedSql :: MemcachedSqlStorage SessionMap } | SessionStorageAcid { sessionStorageAcid :: AcidStorage SessionMap } + deriving (Generic, Typeable) makePrisms ''SomeSessionStorage +data AppMemcached = AppMemcached + { memcachedKey :: AEAD.Key + , memcachedConn :: Memcached.Connection + } deriving (Generic, Typeable) + +makeLenses_ ''AppMemcached + +data AppMemcachedLocal = AppMemcachedLocal + { memcachedLocalARC :: ARCHandle (Fingerprint, Lazy.ByteString) Int (NFDynamic, Maybe POSIXTime) + , memcachedLocalHandleInvalidations :: Async () + , memcachedLocalInvalidationQueue :: TVar (Seq (Fingerprint, Lazy.ByteString)) + } deriving (Generic, Typeable) + +makeLenses_ ''AppMemcachedLocal + -- | The foundation datatype for your application. This can be a good place to -- keep settings and values requiring initialization before your application -- starts running, such as database connections. Every handler will have -- access to the data present here. data UniWorX = UniWorX - { appSettings' :: AppSettings - , appStatic :: EmbeddedStatic -- ^ Settings for static file serving. - , appConnPool :: ConnectionPool -- ^ Database connection pool. - , appSmtpPool :: Maybe SMTPPool - , appLdapPool :: Maybe (Failover (LdapConf, LdapPool)) - , appWidgetMemcached :: Maybe Memcached.Connection -- ^ Actually a proper pool - , appHttpManager :: Manager - , appLogger :: (ReleaseKey, TVar Logger) - , appLogSettings :: TVar LogSettings - , appCryptoIDKey :: CryptoIDKey - , appClusterID :: ClusterId - , appInstanceID :: InstanceId - , appJobState :: TMVar JobState - , appSessionStore :: SomeSessionStorage - , appSecretBoxKey :: SecretBox.Key - , appJSONWebKeySet :: Jose.JwkSet - , appHealthReport :: TVar (Set (UTCTime, HealthReport)) - , appMemcached :: Maybe (AEAD.Key, Memcached.Connection) - , appUploadCache :: Maybe MinioConn - , appVerpSecret :: VerpSecret - } + { appSettings' :: AppSettings + , appStatic :: EmbeddedStatic -- ^ Settings for static file serving. + , appConnPool :: forall m. MonadIO m => Custom.Pool' m DBConnLabel DBConnUseState SqlBackend -- ^ Database connection pool. + , appSmtpPool :: Maybe SMTPPool + , appLdapPool :: Maybe (Failover (LdapConf, LdapPool)) + , appWidgetMemcached :: Maybe Memcached.Connection -- ^ Actually a proper pool + , appHttpManager :: Manager + , appLogger :: (ReleaseKey, TVar Logger) + , appLogSettings :: TVar LogSettings + , appCryptoIDKey :: CryptoIDKey + , appClusterID :: ClusterId + , appInstanceID :: InstanceId + , appJobState :: TMVar JobState + , appSessionStore :: SomeSessionStorage + , appSecretBoxKey :: SecretBox.Key + , appJSONWebKeySet :: Jose.JwkSet + , appHealthReport :: TVar (Set (UTCTime, HealthReport)) + , appMemcached :: Maybe AppMemcached + , appMemcachedLocal :: Maybe AppMemcachedLocal + , appUploadCache :: Maybe MinioConn + , appVerpSecret :: VerpSecret + , appAuthKey :: Auth.Key + , appFileSourceARC :: Maybe (ARCHandle (FileContentChunkReference, (Int, Int)) Int ByteString) + , appFileSourcePrewarm :: Maybe (LRUHandle (FileContentChunkReference, (Int, Int)) UTCTime Int ByteString) + , appFileInjectInhibit :: TVar (IntervalMap UTCTime (Set FileContentReference)) + } deriving (Typeable) makeLenses_ ''UniWorX instance HasInstanceID UniWorX InstanceId where diff --git a/src/Foundation/Yesod/Auth.hs b/src/Foundation/Yesod/Auth.hs index 3d6f747c5..f73fe7152 100644 --- a/src/Foundation/Yesod/Auth.hs +++ b/src/Foundation/Yesod/Auth.hs @@ -15,6 +15,8 @@ import Handler.Utils.Profile import Handler.Utils.StudyFeatures import Handler.Utils.SchoolLdap import Handler.Utils.LdapSystemFunctions +import Handler.Utils.Memcached +import Foundation.Authorization (AuthorizationCacheKey(..)) import Yesod.Auth.Message import Auth.LDAP @@ -359,7 +361,7 @@ upsertCampusUser upsertMode ldapData = do , studyFeaturesFirstObserved = Just now , studyFeaturesLastObserved = now , studyFeaturesValid = True - , studyFeaturesRelevanceCached = False + , studyFeaturesRelevanceCached = Nothing } (sf :) <$> assimilateSubTerms subterms unusedFeats Nothing @@ -476,9 +478,10 @@ upsertCampusUser upsertMode ldapData = do Right str <- return $ Text.decodeUtf8' v' assertM' (not . Text.null) $ Text.strip str - iforM_ userSystemFunctions $ \func preset -> if - | preset -> void $ upsert (UserSystemFunction userId func False False) [] - | otherwise -> deleteWhere [UserSystemFunctionUser ==. userId, UserSystemFunctionFunction ==. func, UserSystemFunctionIsOptOut ==. False, UserSystemFunctionManual ==. False] + iforM_ userSystemFunctions $ \func preset -> do + memcachedByInvalidate (AuthCacheSystemFunctionList func) $ Proxy @(Set UserId) + if | preset -> void $ upsert (UserSystemFunction userId func False False) [] + | otherwise -> deleteWhere [UserSystemFunctionUser ==. userId, UserSystemFunctionFunction ==. func, UserSystemFunctionIsOptOut ==. False, UserSystemFunctionManual ==. False] return user where diff --git a/src/Foundation/Yesod/ErrorHandler.hs b/src/Foundation/Yesod/ErrorHandler.hs index f24a7ea85..af67f5b8b 100644 --- a/src/Foundation/Yesod/ErrorHandler.hs +++ b/src/Foundation/Yesod/ErrorHandler.hs @@ -4,54 +4,88 @@ module Foundation.Yesod.ErrorHandler import Import.NoFoundation hiding (errorHandler) -import Utils.Form - import Foundation.Type import Foundation.I18n import Foundation.Authorization import Foundation.SiteLayout import Foundation.Routes +import Foundation.DB import qualified Data.Aeson as JSON import qualified Data.Text as Text + +import qualified Network.Wai as W errorHandler :: ( MonadSecretBox (HandlerFor UniWorX) , MonadSecretBox (WidgetFor UniWorX) + , MonadSecretBox (ExceptT EncodedSecretBoxException (HandlerFor UniWorX)) + , MonadAuth (HandlerFor UniWorX) , BearerAuthSite UniWorX - , Button UniWorX ButtonSubmit - , BackendCompatible SqlBackend (YesodPersistBackend UniWorX) + , YesodPersistBackend UniWorX ~ SqlBackend ) => ErrorResponse -> HandlerFor UniWorX TypedContent errorHandler err = do - shouldEncrypt <- do - canDecrypt <- (== Authorized) <$> evalAccess AdminErrMsgR True - shouldEncrypt <- getsYesod $ view _appEncryptErrors - return $ shouldEncrypt && not canDecrypt + let shouldEncrypt' = getsYesod $ view _appEncryptErrors + canDecrypt' = runDBRead $ hasWriteAccessTo AdminErrMsgR + decrypted' <- runMaybeT $ do + internalErrorContent <- hoistMaybe $ err ^? _InternalError + exceptTMaybe $ encodedSecretBoxOpen @Text internalErrorContent + let isEncrypted = is _Just decrypted' + shouldEncrypt <- andM + [ shouldEncrypt' + , return $ not isEncrypted + , not <$> canDecrypt' + ] + let decrypted = guardOnM (not shouldEncrypt) decrypted' - sessErr <- bool return (_InternalError $ encodedSecretBox SecretBoxShort) shouldEncrypt err + sessErr <- bool return (traverseOf _InternalError $ encodedSecretBox SecretBoxShort) shouldEncrypt err + + void . runMaybeT $ do + reqHost <- MaybeT $ W.requestHeaderHost <$> waiRequest + approotHost <- MaybeT . getsYesod $ approotScopeHost ApprootDefault + when (approotHost /= reqHost) $ do + authErr <- lift $ encodedAuth sessErr + redirect (ErrorR, [(toPathPiece GetError, authErr)]) + + when (is _NotAuthenticated err) $ do + authed <- is _Just <$> maybeAuthId + unless authed $ do + mCurrent <- getCurrentRoute + gets' <- reqGetParams <$> getRequest + wai <- waiRequest + maybe clearUltDest setUltDest $ do + current <- mCurrent + case current of + _ | W.requestMethod wai /= "GET" -> Nothing + ErrorR -> Nothing + current' -> Just (current', gets') + $logInfoS "errorHandler" "Redirect to LoginR" + redirect $ AuthR LoginR + setSessionJson SessionError sessErr selectRep $ do provideRep $ do mr <- getMessageRender let - encrypted :: ToJSON a => a -> WidgetFor UniWorX () -> WidgetFor UniWorX () + encrypted :: Text -> WidgetFor UniWorX () -> WidgetFor UniWorX () encrypted plaintextJson plaintext = do - if - | shouldEncrypt -> do - ciphertext <- encodedSecretBox SecretBoxPretty plaintextJson - + let displayEncrypted ciphertext = [whamlet| + $newline never

_{MsgErrorResponseEncrypted}

                     #{ciphertext}
                 |]
+          if
+            | isEncrypted && shouldEncrypt -> displayEncrypted plaintextJson
+            | shouldEncrypt -> displayEncrypted =<< encodedSecretBox SecretBoxPretty plaintextJson
             | otherwise -> plaintext
 
         errPage = case err of
           NotFound -> [whamlet|

_{MsgErrorResponseNotFound}|] - InternalError err' -> encrypted err' [whamlet|

#{err'}|] + InternalError err' -> encrypted err' [whamlet|

#{fromMaybe err' decrypted}|] InvalidArgs errs -> [whamlet|