Compare commits

..

100 Commits

Author SHA1 Message Date
4b33971155 release: 2021.3.4 2021-03-16 19:17:50 +01:00
9e71287c25 Merge branch 'next' into version-2021.3 2021-03-16 19:12:55 +01:00
9784c6c828 tests/e2e: fix checks for ak-sidebar since ak-interface uses shadowdom now
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 18:38:17 +01:00
732b6a3556 root: fix typo in bumpversion
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:45:56 +01:00
dc1e17ba0c Merge branch 'master' into version-2021.3 2021-03-16 17:38:39 +01:00
f05d5973af root: fix typo in bumpversion
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:38:34 +01:00
deb48487f3 root: fix typo in bumpversion
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:38:01 +01:00
78f3abc64f web: use sections in sidebar, adjust colouring
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:34:19 +01:00
e45bc3834a web: use ShadowDom for all elements, embed smaller CSS in skeleton
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:24:02 +01:00
0d9db1b6f2 web: use chunking for vendor and api
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 17:00:02 +01:00
ce555aa5e9 root: fix hash for docker build
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 16:45:53 +01:00
07ca82e599 admin: include git build hash in gh-* tags and show build hash in admin overview
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 14:42:01 +01:00
a9339589bb web: fix outpost health display
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 14:02:50 +01:00
c8ed650f1c web: fix system task index
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-16 14:02:04 +01:00
cd78d8d3fa build(deps-dev): bump @typescript-eslint/parser in /web (#640)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 4.17.0 to 4.18.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.18.0/packages/parser)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-16 12:09:00 +01:00
7fdc935fb9 build(deps-dev): bump @typescript-eslint/eslint-plugin in /web (#641)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.17.0 to 4.18.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.18.0/packages/eslint-plugin)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-16 11:50:18 +01:00
c8069325b3 build(deps): bump rollup from 2.41.1 to 2.41.2 in /web (#637)
Bumps [rollup](https://github.com/rollup/rollup) from 2.41.1 to 2.41.2.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.41.1...v2.41.2)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-15 10:17:54 +01:00
9d08e02fe1 build(deps-dev): bump eslint from 7.21.0 to 7.22.0 in /web (#638)
Bumps [eslint](https://github.com/eslint/eslint) from 7.21.0 to 7.22.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.21.0...v7.22.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-15 10:17:42 +01:00
a11ea598a2 build(deps): bump react and react-dom in /website (#639)
Bumps [react](https://github.com/facebook/react/tree/HEAD/packages/react) and [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom). These dependencies needed to be updated together.

Updates `react` from 16.14.0 to 17.0.1
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v17.0.1/packages/react)

Updates `react-dom` from 16.14.0 to 17.0.1
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v17.0.1/packages/react-dom)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-15 10:17:27 +01:00
2713b05e8c Merge branch 'master' into version-2021.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	docker-compose.yml
#	helm/README.md
#	web/src/authentik.css
#	web/src/flows/FlowExecutor.ts
#	web/src/flows/stages/identification/IdentificationStage.ts
#	website/docs/installation/kubernetes.md
2021-03-13 21:36:17 +01:00
fef5a5ca52 Merge branch 'master' into next 2021-03-13 21:27:51 +01:00
9d339d8b11 policies: fix error when clearing policy cache when no policies are cached
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-13 21:10:13 +01:00
4e86aa3f59 sources/oauth: fix error on user enrollment when no enrollment flow is defined
fixes #636

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-03-13 21:08:31 +01:00
221e4b665c docs: add beta opt-in docs 2021-03-12 18:04:42 +01:00
e67f235a9f website: add docs for compose configuration options 2021-03-12 16:43:31 +01:00
741ebbacca Merge branch 'master' into next 2021-03-12 12:41:34 +01:00
b63b789f77 web: prevent duplicate messages 2021-03-12 12:41:17 +01:00
a63702ef90 web: add close button to messages 2021-03-12 12:27:57 +01:00
a4a4550753 Merge branch 'master' into next 2021-03-12 10:06:38 +01:00
fd864655f6 build(deps): bump @sentry/tracing from 6.2.1 to 6.2.2 in /web (#633) 2021-03-12 09:02:44 +01:00
c1da09507a build(deps): bump rollup from 2.41.0 to 2.41.1 in /web (#632) 2021-03-12 09:01:53 +01:00
ed2ea220bf build(deps): bump boto3 from 1.17.25 to 1.17.26 (#634) 2021-03-12 09:01:25 +01:00
7738cbe751 build(deps): bump golang from 1.16.1 to 1.16.2 in /outpost (#635) 2021-03-12 09:01:16 +01:00
bf16ea3607 build(deps): bump @sentry/browser from 6.2.1 to 6.2.2 in /web (#631) 2021-03-12 09:00:10 +01:00
d6f44e069c docs: add notice for launch URL for vcenter 7u2 2021-03-11 22:17:16 +01:00
899cf392f4 web: improve compatibility with password managers 2021-03-11 22:04:59 +01:00
d99451b45c outposts: improve logs for outpost connection 2021-03-11 17:50:57 +01:00
5b31f8edf6 Merge branch 'master' into next
# Conflicts:
#	helm/templates/geoip-pvc.yaml
2021-03-11 17:43:28 +01:00
00235e039b helm: add initial geoip 2021-03-11 17:43:03 +01:00
2dfaef4220 helm: add initial geoip 2021-03-11 17:37:38 +01:00
13fceacfe4 root: add geoip config to docker-compose 2021-03-11 16:42:19 +01:00
f8dc32b387 events: don't fail on boot when geoip can't be opened 2021-03-11 16:38:14 +01:00
828f2f8b92 web: use loadingState for autosubmitStage 2021-03-11 15:39:59 +01:00
734399755d web: improve layout of expanded event info 2021-03-11 15:15:17 +01:00
d8f106b976 web: improve styling for application list 2021-03-11 10:56:22 +01:00
9a524dd671 web: show related edit button for bound stages and policies 2021-03-11 10:12:22 +01:00
0775296003 website: bump postcss 2021-03-11 09:57:33 +01:00
390534c14e build(deps): bump boto3 from 1.17.24 to 1.17.25 (#629)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.24 to 1.17.25.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.24...1.17.25)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-11 09:37:13 +01:00
2a644f64ad build(deps): bump golang from 1.16.0 to 1.16.1 in /outpost (#630)
Bumps golang from 1.16.0 to 1.16.1.

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-11 09:36:39 +01:00
e0298141cf web: backport fix: add missing background filter
# Conflicts:
#	authentik/core/templates/login/base_full.html
2021-03-10 23:23:25 +01:00
df7119bb22 web: backport fix: add missing background filter 2021-03-10 23:22:39 +01:00
1d5bba831e root: add comment for error reporting to compose 2021-03-10 23:15:38 +01:00
0b4be70c00 web: fix path for fallback flow view 2021-03-10 23:15:25 +01:00
786737650b build(deps): bump @docusaurus/core in /website (#628)
Bumps [@docusaurus/core](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus) from 2.0.0-alpha.70 to 2.0.0-alpha.71.
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/master/CHANGELOG-2.x.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v2.0.0-alpha.71/packages/docusaurus)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:19:36 +01:00
54c80a2e1f build(deps-dev): bump rollup-plugin-minify-html-literals in /web (#624)
Bumps [rollup-plugin-minify-html-literals](https://github.com/asyncLiz/rollup-plugin-minify-html-literals) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/asyncLiz/rollup-plugin-minify-html-literals/releases)
- [Changelog](https://github.com/asyncLiz/rollup-plugin-minify-html-literals/blob/master/CHANGELOG.md)
- [Commits](https://github.com/asyncLiz/rollup-plugin-minify-html-literals/compare/v1.2.5...v1.2.6)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:14:16 +01:00
b376211a0e build(deps): bump boto3 from 1.17.23 to 1.17.24 (#625)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.23 to 1.17.24.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.23...1.17.24)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:13:53 +01:00
1990a3063e build(deps): bump github.com/sirupsen/logrus in /outpost (#627)
Bumps [github.com/sirupsen/logrus](https://github.com/sirupsen/logrus) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/sirupsen/logrus/releases)
- [Changelog](https://github.com/sirupsen/logrus/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sirupsen/logrus/compare/v1.8.0...v1.8.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:13:44 +01:00
5abf22ad8a build(deps): bump @docusaurus/preset-classic in /website (#626)
Bumps [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) from 2.0.0-alpha.70 to 2.0.0-alpha.71.
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/master/CHANGELOG-2.x.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v2.0.0-alpha.71/packages/docusaurus-preset-classic)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:13:35 +01:00
b7b87d87fc build(deps): bump @patternfly/patternfly from 4.87.3 to 4.90.5 in /web (#622)
Bumps [@patternfly/patternfly](https://github.com/patternfly/patternfly) from 4.87.3 to 4.90.5.
- [Release notes](https://github.com/patternfly/patternfly/releases)
- [Changelog](https://github.com/patternfly/patternfly/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/patternfly/patternfly/compare/prerelease-v4.87.3...prerelease-v4.90.5)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:12:49 +01:00
20184424ab build(deps): bump rollup from 2.40.0 to 2.41.0 in /web (#623)
Bumps [rollup](https://github.com/rollup/rollup) from 2.40.0 to 2.41.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.40.0...v2.41.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-10 09:12:26 +01:00
d5de12b69e release: 2021.3.3 2021-03-09 18:03:53 +01:00
d1a3350085 release: 2021.3.3 2021-03-09 14:24:01 +01:00
e0b84c71a7 docs: add 2021.3.3 2021-03-09 14:23:48 +01:00
3bc1d6a690 web: fix Source icons not being displayed on firefox
# Conflicts:
#	web/src/elements/stages/identification/IdentificationStage.ts
2021-03-09 13:09:50 +01:00
786c74ef2c stages/authenticator_static: fix error when disable static tokens 2021-03-09 13:09:18 +01:00
3e9b5f5449 stages/authenticator_webauthn: add missing migration 2021-03-09 13:09:07 +01:00
5d071488d3 providers/oauth2: allow protected_resource_view when method is OPTIONS
# Conflicts:
#	authentik/providers/oauth2/views/provider.py
2021-03-09 13:08:33 +01:00
90d234a458 web: fix Colours for user settings in dark mode 2021-03-09 13:07:53 +01:00
0032bb6aee web: fix styling for static token list 2021-03-09 13:07:40 +01:00
6e6755d805 web: fix Flow executor not showing spinner when redirecting
# Conflicts:
#	web/src/pages/generic/FlowExecutor.ts
2021-03-09 13:07:32 +01:00
132b990f10 web: fix Source icons not being displayed on firefox 2021-03-09 13:06:17 +01:00
34a3d81eff stages/authenticator_*: add API for authenticator devices 2021-03-09 10:38:07 +01:00
43a4217497 web: add optional checkboxes to table 2021-03-09 10:38:07 +01:00
e0ec5826ca web: add edit button to LibraryView when user is superuser 2021-03-09 10:38:07 +01:00
5413a01360 web: fix drawer not updating after marking notification as seen 2021-03-09 10:38:07 +01:00
d9c3a29404 build(deps-dev): bump @typescript-eslint/parser in /web (#618)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 4.16.1 to 4.17.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.17.0/packages/parser)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-09 10:37:56 +01:00
bcce91476c build(deps-dev): bump @typescript-eslint/eslint-plugin in /web (#619)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.16.1 to 4.17.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.17.0/packages/eslint-plugin)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-09 09:18:03 +01:00
56f0f454d0 build(deps): bump boto3 from 1.17.22 to 1.17.23 (#620)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.22 to 1.17.23.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.22...1.17.23)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-09 09:17:53 +01:00
25e63edf77 build(deps): bump defusedxml from 0.7.0 to 0.7.1 (#621) 2021-03-09 09:05:50 +01:00
d150851ff5 root: fix date settings 2021-03-08 15:24:11 +01:00
2e2840c71e helm: add service monitors 2021-03-08 13:02:02 +01:00
ff276fcc58 web: fix layout for search 2021-03-08 12:55:13 +01:00
2852fa3c5e web: use generated API Client (#616)
* api: fix types for config API

* api: remove broken swagger UI

* admin: re-fix system task enum

* events: make event optional

* events: fix Schema for notification transport test

* flows: use APIView for Flow Executor

* core: fix schema for Metrics APIs

* web: rewrite to use generated API client

* web: generate API Client in CI

* admin: use x_cord and y_cord to prevent yaml issues

* events: fix linting errors

* web: don't lint generated code

* core: fix fields not being required in TypeSerializer

* flows: fix missing permission_classes

* web: cleanup

* web: fix rendering of graph on Overview page

* web: cleanup imports

* core: fix missing background image filter

* flows: fix flows not advancing properly

* stages/*: fix warnings during get_challenge

* web: send Flow response as JSON instead of FormData

* web: fix styles for horizontal tabs

* web: add base chart class and custom chart for application view

* root: generate ts client for e2e tests

* web: don't attempt to connect to websocket in selenium tests

* web: fix UserTokenList not being included in the build

* web: fix styling for static token list

* web: fix CSRF Token missing

* stages/authenticator_static: fix error when disable static tokens

* core: fix display issue when updating user info

* web: fix Flow executor not showing spinner when redirecting
2021-03-08 11:14:00 +01:00
1c6d498621 web: fix Flow executor not showing spinner when redirecting
# Conflicts:
#	web/src/pages/generic/FlowExecutor.ts
2021-03-08 10:26:42 +01:00
3f0e4bb654 stages/authenticator_static: fix error when disable static tokens 2021-03-08 10:26:03 +01:00
a59d78a7c7 web: fix styling for static token list 2021-03-08 10:25:56 +01:00
0a24202f1e build(deps): bump boto3 from 1.17.21 to 1.17.22 (#617) 2021-03-08 07:45:40 +01:00
cbc86d674d web: fix Colours for user settings in dark mode 2021-03-06 23:00:29 +01:00
082628771b tests/integration: add more tests for docker outpost 2021-03-05 19:09:13 +01:00
93b50e7d6e tests/e2e: add tests for OIDC implicit flow 2021-03-05 17:18:50 +01:00
c6de4e47d7 providers/oauth2: allow protected_resource_view when method is OPTIONS 2021-03-05 16:57:37 +01:00
0e9e378bdf docs: update manual k8s outpost deployment 2021-03-05 15:30:41 +01:00
de4b3d6290 providers/oauth2: always set CORS headers on provider info view 2021-03-05 14:27:16 +01:00
56f75aecc7 docs: bump version of outpost in docs 2021-03-05 14:14:37 +01:00
0fe009d37c stages/authenticator_webauthn: add missing migration 2021-03-05 14:14:37 +01:00
49db283e71 build(deps): bump boto3 from 1.17.20 to 1.17.21 (#613)
Bumps [boto3](https://github.com/boto/boto3) from 1.17.20 to 1.17.21.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.17.20...1.17.21)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-05 09:27:03 +01:00
7058366623 build(deps): bump defusedxml from 0.6.0 to 0.7.0 (#614)
Bumps [defusedxml](https://github.com/tiran/defusedxml) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/tiran/defusedxml/releases)
- [Changelog](https://github.com/tiran/defusedxml/blob/master/CHANGES.txt)
- [Commits](https://github.com/tiran/defusedxml/compare/v0.6.0...v0.7.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-05 09:26:42 +01:00
ced45513b8 build(deps-dev): bump typescript from 4.2.2 to 4.2.3 in /web (#615)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.2.2 to 4.2.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-05 09:26:18 +01:00
15e15c9635 docs: add 2021.3.2 2021-03-04 09:40:27 +01:00
d53c82eee2 core: fix link on login template 2021-03-04 09:39:13 +01:00
213 changed files with 38527 additions and 5042 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2021.3.2
current_version = 2021.3.4
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)
@ -36,3 +36,7 @@ values =
[bumpversion:file:outpost/pkg/version.go]
[bumpversion:file:web/src/constants.ts]
[bumpversion:file:website/docs/outposts/manual-deploy-docker-compose.md]
[bumpversion:file:website/docs/outposts/manual-deploy-kubernetes.md]

View File

@ -18,11 +18,11 @@ jobs:
- name: Building Docker Image
run: docker build
--no-cache
-t beryju/authentik:2021.3.2
-t beryju/authentik:2021.3.4
-t beryju/authentik:latest
-f Dockerfile .
- name: Push Docker Container to Registry (versioned)
run: docker push beryju/authentik:2021.3.2
run: docker push beryju/authentik:2021.3.4
- name: Push Docker Container to Registry (latest)
run: docker push beryju/authentik:latest
build-proxy:
@ -48,17 +48,20 @@ jobs:
cd outpost/
docker build \
--no-cache \
-t beryju/authentik-proxy:2021.3.2 \
-t beryju/authentik-proxy:2021.3.4 \
-t beryju/authentik-proxy:latest \
-f proxy.Dockerfile .
- name: Push Docker Container to Registry (versioned)
run: docker push beryju/authentik-proxy:2021.3.2
run: docker push beryju/authentik-proxy:2021.3.4
- name: Push Docker Container to Registry (latest)
run: docker push beryju/authentik-proxy:latest
build-static:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: prepare ts api client
run: |
docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/src/api --additional-properties=typescriptThreePlus=true
- name: Docker Login Registry
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
@ -69,11 +72,11 @@ jobs:
cd web/
docker build \
--no-cache \
-t beryju/authentik-static:2021.3.2 \
-t beryju/authentik-static:2021.3.4 \
-t beryju/authentik-static:latest \
-f Dockerfile .
- name: Push Docker Container to Registry (versioned)
run: docker push beryju/authentik-static:2021.3.2
run: docker push beryju/authentik-static:2021.3.4
- name: Push Docker Container to Registry (latest)
run: docker push beryju/authentik-static:latest
test-release:
@ -107,5 +110,5 @@ jobs:
SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org
with:
tagName: 2021.3.2
tagName: 2021.3.4
environment: beryjuorg-prod

View File

@ -15,6 +15,9 @@ WORKDIR /
COPY --from=locker /app/requirements.txt /
COPY --from=locker /app/requirements-dev.txt /
ARG GIT_BUILD_HASH
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
RUN apt-get update && \
apt-get install -y --no-install-recommends curl ca-certificates gnupg && \
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \
@ -45,4 +48,5 @@ COPY ./lifecycle/ /lifecycle
USER authentik
STOPSIGNAL SIGINT
ENV TMPDIR /dev/shm/
ENV PYTHONUBUFFERED 1
ENTRYPOINT [ "/lifecycle/bootstrap.sh" ]

174
Pipfile.lock generated
View File

@ -18,45 +18,45 @@
"default": {
"aiohttp": {
"hashes": [
"sha256:119feb2bd551e58d83d1b38bfa4cb921af8ddedec9fad7183132db334c3133e0",
"sha256:16d0683ef8a6d803207f02b899c928223eb219111bd52420ef3d7a8aa76227b6",
"sha256:2eb3efe243e0f4ecbb654b08444ae6ffab37ac0ef8f69d3a2ffb958905379daf",
"sha256:2ffea7904e70350da429568113ae422c88d2234ae776519549513c8f217f58a9",
"sha256:40bd1b101b71a18a528ffce812cc14ff77d4a2a1272dfb8b11b200967489ef3e",
"sha256:418597633b5cd9639e514b1d748f358832c08cd5d9ef0870026535bd5eaefdd0",
"sha256:481d4b96969fbfdcc3ff35eea5305d8565a8300410d3d269ccac69e7256b1329",
"sha256:4c1bdbfdd231a20eee3e56bd0ac1cd88c4ff41b64ab679ed65b75c9c74b6c5c2",
"sha256:5563ad7fde451b1986d42b9bb9140e2599ecf4f8e42241f6da0d3d624b776f40",
"sha256:58c62152c4c8731a3152e7e650b29ace18304d086cb5552d317a54ff2749d32a",
"sha256:5b50e0b9460100fe05d7472264d1975f21ac007b35dcd6fd50279b72925a27f4",
"sha256:5d84ecc73141d0a0d61ece0742bb7ff5751b0657dab8405f899d3ceb104cc7de",
"sha256:5dde6d24bacac480be03f4f864e9a67faac5032e28841b00533cd168ab39cad9",
"sha256:5e91e927003d1ed9283dee9abcb989334fc8e72cf89ebe94dc3e07e3ff0b11e9",
"sha256:62bc216eafac3204877241569209d9ba6226185aa6d561c19159f2e1cbb6abfb",
"sha256:6c8200abc9dc5f27203986100579fc19ccad7a832c07d2bc151ce4ff17190076",
"sha256:6ca56bdfaf825f4439e9e3673775e1032d8b6ea63b8953d3812c71bd6a8b81de",
"sha256:71680321a8a7176a58dfbc230789790639db78dad61a6e120b39f314f43f1907",
"sha256:7c7820099e8b3171e54e7eedc33e9450afe7cd08172632d32128bd527f8cb77d",
"sha256:7dbd087ff2f4046b9b37ba28ed73f15fd0bc9f4fdc8ef6781913da7f808d9536",
"sha256:822bd4fd21abaa7b28d65fc9871ecabaddc42767884a626317ef5b75c20e8a2d",
"sha256:8ec1a38074f68d66ccb467ed9a673a726bb397142c273f90d4ba954666e87d54",
"sha256:950b7ef08b2afdab2488ee2edaff92a03ca500a48f1e1aaa5900e73d6cf992bc",
"sha256:99c5a5bf7135607959441b7d720d96c8e5c46a1f96e9d6d4c9498be8d5f24212",
"sha256:b84ad94868e1e6a5e30d30ec419956042815dfaea1b1df1cef623e4564c374d9",
"sha256:bc3d14bf71a3fb94e5acf5bbf67331ab335467129af6416a437bd6024e4f743d",
"sha256:c2a80fd9a8d7e41b4e38ea9fe149deed0d6aaede255c497e66b8213274d6d61b",
"sha256:c44d3c82a933c6cbc21039326767e778eface44fca55c65719921c4b9661a3f7",
"sha256:cc31e906be1cc121ee201adbdf844522ea3349600dd0a40366611ca18cd40e81",
"sha256:d5d102e945ecca93bcd9801a7bb2fa703e37ad188a2f81b1e65e4abe4b51b00c",
"sha256:dd7936f2a6daa861143e376b3a1fb56e9b802f4980923594edd9ca5670974895",
"sha256:dee68ec462ff10c1d836c0ea2642116aba6151c6880b688e56b4c0246770f297",
"sha256:e76e78863a4eaec3aee5722d85d04dcbd9844bc6cd3bfa6aa880ff46ad16bfcb",
"sha256:eab51036cac2da8a50d7ff0ea30be47750547c9aa1aa2cf1a1b710a1827e7dbe",
"sha256:f4496d8d04da2e98cc9133e238ccebf6a13ef39a93da2e87146c8c8ac9768242",
"sha256:fbd3b5e18d34683decc00d9a360179ac1e7a320a5fee10ab8053ffd6deab76e0",
"sha256:feb24ff1226beeb056e247cf2e24bba5232519efb5645121c4aea5b6ad74c1f2"
"sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe",
"sha256:0563c1b3826945eecd62186f3f5c7d31abb7391fedc893b7e2b26303b5a9f3fe",
"sha256:114b281e4d68302a324dd33abb04778e8557d88947875cbf4e842c2c01a030c5",
"sha256:14762875b22d0055f05d12abc7f7d61d5fd4fe4642ce1a249abdf8c700bf1fd8",
"sha256:15492a6368d985b76a2a5fdd2166cddfea5d24e69eefed4630cbaae5c81d89bd",
"sha256:17c073de315745a1510393a96e680d20af8e67e324f70b42accbd4cb3315c9fb",
"sha256:209b4a8ee987eccc91e2bd3ac36adee0e53a5970b8ac52c273f7f8fd4872c94c",
"sha256:230a8f7e24298dea47659251abc0fd8b3c4e38a664c59d4b89cca7f6c09c9e87",
"sha256:2e19413bf84934d651344783c9f5e22dee452e251cfd220ebadbed2d9931dbf0",
"sha256:393f389841e8f2dfc86f774ad22f00923fdee66d238af89b70ea314c4aefd290",
"sha256:3cf75f7cdc2397ed4442594b935a11ed5569961333d49b7539ea741be2cc79d5",
"sha256:3d78619672183be860b96ed96f533046ec97ca067fd46ac1f6a09cd9b7484287",
"sha256:40eced07f07a9e60e825554a31f923e8d3997cfc7fb31dbc1328c70826e04cde",
"sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf",
"sha256:4b302b45040890cea949ad092479e01ba25911a15e648429c7c5aae9650c67a8",
"sha256:515dfef7f869a0feb2afee66b957cc7bbe9ad0cdee45aec7fdc623f4ecd4fb16",
"sha256:547da6cacac20666422d4882cfcd51298d45f7ccb60a04ec27424d2f36ba3eaf",
"sha256:5df68496d19f849921f05f14f31bd6ef53ad4b00245da3195048c69934521809",
"sha256:64322071e046020e8797117b3658b9c2f80e3267daec409b350b6a7a05041213",
"sha256:7615dab56bb07bff74bc865307aeb89a8bfd9941d2ef9d817b9436da3a0ea54f",
"sha256:79ebfc238612123a713a457d92afb4096e2148be17df6c50fb9bf7a81c2f8013",
"sha256:7b18b97cf8ee5452fa5f4e3af95d01d84d86d32c5e2bfa260cf041749d66360b",
"sha256:932bb1ea39a54e9ea27fc9232163059a0b8855256f4052e776357ad9add6f1c9",
"sha256:a00bb73540af068ca7390e636c01cbc4f644961896fa9363154ff43fd37af2f5",
"sha256:a5ca29ee66f8343ed336816c553e82d6cade48a3ad702b9ffa6125d187e2dedb",
"sha256:af9aa9ef5ba1fd5b8c948bb11f44891968ab30356d65fd0cc6707d989cd521df",
"sha256:bb437315738aa441251214dad17428cafda9cdc9729499f1d6001748e1d432f4",
"sha256:bdb230b4943891321e06fc7def63c7aace16095be7d9cf3b1e01be2f10fba439",
"sha256:c6e9dcb4cb338d91a73f178d866d051efe7c62a7166653a91e7d9fb18274058f",
"sha256:cffe3ab27871bc3ea47df5d8f7013945712c46a3cc5a95b6bee15887f1675c22",
"sha256:d012ad7911653a906425d8473a1465caa9f8dea7fcf07b6d870397b774ea7c0f",
"sha256:d9e13b33afd39ddeb377eff2c1c4f00544e191e1d1dee5b6c51ddee8ea6f0cf5",
"sha256:e4b2b334e68b18ac9817d828ba44d8fcb391f6acb398bcc5062b14b2cbeac970",
"sha256:e54962802d4b8b18b6207d4a927032826af39395a3bd9196a5af43fc4e60b009",
"sha256:f705e12750171c0ab4ef2a3c76b9a4024a62c4103e3a55dd6f99265b9bc6fcfc",
"sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a",
"sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95"
],
"version": "==3.7.4"
"version": "==3.7.4.post0"
},
"aioredis": {
"hashes": [
@ -116,18 +116,17 @@
},
"boto3": {
"hashes": [
"sha256:2219f1ebe88d266afa5516f993983eba8742b957fa4fd6854f3c73aa3030e931",
"sha256:c0d51f344b71656c2d395d2168600d91bea252a64fb5d503a955ea96426cde8b"
"sha256:64a8900b3a110e2d6ff4d87f4d8cd56f0c8527361d9fc9385fcb50efe7a4975a",
"sha256:8e9ff8006c41889ed8a11831dee62adf922e071f14d54c52946d1f7855ae7a8e"
],
"index": "pypi",
"version": "==1.17.20"
"version": "==1.17.26"
},
"botocore": {
"hashes": [
"sha256:80c32a81fb1ee8bdfa074a79bfb885bb2006e8a9782f2353c0c9f6392704e13a",
"sha256:e9e724b59278ebf5caf032be1e32bde0990d79e8052e3bbbb97b6c1d32feba28"
"sha256:4a785847a351e59f2329627fc9a19cf50f07644ea68996a1595d5a20487a423f"
],
"version": "==1.20.20"
"version": "==1.20.26"
},
"cachetools": {
"hashes": [
@ -217,10 +216,10 @@
},
"chardet": {
"hashes": [
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
"sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa",
"sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"
],
"version": "==3.0.4"
"version": "==4.0.0"
},
"click": {
"hashes": [
@ -304,11 +303,11 @@
},
"defusedxml": {
"hashes": [
"sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93",
"sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5"
"sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69",
"sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"
],
"index": "pypi",
"version": "==0.6.0"
"version": "==0.7.1"
},
"django": {
"hashes": [
@ -445,10 +444,10 @@
},
"google-auth": {
"hashes": [
"sha256:d3640ea61ee025d5af00e3ffd82ba0a06dd99724adaf50bdd52f49daf29f3f65",
"sha256:da5218cbf33b8461d7661d6b4ad91c12c0107e2767904d5e3ae6408031d5463e"
"sha256:63a5636d7eacfe6ef5b7e36e112b3149fa1c5b5ad77dd6df54910459bcd6b89f",
"sha256:d8958af6968e4ecd599f82357ebcfeb126f826ed0656126ad68416f810f7531e"
],
"version": "==1.27.0"
"version": "==1.27.1"
},
"gunicorn": {
"hashes": [
@ -817,10 +816,10 @@
},
"prompt-toolkit": {
"hashes": [
"sha256:0fa02fa80363844a4ab4b8d6891f62dd0645ba672723130423ca4037b80c1974",
"sha256:62c811e46bd09130fb11ab759012a4ae385ce4fb2073442d1898867a824183bd"
"sha256:4cea7d09e46723885cb8bc54678175453e5071e9449821dce6f017b1d1fbfc1a",
"sha256:9397a7162cf45449147ad6042fa37983a081b8a73363a5253dd4072666333137"
],
"version": "==3.0.16"
"version": "==3.0.17"
},
"psycopg2-binary": {
"hashes": [
@ -1024,15 +1023,23 @@
"sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
"sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
"sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
"sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347",
"sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
"sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541",
"sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
"sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
"sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc",
"sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
"sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa",
"sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
"sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122",
"sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
"sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
"sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc",
"sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247",
"sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6",
"sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"
],
"index": "pypi",
"version": "==5.4.1"
@ -1069,10 +1076,47 @@
},
"ruamel.yaml": {
"hashes": [
"sha256:012b9470a0ea06e4e44e99e7920277edf6b46eee0232a04487ea73a7386340a5",
"sha256:076cc0bc34f1966d920a49f18b52b6ad559fbe656a0748e3535cf7b3f29ebf9e"
"sha256:64b06e7873eb8e1125525ecef7345447d786368cadca92a7cd9b59eae62e95a3",
"sha256:bb48c514222702878759a05af96f4b7ecdba9b33cd4efcf25c86b882cef3a942"
],
"version": "==0.16.12"
"version": "==0.16.13"
},
"ruamel.yaml.clib": {
"hashes": [
"sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b",
"sha256:1236df55e0f73cd138c0eca074ee086136c3f16a97c2ac719032c050f7e0622f",
"sha256:1f8c0a4577c0e6c99d208de5c4d3fd8aceed9574bb154d7a2b21c16bb924154c",
"sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91",
"sha256:28116f204103cb3a108dfd37668f20abe6e3cafd0d3fd40dba126c732457b3cc",
"sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7",
"sha256:2fd336a5c6415c82e2deb40d08c222087febe0aebe520f4d21910629018ab0f3",
"sha256:30dca9bbcbb1cc858717438218d11eafb78666759e5094dd767468c0d577a7e7",
"sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6",
"sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6",
"sha256:46d6d20815064e8bb023ea8628cfb7402c0f0e83de2c2227a88097e239a7dffd",
"sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0",
"sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62",
"sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99",
"sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5",
"sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026",
"sha256:6c0a5dc52fc74eb87c67374a4e554d4761fd42a4d01390b7e868b30d21f4b8bb",
"sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2",
"sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1",
"sha256:75f0ee6839532e52a3a53f80ce64925ed4aed697dd3fa890c4c918f3304bd4f4",
"sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b",
"sha256:8be05be57dc5c7b4a0b24edcaa2f7275866d9c907725226cdde46da09367d923",
"sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e",
"sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c",
"sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988",
"sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f",
"sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5",
"sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a",
"sha256:daf21aa33ee9b351f66deed30a3d450ab55c14242cfdfcd377798e2c0d25c9f1",
"sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2",
"sha256:f6061a31880c1ed6b6ce341215336e2f3d0c1deccd84957b6fa8ca474b41e89f"
],
"markers": "platform_python_implementation == 'CPython' and python_version < '3.10'",
"version": "==0.2.2"
},
"s3transfer": {
"hashes": [
@ -1765,15 +1809,23 @@
"sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
"sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
"sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
"sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347",
"sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
"sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541",
"sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
"sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
"sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc",
"sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
"sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa",
"sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
"sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122",
"sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
"sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
"sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"
"sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc",
"sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247",
"sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6",
"sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"
],
"index": "pypi",
"version": "==5.4.1"

View File

@ -1,2 +1,3 @@
"""authentik"""
__version__ = "2021.3.2"
__version__ = "2021.3.4"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -7,8 +7,8 @@ from django.db.models import Count, ExpressionWrapper, F, Model
from django.db.models.fields import DurationField
from django.db.models.functions import ExtractHour
from django.utils.timezone import now
from drf_yasg2.utils import swagger_auto_schema
from rest_framework.fields import SerializerMethodField
from drf_yasg2.utils import swagger_auto_schema, swagger_serializer_method
from rest_framework.fields import IntegerField, SerializerMethodField
from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request
from rest_framework.response import Response
@ -37,23 +37,39 @@ def get_events_per_1h(**filter_kwargs) -> list[dict[str, int]]:
for hour in range(0, -24, -1):
results.append(
{
"x": time.mktime((_now + timedelta(hours=hour)).timetuple()) * 1000,
"y": data[hour * -1],
"x_cord": time.mktime((_now + timedelta(hours=hour)).timetuple())
* 1000,
"y_cord": data[hour * -1],
}
)
return results
class AdministrationMetricsSerializer(Serializer):
class CoordinateSerializer(Serializer):
"""Coordinates for diagrams"""
x_cord = IntegerField(read_only=True)
y_cord = IntegerField(read_only=True)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
def update(self, instance: Model, validated_data: dict) -> Model:
raise NotImplementedError
class LoginMetricsSerializer(Serializer):
"""Login Metrics per 1h"""
logins_per_1h = SerializerMethodField()
logins_failed_per_1h = SerializerMethodField()
@swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True))
def get_logins_per_1h(self, _):
"""Get successful logins per hour for the last 24 hours"""
return get_events_per_1h(action=EventAction.LOGIN)
@swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True))
def get_logins_failed_per_1h(self, _):
"""Get failed logins per hour for the last 24 hours"""
return get_events_per_1h(action=EventAction.LOGIN_FAILED)
@ -70,8 +86,8 @@ class AdministrationMetricsViewSet(ViewSet):
permission_classes = [IsAdminUser]
@swagger_auto_schema(responses={200: AdministrationMetricsSerializer(many=True)})
@swagger_auto_schema(responses={200: LoginMetricsSerializer(many=False)})
def list(self, request: Request) -> Response:
"""Login Metrics per 1h"""
serializer = AdministrationMetricsSerializer(True)
serializer = LoginMetricsSerializer(True)
return Response(serializer.data)

View File

@ -25,8 +25,8 @@ class TaskSerializer(Serializer):
task_finish_timestamp = DateTimeField(source="finish_timestamp")
status = ChoiceField(
source="result.status.value",
choices=[(x.value, x.name) for x in TaskResultStatus],
source="result.status.name",
choices=[(x.name, x.name) for x in TaskResultStatus],
)
messages = ListField(source="result.messages")

View File

@ -1,4 +1,6 @@
"""authentik administration overview"""
from os import environ
from django.core.cache import cache
from django.db.models import Model
from drf_yasg2.utils import swagger_auto_schema
@ -11,7 +13,7 @@ from rest_framework.response import Response
from rest_framework.serializers import Serializer
from rest_framework.viewsets import GenericViewSet
from authentik import __version__
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version
@ -20,8 +22,13 @@ class VersionSerializer(Serializer):
version_current = SerializerMethodField()
version_latest = SerializerMethodField()
build_hash = SerializerMethodField()
outdated = SerializerMethodField()
def get_build_hash(self, _) -> str:
"""Get build hash, if version is not latest or released"""
return environ.get(ENV_GIT_HASH_KEY, "")
def get_version_current(self, _) -> str:
"""Get current version"""
return __version__

View File

@ -1,4 +1,5 @@
"""api v2 urls"""
from django.conf import settings
from django.urls import path, re_path
from drf_yasg2 import openapi
from drf_yasg2.views import get_schema_view
@ -54,12 +55,24 @@ from authentik.providers.saml.api import SAMLPropertyMappingViewSet, SAMLProvide
from authentik.sources.ldap.api import LDAPPropertyMappingViewSet, LDAPSourceViewSet
from authentik.sources.oauth.api import OAuthSourceViewSet
from authentik.sources.saml.api import SAMLSourceViewSet
from authentik.stages.authenticator_static.api import AuthenticatorStaticStageViewSet
from authentik.stages.authenticator_totp.api import AuthenticatorTOTPStageViewSet
from authentik.stages.authenticator_static.api import (
AuthenticatorStaticStageViewSet,
StaticAdminDeviceViewSet,
StaticDeviceViewSet,
)
from authentik.stages.authenticator_totp.api import (
AuthenticatorTOTPStageViewSet,
TOTPAdminDeviceViewSet,
TOTPDeviceViewSet,
)
from authentik.stages.authenticator_validate.api import (
AuthenticatorValidateStageViewSet,
)
from authentik.stages.authenticator_webauthn.api import AuthenticateWebAuthnStageViewSet
from authentik.stages.authenticator_webauthn.api import (
AuthenticateWebAuthnStageViewSet,
WebAuthnAdminDeviceViewSet,
WebAuthnDeviceViewSet,
)
from authentik.stages.captcha.api import CaptchaStageViewSet
from authentik.stages.consent.api import ConsentStageViewSet
from authentik.stages.deny.api import DenyStageViewSet
@ -133,6 +146,13 @@ router.register("propertymappings/ldap", LDAPPropertyMappingViewSet)
router.register("propertymappings/saml", SAMLPropertyMappingViewSet)
router.register("propertymappings/scope", ScopeMappingViewSet)
router.register("authenticators/static", StaticDeviceViewSet)
router.register("authenticators/totp", TOTPDeviceViewSet)
router.register("authenticators/webauthn", WebAuthnDeviceViewSet)
router.register("authenticators/admin/static", StaticAdminDeviceViewSet)
router.register("authenticators/admin/totp", TOTPAdminDeviceViewSet)
router.register("authenticators/admin/webauthn", WebAuthnAdminDeviceViewSet)
router.register("stages/all", StageViewSet)
router.register("stages/authenticator/static", AuthenticatorStaticStageViewSet)
router.register("stages/authenticator/totp", AuthenticatorTOTPStageViewSet)
@ -164,27 +184,26 @@ info = openapi.Info(
name="GNU GPLv3", url="https://github.com/BeryJu/authentik/blob/master/LICENSE"
),
)
SchemaView = get_schema_view(
info,
public=True,
permission_classes=(AllowAny,),
)
SchemaView = get_schema_view(info, public=True, permission_classes=(AllowAny,))
urlpatterns = [
re_path(
r"^swagger(?P<format>\.json|\.yaml)$",
SchemaView.without_ui(cache_timeout=0),
name="schema-json",
),
path(
"swagger/",
SchemaView.with_ui("swagger", cache_timeout=0),
name="schema-swagger-ui",
),
path("redoc/", SchemaView.with_ui("redoc", cache_timeout=0), name="schema-redoc"),
urlpatterns = router.urls + [
path(
"flows/executor/<slug:flow_slug>/",
FlowExecutorView.as_view(),
name="flow-executor",
),
] + router.urls
re_path(
r"^swagger(?P<format>\.json|\.yaml)$",
SchemaView.without_ui(cache_timeout=0),
name="schema-json",
),
]
if settings.DEBUG:
urlpatterns = urlpatterns + [
path(
"swagger/",
SchemaView.with_ui("swagger", cache_timeout=0),
name="schema-swagger-ui",
),
]

View File

@ -2,6 +2,7 @@
from django.core.cache import cache
from django.db.models import QuerySet
from django.http.response import Http404
from drf_yasg2.utils import swagger_auto_schema
from guardian.shortcuts import get_objects_for_user
from rest_framework.decorators import action
from rest_framework.fields import SerializerMethodField
@ -13,7 +14,7 @@ from rest_framework.viewsets import ModelViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter
from structlog.stdlib import get_logger
from authentik.admin.api.metrics import get_events_per_1h
from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h
from authentik.core.api.providers import ProviderSerializer
from authentik.core.models import Application
from authentik.events.models import EventAction
@ -109,6 +110,7 @@ class ApplicationViewSet(ModelViewSet):
serializer = self.get_serializer(allowed_applications, many=True)
return self.get_paginated_response(serializer.data)
@swagger_auto_schema(responses={200: CoordinateSerializer(many=True)})
@action(detail=True)
def metrics(self, request: Request, slug: str):
"""Metrics for application logins"""

View File

@ -21,3 +21,4 @@ class GroupViewSet(ModelViewSet):
serializer_class = GroupSerializer
search_fields = ["name", "is_superuser"]
filterset_fields = ["name", "is_superuser"]
ordering = ["name"]

View File

@ -28,9 +28,9 @@ class MetaNameSerializer(Serializer):
class TypeCreateSerializer(Serializer):
"""Types of an object that can be created"""
name = CharField(read_only=True)
description = CharField(read_only=True)
link = CharField(read_only=True)
name = CharField(required=True)
description = CharField(required=True)
link = CharField(required=True)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError

View File

@ -11,9 +11,7 @@
<title>{% block title %}{% trans title|default:config.authentik.branding.title %}{% endblock %}</title>
<link rel="icon" type="image/png" href="{% static 'dist/assets/icons/icon.png' %}?v={{ ak_version }}">
<link rel="shortcut icon" type="image/png" href="{% static 'dist/assets/icons/icon.png' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly-addons.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/fontawesome.min.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly-base.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}?v={{ ak_version }}">
<script src="{% url 'javascript-catalog' %}?v={{ ak_version }}"></script>
{% block head %}

View File

@ -1,9 +1,6 @@
{% extends container_template|default:"administration/base.html" %}
{% load i18n %}
{% load authentik_utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
{% block above_form %}
@ -38,4 +35,3 @@
<input class="pf-c-button pf-m-danger" type="submit" form="delete-form" value="{% trans 'Delete' %}" />
<a class="pf-c-button pf-m-secondary" href="{% back %}">{% trans "Back" %}</a>
</footer>
{% endblock %}

View File

@ -18,7 +18,7 @@
<div class="pf-c-background-image">
<svg xmlns="http://www.w3.org/2000/svg" class="pf-c-background-image__filter" width="0" height="0">
<filter id="image_overlay">
<feColorMatrix type="matrix" values="1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0"></feColorMatrix>
<feColorMatrix in="SourceGraphic" type="matrix" values="1.3 0 0 0 0 0 1.3 0 0 0 0 0 1.3 0 0 0 0 0 1 0" />
<feComponentTransfer color-interpolation-filters="sRGB" result="duotone">
<feFuncR type="table" tableValues="0.086274509803922 0.43921568627451"></feFuncR>
<feFuncG type="table" tableValues="0.086274509803922 0.43921568627451"></feFuncG>
@ -48,7 +48,7 @@
{% endfor %}
{% if config.authentik.branding.title != "authentik" %}
<li>
<a href="https://github.com/beryju/authentik">
<a href="https://goauthentik.io">
{% trans 'Powered by authentik' %}
</a>
</li>

View File

@ -13,7 +13,7 @@
<p>{% trans "Configure settings relevant to your user profile." %}</p>
</div>
</section>
<ak-tabs vertical="true">
<ak-tabs vertical="true" style="height: 100%;">
<section slot="page-1" data-tab-title="{% trans 'User details' %}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75">

View File

@ -7,6 +7,7 @@ from django.contrib.auth.mixins import (
)
from django.contrib.messages.views import SuccessMessageMixin
from django.http.response import HttpResponse
from django.urls import reverse_lazy
from django.utils.translation import gettext as _
from django.views.generic import UpdateView
from django.views.generic.base import TemplateView
@ -34,7 +35,7 @@ class UserDetailsView(SuccessMessageMixin, LoginRequiredMixin, UpdateView):
form_class = UserDetailForm
success_message = _("Successfully updated user.")
success_url = "/"
success_url = reverse_lazy("authentik_core:user-details")
def get_object(self):
return self.request.user

View File

@ -13,7 +13,7 @@ class NotificationSerializer(ModelSerializer):
body = ReadOnlyField()
severity = ReadOnlyField()
event = EventSerializer()
event = EventSerializer(required=False)
class Meta:

View File

@ -1,11 +1,12 @@
"""NotificationTransport API Views"""
from django.http.response import Http404
from drf_yasg2.utils import no_body, swagger_auto_schema
from guardian.shortcuts import get_objects_for_user
from rest_framework.decorators import action
from rest_framework.fields import SerializerMethodField
from rest_framework.fields import CharField, ListField, SerializerMethodField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.serializers import ModelSerializer, Serializer
from rest_framework.viewsets import ModelViewSet
from authentik.events.models import (
@ -38,12 +39,28 @@ class NotificationTransportSerializer(ModelSerializer):
]
class NotificationTransportTestSerializer(Serializer):
"""Notification test serializer"""
messages = ListField(child=CharField())
def create(self, request: Request) -> Response:
raise NotImplementedError
def update(self, request: Request) -> Response:
raise NotImplementedError
class NotificationTransportViewSet(ModelViewSet):
"""NotificationTransport Viewset"""
queryset = NotificationTransport.objects.all()
serializer_class = NotificationTransportSerializer
@swagger_auto_schema(
responses={200: NotificationTransportTestSerializer(many=False)},
request_body=no_body,
)
@action(detail=True, methods=["post"])
# pylint: disable=invalid-name
def test(self, request: Request, pk=None) -> Response:
@ -61,6 +78,10 @@ class NotificationTransportViewSet(ModelViewSet):
user=request.user,
)
try:
return Response(transport.send(notification))
response = NotificationTransportTestSerializer(
data={"messages": transport.send(notification)}
)
response.is_valid()
return Response(response.data)
except NotificationTransportError as exc:
return Response(str(exc.__cause__ or None), status=503)

View File

@ -12,7 +12,10 @@ def get_geoip_reader() -> Optional[Reader]:
path = CONFIG.y("authentik.geoip")
if path == "" or not path:
return None
return Reader(path)
try:
return Reader(path)
except OSError:
return None
GEOIP_READER = get_geoip_reader()

View File

@ -38,7 +38,9 @@ class Challenge(Serializer):
"""Challenge that gets sent to the client based on which stage
is currently active"""
type = ChoiceField(choices=list(ChallengeTypes))
type = ChoiceField(
choices=[(x.name, x.name) for x in ChallengeTypes],
)
component = CharField(required=False)
title = CharField(required=False)
@ -90,7 +92,7 @@ class ChallengeResponse(Serializer):
stage: Optional["StageView"]
def __init__(self, instance, data, **kwargs):
def __init__(self, instance=None, data=None, **kwargs):
self.stage = kwargs.pop("stage", None)
super().__init__(instance=instance, data=data, **kwargs)

View File

@ -4,6 +4,7 @@ from django.http import HttpRequest
from django.http.request import QueryDict
from django.http.response import HttpResponse
from django.views.generic.base import View
from rest_framework.request import Request
from structlog.stdlib import get_logger
from authentik.core.models import DEFAULT_AVATAR, User
@ -67,9 +68,9 @@ class ChallengeStageView(StageView):
return HttpChallengeResponse(challenge)
# pylint: disable=unused-argument
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
def post(self, request: Request, *args, **kwargs) -> HttpResponse:
"""Handle challenge response"""
challenge: ChallengeResponse = self.get_response_instance(data=request.POST)
challenge: ChallengeResponse = self.get_response_instance(data=request.data)
if not challenge.is_valid():
return self.challenge_invalid(challenge)
return self.challenge_valid(challenge)

View File

@ -9,11 +9,16 @@ from django.template.response import TemplateResponse
from django.utils.decorators import method_decorator
from django.views.decorators.clickjacking import xframe_options_sameorigin
from django.views.generic import TemplateView, View
from drf_yasg2.utils import no_body, swagger_auto_schema
from rest_framework.permissions import AllowAny
from rest_framework.views import APIView
from structlog.stdlib import BoundLogger, get_logger
from authentik.core.models import USER_ATTRIBUTE_DEBUG
from authentik.events.models import cleanse_dict
from authentik.flows.challenge import (
Challenge,
ChallengeResponse,
ChallengeTypes,
HttpChallengeResponse,
RedirectChallenge,
@ -40,9 +45,11 @@ SESSION_KEY_GET = "authentik_flows_get"
@method_decorator(xframe_options_sameorigin, name="dispatch")
class FlowExecutorView(View):
class FlowExecutorView(APIView):
"""Stage 1 Flow executor, passing requests to Stage Views"""
permission_classes = [AllowAny]
flow: Flow
plan: Optional[FlowPlan] = None
@ -113,8 +120,13 @@ class FlowExecutorView(View):
self.current_stage_view.request = request
return super().dispatch(request)
@swagger_auto_schema(
responses={200: Challenge()},
request_body=no_body,
operation_id="flows_executor_get",
)
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""pass get request to current stage"""
"""Get the next pending challenge from the currently active flow."""
self._logger.debug(
"f(exec): Passing GET",
view_class=class_to_path(self.current_stage_view.__class__),
@ -127,8 +139,13 @@ class FlowExecutorView(View):
self._logger.exception(exc)
return to_stage_response(request, FlowErrorResponse(request, exc))
@swagger_auto_schema(
responses={200: Challenge()},
request_body=ChallengeResponse(),
operation_id="flows_executor_solve",
)
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""pass post request to current stage"""
"""Solve the previously retrieved challenge and advanced to the next stage."""
self._logger.debug(
"f(exec): Passing POST",
view_class=class_to_path(self.current_stage_view.__class__),
@ -175,8 +192,10 @@ class FlowExecutorView(View):
"f(exec): Continuing with next stage",
reamining=len(self.plan.stages),
)
kwargs = self.kwargs
kwargs.update({"flow_slug": self.flow.slug})
return redirect_with_qs(
"authentik_api:flow-executor", self.request.GET, **self.kwargs
"authentik_api:flow-executor", self.request.GET, **kwargs
)
# User passed all stages
self._logger.debug(

View File

@ -13,6 +13,7 @@ redis:
ws_db: 2
debug: false
log_level: info
# Error reporting, sends stacktrace to sentry.beryju.org

View File

@ -55,13 +55,21 @@ class OutpostConsumer(AuthJsonConsumer):
OutpostState(
uid=self.channel_name, last_seen=datetime.now(), _outpost=self.outpost
).save(timeout=OUTPOST_HELLO_INTERVAL * 1.5)
LOGGER.debug("added channel to cache", channel_name=self.channel_name)
LOGGER.debug(
"added outpost instace to cache",
outpost=self.outpost,
channel_name=self.channel_name,
)
# pylint: disable=unused-argument
def disconnect(self, close_code):
if self.outpost:
OutpostState.for_channel(self.outpost, self.channel_name).delete()
LOGGER.debug("removed channel from cache", channel_name=self.channel_name)
LOGGER.debug(
"removed outpost instance from cache",
outpost=self.outpost,
channel_name=self.channel_name,
)
def receive_json(self, content: Data):
msg = from_dict(WebsocketMessage, content)

View File

@ -26,5 +26,5 @@ def invalidate_policy_cache(sender, instance, **_):
cache.delete_many(keys)
LOGGER.debug("Invalidating policy cache", policy=instance, keys=total)
# Also delete user application cache
keys = cache.keys(user_app_cache_key("*"))
keys = cache.keys(user_app_cache_key("*")) or []
cache.delete_many(keys)

View File

@ -101,7 +101,9 @@ def protected_resource_view(scopes: list[str]):
This decorator also injects the token into `kwargs`"""
def wrapper(view):
def view_wrapper(request, *args, **kwargs):
def view_wrapper(request: HttpRequest, *args, **kwargs):
if request.method == "OPTIONS":
return view(request, *args, **kwargs)
try:
access_token = extract_access_token(request)
if not access_token:

View File

@ -19,6 +19,7 @@ from authentik.providers.oauth2.models import (
ResponseTypes,
ScopeMapping,
)
from authentik.providers.oauth2.utils import cors_allow_any
LOGGER = get_logger()
@ -103,9 +104,10 @@ class ProviderInfoView(View):
provider: OAuth2Provider = get_object_or_404(
OAuth2Provider, pk=application.provider_id
)
response = JsonResponse(
self.get_info(provider), json_dumps_params={"indent": 2}
)
response["Access-Control-Allow-Origin"] = "*"
return JsonResponse(self.get_info(provider), json_dumps_params={"indent": 2})
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
# Since this view only supports get, we can statically set the CORS headers
response = super().dispatch(request, *args, **kwargs)
cors_allow_any(request, response)
return response

View File

@ -74,7 +74,7 @@ class SAMLFlowFinalView(ChallengeStageView):
return super().get(
self.request,
**{
"type": ChallengeTypes.native,
"type": ChallengeTypes.native.value,
"component": "ak-stage-autosubmit",
"title": "Redirecting to %(app)s..." % {"app": application.name},
"url": provider.acs_url,

View File

@ -24,7 +24,7 @@ from sentry_sdk.integrations.celery import CeleryIntegration
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.redis import RedisIntegration
from authentik import __version__
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik.core.middleware import structlog_add_request_id
from authentik.lib.config import CONFIG
from authentik.lib.logging import add_process_id
@ -150,7 +150,6 @@ SWAGGER_SETTINGS = {
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": "authentik.api.pagination.Pagination",
"PAGE_SIZE": 100,
"DATETIME_FORMAT": "%s",
"DEFAULT_FILTER_BACKENDS": [
"rest_framework_guardian.filters.ObjectPermissionsFilter",
"django_filters.rest_framework.DjangoFilterBackend",
@ -475,6 +474,7 @@ for _app in INSTALLED_APPS:
if DEBUG:
CELERY_TASK_ALWAYS_EAGER = True
os.environ[ENV_GIT_HASH_KEY] = "dev"
INSTALLED_APPS.append("authentik.core.apps.AuthentikCoreConfig")

View File

@ -15,9 +15,11 @@ class OAuthSourceForm(forms.ModelForm):
self.fields["authentication_flow"].queryset = Flow.objects.filter(
designation=FlowDesignation.AUTHENTICATION
)
self.fields["authentication_flow"].required = True
self.fields["enrollment_flow"].queryset = Flow.objects.filter(
designation=FlowDesignation.ENROLLMENT
)
self.fields["enrollment_flow"].required = True
if hasattr(self.Meta, "overrides"):
for overide_field, overide_value in getattr(self.Meta, "overrides").items():
self.fields[overide_field].initial = overide_value

View File

@ -4,6 +4,7 @@ from typing import Any, Optional
from django.conf import settings
from django.contrib import messages
from django.http import Http404, HttpRequest, HttpResponse
from django.http.response import HttpResponseBadRequest
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.translation import gettext as _
@ -151,6 +152,8 @@ class OAuthCallback(OAuthClientMixin, View):
PLAN_CONTEXT_REDIRECT: final_redirect,
}
)
if not flow:
return HttpResponseBadRequest()
# We run the Flow planner here so we can pass the Pending user in the context
planner = FlowPlanner(flow)
plan = planner.plan(self.request, kwargs)
@ -233,6 +236,9 @@ class OAuthCallback(OAuthClientMixin, View):
PLAN_CONTEXT_SOURCES_OAUTH_ACCESS: access,
}
# We run the Flow planner here so we can pass the Pending user in the context
if not source.enrollment_flow:
LOGGER.warning("source has no enrollment flow", source=source)
return HttpResponseBadRequest()
planner = FlowPlanner(source.enrollment_flow)
plan = planner.plan(self.request, context)
plan.append(in_memory_stage(PostUserEnrollmentStage))

View File

@ -1,5 +1,8 @@
"""AuthenticatorStaticStage API Views"""
from rest_framework.viewsets import ModelViewSet
from django_otp.plugins.otp_static.models import StaticDevice
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from authentik.flows.api.stages import StageSerializer
from authentik.stages.authenticator_static.models import AuthenticatorStaticStage
@ -19,3 +22,39 @@ class AuthenticatorStaticStageViewSet(ModelViewSet):
queryset = AuthenticatorStaticStage.objects.all()
serializer_class = AuthenticatorStaticStageSerializer
class StaticDeviceSerializer(ModelSerializer):
"""Serializer for static authenticator devices"""
class Meta:
model = StaticDevice
fields = ["name", "token_set"]
depth = 2
class StaticDeviceViewSet(ModelViewSet):
"""Viewset for static authenticator devices"""
queryset = StaticDevice.objects.none()
serializer_class = StaticDeviceSerializer
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]
def get_queryset(self):
if not self.request:
return super().get_queryset()
return StaticDevice.objects.filter(user=self.request.user)
class StaticAdminDeviceViewSet(ReadOnlyModelViewSet):
"""Viewset for static authenticator devices (for admins)"""
permission_classes = [IsAdminUser]
queryset = StaticDevice.objects.all()
serializer_class = StaticDeviceSerializer
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]

View File

@ -31,7 +31,7 @@ class AuthenticatorStaticStageView(ChallengeStageView):
tokens: list[StaticToken] = self.request.session[SESSION_STATIC_TOKENS]
return AuthenticatorStaticChallenge(
data={
"type": ChallengeTypes.native,
"type": ChallengeTypes.native.value,
"component": "ak-stage-authenticator-static",
"codes": [token.token for token in tokens],
}

View File

@ -34,7 +34,8 @@ class UserSettingsView(LoginRequiredMixin, TemplateView):
class DisableView(LoginRequiredMixin, View):
"""Disable Static Tokens for user"""
def get(self, request: HttpRequest) -> HttpResponse:
# pylint: disable=unused-argument
def get(self, request: HttpRequest, **kwargs) -> HttpResponse:
"""Delete all the devices for user"""
devices = StaticDevice.objects.filter(user=request.user, confirmed=True)
devices.delete()

View File

@ -1,5 +1,8 @@
"""AuthenticatorTOTPStage API Views"""
from rest_framework.viewsets import ModelViewSet
from django_otp.plugins.otp_totp.models import TOTPDevice
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from authentik.flows.api.stages import StageSerializer
from authentik.stages.authenticator_totp.models import AuthenticatorTOTPStage
@ -19,3 +22,41 @@ class AuthenticatorTOTPStageViewSet(ModelViewSet):
queryset = AuthenticatorTOTPStage.objects.all()
serializer_class = AuthenticatorTOTPStageSerializer
class TOTPDeviceSerializer(ModelSerializer):
"""Serializer for totp authenticator devices"""
class Meta:
model = TOTPDevice
fields = [
"name",
]
depth = 2
class TOTPDeviceViewSet(ModelViewSet):
"""Viewset for totp authenticator devices"""
queryset = TOTPDevice.objects.none()
serializer_class = TOTPDeviceSerializer
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]
def get_queryset(self):
if not self.request:
return super().get_queryset()
return TOTPDevice.objects.filter(user=self.request.user)
class TOTPAdminDeviceViewSet(ReadOnlyModelViewSet):
"""Viewset for totp authenticator devices (for admins)"""
permission_classes = [IsAdminUser]
queryset = TOTPDevice.objects.all()
serializer_class = TOTPDeviceSerializer
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]

View File

@ -51,7 +51,7 @@ class AuthenticatorTOTPStageView(ChallengeStageView):
device: TOTPDevice = self.request.session[SESSION_TOTP_DEVICE]
return AuthenticatorTOTPChallenge(
data={
"type": ChallengeTypes.native,
"type": ChallengeTypes.native.value,
"component": "ak-stage-authenticator-totp",
"config_url": device.config_url,
}

View File

@ -145,7 +145,7 @@ class AuthenticatorValidateStageView(ChallengeStageView):
challenges = self.request.session["device_challenges"]
return AuthenticatorChallenge(
data={
"type": ChallengeTypes.native,
"type": ChallengeTypes.native.value,
"component": "ak-stage-authenticator-validate",
"device_challenges": challenges,
}

View File

@ -1,8 +1,13 @@
"""AuthenticateWebAuthnStage API Views"""
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from authentik.flows.api.stages import StageSerializer
from authentik.stages.authenticator_webauthn.models import AuthenticateWebAuthnStage
from authentik.stages.authenticator_webauthn.models import (
AuthenticateWebAuthnStage,
WebAuthnDevice,
)
class AuthenticateWebAuthnStageSerializer(StageSerializer):
@ -19,3 +24,41 @@ class AuthenticateWebAuthnStageViewSet(ModelViewSet):
queryset = AuthenticateWebAuthnStage.objects.all()
serializer_class = AuthenticateWebAuthnStageSerializer
class WebAuthnDeviceSerializer(ModelSerializer):
"""Serializer for WebAuthn authenticator devices"""
class Meta:
model = WebAuthnDevice
fields = [
"name",
]
depth = 2
class WebAuthnDeviceViewSet(ModelViewSet):
"""Viewset for WebAuthn authenticator devices"""
queryset = WebAuthnDevice.objects.none()
serializer_class = WebAuthnDeviceSerializer
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]
def get_queryset(self):
if not self.request:
return super().get_queryset()
return WebAuthnDevice.objects.filter(user=self.request.user)
class WebAuthnAdminDeviceViewSet(ReadOnlyModelViewSet):
"""Viewset for WebAuthn authenticator devices (for admins)"""
permission_classes = [IsAdminUser]
queryset = WebAuthnDevice.objects.all()
serializer_class = WebAuthnDeviceSerializer
search_fields = ["name"]
filterset_fields = ["name"]
ordering = ["name"]

View File

@ -0,0 +1,20 @@
# Generated by Django 3.1.7 on 2021-03-04 18:50
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("authentik_stages_authenticator_webauthn", "0003_webauthndevice_confirmed"),
]
operations = [
migrations.AlterModelOptions(
name="webauthndevice",
options={
"verbose_name": "WebAuthn Device",
"verbose_name_plural": "WebAuthn Devices",
},
),
]

View File

@ -122,7 +122,7 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView):
return AuthenticatorWebAuthnChallenge(
data={
"type": ChallengeTypes.native,
"type": ChallengeTypes.native.value,
"component": "ak-stage-authenticator-webauthn",
"registration": make_credential_options.registration_dict,
}

View File

@ -63,7 +63,7 @@ class CaptchaStageView(ChallengeStageView):
def get_challenge(self, *args, **kwargs) -> Challenge:
return CaptchaChallenge(
data={
"type": ChallengeTypes.native,
"type": ChallengeTypes.native.value,
"component": "ak-stage-captcha",
"site_key": self.executor.current_stage.public_key,
}

View File

@ -38,7 +38,7 @@ class ConsentStageView(ChallengeStageView):
def get_challenge(self) -> Challenge:
challenge = ConsentChallenge(
data={
"type": ChallengeTypes.native,
"type": ChallengeTypes.native.value,
"component": "ak-stage-consent",
}
)

View File

@ -24,7 +24,7 @@ class DummyStageView(ChallengeStageView):
def get_challenge(self, *args, **kwargs) -> Challenge:
return DummyChallenge(
data={
"type": ChallengeTypes.native,
"type": ChallengeTypes.native.value,
"component": "",
"title": self.executor.current_stage.name,
}

View File

@ -94,7 +94,7 @@ class EmailStageView(ChallengeStageView):
def get_challenge(self) -> Challenge:
challenge = EmailChallenge(
data={"type": ChallengeTypes.native, "component": "ak-stage-email"}
data={"type": ChallengeTypes.native.value, "component": "ak-stage-email"}
)
return challenge

View File

@ -78,7 +78,7 @@ class IdentificationStageView(ChallengeStageView):
current_stage: IdentificationStage = self.executor.current_stage
challenge = IdentificationChallenge(
data={
"type": ChallengeTypes.native,
"type": ChallengeTypes.native.value,
"component": "ak-stage-identification",
"primary_action": _("Log in"),
"input_type": "text",

View File

@ -78,7 +78,7 @@ class PasswordStageView(ChallengeStageView):
def get_challenge(self) -> Challenge:
challenge = PasswordChallenge(
data={
"type": ChallengeTypes.native,
"type": ChallengeTypes.native.value,
"component": "ak-stage-password",
}
)

View File

@ -164,7 +164,7 @@ class PromptStageView(ChallengeStageView):
fields = list(self.executor.current_stage.fields.all().order_by("order"))
challenge = PromptChallenge(
data={
"type": ChallengeTypes.native,
"type": ChallengeTypes.native.value,
"component": "ak-stage-prompt",
"fields": [PromptSerializer(field).data for field in fields],
},

View File

@ -279,6 +279,7 @@ stages:
displayName: Build static files for e2e
inputs:
script: |
docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/src/api --additional-properties=typescriptThreePlus=true
cd web
npm i
npm run build
@ -380,6 +381,13 @@ stages:
inputs:
containerRegistry: 'beryjuorg-harbor'
repository: 'authentik/server'
command: 'buildAndPush'
command: 'build'
Dockerfile: 'Dockerfile'
tags: "gh-$(branchName)"
tags: 'gh-$(branchName)'
arguments: '--build-arg GIT_BUILD_HASH=$(Build.SourceVersion)'
- task: Docker@2
inputs:
containerRegistry: 'beryjuorg-harbor'
repository: 'authentik/server'
command: 'push'
tags: 'gh-$(branchName)'

View File

@ -19,7 +19,7 @@ services:
networks:
- internal
server:
image: beryju/authentik:${AUTHENTIK_TAG:-2021.3.2}
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.3.4}
command: server
environment:
AUTHENTIK_REDIS__HOST: redis
@ -27,9 +27,11 @@ services:
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
# AUTHENTIK_ERROR_REPORTING__ENABLED: true
volumes:
- ./media:/media
- ./custom-templates:/templates
- geoip:/geoip
ports:
- 8000
networks:
@ -45,7 +47,7 @@ services:
env_file:
- .env
worker:
image: beryju/authentik:${AUTHENTIK_TAG:-2021.3.2}
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.3.4}
command: worker
networks:
- internal
@ -55,14 +57,16 @@ services:
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
# AUTHENTIK_ERROR_REPORTING__ENABLED: true
volumes:
- ./backups:/backups
- /var/run/docker.sock:/var/run/docker.sock
- ./custom-templates:/templates
- geoip:/geoip
env_file:
- .env
static:
image: beryju/authentik-static:${AUTHENTIK_TAG:-2021.3.2}
image: ${AUTHENTIK_IMAGE_STATIC:-beryju/authentik-static}:${AUTHENTIK_TAG:-2021.3.4}
networks:
- internal
labels:
@ -91,10 +95,21 @@ services:
- "127.0.0.1:8080:8080"
networks:
- internal
geoipupdate:
image: "maxmindinc/geoipupdate:latest"
volumes:
- "geoip:/usr/share/GeoIP"
environment:
GEOIPUPDATE_EDITION_IDS: "GeoLite2-City"
GEOIPUPDATE_FREQUENCY: "8"
env_file:
- .env
volumes:
database:
driver: local
geoip:
driver: local
networks:
internal: {}

View File

@ -4,7 +4,7 @@ name: authentik
home: https://goauthentik.io
sources:
- https://github.com/BeryJu/authentik
version: "2021.3.2"
version: "2021.3.4"
icon: https://raw.githubusercontent.com/BeryJu/authentik/master/web/icons/icon.svg
dependencies:
- name: postgresql

View File

@ -4,7 +4,7 @@
|-----------------------------------|-------------------------|-------------|
| image.name | beryju/authentik | Image used to run the authentik server and worker |
| image.name_static | beryju/authentik-static | Image used to run the authentik static server (CSS and JS Files) |
| image.tag | 2021.3.2 | Image tag |
| image.tag | 2021.3.4 | Image tag |
| image.pullPolicy | IfNotPresent | Image Pull Policy used for all deployments |
| serverReplicas | 1 | Replicas for the Server deployment |
| workerReplicas | 1 | Replicas for the Worker deployment |
@ -22,6 +22,10 @@
| config.email.use_ssl | false | Enable SSL |
| config.email.timeout | 10 | SMTP Timeout |
| config.email.from | authentik@localhost | Email address authentik will send from, should have a correct @domain |
| geoip.enabled | false | Optionally enable GeoIP |
| geoip.accountId | | GeoIP MaxMind Account ID |
| geoip.licenseKey | | GeoIP MaxMind License key |
| geoip.image | maxmindinc/geoipupdate:latest | GeoIP Updater image |
| backup.accessKey | | Optionally enable S3 Backup, Access Key |
| backup.secretKey | | Optionally enable S3 Backup, Secret Key |
| backup.bucket | | Optionally enable S3 Backup, Bucket |

View File

@ -0,0 +1,11 @@
{{- if .Values.geoip.enabled -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "authentik.fullname" . }}-geoip-config
data:
GEOIPUPDATE_ACCOUNT_ID: "{{ .Values.geoip.accountId }}"
GEOIPUPDATE_LICENSE_KEY: "{{ .Values.geoip.licenseKey }}"
GEOIPUPDATE_EDITION_IDS: "GeoLite2-City"
GEOIPUPDATE_FREQUENCY: "8"
{{- end }}

View File

@ -0,0 +1,39 @@
{{- if .Values.geoip.enabled -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "authentik.fullname" . }}-geoip
labels:
app.kubernetes.io/name: {{ include "authentik.name" . }}
helm.sh/chart: {{ include "authentik.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
k8s.goauthentik.io/component: geoip
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: {{ include "authentik.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
k8s.goauthentik.io/component: geoip
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "authentik.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
k8s.goauthentik.io/component: geoip
spec:
containers:
- name: geoip
image: "{{ .Values.geoip.image }}"
envFrom:
- configMapRef:
name: {{ include "authentik.fullname" . }}-geoip-config
volumeMounts:
- name: geoip
mountPath: /usr/share/GeoIP
volumes:
- name: geoip
persistentVolumeClaim:
claimName: {{ include "authentik.fullname" . }}-geoip
{{- end }}

View File

@ -0,0 +1,17 @@
{{- if .Values.geoip.enabled -}}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "authentik.fullname" . }}-geoip
labels:
app.kubernetes.io/name: {{ include "authentik.name" . }}
helm.sh/chart: {{ include "authentik.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
{{- end }}

View File

@ -0,0 +1,121 @@
{{- if .Values.monitoring.enabled -}}
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: {{ include "authentik.fullname" . }}-static-rules
labels:
app.kubernetes.io/name: {{ include "authentik.name" . }}
helm.sh/chart: {{ include "authentik.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
groups:
- name: Aggregate request counters
rules:
- record: job:django_http_requests_before_middlewares_total:sum_rate30s
expr: sum(rate(django_http_requests_before_middlewares_total[30s])) by (job)
- record: job:django_http_requests_unknown_latency_total:sum_rate30s
expr: sum(rate(django_http_requests_unknown_latency_total[30s])) by (job)
- record: job:django_http_ajax_requests_total:sum_rate30s
expr: sum(rate(django_http_ajax_requests_total[30s])) by (job)
- record: job:django_http_responses_before_middlewares_total:sum_rate30s
expr: sum(rate(django_http_responses_before_middlewares_total[30s])) by (job)
- record: job:django_http_requests_unknown_latency_including_middlewares_total:sum_rate30s
expr: sum(rate(django_http_requests_unknown_latency_including_middlewares_total[30s])) by (job)
- record: job:django_http_requests_body_total_bytes:sum_rate30s
expr: sum(rate(django_http_requests_body_total_bytes[30s])) by (job)
- record: job:django_http_responses_streaming_total:sum_rate30s
expr: sum(rate(django_http_responses_streaming_total[30s])) by (job)
- record: job:django_http_responses_body_total_bytes:sum_rate30s
expr: sum(rate(django_http_responses_body_total_bytes[30s])) by (job)
- record: job:django_http_requests_total:sum_rate30s
expr: sum(rate(django_http_requests_total_by_method[30s])) by (job)
- record: job:django_http_requests_total_by_method:sum_rate30s
expr: sum(rate(django_http_requests_total_by_method[30s])) by (job,method)
- record: job:django_http_requests_total_by_transport:sum_rate30s
expr: sum(rate(django_http_requests_total_by_transport[30s])) by (job,transport)
- record: job:django_http_requests_total_by_view:sum_rate30s
expr: sum(rate(django_http_requests_total_by_view_transport_method[30s])) by (job,view)
- record: job:django_http_requests_total_by_view_transport_method:sum_rate30s
expr: sum(rate(django_http_requests_total_by_view_transport_method[30s])) by (job,view,transport,method)
- record: job:django_http_responses_total_by_templatename:sum_rate30s
expr: sum(rate(django_http_responses_total_by_templatename[30s])) by (job,templatename)
- record: job:django_http_responses_total_by_status:sum_rate30s
expr: sum(rate(django_http_responses_total_by_status[30s])) by (job,status)
- record: job:django_http_responses_total_by_status_name_method:sum_rate30s
expr: sum(rate(django_http_responses_total_by_status_name_method[30s])) by (job,status,name,method)
- record: job:django_http_responses_total_by_charset:sum_rate30s
expr: sum(rate(django_http_responses_total_by_charset[30s])) by (job,charset)
- record: job:django_http_exceptions_total_by_type:sum_rate30s
expr: sum(rate(django_http_exceptions_total_by_type[30s])) by (job,type)
- record: job:django_http_exceptions_total_by_view:sum_rate30s
expr: sum(rate(django_http_exceptions_total_by_view[30s])) by (job,view)
- name: Aggregate latency histograms
rules:
- record: job:django_http_requests_latency_including_middlewares_seconds:quantile_rate30s
expr: histogram_quantile(0.50, sum(rate(django_http_requests_latency_including_middlewares_seconds_bucket[30s])) by (job, le))
labels:
quantile: "50"
- record: job:django_http_requests_latency_including_middlewares_seconds:quantile_rate30s
expr: histogram_quantile(0.95, sum(rate(django_http_requests_latency_including_middlewares_seconds_bucket[30s])) by (job, le))
labels:
quantile: "95"
- record: job:django_http_requests_latency_including_middlewares_seconds:quantile_rate30s
expr: histogram_quantile(0.99, sum(rate(django_http_requests_latency_including_middlewares_seconds_bucket[30s])) by (job, le))
labels:
quantile: "99"
- record: job:django_http_requests_latency_including_middlewares_seconds:quantile_rate30s
expr: histogram_quantile(0.999, sum(rate(django_http_requests_latency_including_middlewares_seconds_bucket[30s])) by (job, le))
labels:
quantile: "99.9"
- record: job:django_http_requests_latency_seconds:quantile_rate30s
expr: histogram_quantile(0.50, sum(rate(django_http_requests_latency_seconds_bucket[30s])) by (job, le))
labels:
quantile: "50"
- record: job:django_http_requests_latency_seconds:quantile_rate30s
expr: histogram_quantile(0.95, sum(rate(django_http_requests_latency_seconds_bucket[30s])) by (job, le))
labels:
quantile: "95"
- record: job:django_http_requests_latency_seconds:quantile_rate30s
expr: histogram_quantile(0.99, sum(rate(django_http_requests_latency_seconds_bucket[30s])) by (job, le))
labels:
quantile: "99"
- record: job:django_http_requests_latency_seconds:quantile_rate30s
expr: histogram_quantile(0.999, sum(rate(django_http_requests_latency_seconds_bucket[30s])) by (job, le))
labels:
quantile: "99.9"
- name: Aggregate model operations
rules:
- record: job:django_model_inserts_total:sum_rate1m
expr: sum(rate(django_model_inserts_total[1m])) by (job, model)
- record: job:django_model_updates_total:sum_rate1m
expr: sum(rate(django_model_updates_total[1m])) by (job, model)
- record: job:django_model_deletes_total:sum_rate1m
expr: sum(rate(django_model_deletes_total[1m])) by (job, model)
- name: Aggregate database operations
rules:
- record: job:django_db_new_connections_total:sum_rate30s
expr: sum(rate(django_db_new_connections_total[30s])) by (alias, vendor)
- record: job:django_db_new_connection_errors_total:sum_rate30s
expr: sum(rate(django_db_new_connection_errors_total[30s])) by (alias, vendor)
- record: job:django_db_execute_total:sum_rate30s
expr: sum(rate(django_db_execute_total[30s])) by (alias, vendor)
- record: job:django_db_execute_many_total:sum_rate30s
expr: sum(rate(django_db_execute_many_total[30s])) by (alias, vendor)
- record: job:django_db_errors_total:sum_rate30s
expr: sum(rate(django_db_errors_total[30s])) by (alias, vendor, type)
- name: Aggregate migrations
rules:
- record: job:django_migrations_applied_total:max
expr: max(django_migrations_applied_total) by (job, connection)
- record: job:django_migrations_unapplied_total:max
expr: max(django_migrations_unapplied_total) by (job, connection)
- name: Alerts
rules:
- alert: UnappliedMigrations
expr: job:django_migrations_unapplied_total:max > 0
for: 1m
labels:
severity: testing
{{- end }}

View File

@ -0,0 +1,17 @@
{{- if .Values.monitoring.enabled -}}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
app.kubernetes.io/name: {{ include "authentik.name" . }}
helm.sh/chart: {{ include "authentik.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "authentik.fullname" . }}-static-monitoring
spec:
endpoints:
- port: http
selector:
matchLabels:
k8s.goauthentik.io/component: static
{{- end }}

View File

@ -88,9 +88,17 @@ spec:
secretKeyRef:
name: "{{ .Release.Name }}-postgresql"
key: "postgresql-password"
{{ if .Values.geoip.enabled -}}
- name: AUTHENTIK_AUTHENTIK__GEOIP
value: /geoip/GeoLite2-City.mmdb
{{- end }}
volumeMounts:
- name: authentik-uploads
mountPath: /media
{{ if .Values.geoip.enabled -}}
- name: geoip
mountPath: /geoip
{{- end }}
ports:
- name: http
containerPort: 8000
@ -116,3 +124,8 @@ spec:
- name: authentik-uploads
persistentVolumeClaim:
claimName: {{ include "authentik.fullname" . }}-uploads
{{ if .Values.geoip.enabled -}}
- name: geoip
persistentVolumeClaim:
claimName: {{ include "authentik.fullname" . }}-geoip
{{- end }}

View File

@ -0,0 +1,26 @@
{{- if .Values.monitoring.enabled -}}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
app.kubernetes.io/name: {{ include "authentik.name" . }}
helm.sh/chart: {{ include "authentik.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "authentik.fullname" . }}-web-monitoring
spec:
endpoints:
- basicAuth:
password:
name: {{ include "authentik.fullname" . }}-secret-key
key: SECRET_KEY
username:
name: {{ include "authentik.fullname" . }}-secret-key
key: monitoring_username
port: http
path: /metrics/
interval: 10s
selector:
matchLabels:
k8s.goauthentik.io/component: web
{{- end }}

View File

@ -68,6 +68,15 @@ spec:
secretKeyRef:
name: "{{ .Release.Name }}-postgresql"
key: "postgresql-password"
{{ if .Values.geoip.enabled -}}
- name: AUTHENTIK_AUTHENTIK__GEOIP
value: /geoip/GeoLite2-City.mmdb
{{- end }}
{{ if .Values.geoip.enabled -}}
volumeMounts:
- name: geoip
mountPath: /geoip
{{- end }}
resources:
requests:
cpu: 150m
@ -75,3 +84,9 @@ spec:
limits:
cpu: 300m
memory: 600M
{{ if .Values.geoip.enabled -}}
volumes:
- name: geoip
persistentVolumeClaim:
claimName: {{ include "authentik.fullname" . }}-geoip
{{- end -}}

View File

@ -1,22 +0,0 @@
image:
tag: gh-master
pullPolicy: Always
serverReplicas: 1
workerReplicas: 1
config:
# Log level used by web and worker
# Can be either debug, info, warning, error
logLevel: debug
ingress:
hosts:
- authentik.127.0.0.1.nip.io
# These values influence the bundled postgresql and redis charts, but are also used by authentik to connect
postgresql:
postgresqlPassword: EK-5jnKfjrGRm<77
redis:
password: password

View File

@ -5,7 +5,7 @@ image:
name: beryju/authentik
name_static: beryju/authentik-static
name_outposts: beryju/authentik # Prefix used for Outpost deployments, Outpost type and version is appended
tag: 2021.3.2
tag: 2021.3.4
pullPolicy: IfNotPresent
serverReplicas: 1
@ -14,6 +14,9 @@ workerReplicas: 1
# Enable the Kubernetes integration which lets authentik deploy outposts into kubernetes
kubernetesIntegration: true
monitoring:
enabled: true
config:
# Optionally specify fixed secret_key, otherwise generated automatically
# secretKey: _k*@6h2u2@q-dku57hhgzb7tnx*ba9wodcb^s9g0j59@=y(@_o
@ -41,6 +44,13 @@ config:
# Email address authentik will send from, should have a correct @domain
from: authentik@localhost
# Enable MaxMind GeoIP
geoip:
enabled: false
accountId: ""
licenseKey: ""
image: maxmindinc/geoipupdate:latest
# Enable Database Backups to S3
# backup:
# accessKey: access-key

View File

@ -33,7 +33,7 @@ stages:
- task: PublishPipelineArtifact@1
inputs:
targetPath: 'outpost/pkg/'
artifact: 'swagger_client'
artifact: 'go_swagger_client'
publishLocation: 'pipeline'
- stage: lint
jobs:
@ -51,7 +51,7 @@ stages:
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'swagger_client'
artifactName: 'go_swagger_client'
path: "outpost/pkg/"
- task: CmdLine@2
inputs:
@ -70,7 +70,7 @@ stages:
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'swagger_client'
artifactName: 'go_swagger_client'
path: "outpost/pkg/"
- task: Go@0
inputs:
@ -89,7 +89,7 @@ stages:
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'swagger_client'
artifactName: 'go_swagger_client'
path: "outpost/pkg/"
- task: Bash@3
inputs:

View File

@ -24,7 +24,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/pquerna/cachecontrol v0.0.0-20200921180117-858c6e7e6b7e // indirect
github.com/recws-org/recws v1.2.1
github.com/sirupsen/logrus v1.8.0
github.com/sirupsen/logrus v1.8.1
github.com/spf13/afero v1.5.1 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect

View File

@ -618,6 +618,8 @@ github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=

View File

@ -1,3 +1,3 @@
package pkg
const VERSION = "2021.3.2"
const VERSION = "2021.3.4"

View File

@ -1,4 +1,4 @@
FROM golang:1.16.0 AS builder
FROM golang:1.16.2 AS builder
WORKDIR /work

File diff suppressed because it is too large Load Diff

View File

@ -93,7 +93,10 @@ class TestFlowsEnroll(SeleniumTestCase):
self.initial_stages()
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "ak-sidebar")))
interface_admin = self.get_shadow_root("ak-interface-admin")
wait = WebDriverWait(interface_admin, self.wait_timeout)
wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "ak-sidebar")))
self.driver.get(self.shell_url("authentik_core:user-settings"))
user = User.objects.get(username="foo")
@ -188,7 +191,11 @@ class TestFlowsEnroll(SeleniumTestCase):
self.driver.switch_to.window(self.driver.window_handles[0])
# We're now logged in
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "ak-sidebar")))
wait = WebDriverWait(
self.get_shadow_root("ak-interface-admin"), self.wait_timeout
)
wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "ak-sidebar")))
self.driver.get(self.shell_url("authentik_core:user-settings"))
self.assert_user(User.objects.get(username="foo"))

View File

@ -0,0 +1,273 @@
"""test OAuth2 OpenID Provider flow"""
from json import loads
from sys import platform
from time import sleep
from unittest.case import skipUnless
from docker import DockerClient, from_env
from docker.models.containers import Container
from docker.types import Healthcheck
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from structlog.stdlib import get_logger
from authentik.core.models import Application
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow
from authentik.policies.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding
from authentik.providers.oauth2.constants import (
SCOPE_OPENID,
SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE,
)
from authentik.providers.oauth2.generators import (
generate_client_id,
generate_client_secret,
)
from authentik.providers.oauth2.models import ClientTypes, OAuth2Provider, ScopeMapping
from tests.e2e.utils import (
USER,
SeleniumTestCase,
apply_migration,
object_manager,
retry,
)
LOGGER = get_logger()
@skipUnless(platform.startswith("linux"), "requires local docker")
class TestProviderOAuth2OIDCImplicit(SeleniumTestCase):
"""test OAuth with OpenID Provider flow"""
def setUp(self):
self.client_id = generate_client_id()
self.client_secret = generate_client_secret()
self.application_slug = "test"
super().setUp()
def setup_client(self) -> Container:
"""Setup client saml-sp container which we test SAML against"""
sleep(1)
client: DockerClient = from_env()
container = client.containers.run(
image="beryju/oidc-test-client",
detach=True,
network_mode="host",
auto_remove=True,
healthcheck=Healthcheck(
test=["CMD", "wget", "--spider", "http://localhost:9009/health"],
interval=5 * 100 * 1000000,
start_period=1 * 100 * 1000000,
),
environment={
"OIDC_CLIENT_ID": self.client_id,
"OIDC_CLIENT_SECRET": self.client_secret,
"OIDC_PROVIDER": f"{self.live_server_url}/application/o/{self.application_slug}/",
},
)
while True:
container.reload()
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
if status == "healthy":
return container
LOGGER.info("Container failed healthcheck")
sleep(1)
@retry()
@apply_migration("authentik_core", "0003_default_user")
@apply_migration("authentik_flows", "0008_default_flows")
@apply_migration("authentik_flows", "0010_provider_flows")
@apply_migration("authentik_crypto", "0002_create_self_signed_kp")
def test_redirect_uri_error(self):
"""test OpenID Provider flow (invalid redirect URI, check error message)"""
sleep(1)
# Bootstrap all needed objects
authorization_flow = Flow.objects.get(
slug="default-provider-authorization-implicit-consent"
)
provider = OAuth2Provider.objects.create(
name=self.application_slug,
client_type=ClientTypes.CONFIDENTIAL,
client_id=self.client_id,
client_secret=self.client_secret,
rsa_key=CertificateKeyPair.objects.first(),
redirect_uris="http://localhost:9009/",
authorization_flow=authorization_flow,
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
)
)
provider.save()
Application.objects.create(
name=self.application_slug,
slug=self.application_slug,
provider=provider,
)
self.container = self.setup_client()
self.driver.get("http://localhost:9009/implicit/")
sleep(2)
self.assertEqual(
self.driver.find_element(By.CLASS_NAME, "pf-c-title").text,
"Redirect URI Error",
)
@retry()
@apply_migration("authentik_core", "0003_default_user")
@apply_migration("authentik_flows", "0008_default_flows")
@apply_migration("authentik_flows", "0010_provider_flows")
@apply_migration("authentik_crypto", "0002_create_self_signed_kp")
@object_manager
def test_authorization_consent_implied(self):
"""test OpenID Provider flow (default authorization flow with implied consent)"""
sleep(1)
# Bootstrap all needed objects
authorization_flow = Flow.objects.get(
slug="default-provider-authorization-implicit-consent"
)
provider = OAuth2Provider.objects.create(
name=self.application_slug,
client_type=ClientTypes.CONFIDENTIAL,
client_id=self.client_id,
client_secret=self.client_secret,
rsa_key=CertificateKeyPair.objects.first(),
redirect_uris="http://localhost:9009/implicit/",
authorization_flow=authorization_flow,
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
)
)
provider.save()
Application.objects.create(
name=self.application_slug,
slug=self.application_slug,
provider=provider,
)
self.container = self.setup_client()
self.driver.get("http://localhost:9009/implicit/")
self.login()
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "pre")))
sleep(1)
body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text)
print(body)
self.assertEqual(body["profile"]["nickname"], USER().username)
self.assertEqual(body["profile"]["name"], USER().name)
self.assertEqual(body["profile"]["email"], USER().email)
@retry()
@apply_migration("authentik_core", "0003_default_user")
@apply_migration("authentik_flows", "0008_default_flows")
@apply_migration("authentik_flows", "0010_provider_flows")
@apply_migration("authentik_crypto", "0002_create_self_signed_kp")
@object_manager
def test_authorization_consent_explicit(self):
"""test OpenID Provider flow (default authorization flow with explicit consent)"""
sleep(1)
# Bootstrap all needed objects
authorization_flow = Flow.objects.get(
slug="default-provider-authorization-explicit-consent"
)
provider = OAuth2Provider.objects.create(
name=self.application_slug,
authorization_flow=authorization_flow,
client_type=ClientTypes.CONFIDENTIAL,
client_id=self.client_id,
client_secret=self.client_secret,
rsa_key=CertificateKeyPair.objects.first(),
redirect_uris="http://localhost:9009/implicit/",
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
)
)
provider.save()
app = Application.objects.create(
name=self.application_slug,
slug=self.application_slug,
provider=provider,
)
self.container = self.setup_client()
self.driver.get("http://localhost:9009/implicit/")
self.login()
self.wait.until(
ec.presence_of_element_located((By.CSS_SELECTOR, "ak-flow-executor"))
)
flow_executor = self.get_shadow_root("ak-flow-executor")
consent_stage = self.get_shadow_root("ak-stage-consent", flow_executor)
self.assertIn(
app.name,
consent_stage.find_element(By.CSS_SELECTOR, "#header-text").text,
)
consent_stage.find_element(
By.CSS_SELECTOR,
("[type=submit]"),
).click()
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "pre")))
sleep(1)
body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text)
self.assertEqual(body["profile"]["nickname"], USER().username)
self.assertEqual(body["profile"]["name"], USER().name)
self.assertEqual(body["profile"]["email"], USER().email)
@retry()
@apply_migration("authentik_core", "0003_default_user")
@apply_migration("authentik_flows", "0008_default_flows")
@apply_migration("authentik_flows", "0010_provider_flows")
@apply_migration("authentik_crypto", "0002_create_self_signed_kp")
def test_authorization_denied(self):
"""test OpenID Provider flow (default authorization with access deny)"""
sleep(1)
# Bootstrap all needed objects
authorization_flow = Flow.objects.get(
slug="default-provider-authorization-explicit-consent"
)
provider = OAuth2Provider.objects.create(
name=self.application_slug,
authorization_flow=authorization_flow,
client_type=ClientTypes.CONFIDENTIAL,
client_id=self.client_id,
client_secret=self.client_secret,
rsa_key=CertificateKeyPair.objects.first(),
redirect_uris="http://localhost:9009/implicit/",
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
)
)
provider.save()
app = Application.objects.create(
name=self.application_slug,
slug=self.application_slug,
provider=provider,
)
negative_policy = ExpressionPolicy.objects.create(
name="negative-static", expression="return False"
)
PolicyBinding.objects.create(target=app, policy=negative_policy, order=0)
self.container = self.setup_client()
self.driver.get("http://localhost:9009/implicit/")
self.login()
self.wait.until(
ec.presence_of_element_located((By.CSS_SELECTOR, "header > h1"))
)
self.assertEqual(
self.driver.find_element(By.CSS_SELECTOR, "header > h1").text,
"Permission denied",
)

View File

@ -3,11 +3,13 @@ from shutil import rmtree
from tempfile import mkdtemp
from time import sleep
import yaml
from django.test import TestCase
from docker import DockerClient, from_env
from docker.models.containers import Container
from docker.types.healthcheck import Healthcheck
from authentik import __version__
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow
from authentik.outposts.apps import AuthentikOutpostConfig
@ -93,3 +95,14 @@ class OutpostDockerTests(TestCase):
controller = DockerController(self.outpost, self.service_connection)
controller.up()
controller.down()
def test_docker_static(self):
"""test that deployment requires update"""
controller = DockerController(self.outpost, self.service_connection)
manifest = controller.get_static_deployment()
compose = yaml.load(manifest, Loader=yaml.SafeLoader)
self.assertEqual(compose["version"], "3.5")
self.assertEqual(
compose["services"]["authentik_proxy"]["image"],
f"beryju/authentik-proxy:{__version__}",
)

View File

@ -0,0 +1,108 @@
"""outpost tests"""
from shutil import rmtree
from tempfile import mkdtemp
from time import sleep
import yaml
from django.test import TestCase
from docker import DockerClient, from_env
from docker.models.containers import Container
from docker.types.healthcheck import Healthcheck
from authentik import __version__
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow
from authentik.outposts.apps import AuthentikOutpostConfig
from authentik.outposts.models import DockerServiceConnection, Outpost, OutpostType
from authentik.providers.proxy.controllers.docker import DockerController
from authentik.providers.proxy.models import ProxyProvider
class TestProxyDocker(TestCase):
"""Test Docker Controllers"""
def _start_container(self, ssl_folder: str) -> Container:
client: DockerClient = from_env()
container = client.containers.run(
image="library/docker:dind",
detach=True,
network_mode="host",
remove=True,
privileged=True,
healthcheck=Healthcheck(
test=["CMD", "docker", "info"],
interval=5 * 100 * 1000000,
start_period=5 * 100 * 1000000,
),
environment={"DOCKER_TLS_CERTDIR": "/ssl"},
volumes={
f"{ssl_folder}/": {
"bind": "/ssl",
}
},
)
while True:
container.reload()
status = container.attrs.get("State", {}).get("Health", {}).get("Status")
if status == "healthy":
return container
sleep(1)
def setUp(self):
super().setUp()
self.ssl_folder = mkdtemp()
self.container = self._start_container(self.ssl_folder)
# Ensure that local connection have been created
AuthentikOutpostConfig.init_local_connection()
self.provider: ProxyProvider = ProxyProvider.objects.create(
name="test",
internal_host="http://localhost",
external_host="http://localhost",
authorization_flow=Flow.objects.first(),
)
authentication_kp = CertificateKeyPair.objects.create(
name="docker-authentication",
certificate_data=open(f"{self.ssl_folder}/client/cert.pem").read(),
key_data=open(f"{self.ssl_folder}/client/key.pem").read(),
)
verification_kp = CertificateKeyPair.objects.create(
name="docker-verification",
certificate_data=open(f"{self.ssl_folder}/client/ca.pem").read(),
)
self.service_connection = DockerServiceConnection.objects.create(
url="https://localhost:2376",
tls_verification=verification_kp,
tls_authentication=authentication_kp,
)
self.outpost: Outpost = Outpost.objects.create(
name="test",
type=OutpostType.PROXY,
service_connection=self.service_connection,
)
self.outpost.providers.add(self.provider)
self.outpost.save()
def tearDown(self) -> None:
super().tearDown()
self.container.kill()
try:
rmtree(self.ssl_folder)
except PermissionError:
pass
def test_docker_controller(self):
"""test that deployment requires update"""
controller = DockerController(self.outpost, self.service_connection)
controller.up()
controller.down()
def test_docker_static(self):
"""test that deployment requires update"""
controller = DockerController(self.outpost, self.service_connection)
manifest = controller.get_static_deployment()
compose = yaml.load(manifest, Loader=yaml.SafeLoader)
self.assertEqual(compose["version"], "3.5")
self.assertEqual(
compose["services"]["authentik_proxy"]["image"],
f"beryju/authentik-proxy:{__version__}",
)

View File

@ -9,7 +9,7 @@ from authentik.providers.proxy.controllers.kubernetes import ProxyKubernetesCont
from authentik.providers.proxy.models import ProxyProvider
class TestControllers(TestCase):
class TestProxyKubernetes(TestCase):
"""Test Controllers"""
def setUp(self):

View File

@ -4,3 +4,8 @@ node_modules
dist
# don't lint nyc coverage output
coverage
# don't lint generated code
src/api/apis
src/api/models
src/api/index.ts
src/api/runtime.ts

View File

@ -10,6 +10,25 @@ variables:
branchName: ${{ replace(variables['Build.SourceBranchName'], 'refs/heads/', '') }}
stages:
- stage: generate
jobs:
- job: swagger_generate
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: '12.x'
displayName: 'Install Node.js'
- task: CmdLine@2
inputs:
script: |
docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/src/api --additional-properties=typescriptThreePlus=true
- task: PublishPipelineArtifact@1
inputs:
targetPath: 'web/src/api/'
artifact: 'ts_swagger_client'
publishLocation: 'pipeline'
- stage: lint
jobs:
- job: eslint
@ -20,6 +39,11 @@ stages:
inputs:
versionSpec: '12.x'
displayName: 'Install Node.js'
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'ts_swagger_client'
path: "web/src/api/"
- task: Npm@1
inputs:
command: 'install'
@ -37,6 +61,11 @@ stages:
inputs:
versionSpec: '12.x'
displayName: 'Install Node.js'
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'ts_swagger_client'
path: "web/src/api/"
- task: Npm@1
inputs:
command: 'install'
@ -56,6 +85,11 @@ stages:
inputs:
versionSpec: '12.x'
displayName: 'Install Node.js'
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'ts_swagger_client'
path: "web/src/api/"
- task: Npm@1
inputs:
command: 'install'
@ -71,16 +105,21 @@ stages:
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Bash@3
inputs:
targetType: 'inline'
script: |
python ./scripts/az_do_set_branch.py
- task: Docker@2
inputs:
containerRegistry: 'beryjuorg-harbor'
repository: 'authentik/static'
command: 'buildAndPush'
Dockerfile: 'web/Dockerfile'
tags: "gh-$(branchName)"
buildContext: 'web/'
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'ts_swagger_client'
path: "web/src/api/"
- task: Bash@3
inputs:
targetType: 'inline'
script: |
python ./scripts/az_do_set_branch.py
- task: Docker@2
inputs:
containerRegistry: 'beryjuorg-harbor'
repository: 'authentik/static'
command: 'buildAndPush'
Dockerfile: 'web/Dockerfile'
tags: "gh-$(branchName)"
buildContext: 'web/'

406
web/package-lock.json generated
View File

@ -56,6 +56,15 @@
"strip-json-comments": "^3.1.1"
},
"dependencies": {
"globals": {
"version": "12.4.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
"integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
"dev": true,
"requires": {
"type-fest": "^0.8.1"
}
},
"ignore": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
@ -103,9 +112,9 @@
}
},
"@patternfly/patternfly": {
"version": "4.87.3",
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.87.3.tgz",
"integrity": "sha512-hDNMPa7B1zKD8LWFZO4SS5hC/N+yvuci2sAn8HJd+EIbAvbMAUkRsyZ0/XO3BG3RVtpSlgq7q8x1pAHC/FTFuA=="
"version": "4.90.5",
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.90.5.tgz",
"integrity": "sha512-Fe0C8UkzSjtacQ+fHXlFB/LHzrv/c2K4z479C6dboOgkGQE1FyB0wt1NBfxij0D++rhOy04OOYdE+Tr0JSlZKw=="
},
"@rollup/plugin-typescript": {
"version": "8.2.0",
@ -143,27 +152,27 @@
}
},
"@sentry/browser": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.2.1.tgz",
"integrity": "sha512-OAikFZ9EimD3noxMp8tA6Cf6qJcQ2U8k5QSgTPwdx+09nZOGJzbRFteK7WWmrS93ZJdzN61lpSQbg5v+bmmfbQ==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.2.2.tgz",
"integrity": "sha512-K5UGyEePtVPZIFMoiRafhd4Ov0M1kdozVsVKIPZrOpJyjQdPNX+fYDNL/h0nVmgOlE2S/uu4fl4mEfe/6aLShw==",
"requires": {
"@sentry/core": "6.2.1",
"@sentry/types": "6.2.1",
"@sentry/utils": "6.2.1",
"@sentry/core": "6.2.2",
"@sentry/types": "6.2.2",
"@sentry/utils": "6.2.2",
"tslib": "^1.9.3"
},
"dependencies": {
"@sentry/types": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.1.tgz",
"integrity": "sha512-h0OV1QT+fv5ojfK5/+iEXClu33HirmvbjcQC2jf05IHj9yXIOWy6EB10S8nBjuLiiFqQiAQYj3FN9Ip4eN8NJA=="
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.2.tgz",
"integrity": "sha512-Y/1sRtw3a5JU4YdNBig8lLSVJ1UdYtuge+QP1CVLcLSAbq07Ok1bvF+Z+BlNcnHqle2Fl8aKuryG5Yu86enOyQ=="
},
"@sentry/utils": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.1.tgz",
"integrity": "sha512-6kQgM/yBPdXu+3qbJnI6HBcWztN9QfiMkH++ZiKk4ERhg9d2LYWlze478uTU5Fyo/JQYcp+McpjtjpR9QIrr0g==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.2.tgz",
"integrity": "sha512-qaee6X6VDNZ8HeO83/veaKw0KuhDE7j1R+Yryme3PywFzsoTzutDrEQjb7gvcHAhBaAYX8IHUBHgxcFI9BxI+w==",
"requires": {
"@sentry/types": "6.2.1",
"@sentry/types": "6.2.2",
"tslib": "^1.9.3"
}
},
@ -175,48 +184,48 @@
}
},
"@sentry/core": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.2.1.tgz",
"integrity": "sha512-jPqQEtafxxDtLONhCbTHh/Uq8mZRhsfbwJTSVYfPVEe/ELfFZLQK7tP6rOh7zEWKbTkE0mE6XcaoH3ZRAhgrqg==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.2.2.tgz",
"integrity": "sha512-qqWbvvXtymfXh7N5eEvk97MCnMURuyFIgqWdVD4MQM6yIfDCy36CyGfuQ3ViHTLZGdIfEOhLL9/f4kzf1RzqBA==",
"requires": {
"@sentry/hub": "6.2.1",
"@sentry/minimal": "6.2.1",
"@sentry/types": "6.2.1",
"@sentry/utils": "6.2.1",
"@sentry/hub": "6.2.2",
"@sentry/minimal": "6.2.2",
"@sentry/types": "6.2.2",
"@sentry/utils": "6.2.2",
"tslib": "^1.9.3"
},
"dependencies": {
"@sentry/hub": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.2.1.tgz",
"integrity": "sha512-pG7wCQeRpzeP6t0bT4T0X029R19dbDS3/qswF8BL6bg0AI3afjfjBAZm/fqn1Uwe/uBoMHVVdbxgJDZeQ5d4rQ==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.2.2.tgz",
"integrity": "sha512-VR6uQGRYt6RP633FHShlSLj0LUKGVrlTeSlwCoooWM5FR9lmi6akAaweuxpG78/kZvXrAWpjX6/nuYwHKGwzGA==",
"requires": {
"@sentry/types": "6.2.1",
"@sentry/utils": "6.2.1",
"@sentry/types": "6.2.2",
"@sentry/utils": "6.2.2",
"tslib": "^1.9.3"
}
},
"@sentry/minimal": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.2.1.tgz",
"integrity": "sha512-wuSXB4Ayxv9rBEQ4pm7fnG4UU2ZPtPnnChoEfd4/mw1UthXSvmPFEn6O4pdo2G8fTkl8eqm6wT/Q7uIXMEmw+A==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.2.2.tgz",
"integrity": "sha512-l0IgoGQgg1lTd4qDU8bQn25sbZBg8PwIHfuTLbGMlRr1flDXHOM1UXajWK/UKbAPelnU7M2JBSVzgl7PwjprzA==",
"requires": {
"@sentry/hub": "6.2.1",
"@sentry/types": "6.2.1",
"@sentry/hub": "6.2.2",
"@sentry/types": "6.2.2",
"tslib": "^1.9.3"
}
},
"@sentry/types": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.1.tgz",
"integrity": "sha512-h0OV1QT+fv5ojfK5/+iEXClu33HirmvbjcQC2jf05IHj9yXIOWy6EB10S8nBjuLiiFqQiAQYj3FN9Ip4eN8NJA=="
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.2.tgz",
"integrity": "sha512-Y/1sRtw3a5JU4YdNBig8lLSVJ1UdYtuge+QP1CVLcLSAbq07Ok1bvF+Z+BlNcnHqle2Fl8aKuryG5Yu86enOyQ=="
},
"@sentry/utils": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.1.tgz",
"integrity": "sha512-6kQgM/yBPdXu+3qbJnI6HBcWztN9QfiMkH++ZiKk4ERhg9d2LYWlze478uTU5Fyo/JQYcp+McpjtjpR9QIrr0g==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.2.tgz",
"integrity": "sha512-qaee6X6VDNZ8HeO83/veaKw0KuhDE7j1R+Yryme3PywFzsoTzutDrEQjb7gvcHAhBaAYX8IHUBHgxcFI9BxI+w==",
"requires": {
"@sentry/types": "6.2.1",
"@sentry/types": "6.2.2",
"tslib": "^1.9.3"
}
},
@ -228,12 +237,12 @@
}
},
"@sentry/hub": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.2.1.tgz",
"integrity": "sha512-pG7wCQeRpzeP6t0bT4T0X029R19dbDS3/qswF8BL6bg0AI3afjfjBAZm/fqn1Uwe/uBoMHVVdbxgJDZeQ5d4rQ==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.2.2.tgz",
"integrity": "sha512-VR6uQGRYt6RP633FHShlSLj0LUKGVrlTeSlwCoooWM5FR9lmi6akAaweuxpG78/kZvXrAWpjX6/nuYwHKGwzGA==",
"requires": {
"@sentry/types": "6.2.1",
"@sentry/utils": "6.2.1",
"@sentry/types": "6.2.2",
"@sentry/utils": "6.2.2",
"tslib": "^1.9.3"
},
"dependencies": {
@ -245,12 +254,12 @@
}
},
"@sentry/minimal": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.2.1.tgz",
"integrity": "sha512-wuSXB4Ayxv9rBEQ4pm7fnG4UU2ZPtPnnChoEfd4/mw1UthXSvmPFEn6O4pdo2G8fTkl8eqm6wT/Q7uIXMEmw+A==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.2.2.tgz",
"integrity": "sha512-l0IgoGQgg1lTd4qDU8bQn25sbZBg8PwIHfuTLbGMlRr1flDXHOM1UXajWK/UKbAPelnU7M2JBSVzgl7PwjprzA==",
"requires": {
"@sentry/hub": "6.2.1",
"@sentry/types": "6.2.1",
"@sentry/hub": "6.2.2",
"@sentry/types": "6.2.2",
"tslib": "^1.9.3"
},
"dependencies": {
@ -262,14 +271,14 @@
}
},
"@sentry/tracing": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.2.1.tgz",
"integrity": "sha512-bvStY1SnL08wkSeVK3j9K5rivQQJdKFCPR2VYRFOCaUoleZ6ChPUnBvxQ/E2LXc0hk/y/wo1q4r5B0dfCCY+bQ==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.2.2.tgz",
"integrity": "sha512-mAkPoqtofNfka/u9rOVVDQPaEoTmr0AQh654g9ZqsaqsOJLKjB4FDLVNubWs90fjeKqHiYkI3ZHPak2TzHBPkw==",
"requires": {
"@sentry/hub": "6.2.1",
"@sentry/minimal": "6.2.1",
"@sentry/types": "6.2.1",
"@sentry/utils": "6.2.1",
"@sentry/hub": "6.2.2",
"@sentry/minimal": "6.2.2",
"@sentry/types": "6.2.2",
"@sentry/utils": "6.2.2",
"tslib": "^1.9.3"
},
"dependencies": {
@ -281,16 +290,16 @@
}
},
"@sentry/types": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.1.tgz",
"integrity": "sha512-h0OV1QT+fv5ojfK5/+iEXClu33HirmvbjcQC2jf05IHj9yXIOWy6EB10S8nBjuLiiFqQiAQYj3FN9Ip4eN8NJA=="
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.2.2.tgz",
"integrity": "sha512-Y/1sRtw3a5JU4YdNBig8lLSVJ1UdYtuge+QP1CVLcLSAbq07Ok1bvF+Z+BlNcnHqle2Fl8aKuryG5Yu86enOyQ=="
},
"@sentry/utils": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.1.tgz",
"integrity": "sha512-6kQgM/yBPdXu+3qbJnI6HBcWztN9QfiMkH++ZiKk4ERhg9d2LYWlze478uTU5Fyo/JQYcp+McpjtjpR9QIrr0g==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.2.2.tgz",
"integrity": "sha512-qaee6X6VDNZ8HeO83/veaKw0KuhDE7j1R+Yryme3PywFzsoTzutDrEQjb7gvcHAhBaAYX8IHUBHgxcFI9BxI+w==",
"requires": {
"@sentry/types": "6.2.1",
"@sentry/types": "6.2.2",
"tslib": "^1.9.3"
},
"dependencies": {
@ -310,12 +319,13 @@
}
},
"@types/clean-css": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.2.tgz",
"integrity": "sha512-xiTJn3bmDh1lA8c6iVJs4ZhHw+pcmxXlJQXOB6G1oULaak8rmarIeFKI4aTJ7849dEhaO612wgIualZfbxTJwA==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.3.tgz",
"integrity": "sha512-ET0ldU/vpXecy5vO8JRIhtJWSrk1vzXdJcp3Bjf8bARZynl6vfkhEKY/A7njfNIRlmyTGuVFuqnD6I3tOGdXpQ==",
"dev": true,
"requires": {
"@types/node": "*"
"@types/node": "*",
"source-map": "^0.6.0"
}
},
"@types/codemirror": {
@ -404,80 +414,96 @@
}
},
"@types/uglify-js": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.0.tgz",
"integrity": "sha512-I0Yd8TUELTbgRHq2K65j8rnDPAzAP+DiaF/syLem7yXwYLsHZhPd+AM2iXsWmf9P2F2NlFCgl5erZPQx9IbM9Q==",
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.0.tgz",
"integrity": "sha512-EGkrJD5Uy+Pg0NUR8uA4bJ5WMfljyad0G+784vLCNUkD+QwOJXUbBYExXfVGf7YtyzdQp3L/XMYcliB987kL5Q==",
"dev": true,
"requires": {
"source-map": "^0.6.1"
}
},
"@typescript-eslint/eslint-plugin": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.16.1.tgz",
"integrity": "sha512-SK777klBdlkUZpZLC1mPvyOWk9yAFCWmug13eAjVQ4/Q1LATE/NbcQL1xDHkptQkZOLnPmLUA1Y54m8dqYwnoQ==",
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.18.0.tgz",
"integrity": "sha512-Lzkc/2+7EoH7+NjIWLS2lVuKKqbEmJhtXe3rmfA8cyiKnZm3IfLf51irnBcmow8Q/AptVV0XBZmBJKuUJTe6cQ==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "4.16.1",
"@typescript-eslint/scope-manager": "4.16.1",
"@typescript-eslint/experimental-utils": "4.18.0",
"@typescript-eslint/scope-manager": "4.18.0",
"debug": "^4.1.1",
"functional-red-black-tree": "^1.0.1",
"lodash": "^4.17.15",
"regexpp": "^3.0.0",
"semver": "^7.3.2",
"tsutils": "^3.17.1"
}
},
"@typescript-eslint/experimental-utils": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.16.1.tgz",
"integrity": "sha512-0Hm3LSlMYFK17jO4iY3un1Ve9x1zLNn4EM50Lia+0EV99NdbK+cn0er7HC7IvBA23mBg3P+8dUkMXy4leL33UQ==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/scope-manager": "4.16.1",
"@typescript-eslint/types": "4.16.1",
"@typescript-eslint/typescript-estree": "4.16.1",
"eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0"
}
},
"@typescript-eslint/parser": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.16.1.tgz",
"integrity": "sha512-/c0LEZcDL5y8RyI1zLcmZMvJrsR6SM1uetskFkoh3dvqDKVXPsXI+wFB/CbVw7WkEyyTKobC1mUNp/5y6gRvXg==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "4.16.1",
"@typescript-eslint/types": "4.16.1",
"@typescript-eslint/typescript-estree": "4.16.1",
"debug": "^4.1.1"
},
"dependencies": {
"@typescript-eslint/scope-manager": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.16.1.tgz",
"integrity": "sha512-6IlZv9JaurqV0jkEg923cV49aAn8V6+1H1DRfhRcvZUrptQ+UtSKHb5kwTayzOYTJJ/RsYZdcvhOEKiBLyc0Cw==",
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.18.0.tgz",
"integrity": "sha512-olX4yN6rvHR2eyFOcb6E4vmhDPsfdMyfQ3qR+oQNkAv8emKKlfxTWUXU5Mqxs2Fwe3Pf1BoPvrwZtwngxDzYzQ==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.16.1",
"@typescript-eslint/visitor-keys": "4.16.1"
"@typescript-eslint/types": "4.18.0",
"@typescript-eslint/visitor-keys": "4.18.0"
}
},
"@typescript-eslint/types": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.16.1.tgz",
"integrity": "sha512-nnKqBwMgRlhzmJQF8tnFDZWfunXmJyuXj55xc8Kbfup4PbkzdoDXZvzN8//EiKR27J6vUSU8j4t37yUuYPiLqA==",
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.18.0.tgz",
"integrity": "sha512-/BRociARpj5E+9yQ7cwCF/SNOWwXJ3qhjurMuK2hIFUbr9vTuDeu476Zpu+ptxY2kSxUHDGLLKy+qGq2sOg37A==",
"dev": true
},
"@typescript-eslint/visitor-keys": {
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.18.0.tgz",
"integrity": "sha512-Q9t90JCvfYaN0OfFUgaLqByOfz8yPeTAdotn/XYNm5q9eHax90gzdb+RJ6E9T5s97Kv/UHWKERTmqA0jTKAEHw==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.18.0",
"eslint-visitor-keys": "^2.0.0"
}
}
}
},
"@typescript-eslint/experimental-utils": {
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.18.0.tgz",
"integrity": "sha512-92h723Kblt9JcT2RRY3QS2xefFKar4ZQFVs3GityOKWQYgtajxt/tuXIzL7sVCUlM1hgreiV5gkGYyBpdOwO6A==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/scope-manager": "4.18.0",
"@typescript-eslint/types": "4.18.0",
"@typescript-eslint/typescript-estree": "4.18.0",
"eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0"
},
"dependencies": {
"@typescript-eslint/scope-manager": {
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.18.0.tgz",
"integrity": "sha512-olX4yN6rvHR2eyFOcb6E4vmhDPsfdMyfQ3qR+oQNkAv8emKKlfxTWUXU5Mqxs2Fwe3Pf1BoPvrwZtwngxDzYzQ==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.18.0",
"@typescript-eslint/visitor-keys": "4.18.0"
}
},
"@typescript-eslint/types": {
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.18.0.tgz",
"integrity": "sha512-/BRociARpj5E+9yQ7cwCF/SNOWwXJ3qhjurMuK2hIFUbr9vTuDeu476Zpu+ptxY2kSxUHDGLLKy+qGq2sOg37A==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.16.1.tgz",
"integrity": "sha512-m8I/DKHa8YbeHt31T+UGd/l8Kwr0XCTCZL3H4HMvvLCT7HU9V7yYdinTOv1gf/zfqNeDcCgaFH2BMsS8x6NvJg==",
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.18.0.tgz",
"integrity": "sha512-wt4xvF6vvJI7epz+rEqxmoNQ4ZADArGQO9gDU+cM0U5fdVv7N+IAuVoVAoZSOZxzGHBfvE3XQMLdy+scsqFfeg==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.16.1",
"@typescript-eslint/visitor-keys": "4.16.1",
"@typescript-eslint/types": "4.18.0",
"@typescript-eslint/visitor-keys": "4.18.0",
"debug": "^4.1.1",
"globby": "^11.0.1",
"is-glob": "^4.0.1",
@ -486,12 +512,12 @@
}
},
"@typescript-eslint/visitor-keys": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.16.1.tgz",
"integrity": "sha512-s/aIP1XcMkEqCNcPQtl60ogUYjSM8FU2mq1O7y5cFf3Xcob1z1iXWNB6cC43Op+NGRTFgGolri6s8z/efA9i1w==",
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.18.0.tgz",
"integrity": "sha512-Q9t90JCvfYaN0OfFUgaLqByOfz8yPeTAdotn/XYNm5q9eHax90gzdb+RJ6E9T5s97Kv/UHWKERTmqA0jTKAEHw==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.16.1",
"@typescript-eslint/types": "4.18.0",
"eslint-visitor-keys": "^2.0.0"
}
},
@ -511,30 +537,42 @@
}
}
},
"@typescript-eslint/scope-manager": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.16.1.tgz",
"integrity": "sha512-6IlZv9JaurqV0jkEg923cV49aAn8V6+1H1DRfhRcvZUrptQ+UtSKHb5kwTayzOYTJJ/RsYZdcvhOEKiBLyc0Cw==",
"@typescript-eslint/parser": {
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.18.0.tgz",
"integrity": "sha512-W3z5S0ZbecwX3PhJEAnq4mnjK5JJXvXUDBYIYGoweCyWyuvAKfGHvzmpUzgB5L4cRBb+cTu9U/ro66dx7dIimA==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.16.1",
"@typescript-eslint/visitor-keys": "4.16.1"
"@typescript-eslint/scope-manager": "4.18.0",
"@typescript-eslint/types": "4.18.0",
"@typescript-eslint/typescript-estree": "4.18.0",
"debug": "^4.1.1"
}
},
"@typescript-eslint/scope-manager": {
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.18.0.tgz",
"integrity": "sha512-olX4yN6rvHR2eyFOcb6E4vmhDPsfdMyfQ3qR+oQNkAv8emKKlfxTWUXU5Mqxs2Fwe3Pf1BoPvrwZtwngxDzYzQ==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.18.0",
"@typescript-eslint/visitor-keys": "4.18.0"
}
},
"@typescript-eslint/types": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.16.1.tgz",
"integrity": "sha512-nnKqBwMgRlhzmJQF8tnFDZWfunXmJyuXj55xc8Kbfup4PbkzdoDXZvzN8//EiKR27J6vUSU8j4t37yUuYPiLqA==",
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.18.0.tgz",
"integrity": "sha512-/BRociARpj5E+9yQ7cwCF/SNOWwXJ3qhjurMuK2hIFUbr9vTuDeu476Zpu+ptxY2kSxUHDGLLKy+qGq2sOg37A==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.16.1.tgz",
"integrity": "sha512-m8I/DKHa8YbeHt31T+UGd/l8Kwr0XCTCZL3H4HMvvLCT7HU9V7yYdinTOv1gf/zfqNeDcCgaFH2BMsS8x6NvJg==",
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.18.0.tgz",
"integrity": "sha512-wt4xvF6vvJI7epz+rEqxmoNQ4ZADArGQO9gDU+cM0U5fdVv7N+IAuVoVAoZSOZxzGHBfvE3XQMLdy+scsqFfeg==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.16.1",
"@typescript-eslint/visitor-keys": "4.16.1",
"@typescript-eslint/types": "4.18.0",
"@typescript-eslint/visitor-keys": "4.18.0",
"debug": "^4.1.1",
"globby": "^11.0.1",
"is-glob": "^4.0.1",
@ -559,12 +597,12 @@
}
},
"@typescript-eslint/visitor-keys": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.16.1.tgz",
"integrity": "sha512-s/aIP1XcMkEqCNcPQtl60ogUYjSM8FU2mq1O7y5cFf3Xcob1z1iXWNB6cC43Op+NGRTFgGolri6s8z/efA9i1w==",
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.18.0.tgz",
"integrity": "sha512-Q9t90JCvfYaN0OfFUgaLqByOfz8yPeTAdotn/XYNm5q9eHax90gzdb+RJ6E9T5s97Kv/UHWKERTmqA0jTKAEHw==",
"dev": true,
"requires": {
"@typescript-eslint/types": "4.16.1",
"@typescript-eslint/types": "4.18.0",
"eslint-visitor-keys": "^2.0.0"
}
},
@ -1103,9 +1141,9 @@
"dev": true
},
"eslint": {
"version": "7.21.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.21.0.tgz",
"integrity": "sha512-W2aJbXpMNofUp0ztQaF40fveSsJBjlSCSWpy//gzfTvwC+USs/nceBrKmlJOiM8r1bLwP2EuYkCqArn/6QTIgg==",
"version": "7.22.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.22.0.tgz",
"integrity": "sha512-3VawOtjSJUQiiqac8MQc+w457iGLfuNGLFn8JmF051tTKbh5/x/0vlcEj8OgDCaw7Ysa2Jn8paGshV7x2abKXg==",
"dev": true,
"requires": {
"@babel/code-frame": "7.12.11",
@ -1125,7 +1163,7 @@
"file-entry-cache": "^6.0.1",
"functional-red-black-tree": "^1.0.1",
"glob-parent": "^5.0.0",
"globals": "^12.1.0",
"globals": "^13.6.0",
"ignore": "^4.0.6",
"import-fresh": "^3.0.0",
"imurmurhash": "^0.1.4",
@ -1133,7 +1171,7 @@
"js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
"lodash": "^4.17.20",
"lodash": "^4.17.21",
"minimatch": "^3.0.4",
"natural-compare": "^1.4.0",
"optionator": "^0.9.1",
@ -1202,6 +1240,12 @@
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
"dev": true
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@ -1662,12 +1706,20 @@
"dev": true
},
"globals": {
"version": "12.4.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
"integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
"version": "13.6.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.6.0.tgz",
"integrity": "sha512-YFKCX0SiPg7l5oKYCJ2zZGxcXprVXHcSnVuvzrT3oSENQonVLqM5pf9fN5dLGZGyCjhw8TN8Btwe/jKnZ0pjvQ==",
"dev": true,
"requires": {
"type-fest": "^0.8.1"
"type-fest": "^0.20.2"
},
"dependencies": {
"type-fest": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true
}
}
},
"globby": {
@ -2280,16 +2332,16 @@
}
},
"minify-html-literals": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/minify-html-literals/-/minify-html-literals-1.3.2.tgz",
"integrity": "sha512-DBdi0md84vjvwmLoo9xleFV5FkhzOwfKBqcmoVFL54c9CFlSBtG9KTKEQqiwscB+acewculqys1cDnwyrYlNtg==",
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/minify-html-literals/-/minify-html-literals-1.3.5.tgz",
"integrity": "sha512-p8T8ryePRR8FVfJZLVFmM53WY25FL0moCCTycUDuAu6rf9GMLwy0gNjXBGNin3Yun7Y+tIWd28axOf0t2EpAlQ==",
"dev": true,
"requires": {
"@types/html-minifier": "^3.5.3",
"clean-css": "^4.2.1",
"html-minifier": "^4.0.0",
"magic-string": "^0.25.0",
"parse-literals": "^1.2.0"
"parse-literals": "^1.2.1"
}
},
"minimatch": {
@ -2489,20 +2541,12 @@
}
},
"parse-literals": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/parse-literals/-/parse-literals-1.2.0.tgz",
"integrity": "sha512-gh4zPwvFSXx9ginX8lu9MP3OPHN3VV12PXI8IXD6oMCklFqM82pfbU9e/PKf9r7oLpbqlDSDyHYSVlxxuq3Iew==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/parse-literals/-/parse-literals-1.2.1.tgz",
"integrity": "sha512-Ml0w104Ph2wwzuRdxrg9booVWsngXbB4bZ5T2z6WyF8b5oaNkUmBiDtahi34yUIpXD8Y13JjAK6UyIyApJ73RQ==",
"dev": true,
"requires": {
"typescript": "^2.9.2 || ^3.0.0"
},
"dependencies": {
"typescript": {
"version": "3.9.7",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
"integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
"dev": true
}
"typescript": "^2.9.2 || ^3.0.0 || ^4.0.0"
}
},
"parse5": {
@ -2717,9 +2761,9 @@
}
},
"rollup": {
"version": "2.40.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.40.0.tgz",
"integrity": "sha512-WiOGAPbXoHu+TOz6hyYUxIksOwsY/21TRWoO593jgYt8mvYafYqQl+axaA8y1z2HFazNUUrsMSjahV2A6/2R9A==",
"version": "2.41.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.41.2.tgz",
"integrity": "sha512-6u8fJJXJx6fmvKrAC9DHYZgONvSkz8S9b/VFBjoQ6dkKdHyPpPbpqiNl2Bao9XBzDHpq672X6sGZ9G1ZBqAHMg==",
"requires": {
"fsevents": "~2.3.1"
}
@ -2801,12 +2845,12 @@
}
},
"rollup-plugin-minify-html-literals": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/rollup-plugin-minify-html-literals/-/rollup-plugin-minify-html-literals-1.2.5.tgz",
"integrity": "sha512-x4FzCnbBpYdme7MQDS3+18CvYLqakAtM/JmA3hqXplwzMeZWW3l14KU7H33RhJlHH8Klgv49hGtBRLWLfjCudw==",
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/rollup-plugin-minify-html-literals/-/rollup-plugin-minify-html-literals-1.2.6.tgz",
"integrity": "sha512-JRq2fjlCTiw0zu+1Sy3ClHGCxA79dWGr4HLHWSQgd060StVW9fBVksuj8Xw/suPkNSGClJf/4xNQ1MF6JeXPaw==",
"dev": true,
"requires": {
"minify-html-literals": "^1.3.2",
"minify-html-literals": "^1.3.5",
"rollup-pluginutils": "^2.8.2"
}
},
@ -3246,9 +3290,9 @@
},
"dependencies": {
"ajv": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz",
"integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==",
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.1.tgz",
"integrity": "sha512-+nu0HDv7kNSOua9apAVc979qd932rrZeb3WOvoiD31A/p1mIE5/9bN2027pE2rOPYEdS3UHzsvof4hY+lM9/WQ==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
@ -3383,15 +3427,15 @@
"dev": true
},
"typescript": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.2.tgz",
"integrity": "sha512-tbb+NVrLfnsJy3M59lsDgrzWIflR4d4TIUjz+heUnHZwdF7YsrMTKoRERiIvI2lvBG95dfpLxB21WZhys1bgaQ==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz",
"integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==",
"dev": true
},
"uglify-js": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.0.tgz",
"integrity": "sha512-e1KQFRCpOxnrJsJVqDUCjURq+wXvIn7cK2sRAx9XL3HYLL9aezOP4Pb1+Y3/o693EPk111Yj2Q+IUXxcpHlygQ==",
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.0.tgz",
"integrity": "sha512-TWYSWa9T2pPN4DIJYbU9oAjQx+5qdV5RUDxwARg8fmJZrD/V27Zj0JngW5xg1DFz42G0uDYl2XhzF6alSzD62w==",
"dev": true
},
"union-value": {
@ -3479,9 +3523,9 @@
"dev": true
},
"v8-compile-cache": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz",
"integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
"integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
"dev": true
},
"vscode-css-languageservice": {

View File

@ -11,9 +11,9 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.2",
"@patternfly/patternfly": "^4.87.3",
"@sentry/browser": "^6.2.1",
"@sentry/tracing": "^6.2.1",
"@patternfly/patternfly": "^4.90.5",
"@sentry/browser": "^6.2.2",
"@sentry/tracing": "^6.2.2",
"@types/chart.js": "^2.9.31",
"@types/codemirror": "0.0.108",
"@types/grecaptcha": "^3.0.1",
@ -24,7 +24,7 @@
"flowchart.js": "^1.15.0",
"lit-element": "^2.4.0",
"lit-html": "^1.3.0",
"rollup": "^2.40.0",
"rollup": "^2.41.2",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-cssimport": "^1.0.2",
"rollup-plugin-external-globals": "^0.6.1",
@ -33,17 +33,17 @@
},
"devDependencies": {
"@rollup/plugin-typescript": "^8.2.0",
"@typescript-eslint/eslint-plugin": "^4.16.1",
"@typescript-eslint/parser": "^4.16.1",
"eslint": "^7.21.0",
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"eslint": "^7.22.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-lit": "^1.3.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-minify-html-literals": "^1.2.5",
"rollup-plugin-minify-html-literals": "^1.2.6",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-sourcemaps": "^0.6.3",
"rollup-plugin-terser": "^7.0.2",
"ts-lit-plugin": "^1.2.1",
"typescript": "^4.2.2"
"typescript": "^4.2.3"
}
}

View File

@ -8,16 +8,23 @@ import copy from "rollup-plugin-copy";
import externalGlobals from "rollup-plugin-external-globals";
const resources = [
{ src: "node_modules/@patternfly/patternfly/patternfly.css", dest: "dist/" },
{ src: "node_modules/@patternfly/patternfly/patternfly-addons.css", dest: "dist/" },
{ src: "node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css", dest: "dist/" },
{ src: "node_modules/@patternfly/patternfly/patternfly-base.css", dest: "dist/" },
{ src: "node_modules/@patternfly/patternfly/assets/*", dest: "dist/assets/" },
{ src: "src/index.html", dest: "dist" },
{ src: "src/authentik.css", dest: "dist" },
{ src: "src/assets/*", dest: "dist/assets" },
{ src: "./icons/*", dest: "dist/assets/icons" },
];
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function manualChunks(id) {
if (id.includes("node_modules")) {
return "vendor";
}
if (id.includes("src/api/")) {
return "api";
}
}
export default [
{
input: "./src/main.ts",
@ -26,6 +33,7 @@ export default [
format: "es",
dir: "dist",
sourcemap: true,
manualChunks: manualChunks,
},
],
plugins: [
@ -55,6 +63,7 @@ export default [
format: "es",
dir: "dist",
sourcemap: true,
manualChunks: manualChunks,
},
],
plugins: [

5
web/src/api/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
apis/**
models/**
index.ts
runtime.ts
.openapi-generator/**

View File

@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -1,32 +0,0 @@
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
import { Provider } from "./Providers";
export class Application {
pk: string;
name: string;
slug: string;
provider?: Provider;
launch_url: string;
meta_launch_url: string;
meta_icon: string;
meta_description: string;
meta_publisher: string;
policies: string[];
constructor() {
throw Error();
}
static get(slug: string): Promise<Application> {
return DefaultClient.fetch<Application>(["core", "applications", slug]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Application>> {
return DefaultClient.fetch<AKResponse<Application>>(["core", "applications"], filter);
}
static adminUrl(rest: string): string {
return `/administration/applications/${rest}`;
}
}

View File

@ -1,26 +0,0 @@
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
export class CertificateKeyPair {
pk: string;
name: string;
fingerprint: string;
cert_expiry: number;
cert_subject: string;
private_key_available: boolean;
constructor() {
throw Error();
}
static get(slug: string): Promise<CertificateKeyPair> {
return DefaultClient.fetch<CertificateKeyPair>(["crypto", "certificatekeypairs", slug]);
}
static list(filter?: QueryArguments): Promise<AKResponse<CertificateKeyPair>> {
return DefaultClient.fetch<AKResponse<CertificateKeyPair>>(["crypto", "certificatekeypairs"], filter);
}
static adminUrl(rest: string): string {
return `/administration/crypto/certificates/${rest}`;
}
}

View File

@ -1,10 +1,3 @@
import { gettext } from "django";
import { showMessage } from "../elements/messages/MessageContainer";
import { getCookie } from "../utils";
import { NotFoundError, RequestError } from "./Error";
export const VERSION = "v2beta";
export interface QueryArguments {
page?: number;
page_size?: number;
@ -13,104 +6,27 @@ export interface QueryArguments {
export interface BaseInheritanceModel {
object_type: string;
objectType: string;
verbose_name: string;
verbose_name_plural: string;
verboseName: string;
verboseNamePlural: string;
}
export class Client {
makeUrl(url: string[], query?: QueryArguments): string {
let builtUrl = `/api/${VERSION}/${url.join("/")}/`;
if (query) {
const queryString = Object.keys(query)
.filter((k) => query[k] !== null)
// we default to a string in query[k] as we've filtered out the null above
// this is just for type-hinting
.map((k) => encodeURIComponent(k) + "=" + encodeURIComponent(query[k] || ""))
.join("&");
builtUrl += `?${queryString}`;
}
return builtUrl;
}
fetch<T>(url: string[], query?: QueryArguments): Promise<T> {
const finalUrl = this.makeUrl(url, query);
return fetch(finalUrl)
.then((r) => {
if (r.status > 300) {
switch (r.status) {
case 404:
throw new NotFoundError(`URL ${finalUrl} not found`);
default:
throw new RequestError(r.statusText);
}
}
return r;
})
.catch((e) => {
showMessage({
level_tag: "error",
message: gettext(`Unexpected error while fetching: ${e.toString()}`),
});
return e;
})
.then((r) => r.json())
.then((r) => <T>r);
}
private writeRequest<T>(url: string[], body: T, method: string, query?: QueryArguments): Promise<T> {
const finalUrl = this.makeUrl(url, query);
const csrftoken = getCookie("authentik_csrf");
const request = new Request(finalUrl, {
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"X-CSRFToken": csrftoken,
},
});
return fetch(request, {
method: method,
mode: "same-origin",
body: JSON.stringify(body),
})
.then((r) => {
if (r.status > 300) {
switch (r.status) {
case 404:
throw new NotFoundError(`URL ${finalUrl} not found`);
default:
throw new RequestError(r.statusText);
}
}
return r;
})
.then((r) => r.json())
.then((r) => <T>r);
}
update<T>(url: string[], body: T, query?: QueryArguments): Promise<T> {
return this.writeRequest(url, body, "PATCH", query);
}
}
export const DefaultClient = new Client();
export interface PBPagination {
export interface AKPagination {
next?: number;
previous?: number;
count: number;
current: number;
total_pages: number;
totalPages: number;
start_index: number;
end_index: number;
startIndex: number;
endIndex: number;
}
export interface AKResponse<T> {
pagination: PBPagination;
pagination: AKPagination;
results: Array<T>;
}

View File

@ -1,42 +1,39 @@
import { DefaultClient } from "./Client";
import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing";
import { VERSION } from "../constants";
import { SentryIgnoredError } from "../common/errors";
import { Configuration } from "./runtime";
import { RootApi } from "./apis";
import { Config } from ".";
import { getCookie } from "../utils";
export class Config {
branding_logo: string;
branding_title: string;
error_reporting_enabled: boolean;
error_reporting_environment: string;
error_reporting_send_pii: boolean;
constructor() {
throw Error();
export const DEFAULT_CONFIG = new Configuration({
basePath: "/api/v2beta",
headers: {
"X-CSRFToken": getCookie("authentik_csrf"),
}
});
static get(): Promise<Config> {
return DefaultClient.fetch<Config>(["root", "config"]).then((config) => {
if (config.error_reporting_enabled) {
Sentry.init({
dsn: "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8",
release: `authentik@${VERSION}`,
integrations: [
new Integrations.BrowserTracing(),
],
tracesSampleRate: 0.6,
environment: config.error_reporting_environment,
beforeSend(event: Sentry.Event, hint: Sentry.EventHint) {
if (hint.originalException instanceof SentryIgnoredError) {
return null;
}
return event;
},
});
console.debug("authentik/config: Sentry enabled.");
}
return config;
});
}
export function configureSentry(): Promise<Config> {
return new RootApi(DEFAULT_CONFIG).rootConfigList().then((config) => {
if (config.errorReportingEnabled) {
Sentry.init({
dsn: "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8",
release: `authentik@${VERSION}`,
integrations: [
new Integrations.BrowserTracing(),
],
tracesSampleRate: 0.6,
environment: config.errorReportingEnvironment,
beforeSend(event: Sentry.Event, hint: Sentry.EventHint) {
if (hint.originalException instanceof SentryIgnoredError) {
return null;
}
return event;
},
});
console.debug("authentik/config: Sentry enabled.");
}
return config;
});
}

View File

@ -1,30 +0,0 @@
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
import { Event } from "./Events";
export class Notification {
pk: string;
severity: string;
body: string;
created: string;
event?: Event;
seen: boolean;
constructor() {
throw Error();
}
static get(pk: string): Promise<Notification> {
return DefaultClient.fetch<Notification>(["events", "notifications", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Notification>> {
return DefaultClient.fetch<AKResponse<Notification>>(["events", "notifications"], filter);
}
static markSeen(pk: string): Promise<{seen: boolean}> {
return DefaultClient.update(["events", "notifications", pk], {
"seen": true
});
}
}

View File

@ -1,26 +0,0 @@
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
import { Group } from "./Groups";
export class Rule {
pk: string;
name: string;
transports: string[];
severity: string;
group?: Group;
constructor() {
throw Error();
}
static get(pk: string): Promise<Rule> {
return DefaultClient.fetch<Rule>(["events", "rules", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Rule>> {
return DefaultClient.fetch<AKResponse<Rule>>(["events", "rules"], filter);
}
static adminUrl(rest: string): string {
return `/administration/events/rules/${rest}`;
}
}

View File

@ -1,25 +0,0 @@
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
export class Transport {
pk: string;
name: string;
mode: string;
mode_verbose: string;
webhook_url: string;
constructor() {
throw Error();
}
static get(pk: string): Promise<Transport> {
return DefaultClient.fetch<Transport>(["events", "transports", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Transport>> {
return DefaultClient.fetch<AKResponse<Transport>>(["events", "transports"], filter);
}
static adminUrl(rest: string): string {
return `/administration/events/transports/${rest}`;
}
}

View File

@ -1,4 +1,4 @@
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
import { Event } from "./models";
export interface EventUser {
pk: number;
@ -11,37 +11,7 @@ export interface EventContext {
[key: string]: EventContext | string | number | string[];
}
export class Event {
pk: string;
export interface EventWithContext extends Event {
user: EventUser;
action: string;
app: string;
context: EventContext;
client_ip: string;
created: string;
constructor() {
throw Error();
}
static get(pk: string): Promise<Event> {
return DefaultClient.fetch<Event>(["events", "events", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Event>> {
return DefaultClient.fetch<AKResponse<Event>>(["events", "events"], filter);
}
// events/events/top_per_user/?filter_action=authorize_application
static topForUser(action: string): Promise<TopNEvent[]> {
return DefaultClient.fetch<TopNEvent[]>(["events", "events", "top_per_user"], {
"filter_action": action,
});
}
}
export interface TopNEvent {
application: { [key: string]: string};
counted_events: number;
unique_users: number;
}

View File

@ -1,12 +1,4 @@
import { DefaultClient, AKResponse, QueryArguments, BaseInheritanceModel } from "./Client";
import { TypeCreate } from "./Providers";
export enum ChallengeTypes {
native = "native",
response = "response",
shell = "shell",
redirect = "redirect",
}
import { ChallengeTypeEnum } from "./models";
export interface Error {
code: string;
@ -18,11 +10,12 @@ export interface ErrorDict {
}
export interface Challenge {
type: ChallengeTypes;
type: ChallengeTypeEnum;
component?: string;
title?: string;
response_errors?: ErrorDict;
}
export interface WithUserInfoChallenge extends Challenge {
pending_user: string;
pending_user_avatar: string;
@ -31,6 +24,7 @@ export interface WithUserInfoChallenge extends Challenge {
export interface ShellChallenge extends Challenge {
body: string;
}
export interface RedirectChallenge extends Challenge {
to: string;
}
@ -44,104 +38,3 @@ export enum FlowDesignation {
Recovery = "recovery",
StageConfiguration = "stage_configuration",
}
export class Flow {
pk: string;
policybindingmodel_ptr_id: string;
name: string;
slug: string;
title: string;
designation: FlowDesignation;
background: string;
stages: string[];
policies: string[];
cache_count: number;
constructor() {
throw Error();
}
static get(slug: string): Promise<Flow> {
return DefaultClient.fetch<Flow>(["flows", "instances", slug]);
}
static diagram(slug: string): Promise<{ diagram: string }> {
return DefaultClient.fetch<{ diagram: string }>(["flows", "instances", slug, "diagram"]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Flow>> {
return DefaultClient.fetch<AKResponse<Flow>>(["flows", "instances"], filter);
}
static cached(): Promise<number> {
return DefaultClient.fetch<{ count: number }>(["flows", "instances", "cached"]).then(r => {
return r.count;
});
}
static executor(slug: string): Promise<Challenge> {
return DefaultClient.fetch(["flows", "executor", slug]);
}
static adminUrl(rest: string): string {
return `/administration/flows/${rest}`;
}
}
export class Stage implements BaseInheritanceModel {
pk: string;
name: string;
object_type: string;
verbose_name: string;
verbose_name_plural: string;
flow_set: Flow[];
constructor() {
throw Error();
}
static get(slug: string): Promise<Stage> {
return DefaultClient.fetch<Stage>(["stages", "all", slug]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Stage>> {
return DefaultClient.fetch<AKResponse<Stage>>(["stages", "all"], filter);
}
static getTypes(): Promise<TypeCreate[]> {
return DefaultClient.fetch<TypeCreate[]>(["stages", "all", "types"]);
}
static adminUrl(rest: string): string {
return `/administration/stages/${rest}`;
}
}
export class FlowStageBinding {
pk: string;
policybindingmodel_ptr_id: string;
target: string;
stage: string;
stage_obj: Stage;
evaluate_on_plan: boolean;
re_evaluate_policies: boolean;
order: number;
policies: string[];
constructor() {
throw Error();
}
static get(slug: string): Promise<FlowStageBinding> {
return DefaultClient.fetch<FlowStageBinding>(["flows", "bindings", slug]);
}
static list(filter?: QueryArguments): Promise<AKResponse<FlowStageBinding>> {
return DefaultClient.fetch<AKResponse<FlowStageBinding>>(["flows", "bindings"], filter);
}
static adminUrl(rest: string): string {
return `/administration/stages/bindings/${rest}`;
}
}

View File

@ -1,28 +0,0 @@
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
import { EventContext } from "./Events";
export class Group {
pk: string;
name: string;
is_superuser: boolean;
attributes: EventContext;
parent?: Group;
users: number[];
constructor() {
throw Error();
}
static get(pk: string): Promise<Group> {
return DefaultClient.fetch<Group>(["core", "groups", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Group>> {
return DefaultClient.fetch<AKResponse<Group>>(["core", "groups"], filter);
}
static adminUrl(rest: string): string {
return `/administration/groups/${rest}`;
}
}

View File

@ -1,27 +0,0 @@
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
import { EventContext } from "./Events";
import { User } from "./Users";
export class Invitation {
pk: string;
expires: number;
fixed_date: EventContext;
created_by: User;
constructor() {
throw Error();
}
static get(pk: string): Promise<Invitation> {
return DefaultClient.fetch<Invitation>(["stages", "invitation", "invitations", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Invitation>> {
return DefaultClient.fetch<AKResponse<Invitation>>(["stages", "invitation", "invitations"], filter);
}
static adminUrl(rest: string): string {
return `/administration/stages/invitations/${rest}`;
}
}

View File

@ -1,79 +0,0 @@
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
import { Provider, TypeCreate } from "./Providers";
export interface OutpostHealth {
last_seen: number;
version: string;
version_should: string;
version_outdated: boolean;
}
export class Outpost {
pk: string;
name: string;
providers: number[];
providers_obj: Provider[];
service_connection?: string;
_config: QueryArguments;
token_identifier: string;
constructor() {
throw Error();
}
static get(pk: string): Promise<Outpost> {
return DefaultClient.fetch<Outpost>(["outposts", "outposts", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Outpost>> {
return DefaultClient.fetch<AKResponse<Outpost>>(["outposts", "outposts"], filter);
}
static health(pk: string): Promise<OutpostHealth[]> {
return DefaultClient.fetch<OutpostHealth[]>(["outposts", "outposts", pk, "health"]);
}
static adminUrl(rest: string): string {
return `/administration/outposts/${rest}`;
}
}
export interface OutpostServiceConnectionState {
version: string;
healthy: boolean;
}
export class OutpostServiceConnection {
pk: string;
name: string;
local: boolean;
object_type: string;
verbose_name: string;
verbose_name_plural: string;
constructor() {
throw Error();
}
static get(pk: string): Promise<OutpostServiceConnection> {
return DefaultClient.fetch<OutpostServiceConnection>(["outposts", "service_connections", "all", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<OutpostServiceConnection>> {
return DefaultClient.fetch<AKResponse<OutpostServiceConnection>>(["outposts", "service_connections", "all"], filter);
}
static state(pk: string): Promise<OutpostServiceConnectionState> {
return DefaultClient.fetch<OutpostServiceConnectionState>(["outposts", "service_connections", "all", pk, "state"]);
}
static getTypes(): Promise<TypeCreate[]> {
return DefaultClient.fetch<TypeCreate[]>(["outposts", "service_connections", "all", "types"]);
}
static adminUrl(rest: string): string {
return `/administration/outpost_service_connections/${rest}`;
}
}

View File

@ -1,38 +0,0 @@
import { DefaultClient, BaseInheritanceModel, AKResponse, QueryArguments } from "./Client";
import { TypeCreate } from "./Providers";
export class Policy implements BaseInheritanceModel {
pk: string;
name: string;
execution_logging: boolean;
object_type: string;
verbose_name: string;
verbose_name_plural: string;
bound_to: number;
constructor() {
throw Error();
}
static get(pk: string): Promise<Policy> {
return DefaultClient.fetch<Policy>(["policies", "all", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Policy>> {
return DefaultClient.fetch<AKResponse<Policy>>(["policies", "all"], filter);
}
static cached(): Promise<number> {
return DefaultClient.fetch<{ count: number }>(["policies", "all", "cached"]).then(r => {
return r.count;
});
}
static getTypes(): Promise<TypeCreate[]> {
return DefaultClient.fetch<TypeCreate[]>(["policies", "all", "types"]);
}
static adminUrl(rest: string): string {
return `/administration/policies/${rest}`;
}
}

View File

@ -1,31 +0,0 @@
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
import { Group } from "./Groups";
import { Policy } from "./Policies";
import { User } from "./Users";
export class PolicyBinding {
pk: string;
policy?: Policy;
group?: Group;
user?: User;
target: string;
enabled: boolean;
order: number;
timeout: number;
constructor() {
throw Error();
}
static get(pk: string): Promise<PolicyBinding> {
return DefaultClient.fetch<PolicyBinding>(["policies", "bindings", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<PolicyBinding>> {
return DefaultClient.fetch<AKResponse<PolicyBinding>>(["policies", "bindings"], filter);
}
static adminUrl(rest: string): string {
return `/administration/policies/bindings/${rest}`;
}
}

View File

@ -1,30 +0,0 @@
import { DefaultClient, QueryArguments, AKResponse } from "./Client";
import { Stage } from "./Flows";
export class Prompt {
pk: string;
field_key: string;
label: string;
type: string;
required: boolean;
placeholder: string;
order: number;
promptstage_set: Stage[];
constructor() {
throw Error();
}
static get(pk: string): Promise<Prompt> {
return DefaultClient.fetch<Prompt>(["stages", "prompt", "prompts", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Prompt>> {
return DefaultClient.fetch<AKResponse<Prompt>>(["stages", "prompt", "prompts"], filter);
}
static adminUrl(rest: string): string {
return `/administration/stages_prompts/${rest}`;
}
}

View File

@ -1,31 +0,0 @@
import { DefaultClient, AKResponse, QueryArguments } from "./Client";
import { TypeCreate } from "./Providers";
export class PropertyMapping {
pk: string;
name: string;
expression: string;
verbose_name: string;
verbose_name_plural: string;
constructor() {
throw Error();
}
static get(pk: string): Promise<PropertyMapping> {
return DefaultClient.fetch<PropertyMapping>(["propertymappings", "all", pk]);
}
static list(filter?: QueryArguments): Promise<AKResponse<PropertyMapping>> {
return DefaultClient.fetch<AKResponse<PropertyMapping>>(["propertymappings", "all"], filter);
}
static getTypes(): Promise<TypeCreate[]> {
return DefaultClient.fetch<TypeCreate[]>(["propertymappings", "all", "types"]);
}
static adminUrl(rest: string): string {
return `/administration/property-mappings/${rest}`;
}
}

View File

@ -1,40 +0,0 @@
import { BaseInheritanceModel, DefaultClient, AKResponse, QueryArguments } from "./Client";
export interface TypeCreate {
name: string;
description: string;
link: string;
}
export class Provider implements BaseInheritanceModel {
pk: number;
name: string;
authorization_flow: string;
object_type: string;
assigned_application_slug?: string;
assigned_application_name?: string;
verbose_name: string;
verbose_name_plural: string;
constructor() {
throw Error();
}
static get(id: number): Promise<Provider> {
return DefaultClient.fetch<Provider>(["providers", "all", id.toString()]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Provider>> {
return DefaultClient.fetch<AKResponse<Provider>>(["providers", "all"], filter);
}
static getTypes(): Promise<TypeCreate[]> {
return DefaultClient.fetch<TypeCreate[]>(["providers", "all", "types"]);
}
static adminUrl(rest: string): string {
return `/administration/providers/${rest}`;
}
}

View File

@ -1,34 +0,0 @@
import { BaseInheritanceModel, DefaultClient, AKResponse, QueryArguments } from "./Client";
import { TypeCreate } from "./Providers";
export class Source implements BaseInheritanceModel {
pk: string;
name: string;
slug: string;
enabled: boolean;
authentication_flow: string;
enrollment_flow: string;
constructor() {
throw Error();
}
object_type: string;
verbose_name: string;
verbose_name_plural: string;
static get(slug: string): Promise<Source> {
return DefaultClient.fetch<Source>(["sources", "all", slug]);
}
static list(filter?: QueryArguments): Promise<AKResponse<Source>> {
return DefaultClient.fetch<AKResponse<Source>>(["sources", "all"], filter);
}
static getTypes(): Promise<TypeCreate[]> {
return DefaultClient.fetch<TypeCreate[]>(["sources", "all", "types"]);
}
static adminUrl(rest: string): string {
return `/administration/sources/${rest}`;
}
}

View File

@ -1,33 +0,0 @@
import { DefaultClient, QueryArguments } from "./Client";
export enum TaskStatus {
SUCCESSFUL = 1,
WARNING = 2,
ERROR = 4,
}
export class SystemTask {
task_name: string;
task_description: string;
task_finish_timestamp: number;
status: TaskStatus;
messages: string[];
constructor() {
throw Error();
}
static get(task_name: string): Promise<SystemTask> {
return DefaultClient.fetch<SystemTask>(["admin", "system_tasks", task_name]);
}
static list(filter?: QueryArguments): Promise<SystemTask[]> {
return DefaultClient.fetch<SystemTask[]>(["admin", "system_tasks"], filter);
}
static retry(task_name: string): string {
return DefaultClient.makeUrl(["admin", "system_tasks", task_name, "retry"]);
}
}

Some files were not shown because too many files have changed in this diff Show More