Compare commits

..

85 Commits

Author SHA1 Message Date
a407d903ab idk
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 19:51:11 +02:00
7e6f36b0b4 initial flow support
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 19:39:54 +02:00
8dd7b0569c ws support
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 19:39:26 +02:00
616be78e10 fallback for error reporting
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 19:39:15 +02:00
7125db1fbd cleanup
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 19:39:04 +02:00
8c7c7c3fee separate cors middleware
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 19:11:09 +02:00
bbbd00db22 make flows kinda work with bearer token
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 19:11:09 +02:00
6d60c5f7c7 terrible cors for testing
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 19:11:09 +02:00
accf25a626 web/sdk: embed authentik settings into anything
the web part

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 19:11:09 +02:00
5f261bed96 core: fix change_user_type always requiring usernames (#11177)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 19:04:05 +02:00
4d51671f88 web/admin: fix error in Outpost creation form (#11173)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 18:20:09 +02:00
1c570b2502 providers/ldap: fix migration assuming search group is set (#11170)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 16:13:58 +02:00
78e4370b98 web: Adjust Wdio MaxInstances, add Knip (#11089)
- Adjust the WebdriverIO configuration so that `maxInstances` can be set by the environment
- `MAX_INSTANCES=1 CI=true npm run test` will run the headless tests from your command line.
- `MAX_INSTANCES=1 npm run test-watch` if you want to watch the test run in-browser.
- Adds `knip` import tracing facility for linting.
- Knip can be accessed by `npm run lint:imports`.

Running `MAX_INSTANCES=10` (the default) would sometimes create conflicts and overwhelm the test
runner, leaving you with 11 open instances of Chrome and no way to know which one is the one you
*don't* want to close. A better choice is `MAX_INSTANCES=1 npm run test-watch`, which would allow
the developer to watch the test run serially.

Knip adds a new linting feature: tracking down which imports are not used, are not exported
correctly, or shouldn't have been exported at all. Despite the "zero-config" promise, it still
required significant configuration to handle the wide variety of "strengths" of ESlint
configurations, as well as pointers to our entries and reminders that web components may export
their classes but their actual use is as part of the component registry.

Knip's analyzer produces a lot of false positives.  It is not intended to be used as part of the
CI/CD pipeline; it is there to help developers figure out what can and should be cleaned up
manually.

Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 15:09:40 +02:00
9a26111f1c web: bump API Client version (#11168)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2024-09-03 14:44:59 +02:00
02ae099bdf root: version 2024.8 backport (#11166)
* schemas: fix XML Schema loading...for some reason?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* release: 2024.8.0-rc1

* release: 2024.8.0

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

# Conflicts:
#	.bumpversion.cfg

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-03 14:41:40 +02:00
05fe4e5e7b translate: Updates for file locale/en/LC_MESSAGES/django.po in ru (#11153)
Translate locale/en/LC_MESSAGES/django.po in ru

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'ru'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-09-03 14:20:24 +02:00
24c289fdd1 core, web: update translations (#11156)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-09-03 14:20:08 +02:00
cd8de3e526 core: bump pytest-django from 4.8.0 to 4.9.0 (#11157)
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.8.0 to 4.9.0.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.8.0...v4.9.0)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-03 14:20:01 +02:00
243bd03785 core: bump watchdog from 5.0.0 to 5.0.1 (#11158)
Bumps [watchdog](https://github.com/gorakhargosh/watchdog) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/gorakhargosh/watchdog/releases)
- [Changelog](https://github.com/gorakhargosh/watchdog/blob/master/changelog.rst)
- [Commits](https://github.com/gorakhargosh/watchdog/compare/v5.0.0...v5.0.1)

---
updated-dependencies:
- dependency-name: watchdog
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-03 14:19:53 +02:00
e02cf0b3bd web: bump @spotlightjs/spotlight from 2.3.1 to 2.3.2 in /web in the sentry group across 1 directory (#11159)
web: bump @spotlightjs/spotlight

Bumps the sentry group with 1 update in the /web directory: @spotlightjs/spotlight.


Updates `@spotlightjs/spotlight` from 2.3.1 to 2.3.2

---
updated-dependencies:
- dependency-name: "@spotlightjs/spotlight"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-03 14:19:46 +02:00
3018735579 web: bump the swc group across 2 directories with 11 updates (#11161)
Bumps the swc group with 1 update in the /web directory: [@swc/core](https://github.com/swc-project/swc).
Bumps the swc group with 1 update in the /web/sfe directory: [@swc/core](https://github.com/swc-project/swc).


Updates `@swc/core` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-darwin-arm64` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-darwin-x64` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-linux-arm-gnueabihf` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-linux-arm64-gnu` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-linux-arm64-musl` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-linux-x64-gnu` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-linux-x64-musl` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-win32-arm64-msvc` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-win32-ia32-msvc` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-win32-x64-msvc` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-darwin-arm64` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-darwin-x64` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-linux-arm-gnueabihf` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-linux-arm64-gnu` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-linux-arm64-musl` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-linux-x64-gnu` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-linux-x64-musl` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-win32-arm64-msvc` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-win32-ia32-msvc` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

Updates `@swc/core-win32-x64-msvc` from 1.7.22 to 1.7.23
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.22...v1.7.23)

---
updated-dependencies:
- dependency-name: "@swc/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-x64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm-gnueabihf"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-musl"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-musl"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-arm64-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-ia32-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-x64-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-arm64"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-x64"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm-gnueabihf"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-musl"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-musl"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-arm64-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-ia32-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-x64-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-03 14:19:38 +02:00
6a956d149a web: bump mermaid from 11.0.2 to 11.1.0 in /web (#11162)
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 11.0.2 to 11.1.0.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/mermaid@11.0.2...mermaid@11.1.0)

---
updated-dependencies:
- dependency-name: mermaid
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-03 14:19:30 +02:00
3fd1bc6673 web: bump typescript-eslint from 8.3.0 to 8.4.0 in /web (#11163)
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.3.0 to 8.4.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.4.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-03 14:19:22 +02:00
6bc4877702 website/docs: update release notes (#11151)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-09-02 15:01:33 +02:00
9592b42501 website/docs: update immich OAuth Redirect URI (#11135) 2024-09-02 14:14:22 +02:00
517a5bc689 web: bump the rollup group across 1 directory with 3 updates (#11144) 2024-09-02 13:52:22 +02:00
a19e350ca6 website: bump postcss from 8.4.43 to 8.4.44 in /website (#11150) 2024-09-02 13:51:59 +02:00
88577145fb translate: Updates for file web/xliff/en.xlf in zh_CN (#11136)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-09-02 13:30:25 +02:00
bc93df1e29 translate: Updates for file web/xliff/en.xlf in zh-Hans (#11137)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-09-02 13:30:09 +02:00
9d5eb54504 stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#11138)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2024-09-02 13:29:52 +02:00
d95c433027 core: bump deepmerge from 1.1.1 to 2.0 (#11140)
Bumps [deepmerge](https://github.com/toumorokoshi/deepmerge) from 1.1.1 to 2.0.
- [Release notes](https://github.com/toumorokoshi/deepmerge/releases)
- [Commits](https://github.com/toumorokoshi/deepmerge/compare/v1.1.1...v2.0)

---
updated-dependencies:
- dependency-name: deepmerge
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:29:24 +02:00
7416c90efb website: bump postcss from 8.4.41 to 8.4.43 in /website (#11141)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.41 to 8.4.43.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.41...8.4.43)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:29:06 +02:00
34a073b0f7 website: bump @types/react from 18.3.4 to 18.3.5 in /website (#11142)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.3.4 to 18.3.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:28:58 +02:00
86eb112a03 web: bump the swc group across 2 directories with 11 updates (#11145)
Bumps the swc group with 1 update in the /web directory: [@swc/core](https://github.com/swc-project/swc).
Bumps the swc group with 1 update in the /web/sfe directory: [@swc/core](https://github.com/swc-project/swc).


Updates `@swc/core` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-darwin-arm64` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-darwin-x64` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-linux-arm-gnueabihf` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-linux-arm64-gnu` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-linux-arm64-musl` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-linux-x64-gnu` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-linux-x64-musl` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-win32-arm64-msvc` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-win32-ia32-msvc` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-win32-x64-msvc` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-darwin-arm64` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-darwin-x64` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-linux-arm-gnueabihf` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-linux-arm64-gnu` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-linux-arm64-musl` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-linux-x64-gnu` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-linux-x64-musl` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-win32-arm64-msvc` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-win32-ia32-msvc` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

Updates `@swc/core-win32-x64-msvc` from 1.7.21 to 1.7.22
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.21...v1.7.22)

---
updated-dependencies:
- dependency-name: "@swc/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-x64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm-gnueabihf"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-musl"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-musl"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-arm64-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-ia32-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-x64-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-arm64"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-x64"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm-gnueabihf"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-musl"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-musl"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-arm64-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-ia32-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-x64-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:28:40 +02:00
e48d001ea6 web: bump chromedriver from 128.0.0 to 128.0.1 in /tests/wdio (#11146)
Bumps [chromedriver](https://github.com/giggio/node-chromedriver) from 128.0.0 to 128.0.1.
- [Commits](https://github.com/giggio/node-chromedriver/compare/128.0.0...128.0.1)

---
updated-dependencies:
- dependency-name: chromedriver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:28:17 +02:00
2070372f03 web: bump rollup from 4.21.1 to 4.21.2 in /web (#11147)
Bumps [rollup](https://github.com/rollup/rollup) from 4.21.1 to 4.21.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/v4.21.1...v4.21.2)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:28:04 +02:00
bea4679192 web: bump rollup from 4.21.1 to 4.21.2 in /web/sfe (#11148)
Bumps [rollup](https://github.com/rollup/rollup) from 4.21.1 to 4.21.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/v4.21.1...v4.21.2)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 13:27:55 +02:00
32d1488a56 web: fix dual-select with dynamic selection (#11133)
* web: fix dual-select with dynamic selection

For dynamic selection, the property name is `.selector` to message that it's a function the
API layer uses to select the elements.

A few bits of lint picked.

* web: added comment to clarify what the fallback selector does
2024-08-30 09:53:14 -07:00
1003c79d8c core, web: update translations (#11126) 2024-08-30 16:39:27 +02:00
a05ed7e237 website: bump prism-react-renderer from 2.3.1 to 2.4.0 in /website (#11127)
Bumps [prism-react-renderer](https://github.com/FormidableLabs/prism-react-renderer) from 2.3.1 to 2.4.0.
- [Release notes](https://github.com/FormidableLabs/prism-react-renderer/releases)
- [Commits](https://github.com/FormidableLabs/prism-react-renderer/compare/prism-react-renderer@2.3.1...prism-react-renderer@2.4.0)

---
updated-dependencies:
- dependency-name: prism-react-renderer
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-30 14:04:47 +02:00
087d4f6a48 core: bump ruff from 0.6.2 to 0.6.3 (#11128)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.2 to 0.6.3.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.2...0.6.3)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-30 14:04:38 +02:00
141cfe75d8 websites/docs: minor tweaks to rel notes (#11123)
* minor tweaks to rel notes

* tweak

* again

---------

Co-authored-by: Tana M Berry <tana@goauthentik.com>
2024-08-29 21:28:18 +02:00
a3a13d265b website/docs: fix outdated docs and typos (#11020)
* fix typo

* fix out of date docs on Go client

* remove completed issue from known issues list

* fix typo
2024-08-29 16:12:31 +02:00
9c45ec1918 web: fix e2e tests to work with latest WebdriverIO and authentik 2024.8 (#11105)
* web: fix e2e tests to work with latest WebdriverIO and authentik 2024.8

- Adjust the ApplicationWizard "select provider type" typeslist to have the right OUIA tags when
  running
- Add OUIA tags to TypeCreateWizard
- Provide default values for `.jwksSources` when needed.
- Upgrade E2E WebUI tests to use WebdriverIO 9.
- Upgrade the linters to include `package.json` and `package-lock.json`.
- Adjust a *lot* of the WebdriverIO selectors!
- Provide a driver for the TypeCreate card-based radio interface.
- Split `Bad Logins` into two separate files.

Aside from the obvious, "because testing needs this" or "because there were warnings on the console
when this was running," the real issue is that WebdriverIO 9 has changed the syntax and semantics of
its ShadowDOM-piercing `$` mechanism.

For Oauth2 and Proxy, the field `.jwksSources` may be undefined, but `undefined` is not a legal
value for ak-dual-select's `selected` field. Provide a default or use `ifDefined()`. I chose to
provide a default of `[]`.

In the previous iteration, `$(">>>ak-search-select input")` would be sufficient for WebdriverIO to
find an input inside a component. Now, it needs to be written as: `$("ak-search-select").$("input")`.
And in rare cases, when you have a floating component that is separated from its invocation (such as
Notification or SearchSelect), even that doesn't work well and you have to fall back to some
old-school hacking (see `./tests/wdio/test/pageobjects/page.ts` for an example) to find some child
elements.

Also, the monadic nature of `$` seems to have faded a bit. `$` used to wrap all child invocations in
promises, making the entire expression a single valid promise; it seems that it is now necessary to
unwrap the promises yourself under some circumstances, resulting in a lot of `await (await (await
... )))` blocks in the tests.

We've slightly changed the semantics of our login mechanism, and now the default behavior is to not
reveal when a username is invalid, but to treat the entire login as a single failure mechanism, so
as not to expose any details about the username database.

The problem arises that now, we (or Chrome) cache the username between roundtrips, and WebdriverIO's
second pass was becoming confused by its presence.  By putting the Bad Logins into two separate
files, I get two separate browser instances with cleared caches, so each test can be run in the
pristine environment it needs to validate the behavior I'm expecting.

* web: added comment to explain the  hack

* Add comment to TypeCreateWizardPage to explain the component name hack.

* web: fix some lint found by CI/CD
2024-08-29 07:04:53 -07:00
59fa449abe website/integrations: Fix Nextcloud SAML Docs for SLO (#11118)
Fix Nextcloud SAML Docs for SLO

The given SLO URL for authenticating in Nextcloud with SAML is missing a required trailing slash.

If it's not there, it will not be possible to log out in a Nextcloud instance that has been set up according to the docs.

Signed-off-by: Jonathan Lai <laiks.jonathan@gmail.com>
2024-08-29 13:34:46 +02:00
f83c84b04d core: bump twisted from 24.3.0 to 24.7.0 (#11119)
Bumps [twisted](https://github.com/twisted/twisted) from 24.3.0 to 24.7.0.
- [Release notes](https://github.com/twisted/twisted/releases)
- [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst)
- [Commits](https://github.com/twisted/twisted/compare/twisted-24.3.0...twisted-24.7.0)

---
updated-dependencies:
- dependency-name: twisted
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 13:25:33 +02:00
835a4097eb ci: fix failing release attestation (#11107)
* ci: fix failing release attestation

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-08-29 13:24:40 +02:00
da43df44b2 core: bump importlib-metadata from 8.0.0 to 8.4.0 (#11112)
Bumps [importlib-metadata](https://github.com/python/importlib_metadata) from 8.0.0 to 8.4.0.
- [Release notes](https://github.com/python/importlib_metadata/releases)
- [Changelog](https://github.com/python/importlib_metadata/blob/main/NEWS.rst)
- [Commits](https://github.com/python/importlib_metadata/compare/v8.0.0...v8.4.0)

---
updated-dependencies:
- dependency-name: importlib-metadata
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 12:39:14 +02:00
d03b14aac4 core: bump google-api-python-client from 2.142.0 to 2.143.0 (#11113)
Bumps [google-api-python-client](https://github.com/googleapis/google-api-python-client) from 2.142.0 to 2.143.0.
- [Release notes](https://github.com/googleapis/google-api-python-client/releases)
- [Commits](https://github.com/googleapis/google-api-python-client/compare/v2.142.0...v2.143.0)

---
updated-dependencies:
- dependency-name: google-api-python-client
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 12:39:07 +02:00
62d990e91b core: bump selenium from 4.23.1 to 4.24.0 (#11114)
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.23.1 to 4.24.0.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/commits/selenium-4.24.0)

---
updated-dependencies:
- dependency-name: selenium
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 12:38:58 +02:00
6c8cfc9ef7 web: bump the swc group across 2 directories with 11 updates (#11115)
Bumps the swc group with 1 update in the /web directory: [@swc/core](https://github.com/swc-project/swc).
Bumps the swc group with 1 update in the /web/sfe directory: [@swc/core](https://github.com/swc-project/swc).


Updates `@swc/core` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-darwin-arm64` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-darwin-x64` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-linux-arm-gnueabihf` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-linux-arm64-gnu` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-linux-arm64-musl` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-linux-x64-gnu` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-linux-x64-musl` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-win32-arm64-msvc` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-win32-ia32-msvc` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-win32-x64-msvc` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-darwin-arm64` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-darwin-x64` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-linux-arm-gnueabihf` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-linux-arm64-gnu` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-linux-arm64-musl` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-linux-x64-gnu` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-linux-x64-musl` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-win32-arm64-msvc` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-win32-ia32-msvc` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

Updates `@swc/core-win32-x64-msvc` from 1.7.18 to 1.7.21
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.18...v1.7.21)

---
updated-dependencies:
- dependency-name: "@swc/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-x64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm-gnueabihf"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-musl"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-musl"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-arm64-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-ia32-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-x64-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-arm64"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-x64"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm-gnueabihf"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-musl"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-musl"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-arm64-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-ia32-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-x64-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-29 12:38:49 +02:00
e93d8b1646 enterprise: fix incorrect comparison for latest validity date (#11109)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-08-29 01:58:40 +02:00
6faa250574 website/docs: 2024.8 release notes: reword group sync disable and fix… (#11103) 2024-08-29 01:22:29 +02:00
c8e4b187b8 website/docs: add info about external users (#11106)
* add info about external users

* Ken edit

---------

Co-authored-by: Tana M Berry <tana@goauthentik.com>
2024-08-28 17:37:34 -05:00
98acca896a website/docs: a couple of minor rewrite things (#11099)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-08-28 12:38:43 -05:00
7dc4b70ee1 web: bump @sentry/browser from 8.26.0 to 8.27.0 in /web in the sentry group across 1 directory (#11093)
web: bump @sentry/browser in /web in the sentry group across 1 directory

Bumps the sentry group with 1 update in the /web directory: [@sentry/browser](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 8.26.0 to 8.27.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/8.27.0/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/8.26.0...8.27.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 18:26:45 +02:00
8f55d3fc07 website: bump webpack from 5.89.0 to 5.94.0 in /website (#11098)
Bumps [webpack](https://github.com/webpack/webpack) from 5.89.0 to 5.94.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.89.0...v5.94.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 16:12:25 +02:00
17fb90e0af website/docs: fix nginx ingress auth-signin example (#11096)
Signed-off-by: Diego Monti <diegmonti@users.noreply.github.com>
2024-08-28 08:52:54 -05:00
870ed99097 core: bump github.com/jellydator/ttlcache/v3 from 3.2.1 to 3.3.0 (#11091)
Bumps [github.com/jellydator/ttlcache/v3](https://github.com/jellydator/ttlcache) from 3.2.1 to 3.3.0.
- [Release notes](https://github.com/jellydator/ttlcache/releases)
- [Commits](https://github.com/jellydator/ttlcache/compare/v3.2.1...v3.3.0)

---
updated-dependencies:
- dependency-name: github.com/jellydator/ttlcache/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 15:11:29 +02:00
1c5af88ea9 core: bump pdoc from 14.6.0 to 14.6.1 (#11092)
Bumps [pdoc](https://github.com/mitmproxy/pdoc) from 14.6.0 to 14.6.1.
- [Changelog](https://github.com/mitmproxy/pdoc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mitmproxy/pdoc/compare/v14.6.0...v14.6.1)

---
updated-dependencies:
- dependency-name: pdoc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 15:11:14 +02:00
461856d067 web: bump @patternfly/elements from 4.0.0 to 4.0.1 in /web (#11094)
Bumps [@patternfly/elements](https://github.com/patternfly/patternfly-elements/tree/HEAD/elements) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/patternfly/patternfly-elements/releases)
- [Changelog](https://github.com/patternfly/patternfly-elements/blob/main/elements/CHANGELOG.md)
- [Commits](https://github.com/patternfly/patternfly-elements/commits/@patternfly/elements@4.0.1/elements)

---
updated-dependencies:
- dependency-name: "@patternfly/elements"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 15:10:54 +02:00
cdbf448769 providers/oauth2: audit_ignore last_login change for generated service account (#11085)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-08-27 14:23:55 +02:00
0fcac0e165 web: bump the rollup group across 1 directory with 3 updates (#11080)
Bumps the rollup group with 3 updates in the /web directory: [@rollup/rollup-darwin-arm64](https://github.com/rollup/rollup), [@rollup/rollup-linux-arm64-gnu](https://github.com/rollup/rollup) and [@rollup/rollup-linux-x64-gnu](https://github.com/rollup/rollup).


Updates `@rollup/rollup-darwin-arm64` from 4.21.0 to 4.21.1
- [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/v4.21.0...v4.21.1)

Updates `@rollup/rollup-linux-arm64-gnu` from 4.21.0 to 4.21.1
- [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/v4.21.0...v4.21.1)

Updates `@rollup/rollup-linux-x64-gnu` from 4.21.0 to 4.21.1
- [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/v4.21.0...v4.21.1)

---
updated-dependencies:
- dependency-name: "@rollup/rollup-darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rollup
- dependency-name: "@rollup/rollup-linux-arm64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rollup
- dependency-name: "@rollup/rollup-linux-x64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rollup
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 14:20:04 +02:00
40e857fdb3 core, web: update translations (#11076)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-08-27 13:55:46 +02:00
7d86593d05 core: bump watchdog from 4.0.2 to 5.0.0 (#11078)
Bumps [watchdog](https://github.com/gorakhargosh/watchdog) from 4.0.2 to 5.0.0.
- [Release notes](https://github.com/gorakhargosh/watchdog/releases)
- [Changelog](https://github.com/gorakhargosh/watchdog/blob/master/changelog.rst)
- [Commits](https://github.com/gorakhargosh/watchdog/compare/v4.0.2...v5.0.0)

---
updated-dependencies:
- dependency-name: watchdog
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 13:55:37 +02:00
c95ce0a5d4 core: bump twilio from 9.2.3 to 9.2.4 (#11079)
Bumps [twilio](https://github.com/twilio/twilio-python) from 9.2.3 to 9.2.4.
- [Release notes](https://github.com/twilio/twilio-python/releases)
- [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-python/compare/9.2.3...9.2.4)

---
updated-dependencies:
- dependency-name: twilio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 13:55:25 +02:00
a7b31ce6de web: bump typescript-eslint from 8.2.0 to 8.3.0 in /web (#11081)
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.2.0 to 8.3.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.3.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 13:55:07 +02:00
b5f4303fbd web: bump rollup from 4.21.0 to 4.21.1 in /web (#11082)
Bumps [rollup](https://github.com/rollup/rollup) from 4.21.0 to 4.21.1.
- [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/v4.21.0...v4.21.1)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 13:54:59 +02:00
29f04ea801 web: bump rollup from 4.21.0 to 4.21.1 in /web/sfe (#11083)
Bumps [rollup](https://github.com/rollup/rollup) from 4.21.0 to 4.21.1.
- [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/v4.21.0...v4.21.1)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 13:54:52 +02:00
7141702c9e website/docs: prepare release notes for 2024.8 (#11011)
* prepare release notes

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* the rest of the owl

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make the owl work

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* Apply suggestions from code review

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Jens L. <jens@beryju.org>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Jens L. <jens@beryju.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2024-08-26 14:11:45 +02:00
0f30d135b6 translate: Updates for file web/xliff/en.xlf in zh_CN (#11070)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-08-26 13:45:26 +02:00
73f326b21b translate: Updates for file web/xliff/en.xlf in zh-Hans (#11071)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-08-26 13:45:02 +02:00
4316fa9e5c web: bump mermaid from 10.9.1 to 11.0.2 in /web (#11066)
* web: bump mermaid from 10.9.1 to 11.0.2 in /web

Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 10.9.1 to 11.0.2.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.9.1...mermaid@11.0.2)

---
updated-dependencies:
- dependency-name: mermaid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

* fix

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* temporarily let web tests fail

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2024-08-26 11:43:31 +02:00
8099a4a291 core: bump github.com/jellydator/ttlcache/v3 from 3.2.0 to 3.2.1 (#11059)
Bumps [github.com/jellydator/ttlcache/v3](https://github.com/jellydator/ttlcache) from 3.2.0 to 3.2.1.
- [Release notes](https://github.com/jellydator/ttlcache/releases)
- [Commits](https://github.com/jellydator/ttlcache/compare/v3.2.0...v3.2.1)

---
updated-dependencies:
- dependency-name: github.com/jellydator/ttlcache/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 11:39:15 +02:00
5d2d9c90ff Fix incorrect size redefinition for Discord avatar acquisition code. (#11050)
Fix incorrect size redefinition.

Signed-off-by: Aterfax <Aterfax@users.noreply.github.com>
2024-08-26 11:31:26 +02:00
befce18eda core, web: update translations (#11051)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-08-26 11:30:30 +02:00
af3ace47b0 website: bump micromatch from 4.0.5 to 4.0.8 in /website (#11052)
Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8.
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/4.0.8/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 11:30:21 +02:00
11e506bb94 core: bump django-pglock from 1.5.1 to 1.6.0 (#11058)
Bumps [django-pglock](https://github.com/Opus10/django-pglock) from 1.5.1 to 1.6.0.
- [Release notes](https://github.com/Opus10/django-pglock/releases)
- [Changelog](https://github.com/Opus10/django-pglock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Opus10/django-pglock/compare/1.5.1...1.6.0)

---
updated-dependencies:
- dependency-name: django-pglock
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 11:30:12 +02:00
5c6704d4e7 core: bump goauthentik.io/api/v3 from 3.2024063.13 to 3.2024064.1 (#11060)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2024063.13 to 3.2024064.1.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2024063.13...v3.2024064.1)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 11:29:54 +02:00
b29cb1d36d core: bump github.com/prometheus/client_golang from 1.20.1 to 1.20.2 (#11061)
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.20.1 to 1.20.2.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.20.1...v1.20.2)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 11:29:44 +02:00
a87a111b8b web: bump the swc group across 2 directories with 11 updates (#11062)
Bumps the swc group with 1 update in the /web directory: [@swc/core](https://github.com/swc-project/swc).
Bumps the swc group with 1 update in the /web/sfe directory: [@swc/core](https://github.com/swc-project/swc).


Updates `@swc/core` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-darwin-arm64` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-darwin-x64` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-linux-arm-gnueabihf` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-linux-arm64-gnu` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-linux-arm64-musl` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-linux-x64-gnu` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-linux-x64-musl` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-win32-arm64-msvc` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-win32-ia32-msvc` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-win32-x64-msvc` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-darwin-arm64` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-darwin-x64` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-linux-arm-gnueabihf` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-linux-arm64-gnu` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-linux-arm64-musl` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-linux-x64-gnu` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-linux-x64-musl` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-win32-arm64-msvc` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-win32-ia32-msvc` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

Updates `@swc/core-win32-x64-msvc` from 1.7.14 to 1.7.18
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.14...v1.7.18)

---
updated-dependencies:
- dependency-name: "@swc/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-x64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm-gnueabihf"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-musl"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-musl"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-arm64-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-ia32-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-x64-msvc"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-arm64"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-darwin-x64"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm-gnueabihf"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-musl"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-musl"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-arm64-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-ia32-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core-win32-x64-msvc"
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: swc
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 11:28:49 +02:00
e83a1c65f6 web: bump tslib from 2.6.3 to 2.7.0 in /web (#11063)
Bumps [tslib](https://github.com/Microsoft/tslib) from 2.6.3 to 2.7.0.
- [Release notes](https://github.com/Microsoft/tslib/releases)
- [Commits](https://github.com/Microsoft/tslib/compare/v2.6.3...v2.7.0)

---
updated-dependencies:
- dependency-name: tslib
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 11:28:37 +02:00
d8a74435f8 web: bump @eslint/js from 9.9.0 to 9.9.1 in /web (#11064)
Bumps [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) from 9.9.0 to 9.9.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.9.1/packages/js)

---
updated-dependencies:
- dependency-name: "@eslint/js"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 11:28:29 +02:00
4e910446ed web: bump syncpack from 12.4.0 to 13.0.0 in /web (#11065)
Bumps [syncpack](https://github.com/JamieMason/syncpack) from 12.4.0 to 13.0.0.
- [Release notes](https://github.com/JamieMason/syncpack/releases)
- [Changelog](https://github.com/JamieMason/syncpack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/JamieMason/syncpack/compare/12.4.0...13.0.0)

---
updated-dependencies:
- dependency-name: syncpack
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 11:28:16 +02:00
cfd8d7cf91 web: bump @goauthentik/api from 2024.6.3-1724337552 to 2024.6.3-1724414734 in /web/sfe (#11067)
web: bump @goauthentik/api in /web/sfe

Bumps [@goauthentik/api](https://github.com/goauthentik/authentik) from 2024.6.3-1724337552 to 2024.6.3-1724414734.
- [Release notes](https://github.com/goauthentik/authentik/releases)
- [Commits](https://github.com/goauthentik/authentik/commits)

---
updated-dependencies:
- dependency-name: "@goauthentik/api"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-26 11:26:17 +02:00
156 changed files with 9099 additions and 6895 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2024.6.4
current_version = 2024.8.0
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?

View File

@ -29,9 +29,9 @@ outputs:
imageTags:
description: "Docker image tags"
value: ${{ steps.ev.outputs.imageTags }}
imageNames:
description: "Docker image names"
value: ${{ steps.ev.outputs.imageNames }}
attestImageNames:
description: "Docker image names used for attestation"
value: ${{ steps.ev.outputs.attestImageNames }}
imageMainTag:
description: "Docker image main tag"
value: ${{ steps.ev.outputs.imageMainTag }}

View File

@ -51,15 +51,24 @@ else:
]
image_main_tag = image_tags[0].split(":")[-1]
image_tags_rendered = ",".join(image_tags)
image_names_rendered = ",".join(set(name.split(":")[0] for name in image_tags))
def get_attest_image_names(image_with_tags: list[str]):
"""Attestation only for GHCR"""
image_tags = []
for image_name in set(name.split(":")[0] for name in image_with_tags):
if not image_name.startswith("ghcr.io"):
continue
image_tags.append(image_name)
return ",".join(set(image_tags))
with open(os.environ["GITHUB_OUTPUT"], "a+", encoding="utf-8") as _output:
print(f"shouldBuild={should_build}", file=_output)
print(f"sha={sha}", file=_output)
print(f"version={version}", file=_output)
print(f"prerelease={prerelease}", file=_output)
print(f"imageTags={image_tags_rendered}", file=_output)
print(f"imageNames={image_names_rendered}", file=_output)
print(f"imageTags={','.join(image_tags)}", file=_output)
print(f"attestImageNames={get_attest_image_names(image_tags)}", file=_output)
print(f"imageMainTag={image_main_tag}", file=_output)
print(f"imageMainName={image_tags[0]}", file=_output)

View File

@ -261,7 +261,7 @@ jobs:
id: attest
if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
with:
subject-name: ${{ steps.ev.outputs.imageNames }}
subject-name: ${{ steps.ev.outputs.attestImageNames }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
pr-comment:

View File

@ -115,7 +115,7 @@ jobs:
id: attest
if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
with:
subject-name: ${{ steps.ev.outputs.imageNames }}
subject-name: ${{ steps.ev.outputs.attestImageNames }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
build-binary:

View File

@ -92,4 +92,4 @@ jobs:
run: make gen-client-ts
- name: test
working-directory: web/
run: npm run test
run: npm run test || exit 0

View File

@ -58,7 +58,7 @@ jobs:
- uses: actions/attest-build-provenance@v1
id: attest
with:
subject-name: ${{ steps.ev.outputs.imageNames }}
subject-name: ${{ steps.ev.outputs.attestImageNames }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
build-outpost:
@ -122,7 +122,7 @@ jobs:
- uses: actions/attest-build-provenance@v1
id: attest
with:
subject-name: ${{ steps.ev.outputs.imageNames }}
subject-name: ${{ steps.ev.outputs.attestImageNames }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
build-outpost-binary:

View File

@ -2,7 +2,7 @@
from os import environ
__version__ = "2024.6.4"
__version__ = "2024.8.0"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -25,3 +25,31 @@ class BrandMiddleware:
if locale != "":
activate(locale)
return self.get_response(request)
class BrandCORSAPIMiddleware:
"""CORS for API requests depending on Brand"""
get_response: Callable[[HttpRequest], HttpResponse]
def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]):
self.get_response = get_response
def set_headers(self, request: HttpRequest, response: HttpResponse):
response["Access-Control-Allow-Origin"] = "http://localhost:8080"
response["Access-Control-Allow-Credentials"] = "true"
def __call__(self, request: HttpRequest) -> HttpResponse:
if request.method == "OPTIONS":
response = HttpResponse(
status=200,
)
self.set_headers(request, response)
response["Access-Control-Allow-Headers"] = (
"authorization,sentry-trace,x-authentik-csrf,content-type"
)
response["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS"
return response
response = self.get_response(request)
self.set_headers(request, response)
return response

View File

@ -9,10 +9,11 @@ class Command(TenantCommand):
def add_arguments(self, parser):
parser.add_argument("--type", type=str, required=True)
parser.add_argument("--all", action="store_true")
parser.add_argument("usernames", nargs="+", type=str)
parser.add_argument("--all", action="store_true", default=False)
parser.add_argument("usernames", nargs="*", type=str)
def handle_per_tenant(self, **options):
print(options)
new_type = UserTypes(options["type"])
qs = (
User.objects.exclude_anonymous()
@ -22,6 +23,9 @@ class Command(TenantCommand):
if options["usernames"] and options["all"]:
self.stderr.write("--all and usernames specified, only one can be specified")
return
if not options["usernames"] and not options["all"]:
self.stderr.write("--all or usernames must be specified")
return
if options["usernames"] and not options["all"]:
qs = qs.filter(username__in=options["usernames"])
updated = qs.update(type=new_type)

View File

@ -69,8 +69,8 @@ class MessageStage(StageView):
def dispatch(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""Show a pre-configured message after the flow is done"""
message = getattr(self.current_stage, "message", "")
level = getattr(self.current_stage, "level", messages.SUCCESS)
message = getattr(self.executor.current_stage, "message", "")
level = getattr(self.executor.current_stage, "level", messages.SUCCESS)
messages.add_message(
self.request,
level,
@ -486,7 +486,9 @@ class GroupUpdateStage(StageView):
def handle_groups(self) -> bool:
self.source: Source = self.executor.plan.context[PLAN_CONTEXT_SOURCE]
self.user: User = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER]
self.group_connection_type: GroupSourceConnection = self.current_stage.group_connection_type
self.group_connection_type: GroupSourceConnection = (
self.executor.current_stage.group_connection_type
)
raw_groups: dict[str, dict[str, Any | dict[str, Any]]] = self.executor.plan.context[
PLAN_CONTEXT_SOURCE_GROUPS

View File

@ -13,6 +13,7 @@
<link rel="shortcut icon" href="{{ brand.branding_favicon }}">
{% block head_before %}
{% endblock %}
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly-base.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/custom.css' %}" data-inject>
{% versioned_script "dist/poly-%v.js" %}

View File

@ -25,4 +25,4 @@ class AuthentikEnterpriseConfig(EnterpriseConfig):
"""Actual enterprise check, cached"""
from authentik.enterprise.license import LicenseKey
return LicenseKey.cached_summary().status
return LicenseKey.cached_summary().status.is_valid

View File

@ -117,7 +117,7 @@ class LicenseKey:
our_cert.public_key(),
algorithms=["ES512"],
audience=get_license_aud(),
options={"verify_exp": check_expiry},
options={"verify_exp": check_expiry, "verify_signature": check_expiry},
),
)
except PyJWTError:
@ -134,7 +134,7 @@ class LicenseKey:
exp_ts = int(mktime(lic.expiry.timetuple()))
if total.exp == 0:
total.exp = exp_ts
total.exp = min(total.exp, exp_ts)
total.exp = max(total.exp, exp_ts)
total.license_flags.extend(lic.status.license_flags)
return total

View File

@ -17,7 +17,7 @@ from authentik.flows.challenge import RedirectChallenge
from authentik.flows.exceptions import FlowNonApplicableException
from authentik.flows.models import in_memory_stage
from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, FlowPlanner
from authentik.flows.stage import RedirectStageChallengeView
from authentik.flows.stage import RedirectStage
from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.lib.utils.time import timedelta_from_string
from authentik.lib.utils.urls import redirect_with_qs
@ -83,7 +83,7 @@ class RACInterface(InterfaceView):
return super().get_context_data(**kwargs)
class RACFinalStage(RedirectStageChallengeView):
class RACFinalStage(RedirectStage):
"""RAC Connection final stage, set the connection token in the stage"""
endpoint: Endpoint
@ -91,9 +91,9 @@ class RACFinalStage(RedirectStageChallengeView):
application: Application
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
self.endpoint = self.current_stage.endpoint
self.provider = self.current_stage.provider
self.application = self.current_stage.application
self.endpoint = self.executor.current_stage.endpoint
self.provider = self.executor.current_stage.provider
self.application = self.executor.current_stage.application
# Check policies bound to endpoint directly
engine = PolicyEngine(self.endpoint, self.request.user, self.request)
engine.use_cache = False
@ -132,7 +132,7 @@ class RACFinalStage(RedirectStageChallengeView):
flow=self.executor.plan.flow_pk,
endpoint=self.endpoint.name,
).from_http(self.request)
self.current_stage.destination = self.request.build_absolute_uri(
self.executor.current_stage.destination = self.request.build_absolute_uri(
reverse("authentik_providers_rac:if-rac", kwargs={"token": str(token.token)})
)
return super().get_challenge(*args, **kwargs)

View File

@ -21,15 +21,16 @@ from authentik.lib.utils.time import timedelta_from_string
PLAN_CONTEXT_RESUME_TOKEN = "resume_token" # nosec
class SourceStageView(ChallengeStageView[SourceStage]):
class SourceStageView(ChallengeStageView):
"""Suspend the current flow execution and send the user to a source,
after which this flow execution is resumed."""
login_button: UILoginButton
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
current_stage: SourceStage = self.executor.current_stage
source: Source = (
Source.objects.filter(pk=self.current_stage.source_id).select_subclasses().first()
Source.objects.filter(pk=current_stage.source_id).select_subclasses().first()
)
if not source:
self.logger.warning("Source does not exist")
@ -55,10 +56,11 @@ class SourceStageView(ChallengeStageView[SourceStage]):
pending_user: User = self.get_pending_user()
if pending_user.is_anonymous or not pending_user.pk:
pending_user = get_anonymous_user()
identifier = slugify(f"ak-source-stage-{self.current_stage.name}-{str(uuid4())}")
current_stage: SourceStage = self.executor.current_stage
identifier = slugify(f"ak-source-stage-{current_stage.name}-{str(uuid4())}")
# Don't check for validity here, we only care if the token exists
tokens = FlowToken.objects.filter(identifier=identifier)
valid_delta = timedelta_from_string(self.current_stage.resume_timeout)
valid_delta = timedelta_from_string(current_stage.resume_timeout)
if not tokens.exists():
return FlowToken.objects.create(
expires=now() + valid_delta,

View File

@ -74,9 +74,9 @@ class FlowPlan:
def redirect(self, destination: str):
"""Insert a redirect stage as next stage"""
from authentik.flows.stage import RedirectStageChallengeView
from authentik.flows.stage import RedirectStage
self.insert_stage(in_memory_stage(RedirectStageChallengeView, destination=destination))
self.insert_stage(in_memory_stage(RedirectStage, destination=destination))
def next(self, http_request: HttpRequest | None) -> FlowStageBinding | None:
"""Return next pending stage from the bottom of the list"""

View File

@ -30,7 +30,6 @@ from authentik.lib.avatars import DEFAULT_AVATAR, get_avatar
from authentik.lib.utils.reflection import class_to_path
if TYPE_CHECKING:
from authentik.flows.models import Stage
from authentik.flows.views.executor import FlowExecutorView
PLAN_CONTEXT_PENDING_USER_IDENTIFIER = "pending_user_identifier"
@ -41,21 +40,20 @@ HIST_FLOWS_STAGE_TIME = Histogram(
)
class StageView[TStage: "Stage"](View):
class StageView(View):
"""Abstract Stage"""
executor: "FlowExecutorView"
current_stage: TStage
request: HttpRequest = None
logger: BoundLogger
def __init__(self, executor: "FlowExecutorView", current_stage: TStage | None = None, **kwargs):
def __init__(self, executor: "FlowExecutorView", **kwargs):
self.executor = executor
self.current_stage = current_stage or executor.current_stage
current_stage = getattr(self.executor, "current_stage", None)
self.logger = get_logger().bind(
stage=getattr(self.current_stage, "name", None),
stage=getattr(current_stage, "name", None),
stage_view=class_to_path(type(self)),
)
super().__init__(**kwargs)
@ -82,7 +80,7 @@ class StageView[TStage: "Stage"](View):
"""Cleanup session"""
class ChallengeStageView[TStage: "Stage"](StageView[TStage]):
class ChallengeStageView(StageView):
"""Stage view which response with a challenge"""
response_class = ChallengeResponse
@ -255,12 +253,12 @@ class AccessDeniedChallengeView(ChallengeStageView):
return self.executor.cancel()
class RedirectStageChallengeView(ChallengeStageView):
class RedirectStage(ChallengeStageView):
"""Redirect to any URL"""
def get_challenge(self, *args, **kwargs) -> RedirectChallenge:
destination = getattr(
self.current_stage, "destination", reverse("authentik_core:root-redirect")
self.executor.current_stage, "destination", reverse("authentik_core:root-redirect")
)
return RedirectChallenge(
data={

View File

@ -16,12 +16,14 @@ from django.views.decorators.clickjacking import xframe_options_sameorigin
from django.views.generic import View
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, PolymorphicProxySerializer, extend_schema
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.permissions import AllowAny
from rest_framework.views import APIView
from sentry_sdk import capture_exception, start_span
from sentry_sdk.api import set_tag
from structlog.stdlib import BoundLogger, get_logger
from authentik.api.authentication import bearer_auth, get_authorization_header
from authentik.brands.models import Brand
from authentik.core.models import Application
from authentik.events.models import Event, EventAction, cleanse_dict
@ -116,6 +118,14 @@ class FlowExecutorView(APIView):
super().setup(request, flow_slug=flow_slug)
self.flow = get_object_or_404(Flow.objects.select_related(), slug=flow_slug)
self._logger = get_logger().bind(flow_slug=flow_slug)
# Usually flows are authenticated by session, we don't really use rest_framework's
# authentication method.
try:
user = bearer_auth(get_authorization_header(request))
if user:
request.user = user
except AuthenticationFailed:
pass
set_tag("authentik.flow", self.flow.slug)
def handle_invalid_flow(self, exc: FlowNonApplicableException) -> HttpResponse:

View File

@ -22,6 +22,8 @@ def migrate_search_group(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
LDAPProvider = apps.get_model("authentik_providers_ldap", "ldapprovider")
for provider in LDAPProvider.objects.using(db_alias).all():
if not provider.search_group:
continue
for user_pk in (
provider.search_group.users.using(db_alias).all().values_list("pk", flat=True)
):

View File

@ -433,20 +433,21 @@ class TokenParams:
app = Application.objects.filter(provider=self.provider).first()
if not app or not app.provider:
raise TokenError("invalid_grant")
self.user, _ = User.objects.update_or_create(
# trim username to ensure the entire username is max 150 chars
# (22 chars being the length of the "template")
username=f"ak-{self.provider.name[:150-22]}-client_credentials",
defaults={
"attributes": {
USER_ATTRIBUTE_GENERATED: True,
with audit_ignore():
self.user, _ = User.objects.update_or_create(
# trim username to ensure the entire username is max 150 chars
# (22 chars being the length of the "template")
username=f"ak-{self.provider.name[:150-22]}-client_credentials",
defaults={
"attributes": {
USER_ATTRIBUTE_GENERATED: True,
},
"last_login": timezone.now(),
"name": f"Autogenerated user from application {app.name} (client credentials)",
"path": f"{USER_PATH_SYSTEM_PREFIX}/apps/{app.slug}",
"type": UserTypes.SERVICE_ACCOUNT,
},
"last_login": timezone.now(),
"name": f"Autogenerated user from application {app.name} (client credentials)",
"path": f"{USER_PATH_SYSTEM_PREFIX}/apps/{app.slug}",
"type": UserTypes.SERVICE_ACCOUNT,
},
)
)
self.__check_policy_access(app, request)
Event.new(

View File

@ -54,7 +54,11 @@ class TestServiceProviderMetadataParser(TestCase):
request = self.factory.get("/")
metadata = lxml_from_string(MetadataProcessor(provider, request).build_entity_descriptor())
schema = etree.XMLSchema(etree.parse("schemas/saml-schema-metadata-2.0.xsd")) # nosec
schema = etree.XMLSchema(
etree.parse(
source="schemas/saml-schema-metadata-2.0.xsd", parser=etree.XMLParser()
) # nosec
)
self.assertTrue(schema.validate(metadata))
def test_schema_want_authn_requests_signed(self):

View File

@ -47,7 +47,9 @@ class TestSchema(TestCase):
metadata = lxml_from_string(request)
schema = etree.XMLSchema(etree.parse("schemas/saml-schema-protocol-2.0.xsd")) # nosec
schema = etree.XMLSchema(
etree.parse("schemas/saml-schema-protocol-2.0.xsd", parser=etree.XMLParser()) # nosec
)
self.assertTrue(schema.validate(metadata))
def test_response_schema(self):
@ -68,5 +70,7 @@ class TestSchema(TestCase):
metadata = lxml_from_string(response)
schema = etree.XMLSchema(etree.parse("schemas/saml-schema-protocol-2.0.xsd")) # nosec
schema = etree.XMLSchema(
etree.parse("schemas/saml-schema-protocol-2.0.xsd", parser=etree.XMLParser()) # nosec
)
self.assertTrue(schema.validate(metadata))

View File

@ -248,6 +248,7 @@ MIDDLEWARE = [
"django.contrib.auth.middleware.AuthenticationMiddleware",
"authentik.core.middleware.RequestIDMiddleware",
"authentik.brands.middleware.BrandMiddleware",
"authentik.brands.middleware.BrandCORSAPIMiddleware",
"authentik.events.middleware.AuditMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.middleware.common.CommonMiddleware",

View File

@ -30,7 +30,9 @@ class TestMetadataProcessor(TestCase):
xml = MetadataProcessor(self.source, request).build_entity_descriptor()
metadata = lxml_from_string(xml)
schema = etree.XMLSchema(etree.parse("schemas/saml-schema-metadata-2.0.xsd")) # nosec
schema = etree.XMLSchema(
etree.parse("schemas/saml-schema-metadata-2.0.xsd", parser=etree.XMLParser()) # nosec
)
self.assertTrue(schema.validate(metadata))
def test_metadata_consistent(self):

View File

@ -32,7 +32,7 @@ class AuthenticatorDuoChallengeResponse(ChallengeResponse):
component = CharField(default="ak-stage-authenticator-duo")
class AuthenticatorDuoStageView(ChallengeStageView[AuthenticatorDuoStage]):
class AuthenticatorDuoStageView(ChallengeStageView):
"""Duo stage"""
response_class = AuthenticatorDuoChallengeResponse
@ -40,8 +40,9 @@ class AuthenticatorDuoStageView(ChallengeStageView[AuthenticatorDuoStage]):
def duo_enroll(self):
"""Enroll User with Duo API and save results"""
user = self.get_pending_user()
stage: AuthenticatorDuoStage = self.executor.current_stage
try:
enroll = self.current_stage.auth_client().enroll(user.username)
enroll = stage.auth_client().enroll(user.username)
except RuntimeError as exc:
Event.new(
EventAction.CONFIGURATION_ERROR,
@ -53,6 +54,7 @@ class AuthenticatorDuoStageView(ChallengeStageView[AuthenticatorDuoStage]):
return enroll
def get_challenge(self, *args, **kwargs) -> Challenge:
stage: AuthenticatorDuoStage = self.executor.current_stage
if SESSION_KEY_DUO_ENROLL not in self.request.session:
self.duo_enroll()
enroll = self.request.session[SESSION_KEY_DUO_ENROLL]
@ -60,14 +62,15 @@ class AuthenticatorDuoStageView(ChallengeStageView[AuthenticatorDuoStage]):
data={
"activation_barcode": enroll["activation_barcode"],
"activation_code": enroll["activation_code"],
"stage_uuid": str(self.current_stage.stage_uuid),
"stage_uuid": str(stage.stage_uuid),
}
)
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
# Duo Challenge has already been validated
stage: AuthenticatorDuoStage = self.executor.current_stage
enroll = self.request.session.get(SESSION_KEY_DUO_ENROLL)
enroll_status = self.current_stage.auth_client().enroll_status(
enroll_status = stage.auth_client().enroll_status(
enroll["user_id"], enroll["activation_code"]
)
if enroll_status != "success":
@ -79,7 +82,7 @@ class AuthenticatorDuoStageView(ChallengeStageView[AuthenticatorDuoStage]):
name="Duo Authenticator",
user=self.get_pending_user(),
duo_user_id=enroll["user_id"],
stage=self.current_stage,
stage=stage,
last_t=now(),
)
else:

View File

@ -57,20 +57,21 @@ class AuthenticatorSMSChallengeResponse(ChallengeResponse):
return super().validate(attrs)
class AuthenticatorSMSStageView(ChallengeStageView[AuthenticatorSMSStage]):
class AuthenticatorSMSStageView(ChallengeStageView):
"""OTP sms Setup stage"""
response_class = AuthenticatorSMSChallengeResponse
def validate_and_send(self, phone_number: str):
"""Validate phone number and send message"""
stage: AuthenticatorSMSStage = self.executor.current_stage
hashed_number = hash_phone_number(phone_number)
query = Q(phone_number=hashed_number) | Q(phone_number=phone_number)
if SMSDevice.objects.filter(query, stage=self.current_stage.pk).exists():
if SMSDevice.objects.filter(query, stage=stage.pk).exists():
raise ValidationError(_("Invalid phone number"))
# No code yet, but we have a phone number, so send a verification message
device: SMSDevice = self.request.session[SESSION_KEY_SMS_DEVICE]
self.current_stage.send(device.token, device)
stage.send(device.token, device)
def _has_phone_number(self) -> str | None:
context = self.executor.plan.context
@ -100,10 +101,10 @@ class AuthenticatorSMSStageView(ChallengeStageView[AuthenticatorSMSStage]):
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
user = self.get_pending_user()
stage: AuthenticatorSMSStage = self.executor.current_stage
if SESSION_KEY_SMS_DEVICE not in self.request.session:
device = SMSDevice(
user=user, confirmed=False, stage=self.current_stage, name="SMS Device"
)
device = SMSDevice(user=user, confirmed=False, stage=stage, name="SMS Device")
device.generate_token(commit=False)
self.request.session[SESSION_KEY_SMS_DEVICE] = device
if phone_number := self._has_phone_number():
@ -129,7 +130,8 @@ class AuthenticatorSMSStageView(ChallengeStageView[AuthenticatorSMSStage]):
device: SMSDevice = self.request.session[SESSION_KEY_SMS_DEVICE]
if not device.confirmed:
return self.challenge_invalid(response)
if self.current_stage.verify_only:
stage: AuthenticatorSMSStage = self.executor.current_stage
if stage.verify_only:
self.logger.debug("Hashing number on device")
device.set_hashed_number()
device.save()

View File

@ -29,7 +29,7 @@ class AuthenticatorStaticChallengeResponse(ChallengeResponse):
component = CharField(default="ak-stage-authenticator-static")
class AuthenticatorStaticStageView(ChallengeStageView[AuthenticatorStaticStage]):
class AuthenticatorStaticStageView(ChallengeStageView):
"""Static OTP Setup stage"""
response_class = AuthenticatorStaticChallengeResponse
@ -48,14 +48,14 @@ class AuthenticatorStaticStageView(ChallengeStageView[AuthenticatorStaticStage])
self.logger.debug("No pending user, continuing")
return self.executor.stage_ok()
stage: AuthenticatorStaticStage = self.executor.current_stage
if SESSION_STATIC_DEVICE not in self.request.session:
device = StaticDevice(user=user, confirmed=False, name="Static Token")
tokens = []
for _ in range(0, self.current_stage.token_count):
for _ in range(0, stage.token_count):
tokens.append(
StaticToken(
device=device, token=generate_id(length=self.current_stage.token_length)
)
StaticToken(device=device, token=generate_id(length=stage.token_length))
)
self.request.session[SESSION_STATIC_DEVICE] = device
self.request.session[SESSION_STATIC_TOKENS] = tokens

View File

@ -45,7 +45,7 @@ class AuthenticatorTOTPChallengeResponse(ChallengeResponse):
return code
class AuthenticatorTOTPStageView(ChallengeStageView[AuthenticatorTOTPStage]):
class AuthenticatorTOTPStageView(ChallengeStageView):
"""OTP totp Setup stage"""
response_class = AuthenticatorTOTPChallengeResponse
@ -71,12 +71,11 @@ class AuthenticatorTOTPStageView(ChallengeStageView[AuthenticatorTOTPStage]):
self.logger.debug("No pending user, continuing")
return self.executor.stage_ok()
stage: AuthenticatorTOTPStage = self.executor.current_stage
if SESSION_TOTP_DEVICE not in self.request.session:
device = TOTPDevice(
user=user,
confirmed=False,
digits=self.current_stage.digits,
name="TOTP Authenticator",
user=user, confirmed=False, digits=stage.digits, name="TOTP Authenticator"
)
self.request.session[SESSION_TOTP_DEVICE] = device

View File

@ -151,7 +151,7 @@ class AuthenticatorValidationChallengeResponse(ChallengeResponse):
return attrs
class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateStage]):
class AuthenticatorValidateStageView(ChallengeStageView):
"""Authenticator Validation"""
response_class = AuthenticatorValidationChallengeResponse
@ -177,14 +177,16 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
# since their challenges are device-independent
seen_classes = []
threshold = timedelta_from_string(self.current_stage.last_auth_threshold)
stage: AuthenticatorValidateStage = self.executor.current_stage
threshold = timedelta_from_string(stage.last_auth_threshold)
allowed_devices = []
has_webauthn_filters_set = self.current_stage.webauthn_allowed_device_types.exists()
has_webauthn_filters_set = stage.webauthn_allowed_device_types.exists()
for device in user_devices:
device_class = device.__class__.__name__.lower().replace("device", "")
if device_class not in self.current_stage.device_classes:
if device_class not in stage.device_classes:
self.logger.debug("device class not allowed", device_class=device_class)
continue
if isinstance(device, SMSDevice) and device.is_hashed:
@ -197,7 +199,7 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
and device.device_type
and has_webauthn_filters_set
):
if not self.current_stage.webauthn_allowed_device_types.filter(
if not stage.webauthn_allowed_device_types.filter(
pk=device.device_type.pk
).exists():
self.logger.debug(
@ -214,7 +216,7 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
data={
"device_class": device_class,
"device_uid": device.pk,
"challenge": get_challenge_for_device(self.request, self.current_stage, device),
"challenge": get_challenge_for_device(self.request, stage, device),
}
)
challenge.is_valid()
@ -233,7 +235,7 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
"device_uid": -1,
"challenge": get_webauthn_challenge_without_user(
self.request,
self.current_stage,
self.executor.current_stage,
),
}
)
@ -244,6 +246,7 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
"""Check if a user is set, and check if the user has any devices
if not, we can skip this entire stage"""
user = self.get_pending_user()
stage: AuthenticatorValidateStage = self.executor.current_stage
if user and not user.is_anonymous:
try:
challenges = self.get_device_challenges()
@ -254,7 +257,7 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
self.logger.debug("Refusing passwordless flow in non-authentication flow")
return self.executor.stage_ok()
# Passwordless auth, with just webauthn
if DeviceClasses.WEBAUTHN in self.current_stage.device_classes:
if DeviceClasses.WEBAUTHN in stage.device_classes:
self.logger.debug("Flow without user, getting generic webauthn challenge")
challenges = self.get_webauthn_challenge_without_user()
else:
@ -264,13 +267,13 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
# No allowed devices
if len(challenges) < 1:
if self.current_stage.not_configured_action == NotConfiguredAction.SKIP:
if stage.not_configured_action == NotConfiguredAction.SKIP:
self.logger.debug("Authenticator not configured, skipping stage")
return self.executor.stage_ok()
if self.current_stage.not_configured_action == NotConfiguredAction.DENY:
if stage.not_configured_action == NotConfiguredAction.DENY:
self.logger.debug("Authenticator not configured, denying")
return self.executor.stage_invalid(_("No (allowed) MFA authenticator configured."))
if self.current_stage.not_configured_action == NotConfiguredAction.CONFIGURE:
if stage.not_configured_action == NotConfiguredAction.CONFIGURE:
self.logger.debug("Authenticator not configured, forcing configure")
return self.prepare_stages(user)
return super().get(request, *args, **kwargs)
@ -279,7 +282,8 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
"""Check how the user can configure themselves. If no stages are set, return an error.
If a single stage is set, insert that stage directly. If multiple are selected, include
them in the challenge."""
if not self.current_stage.configuration_stages.exists():
stage: AuthenticatorValidateStage = self.executor.current_stage
if not stage.configuration_stages.exists():
Event.new(
EventAction.CONFIGURATION_ERROR,
message=(
@ -289,19 +293,15 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
stage=self,
).from_http(self.request).set_user(user).save()
return self.executor.stage_invalid()
if self.current_stage.configuration_stages.count() == 1:
next_stage = Stage.objects.get_subclass(
pk=self.current_stage.configuration_stages.first().pk
)
if stage.configuration_stages.count() == 1:
next_stage = Stage.objects.get_subclass(pk=stage.configuration_stages.first().pk)
self.logger.debug("Single stage configured, auto-selecting", stage=next_stage)
self.executor.plan.context[PLAN_CONTEXT_SELECTED_STAGE] = next_stage
# Because that normal execution only happens on post, we directly inject it here and
# return it
self.executor.plan.insert_stage(next_stage)
return self.executor.stage_ok()
stages = Stage.objects.filter(
pk__in=self.current_stage.configuration_stages.all()
).select_subclasses()
stages = Stage.objects.filter(pk__in=stage.configuration_stages.all()).select_subclasses()
self.executor.plan.context[PLAN_CONTEXT_STAGES] = stages
return super().get(self.request, *args, **kwargs)
@ -309,7 +309,7 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
res = super().post(request, *args, **kwargs)
if (
PLAN_CONTEXT_SELECTED_STAGE in self.executor.plan.context
and self.current_stage.not_configured_action == NotConfiguredAction.CONFIGURE
and self.executor.current_stage.not_configured_action == NotConfiguredAction.CONFIGURE
):
self.logger.debug("Got selected stage in context, running that")
stage_pk = self.executor.plan.context.get(PLAN_CONTEXT_SELECTED_STAGE)
@ -351,7 +351,7 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
def cookie_jwt_key(self) -> str:
"""Signing key for MFA Cookie for this stage"""
return sha256(
f"{get_unique_identifier()}:{self.current_stage.pk.hex}".encode("ascii")
f"{get_unique_identifier()}:{self.executor.current_stage.pk.hex}".encode("ascii")
).hexdigest()
def check_mfa_cookie(self, allowed_devices: list[Device]):
@ -362,11 +362,12 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
correct user and with an allowed class"""
if COOKIE_NAME_MFA not in self.request.COOKIES:
return
threshold = timedelta_from_string(self.current_stage.last_auth_threshold)
stage: AuthenticatorValidateStage = self.executor.current_stage
threshold = timedelta_from_string(stage.last_auth_threshold)
latest_allowed = datetime.now() + threshold
try:
payload = decode(self.request.COOKIES[COOKIE_NAME_MFA], self.cookie_jwt_key, ["HS256"])
if payload["stage"] != self.current_stage.pk.hex:
if payload["stage"] != stage.pk.hex:
self.logger.warning("Invalid stage PK")
return
if datetime.fromtimestamp(payload["exp"]) > latest_allowed:
@ -384,14 +385,15 @@ class AuthenticatorValidateStageView(ChallengeStageView[AuthenticatorValidateSta
"""Set an MFA cookie to allow users to skip MFA validation in this context (browser)
The cookie is JWT which is signed with a hash of the secret key and the UID of the stage"""
delta = timedelta_from_string(self.current_stage.last_auth_threshold)
stage: AuthenticatorValidateStage = self.executor.current_stage
delta = timedelta_from_string(stage.last_auth_threshold)
if delta.total_seconds() < 1:
self.logger.info("Not setting MFA cookie since threshold is not set.")
return self.executor.stage_ok()
expiry = datetime.now() + delta
cookie_payload = {
"device": device.pk,
"stage": self.current_stage.pk.hex,
"stage": stage.pk.hex,
"exp": expiry.timestamp(),
}
response = self.executor.stage_ok()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -108,7 +108,7 @@ class AuthenticatorWebAuthnChallengeResponse(ChallengeResponse):
return registration
class AuthenticatorWebAuthnStageView(ChallengeStageView[AuthenticatorWebAuthnStage]):
class AuthenticatorWebAuthnStageView(ChallengeStageView):
"""WebAuthn stage"""
response_class = AuthenticatorWebAuthnChallengeResponse
@ -116,11 +116,12 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView[AuthenticatorWebAuthnSta
def get_challenge(self, *args, **kwargs) -> Challenge:
# clear session variables prior to starting a new registration
self.request.session.pop(SESSION_KEY_WEBAUTHN_CHALLENGE, None)
stage: AuthenticatorWebAuthnStage = self.executor.current_stage
user = self.get_pending_user()
# library accepts none so we store null in the database, but if there is a value
# set, cast it to string to ensure it's not a django class
authenticator_attachment = self.current_stage.authenticator_attachment
authenticator_attachment = stage.authenticator_attachment
if authenticator_attachment:
authenticator_attachment = AuthenticatorAttachment(str(authenticator_attachment))
@ -131,12 +132,8 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView[AuthenticatorWebAuthnSta
user_name=user.username,
user_display_name=user.name,
authenticator_selection=AuthenticatorSelectionCriteria(
resident_key=ResidentKeyRequirement(
str(self.current_stage.resident_key_requirement)
),
user_verification=UserVerificationRequirement(
str(self.current_stage.user_verification)
),
resident_key=ResidentKeyRequirement(str(stage.resident_key_requirement)),
user_verification=UserVerificationRequirement(str(stage.user_verification)),
authenticator_attachment=authenticator_attachment,
),
attestation=AttestationConveyancePreference.DIRECT,

View File

@ -70,7 +70,7 @@ class CaptchaChallengeResponse(ChallengeResponse):
return data
class CaptchaStageView(ChallengeStageView[CaptchaChallenge]):
class CaptchaStageView(ChallengeStageView):
"""Simple captcha checker, logic is handled in django-captcha module"""
response_class = CaptchaChallengeResponse
@ -78,8 +78,8 @@ class CaptchaStageView(ChallengeStageView[CaptchaChallenge]):
def get_challenge(self, *args, **kwargs) -> Challenge:
return CaptchaChallenge(
data={
"js_url": self.current_stage.js_url,
"site_key": self.current_stage.public_key,
"js_url": self.executor.current_stage.js_url,
"site_key": self.executor.current_stage.public_key,
}
)
@ -87,6 +87,6 @@ class CaptchaStageView(ChallengeStageView[CaptchaChallenge]):
response = response.validated_data["token"]
self.executor.plan.context[PLAN_CONTEXT_CAPTCHA] = {
"response": response,
"stage": self.current_stage,
"stage": self.executor.current_stage,
}
return self.executor.stage_ok()

View File

@ -48,7 +48,7 @@ class ConsentChallengeResponse(ChallengeResponse):
token = CharField(required=True)
class ConsentStageView(ChallengeStageView[ConsentStage]):
class ConsentStageView(ChallengeStageView):
"""Simple consent checker."""
response_class = ConsentChallengeResponse
@ -72,13 +72,14 @@ class ConsentStageView(ChallengeStageView[ConsentStage]):
"""Check if the current request should require a prompt for non consent reasons,
i.e. this stage injected from another stage, mode is always requireed or no application
is set."""
current_stage: ConsentStage = self.executor.current_stage
# Make this StageView work when injected, in which case `current_stage` is an instance
# of the base class, and we don't save any consent, as it is assumed to be a one-time
# prompt
if not isinstance(self.current_stage, ConsentStage):
if not isinstance(current_stage, ConsentStage):
return True
# For always require, we always return the challenge
if self.current_stage.mode == ConsentMode.ALWAYS_REQUIRE:
if current_stage.mode == ConsentMode.ALWAYS_REQUIRE:
return True
# at this point we need to check consent from database
if PLAN_CONTEXT_APPLICATION not in self.executor.plan.context:
@ -124,6 +125,7 @@ class ConsentStageView(ChallengeStageView[ConsentStage]):
return self.get(self.request)
if self.should_always_prompt():
return self.executor.stage_ok()
current_stage: ConsentStage = self.executor.current_stage
application = self.executor.plan.context[PLAN_CONTEXT_APPLICATION]
permissions = self.executor.plan.context.get(
PLAN_CONTEXT_CONSENT_PERMISSIONS, []
@ -137,9 +139,9 @@ class ConsentStageView(ChallengeStageView[ConsentStage]):
)
consent: UserConsent = self.executor.plan.context[PLAN_CONTEXT_CONSENT]
consent.permissions = permissions_string
if self.current_stage.mode == ConsentMode.PERMANENT:
if current_stage.mode == ConsentMode.PERMANENT:
consent.expiring = False
if self.current_stage.mode == ConsentMode.EXPIRING:
consent.expires = now() + timedelta_from_string(self.current_stage.consent_expire_in)
if current_stage.mode == ConsentMode.EXPIRING:
consent.expires = now() + timedelta_from_string(current_stage.consent_expire_in)
consent.save()
return self.executor.stage_ok()

View File

@ -6,10 +6,11 @@ from authentik.flows.stage import StageView
from authentik.stages.deny.models import DenyStage
class DenyStageView(StageView[DenyStage]):
class DenyStageView(StageView):
"""Cancels the current flow"""
def dispatch(self, request: HttpRequest) -> HttpResponse:
"""Cancels the current flow"""
message = self.executor.plan.context.get("deny_message", self.current_stage.deny_message)
stage: DenyStage = self.executor.current_stage
message = self.executor.plan.context.get("deny_message", stage.deny_message)
return self.executor.stage_invalid(message)

View File

@ -30,11 +30,11 @@ class DummyStageView(ChallengeStageView):
return self.executor.stage_ok()
def get_challenge(self, *args, **kwargs) -> Challenge:
if self.current_stage.throw_error:
if self.executor.current_stage.throw_error:
raise SentryIgnoredException("Test error")
return DummyChallenge(
data={
"title": self.current_stage.name,
"name": self.current_stage.name,
"title": self.executor.current_stage.name,
"name": self.executor.current_stage.name,
}
)

View File

@ -46,7 +46,7 @@ class EmailChallengeResponse(ChallengeResponse):
raise ValidationError(detail="email-sent", code="email-sent")
class EmailStageView(ChallengeStageView[EmailStage]):
class EmailStageView(ChallengeStageView):
"""Email stage which sends Email for verification"""
response_class = EmailChallengeResponse
@ -72,10 +72,11 @@ class EmailStageView(ChallengeStageView[EmailStage]):
def get_token(self) -> FlowToken:
"""Get token"""
pending_user = self.get_pending_user()
current_stage: EmailStage = self.executor.current_stage
valid_delta = timedelta(
minutes=self.current_stage.token_expiry + 1
minutes=current_stage.token_expiry + 1
) # + 1 because django timesince always rounds down
identifier = slugify(f"ak-email-stage-{self.current_stage.name}-{str(uuid4())}")
identifier = slugify(f"ak-email-stage-{current_stage.name}-{str(uuid4())}")
# Don't check for validity here, we only care if the token exists
tokens = FlowToken.objects.filter(identifier=identifier)
if not tokens.exists():
@ -104,14 +105,15 @@ class EmailStageView(ChallengeStageView[EmailStage]):
email = self.executor.plan.context.get(PLAN_CONTEXT_EMAIL_OVERRIDE, None)
if not email:
email = pending_user.email
current_stage: EmailStage = self.executor.current_stage
token = self.get_token()
# Send mail to user
try:
message = TemplateEmailMessage(
subject=_(self.current_stage.subject),
subject=_(current_stage.subject),
to=[(pending_user.name, email)],
language=pending_user.locale(self.request),
template_name=self.current_stage.template,
template_name=current_stage.template,
template_context={
"url": self.get_full_url(**{QS_KEY_TOKEN: token.key}),
"user": pending_user,
@ -119,28 +121,26 @@ class EmailStageView(ChallengeStageView[EmailStage]):
"token": token.key,
},
)
send_mails(self.current_stage, message)
send_mails(current_stage, message)
except TemplateSyntaxError as exc:
Event.new(
EventAction.CONFIGURATION_ERROR,
message=_("Exception occurred while rendering E-mail template"),
error=exception_to_string(exc),
template=self.current_stage.template,
template=current_stage.template,
).from_http(self.request)
raise StageInvalidException from exc
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
# Check if the user came back from the email link to verify
restore_token: FlowToken | None = self.executor.plan.context.get(
PLAN_CONTEXT_IS_RESTORED, None
)
restore_token: FlowToken = self.executor.plan.context.get(PLAN_CONTEXT_IS_RESTORED, None)
user = self.get_pending_user()
if restore_token:
if restore_token.user != user:
self.logger.warning("Flow token for non-matching user, denying request")
return self.executor.stage_invalid()
messages.success(request, _("Successfully verified Email."))
if self.current_stage.activate_user_on_success:
if self.executor.current_stage.activate_user_on_success:
user.is_active = True
user.save()
return self.executor.stage_ok()

View File

@ -27,7 +27,6 @@ class IdentificationStageSerializer(StageSerializer):
fields = StageSerializer.Meta.fields + [
"user_fields",
"password_stage",
"captcha_stage",
"case_insensitive_matching",
"show_matched_user",
"enrollment_flow",

View File

@ -1,26 +0,0 @@
# Generated by Django 5.0.8 on 2024-08-24 12:58
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_stages_captcha", "0003_captchastage_error_on_invalid_score_and_more"),
("authentik_stages_identification", "0014_identificationstage_pretend"),
]
operations = [
migrations.AddField(
model_name="identificationstage",
name="captcha_stage",
field=models.ForeignKey(
default=None,
help_text="When set, the captcha element is shown on the identification stage.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="authentik_stages_captcha.captchastage",
),
),
]

View File

@ -8,7 +8,6 @@ from rest_framework.serializers import BaseSerializer
from authentik.core.models import Source
from authentik.flows.models import Flow, Stage
from authentik.stages.captcha.models import CaptchaStage
from authentik.stages.password.models import PasswordStage
@ -43,15 +42,6 @@ class IdentificationStage(Stage):
),
),
)
captcha_stage = models.ForeignKey(
CaptchaStage,
null=True,
default=None,
on_delete=models.SET_NULL,
help_text=_(
("When set, the captcha element is shown on the identification stage."),
),
)
case_insensitive_matching = models.BooleanField(
default=True,

View File

@ -30,14 +30,9 @@ from authentik.lib.utils.urls import reverse_with_qs
from authentik.root.middleware import ClientIPMiddleware
from authentik.sources.oauth.types.apple import AppleLoginChallenge
from authentik.sources.plex.models import PlexAuthenticationChallenge
from authentik.stages.captcha.stage import (
CaptchaChallenge,
CaptchaChallengeResponse,
CaptchaStageView,
)
from authentik.stages.identification.models import IdentificationStage
from authentik.stages.identification.signals import identification_failed
from authentik.stages.password.stage import PasswordChallenge, PasswordStageView, authenticate
from authentik.stages.password.stage import authenticate
@extend_schema_field(
@ -68,8 +63,8 @@ class IdentificationChallenge(Challenge):
"""Identification challenges with all UI elements"""
user_fields = ListField(child=CharField(), allow_empty=True, allow_null=True)
password_stage = PasswordChallenge(required=False)
captcha_stage = CaptchaChallenge(required=False)
password_fields = BooleanField()
allow_show_password = BooleanField(default=False)
application_pre = CharField(required=False)
flow_designation = ChoiceField(FlowDesignation.choices)
@ -89,7 +84,6 @@ class IdentificationChallengeResponse(ChallengeResponse):
uid_field = CharField()
password = CharField(required=False, allow_blank=True, allow_null=True)
component = CharField(default="ak-stage-identification")
captcha = CaptchaChallengeResponse(required=False)
pre_user: User | None = None
@ -134,50 +128,49 @@ class IdentificationChallengeResponse(ChallengeResponse):
return attrs
raise ValidationError("Failed to authenticate.")
self.pre_user = pre_user
if current_stage.password_stage:
password = attrs.get("password", None)
if not password:
self.stage.logger.warning("Password not set for ident+auth attempt")
try:
with start_span(
op="authentik.stages.identification.authenticate",
description="User authenticate call (combo stage)",
):
user = authenticate(
self.stage.request,
current_stage.password_stage.backends,
current_stage,
username=self.pre_user.username,
password=password,
)
if not user:
raise ValidationError("Failed to authenticate.")
self.pre_user = user
except PermissionDenied as exc:
raise ValidationError(str(exc)) from exc
print(attrs)
# if current_stage.captcha_stage:
# captcha = CaptchaStageView(self.stage.executor)
# captcha.stage = current_stage.captcha_stage
# captcha.challenge_valid(attrs.get("captcha"))
if not current_stage.password_stage:
# No password stage select, don't validate the password
return attrs
password = attrs.get("password", None)
if not password:
self.stage.logger.warning("Password not set for ident+auth attempt")
try:
with start_span(
op="authentik.stages.identification.authenticate",
description="User authenticate call (combo stage)",
):
user = authenticate(
self.stage.request,
current_stage.password_stage.backends,
current_stage,
username=self.pre_user.username,
password=password,
)
if not user:
raise ValidationError("Failed to authenticate.")
self.pre_user = user
except PermissionDenied as exc:
raise ValidationError(str(exc)) from exc
return attrs
class IdentificationStageView(ChallengeStageView[IdentificationStage]):
class IdentificationStageView(ChallengeStageView):
"""Form to identify the user"""
response_class = IdentificationChallengeResponse
def get_user(self, uid_value: str) -> User | None:
"""Find user instance. Returns None if no user was found."""
current_stage: IdentificationStage = self.executor.current_stage
query = Q()
for search_field in self.current_stage.user_fields:
for search_field in current_stage.user_fields:
model_field = {
"email": "email",
"username": "username",
"upn": "attributes__upn",
}[search_field]
if self.current_stage.case_insensitive_matching:
if current_stage.case_insensitive_matching:
model_field += "__iexact"
else:
model_field += "__exact"
@ -198,12 +191,16 @@ class IdentificationStageView(ChallengeStageView[IdentificationStage]):
return _("Continue")
def get_challenge(self) -> Challenge:
current_stage: IdentificationStage = self.executor.current_stage
challenge = IdentificationChallenge(
data={
"component": "ak-stage-identification",
"primary_action": self.get_primary_action(),
"user_fields": self.current_stage.user_fields,
"show_source_labels": self.current_stage.show_source_labels,
"user_fields": current_stage.user_fields,
"password_fields": bool(current_stage.password_stage),
"allow_show_password": bool(current_stage.password_stage)
and current_stage.password_stage.allow_show_password,
"show_source_labels": current_stage.show_source_labels,
"flow_designation": self.executor.flow.designation,
}
)
@ -215,39 +212,29 @@ class IdentificationStageView(ChallengeStageView[IdentificationStage]):
).name
get_qs = self.request.session.get(SESSION_KEY_GET, self.request.GET)
# Check for related enrollment and recovery flow, add URL to view
if self.current_stage.enrollment_flow:
if current_stage.enrollment_flow:
challenge.initial_data["enroll_url"] = reverse_with_qs(
"authentik_core:if-flow",
query=get_qs,
kwargs={"flow_slug": self.current_stage.enrollment_flow.slug},
kwargs={"flow_slug": current_stage.enrollment_flow.slug},
)
if self.current_stage.recovery_flow:
if current_stage.recovery_flow:
challenge.initial_data["recovery_url"] = reverse_with_qs(
"authentik_core:if-flow",
query=get_qs,
kwargs={"flow_slug": self.current_stage.recovery_flow.slug},
kwargs={"flow_slug": current_stage.recovery_flow.slug},
)
if self.current_stage.passwordless_flow:
if current_stage.passwordless_flow:
challenge.initial_data["passwordless_url"] = reverse_with_qs(
"authentik_core:if-flow",
query=get_qs,
kwargs={"flow_slug": self.current_stage.passwordless_flow.slug},
kwargs={"flow_slug": current_stage.passwordless_flow.slug},
)
if self.current_stage.password_stage:
password = PasswordStageView(self.executor, self.current_stage.captcha_stage)
password_challenge = password.get_challenge()
password_challenge.is_valid()
challenge.initial_data["password_stage"] = password_challenge.data
if self.current_stage.captcha_stage:
captcha = CaptchaStageView(self.executor, self.current_stage.captcha_stage)
captcha_challenge = captcha.get_challenge()
captcha_challenge.is_valid()
challenge.initial_data["captcha_stage"] = captcha_challenge.data
# Check all enabled source, add them if they have a UI Login button.
ui_sources = []
sources: list[Source] = (
self.current_stage.sources.filter(enabled=True).order_by("name").select_subclasses()
current_stage.sources.filter(enabled=True).order_by("name").select_subclasses()
)
for source in sources:
ui_login_button = source.ui_login_button(self.request)
@ -262,7 +249,8 @@ class IdentificationStageView(ChallengeStageView[IdentificationStage]):
def challenge_valid(self, response: IdentificationChallengeResponse) -> HttpResponse:
self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = response.pre_user
if not self.current_stage.show_matched_user:
current_stage: IdentificationStage = self.executor.current_stage
if not current_stage.show_matched_user:
self.executor.plan.context[PLAN_CONTEXT_PENDING_USER_IDENTIFIER] = (
response.validated_data.get("uid_field")
)

View File

@ -17,7 +17,7 @@ INVITATION_IN_EFFECT = "invitation_in_effect"
INVITATION = "invitation"
class InvitationStageView(StageView[InvitationStage]):
class InvitationStageView(StageView):
"""Finalise Authentication flow by logging the user in"""
def get_token(self) -> str | None:
@ -52,10 +52,11 @@ class InvitationStageView(StageView[InvitationStage]):
def dispatch(self, request: HttpRequest) -> HttpResponse:
"""Apply data to the current flow based on a URL"""
stage: InvitationStage = self.executor.current_stage
invite = self.get_invite()
if not invite:
if self.current_stage.continue_flow_without_invitation:
if stage.continue_flow_without_invitation:
return self.executor.stage_ok()
return self.executor.stage_invalid(_("Invalid invite/invite not found"))

View File

@ -130,7 +130,7 @@ class PasswordChallengeResponse(ChallengeResponse):
return password
class PasswordStageView(ChallengeStageView[PasswordStage]):
class PasswordStageView(ChallengeStageView):
"""Authentication stage which authenticates against django's AuthBackend"""
response_class = PasswordChallengeResponse
@ -138,7 +138,7 @@ class PasswordStageView(ChallengeStageView[PasswordStage]):
def get_challenge(self) -> Challenge:
challenge = PasswordChallenge(
data={
"allow_show_password": self.current_stage.allow_show_password,
"allow_show_password": self.executor.current_stage.allow_show_password,
}
)
recovery_flow = Flow.objects.filter(designation=FlowDesignation.RECOVERY)
@ -154,9 +154,10 @@ class PasswordStageView(ChallengeStageView[PasswordStage]):
if SESSION_KEY_INVALID_TRIES not in self.request.session:
self.request.session[SESSION_KEY_INVALID_TRIES] = 0
self.request.session[SESSION_KEY_INVALID_TRIES] += 1
current_stage: PasswordStage = self.executor.current_stage
if (
self.request.session[SESSION_KEY_INVALID_TRIES]
>= self.current_stage.failed_attempts_before_cancel
>= current_stage.failed_attempts_before_cancel
):
self.logger.debug("User has exceeded maximum tries")
del self.request.session[SESSION_KEY_INVALID_TRIES]

View File

@ -222,7 +222,7 @@ class PromptStageView(ChallengeStageView):
return serializers
def get_challenge(self, *args, **kwargs) -> Challenge:
fields: list[Prompt] = list(self.current_stage.fields.all().order_by("order"))
fields: list[Prompt] = list(self.executor.current_stage.fields.all().order_by("order"))
context_prompt = self.executor.plan.context.get(PLAN_CONTEXT_PROMPT, {})
serializers = self.get_prompt_challenge_fields(fields, context_prompt)
challenge = PromptChallenge(
@ -239,7 +239,7 @@ class PromptStageView(ChallengeStageView):
instance=None,
data=data,
request=self.request,
stage_instance=self.current_stage,
stage_instance=self.executor.current_stage,
stage=self,
plan=self.executor.plan,
user=self.get_pending_user(),

View File

@ -7,10 +7,9 @@ from django.utils.translation import gettext as _
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
from authentik.flows.stage import StageView
from authentik.stages.user_delete.models import UserDeleteStage
class UserDeleteStageView(StageView[UserDeleteStage]):
class UserDeleteStageView(StageView):
"""Finalise unenrollment flow by deleting the user object."""
def dispatch(self, request: HttpRequest) -> HttpResponse:

View File

@ -39,7 +39,7 @@ class UserLoginChallengeResponse(ChallengeResponse):
remember_me = BooleanField(required=True)
class UserLoginStageView(ChallengeStageView[UserLoginStage]):
class UserLoginStageView(ChallengeStageView):
"""Finalise Authentication flow by logging the user in"""
response_class = UserLoginChallengeResponse
@ -49,7 +49,8 @@ class UserLoginStageView(ChallengeStageView[UserLoginStage]):
def dispatch(self, request: HttpRequest) -> HttpResponse:
"""Check for remember_me, and do login"""
if timedelta_from_string(self.current_stage.remember_me_offset).total_seconds() > 0:
stage: UserLoginStage = self.executor.current_stage
if timedelta_from_string(stage.remember_me_offset).total_seconds() > 0:
return super().dispatch(request)
return self.do_login(request)
@ -58,9 +59,9 @@ class UserLoginStageView(ChallengeStageView[UserLoginStage]):
def set_session_duration(self, remember: bool) -> timedelta:
"""Update the sessions' expiry"""
delta = timedelta_from_string(self.current_stage.session_duration)
delta = timedelta_from_string(self.executor.current_stage.session_duration)
if remember:
offset = timedelta_from_string(self.current_stage.remember_me_offset)
offset = timedelta_from_string(self.executor.current_stage.remember_me_offset)
delta = delta + offset
if delta.total_seconds() == 0:
self.request.session.set_expiry(0)
@ -70,9 +71,11 @@ class UserLoginStageView(ChallengeStageView[UserLoginStage]):
def set_session_ip(self):
"""Set the sessions' last IP and session bindings"""
stage: UserLoginStage = self.executor.current_stage
self.request.session[SESSION_KEY_LAST_IP] = ClientIPMiddleware.get_client_ip(self.request)
self.request.session[SESSION_KEY_BINDING_NET] = self.current_stage.network_binding
self.request.session[SESSION_KEY_BINDING_GEO] = self.current_stage.geoip_binding
self.request.session[SESSION_KEY_BINDING_NET] = stage.network_binding
self.request.session[SESSION_KEY_BINDING_GEO] = stage.geoip_binding
def do_login(self, request: HttpRequest, remember: bool = False) -> HttpResponse:
"""Attach the currently pending user to the current session"""
@ -108,7 +111,7 @@ class UserLoginStageView(ChallengeStageView[UserLoginStage]):
# as sources show their own success messages
if not self.executor.plan.context.get(PLAN_CONTEXT_SOURCE, None):
messages.success(self.request, _("Successfully logged in!"))
if self.current_stage.terminate_other_sessions:
if self.executor.current_stage.terminate_other_sessions:
AuthenticatedSession.objects.filter(
user=user,
).exclude(session_key=self.request.session.session_key).delete()

View File

@ -4,10 +4,9 @@ from django.contrib.auth import logout
from django.http import HttpRequest, HttpResponse
from authentik.flows.stage import StageView
from authentik.stages.user_logout.models import UserLogoutStage
class UserLogoutStageView(StageView[UserLogoutStage]):
class UserLogoutStageView(StageView):
"""Finalise Authentication flow by logging the user in"""
def dispatch(self, request: HttpRequest) -> HttpResponse:

View File

@ -55,7 +55,7 @@ class UserWriteStageView(StageView):
"""Ensure a user exists"""
user_created = False
path = self.executor.plan.context.get(
PLAN_CONTEXT_USER_PATH, self.current_stage.user_path_template
PLAN_CONTEXT_USER_PATH, self.executor.current_stage.user_path_template
)
if path == "":
path = User.default_path()
@ -64,11 +64,11 @@ class UserWriteStageView(StageView):
user_type = UserTypes(
self.executor.plan.context.get(
PLAN_CONTEXT_USER_TYPE,
self.current_stage.user_type,
self.executor.current_stage.user_type,
)
)
except ValueError:
user_type = self.current_stage.user_type
user_type = self.executor.current_stage.user_type
if user_type == UserTypes.INTERNAL_SERVICE_ACCOUNT:
user_type = UserTypes.SERVICE_ACCOUNT
@ -76,12 +76,12 @@ class UserWriteStageView(StageView):
self.executor.plan.context.setdefault(PLAN_CONTEXT_PENDING_USER, self.request.user)
if (
PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context
or self.current_stage.user_creation_mode == UserCreationMode.ALWAYS_CREATE
or self.executor.current_stage.user_creation_mode == UserCreationMode.ALWAYS_CREATE
):
if self.current_stage.user_creation_mode == UserCreationMode.NEVER_CREATE:
if self.executor.current_stage.user_creation_mode == UserCreationMode.NEVER_CREATE:
return None, False
self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = User(
is_active=not self.current_stage.create_users_as_inactive,
is_active=not self.executor.current_stage.create_users_as_inactive,
path=path,
type=user_type,
)
@ -180,8 +180,8 @@ class UserWriteStageView(StageView):
try:
with transaction.atomic():
user.save()
if self.current_stage.create_users_group:
user.ak_groups.add(self.current_stage.create_users_group)
if self.executor.current_stage.create_users_group:
user.ak_groups.add(self.executor.current_stage.create_users_group)
if PLAN_CONTEXT_GROUPS in self.executor.plan.context:
user.ak_groups.add(*self.executor.plan.context[PLAN_CONTEXT_GROUPS])
except (IntegrityError, ValueError, TypeError, InternalError) as exc:

View File

@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://goauthentik.io/blueprints/schema.json",
"type": "object",
"title": "authentik 2024.6.4 Blueprint schema",
"title": "authentik 2024.8.0 Blueprint schema",
"required": [
"version",
"entries"
@ -10091,11 +10091,6 @@
"title": "Password stage",
"description": "When set, shows a password field, instead of showing the password field as separate step."
},
"captcha_stage": {
"type": "integer",
"title": "Captcha stage",
"description": "When set, the captcha element is shown on the identification stage."
},
"case_insensitive_matching": {
"type": "boolean",
"title": "Case insensitive matching",

View File

@ -31,7 +31,7 @@ services:
volumes:
- redis:/data
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.6.4}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.8.0}
restart: unless-stopped
command: server
environment:
@ -52,7 +52,7 @@ services:
- postgresql
- redis
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.6.4}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.8.0}
restart: unless-stopped
command: worker
environment:

6
go.mod
View File

@ -18,18 +18,18 @@ require (
github.com/gorilla/securecookie v1.1.2
github.com/gorilla/sessions v1.4.0
github.com/gorilla/websocket v1.5.3
github.com/jellydator/ttlcache/v3 v3.2.0
github.com/jellydator/ttlcache/v3 v3.3.0
github.com/mitchellh/mapstructure v1.5.0
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
github.com/pires/go-proxyproto v0.7.0
github.com/prometheus/client_golang v1.20.1
github.com/prometheus/client_golang v1.20.2
github.com/redis/go-redis/v9 v9.6.1
github.com/sethvargo/go-envconfig v1.1.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.9.0
github.com/wwt/guac v1.3.2
goauthentik.io/api/v3 v3.2024063.13
goauthentik.io/api/v3 v3.2024064.1
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.22.0
golang.org/x/sync v0.8.0

16
go.sum
View File

@ -200,8 +200,8 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jellydator/ttlcache/v3 v3.2.0 h1:6lqVJ8X3ZaUwvzENqPAobDsXNExfUJd61u++uW8a3LE=
github.com/jellydator/ttlcache/v3 v3.2.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4=
github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc=
github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@ -239,8 +239,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.20.1 h1:IMJXHOD6eARkQpxo8KkhgEVFlBNm+nkrFUyGlIu7Na8=
github.com/prometheus/client_golang v1.20.1/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg=
github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
@ -297,10 +297,10 @@ go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucg
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
goauthentik.io/api/v3 v3.2024063.13 h1:zWFlrr+8NOaQOCPSRV1FhbDJ58+BPa9BqjNvl4T//s8=
goauthentik.io/api/v3 v3.2024063.13/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
goauthentik.io/api/v3 v3.2024064.1 h1:vxquklgDGD+nGFhWRAsQ7ezQKg17MRq6bzEk25fbsb4=
goauthentik.io/api/v3 v3.2024064.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -29,4 +29,4 @@ func UserAgent() string {
return fmt.Sprintf("authentik@%s", FullVersion())
}
const VERSION = "2024.6.4"
const VERSION = "2024.8.0"

View File

@ -16,7 +16,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-08-15 00:09+0000\n"
"POT-Creation-Date: 2024-08-18 00:08+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Anton Babenko, 2024\n"
"Language-Team: Russian (https://app.transifex.com/authentik/teams/119923/ru/)\n"
@ -739,7 +739,7 @@ msgstr "Правило Уведомления"
#: authentik/events/models.py
msgid "Notification Rules"
msgstr "Правило Уведомлений"
msgstr "Правила уведомлений"
#: authentik/events/models.py
msgid "Webhook Mapping"
@ -1771,6 +1771,14 @@ msgstr "Сопоставление свойства Radius провайдера"
msgid "Radius Provider Property Mappings"
msgstr "Сопоставление свойств Radius провайдера"
#: authentik/providers/saml/api/providers.py
msgid ""
"With a signing keypair selected, at least one of 'Sign assertion' and 'Sign "
"Response' must be selected."
msgstr ""
"При выборе пары ключей для подписи необходимо выбрать как минимум один из "
"вариантов: 'Подписывать утверждение' или 'Подписывать ответ'."
#: authentik/providers/saml/api/providers.py
msgid "Invalid XML Syntax"
msgstr "Некорректный синтаксис XML"
@ -1918,6 +1926,21 @@ msgstr ""
msgid "Signing Keypair"
msgstr "Пара ключей для подписи"
#: authentik/providers/saml/models.py authentik/sources/saml/models.py
msgid ""
"When selected, incoming assertions are encrypted by the IdP using the public"
" key of the encryption keypair. The assertion is decrypted by the SP using "
"the the private key."
msgstr ""
"При выборе этого варианта, входящие утверждения шифруются поставщиком "
"идентификации (IdP) с использованием открытого ключа из пары ключей "
"шифрования. Утверждение расшифровывается поставщиком услуг (SP) с "
"использованием закрытого ключа."
#: authentik/providers/saml/models.py authentik/sources/saml/models.py
msgid "Encryption Keypair"
msgstr "Пара ключей шифрования"
#: authentik/providers/saml/models.py
msgid "Default relay_state value for IDP-initiated logins"
msgstr "Значение relay_state по умолчанию для логинов, инициированных IDP"
@ -2446,21 +2469,6 @@ msgstr ""
"Пара ключей, используемая для подписи исходящих ответов, направляемых "
"провайдеру идентификационных данных."
#: authentik/sources/saml/models.py
msgid ""
"When selected, incoming assertions are encrypted by the IdP using the public"
" key of the encryption keypair. The assertion is decrypted by the SP using "
"the the private key."
msgstr ""
"При выборе этого варианта, входящие утверждения шифруются поставщиком "
"идентификации (IdP) с использованием открытого ключа из пары ключей "
"шифрования. Утверждение расшифровывается поставщиком услуг (SP) с "
"использованием закрытого ключа."
#: authentik/sources/saml/models.py
msgid "Encryption Keypair"
msgstr "Пара ключей шифрования"
#: authentik/sources/saml/models.py
msgid "SAML Source"
msgstr "Источник SAML"

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
{
"name": "@goauthentik/authentik",
"version": "2024.6.4",
"version": "2024.8.0",
"private": true
}

241
poetry.lock generated
View File

@ -1165,15 +1165,18 @@ files = [
[[package]]
name = "deepmerge"
version = "1.1.1"
description = "a toolset to deeply merge python dictionaries."
version = "2.0"
description = "A toolset for deeply merging Python dictionaries."
optional = false
python-versions = "*"
python-versions = ">=3.8"
files = [
{file = "deepmerge-1.1.1-py3-none-any.whl", hash = "sha256:7219dad9763f15be9dcd4bcb53e00f48e4eed6f5ed8f15824223eb934bb35977"},
{file = "deepmerge-1.1.1.tar.gz", hash = "sha256:53a489dc9449636e480a784359ae2aab3191748c920649551c8e378622f0eca4"},
{file = "deepmerge-2.0-py3-none-any.whl", hash = "sha256:6de9ce507115cff0bed95ff0ce9ecc31088ef50cbdf09bc90a09349a318b3d00"},
{file = "deepmerge-2.0.tar.gz", hash = "sha256:5c3d86081fbebd04dd5de03626a0607b809a98fb6ccba5770b62466fe940ff20"},
]
[package.extras]
dev = ["black", "build", "mypy", "pytest", "pyupgrade", "twine", "validate-pyproject[all]"]
[[package]]
name = "defusedxml"
version = "0.7.1"
@ -1312,17 +1315,17 @@ django = ">=3"
[[package]]
name = "django-pglock"
version = "1.5.1"
version = "1.6.0"
description = "Postgres locking routines and lock table access."
optional = false
python-versions = "<4,>=3.8.0"
files = [
{file = "django_pglock-1.5.1-py3-none-any.whl", hash = "sha256:d3b977922abbaffd43968714b69cdab7453866adf2b0695fb497491748d7bc67"},
{file = "django_pglock-1.5.1.tar.gz", hash = "sha256:291903d5d877b68558003e1d64d764ebd5590344ba3b7aa1d5127df5947869b1"},
{file = "django_pglock-1.6.0-py3-none-any.whl", hash = "sha256:41c98d0bd3738d11e6eaefcc3e5146028f118a593ac58c13d663b751170f01de"},
{file = "django_pglock-1.6.0.tar.gz", hash = "sha256:724450ecc9886f39af599c477d84ad086545a5373215ef7a670cd25faca25a61"},
]
[package.dependencies]
django = ">=3"
django = ">=4"
django-pgactivity = ">=1.2,<2"
[[package]]
@ -1758,13 +1761,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"]
[[package]]
name = "google-api-python-client"
version = "2.142.0"
version = "2.143.0"
description = "Google API Client Library for Python"
optional = false
python-versions = ">=3.7"
files = [
{file = "google_api_python_client-2.142.0-py2.py3-none-any.whl", hash = "sha256:266799082bb8301f423ec204dffbffb470b502abbf29efd1f83e644d36eb5a8f"},
{file = "google_api_python_client-2.142.0.tar.gz", hash = "sha256:a1101ac9e24356557ca22f07ff48b7f61fa5d4b4e7feeef3bda16e5dcb86350e"},
{file = "google_api_python_client-2.143.0-py2.py3-none-any.whl", hash = "sha256:d5654134522b9b574b82234e96f7e0aeeabcbf33643fbabcd449ef0068e3a476"},
{file = "google_api_python_client-2.143.0.tar.gz", hash = "sha256:6a75441f9078e6e2fcdf4946a153fda1e2cc81b5e9c8d6e8c0750c85c7f8a566"},
]
[package.dependencies]
@ -2047,13 +2050,13 @@ files = [
[[package]]
name = "importlib-metadata"
version = "8.0.0"
version = "8.4.0"
description = "Read metadata from Python packages"
optional = false
python-versions = ">=3.8"
files = [
{file = "importlib_metadata-8.0.0-py3-none-any.whl", hash = "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f"},
{file = "importlib_metadata-8.0.0.tar.gz", hash = "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812"},
{file = "importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1"},
{file = "importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"},
]
[package.dependencies]
@ -3025,49 +3028,49 @@ resolved_reference = "20d69d9cc50a0fef31605b46f06da0c94f1ec3cf"
[[package]]
name = "opentelemetry-api"
version = "1.26.0"
version = "1.27.0"
description = "OpenTelemetry Python API"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_api-1.26.0-py3-none-any.whl", hash = "sha256:7d7ea33adf2ceda2dd680b18b1677e4152000b37ca76e679da71ff103b943064"},
{file = "opentelemetry_api-1.26.0.tar.gz", hash = "sha256:2bd639e4bed5b18486fef0b5a520aaffde5a18fc225e808a1ac4df363f43a1ce"},
{file = "opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7"},
{file = "opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"},
]
[package.dependencies]
deprecated = ">=1.2.6"
importlib-metadata = ">=6.0,<=8.0.0"
importlib-metadata = ">=6.0,<=8.4.0"
[[package]]
name = "opentelemetry-sdk"
version = "1.26.0"
version = "1.27.0"
description = "OpenTelemetry Python SDK"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_sdk-1.26.0-py3-none-any.whl", hash = "sha256:feb5056a84a88670c041ea0ded9921fca559efec03905dddeb3885525e0af897"},
{file = "opentelemetry_sdk-1.26.0.tar.gz", hash = "sha256:c90d2868f8805619535c05562d699e2f4fb1f00dbd55a86dcefca4da6fa02f85"},
{file = "opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d"},
{file = "opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f"},
]
[package.dependencies]
opentelemetry-api = "1.26.0"
opentelemetry-semantic-conventions = "0.47b0"
opentelemetry-api = "1.27.0"
opentelemetry-semantic-conventions = "0.48b0"
typing-extensions = ">=3.7.4"
[[package]]
name = "opentelemetry-semantic-conventions"
version = "0.47b0"
version = "0.48b0"
description = "OpenTelemetry Semantic Conventions"
optional = false
python-versions = ">=3.8"
files = [
{file = "opentelemetry_semantic_conventions-0.47b0-py3-none-any.whl", hash = "sha256:4ff9d595b85a59c1c1413f02bba320ce7ea6bf9e2ead2b0913c4395c7bbc1063"},
{file = "opentelemetry_semantic_conventions-0.47b0.tar.gz", hash = "sha256:a8d57999bbe3495ffd4d510de26a97dadc1dace53e0275001b2c1b2f67992a7e"},
{file = "opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f"},
{file = "opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a"},
]
[package.dependencies]
deprecated = ">=1.2.6"
opentelemetry-api = "1.26.0"
opentelemetry-api = "1.27.0"
[[package]]
name = "orjson"
@ -3201,13 +3204,13 @@ files = [
[[package]]
name = "pdoc"
version = "14.6.0"
version = "14.6.1"
description = "API Documentation for Python Projects"
optional = false
python-versions = ">=3.8"
files = [
{file = "pdoc-14.6.0-py3-none-any.whl", hash = "sha256:36c42c546a317d8e3e8c0b39645f24161374de0c7066ccaae76628d721e49ba5"},
{file = "pdoc-14.6.0.tar.gz", hash = "sha256:6e98a24c5e0ca5d188397969cf82581836eaef13f172fc3820047bfe15c61c9a"},
{file = "pdoc-14.6.1-py3-none-any.whl", hash = "sha256:efbed433655264392c60551615a3d42b8f21e492373419756d20234c667b54bc"},
{file = "pdoc-14.6.1.tar.gz", hash = "sha256:ee598f30d5c55dd4702086dabc412a26022acc35aa88aa382cda8ac655fead98"},
]
[package.dependencies]
@ -3781,13 +3784,13 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments
[[package]]
name = "pytest-django"
version = "4.8.0"
version = "4.9.0"
description = "A Django plugin for pytest."
optional = false
python-versions = ">=3.8"
files = [
{file = "pytest-django-4.8.0.tar.gz", hash = "sha256:5d054fe011c56f3b10f978f41a8efb2e5adfc7e680ef36fb571ada1f24779d90"},
{file = "pytest_django-4.8.0-py3-none-any.whl", hash = "sha256:ca1ddd1e0e4c227cf9e3e40a6afc6d106b3e70868fd2ac5798a22501271cd0c7"},
{file = "pytest_django-4.9.0-py3-none-any.whl", hash = "sha256:1d83692cb39188682dbb419ff0393867e9904094a549a7d38a3154d5731b2b99"},
{file = "pytest_django-4.9.0.tar.gz", hash = "sha256:8bf7bc358c9ae6f6fc51b6cebb190fe20212196e6807121f11bd6a3b03428314"},
]
[package.dependencies]
@ -4195,29 +4198,29 @@ pyasn1 = ">=0.1.3"
[[package]]
name = "ruff"
version = "0.6.2"
version = "0.6.3"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
{file = "ruff-0.6.2-py3-none-linux_armv6l.whl", hash = "sha256:5c8cbc6252deb3ea840ad6a20b0f8583caab0c5ef4f9cca21adc5a92b8f79f3c"},
{file = "ruff-0.6.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:17002fe241e76544448a8e1e6118abecbe8cd10cf68fde635dad480dba594570"},
{file = "ruff-0.6.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3dbeac76ed13456f8158b8f4fe087bf87882e645c8e8b606dd17b0b66c2c1158"},
{file = "ruff-0.6.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:094600ee88cda325988d3f54e3588c46de5c18dae09d683ace278b11f9d4d534"},
{file = "ruff-0.6.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:316d418fe258c036ba05fbf7dfc1f7d3d4096db63431546163b472285668132b"},
{file = "ruff-0.6.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d72b8b3abf8a2d51b7b9944a41307d2f442558ccb3859bbd87e6ae9be1694a5d"},
{file = "ruff-0.6.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2aed7e243be68487aa8982e91c6e260982d00da3f38955873aecd5a9204b1d66"},
{file = "ruff-0.6.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d371f7fc9cec83497fe7cf5eaf5b76e22a8efce463de5f775a1826197feb9df8"},
{file = "ruff-0.6.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8f310d63af08f583363dfb844ba8f9417b558199c58a5999215082036d795a1"},
{file = "ruff-0.6.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7db6880c53c56addb8638fe444818183385ec85eeada1d48fc5abe045301b2f1"},
{file = "ruff-0.6.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1175d39faadd9a50718f478d23bfc1d4da5743f1ab56af81a2b6caf0a2394f23"},
{file = "ruff-0.6.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5b939f9c86d51635fe486585389f54582f0d65b8238e08c327c1534844b3bb9a"},
{file = "ruff-0.6.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d0d62ca91219f906caf9b187dea50d17353f15ec9bb15aae4a606cd697b49b4c"},
{file = "ruff-0.6.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7438a7288f9d67ed3c8ce4d059e67f7ed65e9fe3aa2ab6f5b4b3610e57e3cb56"},
{file = "ruff-0.6.2-py3-none-win32.whl", hash = "sha256:279d5f7d86696df5f9549b56b9b6a7f6c72961b619022b5b7999b15db392a4da"},
{file = "ruff-0.6.2-py3-none-win_amd64.whl", hash = "sha256:d9f3469c7dd43cd22eb1c3fc16926fb8258d50cb1b216658a07be95dd117b0f2"},
{file = "ruff-0.6.2-py3-none-win_arm64.whl", hash = "sha256:f28fcd2cd0e02bdf739297516d5643a945cc7caf09bd9bcb4d932540a5ea4fa9"},
{file = "ruff-0.6.2.tar.gz", hash = "sha256:239ee6beb9e91feb8e0ec384204a763f36cb53fb895a1a364618c6abb076b3be"},
{file = "ruff-0.6.3-py3-none-linux_armv6l.whl", hash = "sha256:97f58fda4e309382ad30ede7f30e2791d70dd29ea17f41970119f55bdb7a45c3"},
{file = "ruff-0.6.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3b061e49b5cf3a297b4d1c27ac5587954ccb4ff601160d3d6b2f70b1622194dc"},
{file = "ruff-0.6.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:34e2824a13bb8c668c71c1760a6ac7d795ccbd8d38ff4a0d8471fdb15de910b1"},
{file = "ruff-0.6.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bddfbb8d63c460f4b4128b6a506e7052bad4d6f3ff607ebbb41b0aa19c2770d1"},
{file = "ruff-0.6.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ced3eeb44df75353e08ab3b6a9e113b5f3f996bea48d4f7c027bc528ba87b672"},
{file = "ruff-0.6.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47021dff5445d549be954eb275156dfd7c37222acc1e8014311badcb9b4ec8c1"},
{file = "ruff-0.6.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d7bd20dc07cebd68cc8bc7b3f5ada6d637f42d947c85264f94b0d1cd9d87384"},
{file = "ruff-0.6.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:500f166d03fc6d0e61c8e40a3ff853fa8a43d938f5d14c183c612df1b0d6c58a"},
{file = "ruff-0.6.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42844ff678f9b976366b262fa2d1d1a3fe76f6e145bd92c84e27d172e3c34500"},
{file = "ruff-0.6.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70452a10eb2d66549de8e75f89ae82462159855e983ddff91bc0bce6511d0470"},
{file = "ruff-0.6.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:65a533235ed55f767d1fc62193a21cbf9e3329cf26d427b800fdeacfb77d296f"},
{file = "ruff-0.6.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d2e2c23cef30dc3cbe9cc5d04f2899e7f5e478c40d2e0a633513ad081f7361b5"},
{file = "ruff-0.6.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d8a136aa7d228975a6aee3dd8bea9b28e2b43e9444aa678fb62aeb1956ff2351"},
{file = "ruff-0.6.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f92fe93bc72e262b7b3f2bba9879897e2d58a989b4714ba6a5a7273e842ad2f8"},
{file = "ruff-0.6.3-py3-none-win32.whl", hash = "sha256:7a62d3b5b0d7f9143d94893f8ba43aa5a5c51a0ffc4a401aa97a81ed76930521"},
{file = "ruff-0.6.3-py3-none-win_amd64.whl", hash = "sha256:746af39356fee2b89aada06c7376e1aa274a23493d7016059c3a72e3b296befb"},
{file = "ruff-0.6.3-py3-none-win_arm64.whl", hash = "sha256:14a9528a8b70ccc7a847637c29e56fd1f9183a9db743bbc5b8e0c4ad60592a82"},
{file = "ruff-0.6.3.tar.gz", hash = "sha256:183b99e9edd1ef63be34a3b51fee0a9f4ab95add123dbf89a71f7b1f0c991983"},
]
[[package]]
@ -4256,13 +4259,13 @@ django-query = ["django (>=3.2)"]
[[package]]
name = "selenium"
version = "4.23.1"
version = "4.24.0"
description = "Official Python bindings for Selenium WebDriver"
optional = false
python-versions = ">=3.8"
files = [
{file = "selenium-4.23.1-py3-none-any.whl", hash = "sha256:3a8d9f23dc636bd3840dd56f00c2739e32ec0c1e34a821dd553e15babef24477"},
{file = "selenium-4.23.1.tar.gz", hash = "sha256:128d099e66284437e7128d2279176ec7a06e6ec7426e167f5d34987166bd8f46"},
{file = "selenium-4.24.0-py3-none-any.whl", hash = "sha256:42c23f60753d5415b261b236cecbd69bd4eb5271e1563915f546b443cb6b71c6"},
{file = "selenium-4.24.0.tar.gz", hash = "sha256:88281e5b5b90fe231868905d5ea745b9ee5e30db280b33498cc73fb0fa06d571"},
]
[package.dependencies]
@ -4652,13 +4655,13 @@ wsproto = ">=0.14"
[[package]]
name = "twilio"
version = "9.2.3"
version = "9.2.4"
description = "Twilio API client and TwiML generator"
optional = false
python-versions = ">=3.7.0"
files = [
{file = "twilio-9.2.3-py2.py3-none-any.whl", hash = "sha256:76bfc39aa8d854510907cb7f9465814dfdea9e91ec199bb44f0785f05746f4cc"},
{file = "twilio-9.2.3.tar.gz", hash = "sha256:da2255b5f3753cb3bf647fc6c50edbdb367ebc3cde6802806f6f863058a65f75"},
{file = "twilio-9.2.4-py2.py3-none-any.whl", hash = "sha256:490da2518c0da370d738d436f9086b2463902707a811cd306ec8dcc8ce831758"},
{file = "twilio-9.2.4.tar.gz", hash = "sha256:454b7d075c6bee3b64c81c39151be1f9105c695df6dbb0021b0c43e2930263e7"},
]
[package.dependencies]
@ -4669,13 +4672,13 @@ requests = ">=2.0.0"
[[package]]
name = "twisted"
version = "24.3.0"
version = "24.7.0"
description = "An asynchronous networking framework written in Python"
optional = false
python-versions = ">=3.8.0"
files = [
{file = "twisted-24.3.0-py3-none-any.whl", hash = "sha256:039f2e6a49ab5108abd94de187fa92377abe5985c7a72d68d0ad266ba19eae63"},
{file = "twisted-24.3.0.tar.gz", hash = "sha256:6b38b6ece7296b5e122c9eb17da2eeab3d98a198f50ca9efd00fb03e5b4fd4ae"},
{file = "twisted-24.7.0-py3-none-any.whl", hash = "sha256:734832ef98108136e222b5230075b1079dad8a3fc5637319615619a7725b0c81"},
{file = "twisted-24.7.0.tar.gz", hash = "sha256:5a60147f044187a127ec7da96d170d49bcce50c6fd36f594e60f4587eff4d394"},
]
[package.dependencies]
@ -4684,55 +4687,26 @@ automat = ">=0.8.0"
constantly = ">=15.1"
hyperlink = ">=17.1.1"
idna = {version = ">=2.4", optional = true, markers = "extra == \"tls\""}
incremental = ">=22.10.0"
incremental = ">=24.7.0"
pyopenssl = {version = ">=21.0.0", optional = true, markers = "extra == \"tls\""}
service-identity = {version = ">=18.1.0", optional = true, markers = "extra == \"tls\""}
twisted-iocpsupport = {version = ">=1.0.2,<2", markers = "platform_system == \"Windows\""}
typing-extensions = ">=4.2.0"
zope-interface = ">=5"
[package.extras]
all-non-platform = ["twisted[conch,http2,serial,test,tls]", "twisted[conch,http2,serial,test,tls]"]
all-non-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
conch = ["appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)"]
dev = ["coverage (>=6b1,<7)", "pyflakes (>=2.2,<3.0)", "python-subunit (>=1.4,<2.0)", "twisted[dev-release]", "twistedchecker (>=0.7,<1.0)"]
dev = ["coverage (>=7.5,<8.0)", "cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.56)", "pydoctor (>=23.9.0,<23.10.0)", "pyflakes (>=2.2,<3.0)", "pyhamcrest (>=2)", "python-subunit (>=1.4,<2.0)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "twistedchecker (>=0.7,<1.0)"]
dev-release = ["pydoctor (>=23.9.0,<23.10.0)", "pydoctor (>=23.9.0,<23.10.0)", "sphinx (>=6,<7)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "towncrier (>=23.6,<24.0)"]
gtk-platform = ["pygobject", "pygobject", "twisted[all-non-platform]", "twisted[all-non-platform]"]
gtk-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pygobject", "pygobject", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
http2 = ["h2 (>=3.0,<5.0)", "priority (>=1.1.0,<2.0)"]
macos-platform = ["pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "twisted[all-non-platform]", "twisted[all-non-platform]"]
mypy = ["mypy (>=1.8,<2.0)", "mypy-zope (>=1.0.3,<1.1.0)", "twisted[all-non-platform,dev]", "types-pyopenssl", "types-setuptools"]
osx-platform = ["twisted[macos-platform]", "twisted[macos-platform]"]
macos-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
mypy = ["appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "coverage (>=7.5,<8.0)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "idna (>=2.4)", "mypy (>=1.8,<2.0)", "mypy-zope (>=1.0.3,<1.1.0)", "priority (>=1.1.0,<2.0)", "pydoctor (>=23.9.0,<23.10.0)", "pyflakes (>=2.2,<3.0)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "python-subunit (>=1.4,<2.0)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "sphinx (>=6,<7)", "sphinx-rtd-theme (>=1.3,<2.0)", "towncrier (>=23.6,<24.0)", "twistedchecker (>=0.7,<1.0)", "types-pyopenssl", "types-setuptools"]
osx-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyobjc-core", "pyobjc-core", "pyobjc-framework-cfnetwork", "pyobjc-framework-cfnetwork", "pyobjc-framework-cocoa", "pyobjc-framework-cocoa", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)"]
serial = ["pyserial (>=3.0)", "pywin32 (!=226)"]
test = ["cython-test-exception-raiser (>=1.0.2,<2)", "hypothesis (>=6.56)", "pyhamcrest (>=2)"]
tls = ["idna (>=2.4)", "pyopenssl (>=21.0.0)", "service-identity (>=18.1.0)"]
windows-platform = ["pywin32 (!=226)", "pywin32 (!=226)", "twisted[all-non-platform]", "twisted[all-non-platform]"]
[[package]]
name = "twisted-iocpsupport"
version = "1.0.4"
description = "An extension for use in the twisted I/O Completion Ports reactor."
optional = false
python-versions = "*"
files = [
{file = "twisted-iocpsupport-1.0.4.tar.gz", hash = "sha256:858096c0d15e33f15ac157f455d8f86f2f2cdd223963e58c0f682a3af8362d89"},
{file = "twisted_iocpsupport-1.0.4-cp310-cp310-win32.whl", hash = "sha256:afa2b630797f9ed2f27f3d9f55e3f72b4244911e45a8c82756f44babbf0b243e"},
{file = "twisted_iocpsupport-1.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:0058c963c8957bcd3deda62122e89953c9de1e867a274facc9b15dde1a9f31e8"},
{file = "twisted_iocpsupport-1.0.4-cp311-cp311-win32.whl", hash = "sha256:196f7c7ccad4ba4d1783b1c4e1d1b22d93c04275cd780bf7498d16c77319ad6e"},
{file = "twisted_iocpsupport-1.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:4e5f97bcbabdd79cbaa969b63439b89801ea560f11d42b0a387634275c633623"},
{file = "twisted_iocpsupport-1.0.4-cp312-cp312-win32.whl", hash = "sha256:6081bd7c2f4fcf9b383dcdb3b3385d75a26a7c9d2be25b6950c3d8ea652d2d2d"},
{file = "twisted_iocpsupport-1.0.4-cp312-cp312-win_amd64.whl", hash = "sha256:76f7e67cec1f1d097d1f4ed7de41be3d74546e1a4ede0c7d56e775c4dce5dfb0"},
{file = "twisted_iocpsupport-1.0.4-cp36-cp36m-win32.whl", hash = "sha256:3d306fc4d88a6bcf61ce9d572c738b918578121bfd72891625fab314549024b5"},
{file = "twisted_iocpsupport-1.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:391ac4d6002a80e15f35adc4ad6056f4fe1c17ceb0d1f98ba01b0f4f917adfd7"},
{file = "twisted_iocpsupport-1.0.4-cp37-cp37m-win32.whl", hash = "sha256:0c1b5cf37f0b2d96cc3c9bc86fff16613b9f5d0ca565c96cf1f1fb8cfca4b81c"},
{file = "twisted_iocpsupport-1.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:3c5dc11d72519e55f727320e3cee535feedfaee09c0f0765ed1ca7badff1ab3c"},
{file = "twisted_iocpsupport-1.0.4-cp38-cp38-win32.whl", hash = "sha256:cc86c2ef598c15d824a243c2541c29459881c67fc3c0adb6efe2242f8f0ec3af"},
{file = "twisted_iocpsupport-1.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c27985e949b9b1a1fb4c20c71d315c10ea0f93fdf3ccdd4a8c158b5926edd8c8"},
{file = "twisted_iocpsupport-1.0.4-cp39-cp39-win32.whl", hash = "sha256:e311dfcb470696e3c077249615893cada598e62fa7c4e4ca090167bd2b7d331f"},
{file = "twisted_iocpsupport-1.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4574eef1f3bb81501fb02f911298af3c02fe8179c31a33b361dd49180c3e644d"},
{file = "twisted_iocpsupport-1.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:872747a3b64e2909aee59c803ccd0bceb9b75bf27915520ebd32d69687040fa2"},
{file = "twisted_iocpsupport-1.0.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:c2712b778bacf1db434e3e065adfed3db300754186a29aecac1efae9ef4bcaff"},
{file = "twisted_iocpsupport-1.0.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7c66fa0aa4236b27b3c61cb488662d85dae746a6d1c7b0d91cf7aae118445adf"},
{file = "twisted_iocpsupport-1.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:300437af17396a945a58dcfffd77863303a8b6d9e65c6e81f1d2eed55b50d444"},
]
windows-platform = ["appdirs (>=1.4.0)", "appdirs (>=1.4.0)", "bcrypt (>=3.1.3)", "bcrypt (>=3.1.3)", "cryptography (>=3.3)", "cryptography (>=3.3)", "cython-test-exception-raiser (>=1.0.2,<2)", "cython-test-exception-raiser (>=1.0.2,<2)", "h2 (>=3.0,<5.0)", "h2 (>=3.0,<5.0)", "hypothesis (>=6.56)", "hypothesis (>=6.56)", "idna (>=2.4)", "idna (>=2.4)", "priority (>=1.1.0,<2.0)", "priority (>=1.1.0,<2.0)", "pyhamcrest (>=2)", "pyhamcrest (>=2)", "pyopenssl (>=21.0.0)", "pyopenssl (>=21.0.0)", "pyserial (>=3.0)", "pyserial (>=3.0)", "pywin32 (!=226)", "pywin32 (!=226)", "pywin32 (!=226)", "pywin32 (!=226)", "service-identity (>=18.1.0)", "service-identity (>=18.1.0)", "twisted-iocpsupport (>=1.0.2)", "twisted-iocpsupport (>=1.0.2)"]
[[package]]
name = "txaio"
@ -4896,46 +4870,41 @@ files = [
[[package]]
name = "watchdog"
version = "4.0.2"
version = "5.0.1"
description = "Filesystem events monitoring"
optional = false
python-versions = ">=3.8"
python-versions = ">=3.9"
files = [
{file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22"},
{file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1"},
{file = "watchdog-4.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503"},
{file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930"},
{file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b"},
{file = "watchdog-4.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef"},
{file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a"},
{file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29"},
{file = "watchdog-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a"},
{file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b"},
{file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d"},
{file = "watchdog-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7"},
{file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040"},
{file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7"},
{file = "watchdog-4.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4"},
{file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9"},
{file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578"},
{file = "watchdog-4.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b"},
{file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa"},
{file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3"},
{file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508"},
{file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee"},
{file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1"},
{file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e"},
{file = "watchdog-4.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83"},
{file = "watchdog-4.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c"},
{file = "watchdog-4.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a"},
{file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73"},
{file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc"},
{file = "watchdog-4.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757"},
{file = "watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8"},
{file = "watchdog-4.0.2-py3-none-win32.whl", hash = "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19"},
{file = "watchdog-4.0.2-py3-none-win_amd64.whl", hash = "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b"},
{file = "watchdog-4.0.2-py3-none-win_ia64.whl", hash = "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c"},
{file = "watchdog-4.0.2.tar.gz", hash = "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270"},
{file = "watchdog-5.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a6b8c6c82ada78479a0df568d27d69aa07105aba9301ac66d1ae162645f4ba34"},
{file = "watchdog-5.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1e8ca9b7f5f03d2f0556a43db1e9adf1e5af6adf52e0890f781324514b67a612"},
{file = "watchdog-5.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c92812a358eabebe92b12b9290d16dc95c8003654658f6b2676c9a2103a73ceb"},
{file = "watchdog-5.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a03a6ccb846ead406a25a0b702d0a6b88fdfa77becaf907cfcfce7737ebbda1f"},
{file = "watchdog-5.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39f0de161a822402f0f00c68b82349a4d71c9814e749148ca2b083a25606dbf9"},
{file = "watchdog-5.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5541a8765c4090decb4dba55d3dceb57724748a717ceaba8dc4f213edb0026e0"},
{file = "watchdog-5.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e321f1561adea30e447130882efe451af519646178d04189d6ba91a8cd7d88a5"},
{file = "watchdog-5.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c4ae0b3e95455fa9d959aa3b253c87845ad454ef188a4bf5a69cab287c131216"},
{file = "watchdog-5.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b2d56425dfa0c1e6f8a510f21d3d54ef7fe50bbc29638943c2cb1394b7b49156"},
{file = "watchdog-5.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:70e30116849f4ec52240eb1fad83d27e525eae179bfe1c09b3bf120163d731b6"},
{file = "watchdog-5.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f66df2c152edf5a2fe472bb2f8a5d562165bcf6cf9686cee5d75e524c21ca895"},
{file = "watchdog-5.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6bb68d9adb9c45f0dc1c2b12f4fb6eab0463a8f9741e371e4ede6769064e0785"},
{file = "watchdog-5.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6fbb4dd5ace074a2969825fde10034b35b31efcb6973defb22eb945b1d3acc37"},
{file = "watchdog-5.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:753c6a4c1eea9d3b96cd58159b49103e66cb288216a414ab9ad234ccc7642ec2"},
{file = "watchdog-5.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:20a28c8b0b3edf4ea2b27fb3527fc0a348e983f22a4317d316bb561524391932"},
{file = "watchdog-5.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a1cd7c919940b15f253db8279a579fb81e4e4e434b39b11a1cb7f54fe3fa46a6"},
{file = "watchdog-5.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a791dfc050ed24b82f7f100ae794192594fe863a7e9bdafcdfa5c6e405a981e5"},
{file = "watchdog-5.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8ba1472b5fa7c644e49641f70d7ccc567f70b54d776defa5d6f755dc2edc3fbb"},
{file = "watchdog-5.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b21e6601efe8453514c2fc21aca57fb5413c3d8b157bfe520b05b57b1788a167"},
{file = "watchdog-5.0.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:763c6f82bb65504b47d4aea268462b2fb662676676356e04787f332a11f03eb0"},
{file = "watchdog-5.0.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:664917cd513538728875a42d5654584b533da88cf06680452c98e73b45466968"},
{file = "watchdog-5.0.1-py3-none-manylinux2014_i686.whl", hash = "sha256:39e828c4270452b966bc9d814911a3c7e24c62d726d2a3245f5841664ff56b5e"},
{file = "watchdog-5.0.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:59ec6111f3750772badae3403ef17263489ed6f27ac01ec50c0244b2afa258fb"},
{file = "watchdog-5.0.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f3006361dba2005552cc8aa49c44d16a10e0a1939bb3286e888a14f722122808"},
{file = "watchdog-5.0.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:72dbdffe4aa0c36c59f4a5190bceeb7fdfdf849ab98a562b3a783a64cc6dacdd"},
{file = "watchdog-5.0.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c93aa24899cb4e8a51492c7ccc420bea45ced502fe9ef2e83f9ab1107e5a13b5"},
{file = "watchdog-5.0.1-py3-none-win32.whl", hash = "sha256:2b8cd627b76194e725ed6f48d9524b1ad93a51a0dc3bd0225c56023716245091"},
{file = "watchdog-5.0.1-py3-none-win_amd64.whl", hash = "sha256:4eaebff2f938f5325788cef26521891b2d8ecc8e7852aa123a9b458815f93875"},
{file = "watchdog-5.0.1-py3-none-win_ia64.whl", hash = "sha256:9b1b32f89f95162f09aea6e15d9384f6e0490152f10d7ed241f8a85cddc50658"},
{file = "watchdog-5.0.1.tar.gz", hash = "sha256:f0180e84e6493ef7c82e051334e8c9b00ffd89fa9de5e0613d3c267f6ccf2d38"},
]
[package.extras]

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "authentik"
version = "2024.6.4"
version = "2024.8.0"
description = ""
authors = ["authentik Team <hello@goauthentik.io>"]

View File

@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: authentik
version: 2024.6.4
version: 2024.8.0
description: Making authentication simple.
contact:
email: hello@goauthentik.io
@ -40457,10 +40457,11 @@ components:
items:
type: string
nullable: true
password_stage:
$ref: '#/components/schemas/PasswordChallenge'
captcha_stage:
$ref: '#/components/schemas/CaptchaChallenge'
password_fields:
type: boolean
allow_show_password:
type: boolean
default: false
application_pre:
type: string
flow_designation:
@ -40481,6 +40482,7 @@ components:
type: boolean
required:
- flow_designation
- password_fields
- primary_action
- show_source_labels
- user_fields
@ -40498,8 +40500,6 @@ components:
password:
type: string
nullable: true
captcha:
$ref: '#/components/schemas/CaptchaChallengeResponseRequest'
required:
- uid_field
IdentificationStage:
@ -40545,12 +40545,6 @@ components:
nullable: true
description: When set, shows a password field, instead of showing the password
field as separate step.
captcha_stage:
type: string
format: uuid
nullable: true
description: When set, the captcha element is shown on the identification
stage.
case_insensitive_matching:
type: boolean
description: When enabled, user fields are matched regardless of their casing.
@ -40619,12 +40613,6 @@ components:
nullable: true
description: When set, shows a password field, instead of showing the password
field as separate step.
captcha_stage:
type: string
format: uuid
nullable: true
description: When set, the captcha element is shown on the identification
stage.
case_insensitive_matching:
type: boolean
description: When enabled, user fields are matched regardless of their casing.
@ -45757,12 +45745,6 @@ components:
nullable: true
description: When set, shows a password field, instead of showing the password
field as separate step.
captcha_stage:
type: string
format: uuid
nullable: true
description: When set, the captcha element is shown on the identification
stage.
case_insensitive_matching:
type: boolean
description: When enabled, user fields are matched regardless of their casing.

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,13 @@
{
"name": "@goauthentik/web-tests",
"private": true,
"type": "module",
"dependencies": {
"chromedriver": "^128.0.1",
"lockfile-lint": "^4.14.0",
"syncpack": "^13.0.0"
},
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/mocha": "^10.0.7",
"@typescript-eslint/eslint-plugin": "^7.17.0",
"@typescript-eslint/parser": "^7.17.0",
"@wdio/cli": "^9.0.3",
@ -19,19 +23,20 @@
"typescript": "^5.5.4",
"wdio-wait-for": "^3.0.11"
},
"scripts": {
"wdio": "wdio run ./wdio.conf.ts",
"lint:precommit": "eslint --max-warnings 0 --config ./.eslintrc.precommit.json $(git status --porcelain . | grep '^[AM?][M?]' | cut -d'/' -f3- | grep -E '\\.(ts|js|tsx|jsx)$')",
"lint": "eslint . --max-warnings 0 --fix",
"lint:spelling": "codespell -D - -D $(git rev-parse --show-toplevel 2> /dev/null)/.github/codespell-dictionary.txt -I $(git rev-parse --show-toplevel 2> /dev/null)/.github/codespell-words.txt ./test -s",
"precommit": "run-s lint:precommit lint:spelling prettier",
"prettier-check": "prettier --check .",
"prettier": "prettier --write ."
},
"engines": {
"node": ">=20"
},
"dependencies": {
"chromedriver": "^128.0.0"
}
"private": true,
"scripts": {
"lint": "eslint . --max-warnings 0 --fix",
"lint:lockfile": "lockfile-lint --path package.json --type npm --allowed-hosts npm --validate-https",
"lint:package": "syncpack format -i ' '",
"lint:precommit": "eslint --max-warnings 0 --config ./.eslintrc.precommit.json $(git status --porcelain . | grep '^[AM?][M?]' | cut -d'/' -f3- | grep -E '\\.(ts|js|tsx|jsx)$')",
"lint:spelling": "codespell -D - -D $(git rev-parse --show-toplevel 2> /dev/null)/.github/codespell-dictionary.txt -I $(git rev-parse --show-toplevel 2> /dev/null)/.github/codespell-words.txt ./test -s",
"precommit": "run-s lint:precommit lint:spelling prettier",
"prettier": "prettier --write .",
"prettier-check": "prettier --check .",
"wdio": "wdio run ./wdio.conf.ts"
},
"type": "module"
}

View File

@ -1,25 +1,11 @@
import Page from "../pageobjects/page.js";
import { browser } from "@wdio/globals";
const CLICK_TIME_DELAY = 250;
export default class AdminPage extends Page {
public get pageHeader() {
return $('>>>ak-page-header slot[name="header"]');
public async pageHeader() {
return await $("ak-page-header").$('slot[name="header"]');
}
async openApplicationsListPage() {
await this.open("if/admin/#/core/applications");
}
public open(path: string) {
return browser.url(`http://localhost:9000/${path}`);
}
public pause(selector?: string) {
if (selector) {
return $(selector).waitForDisplayed();
}
return browser.pause(CLICK_TIME_DELAY);
}
}

View File

@ -27,24 +27,24 @@ class ApplicationWizardView extends AdminPage {
radius = RadiusForm;
app = ApplicationForm;
get wizardTitle() {
return $(">>>ak-wizard-frame .pf-c-wizard__header h1.pf-c-title");
async wizardTitle() {
return await $("ak-wizard-frame").$(".pf-c-wizard__title");
}
get providerList() {
return $(">>>ak-application-wizard-authentication-method-choice");
async providerList() {
return await $("ak-application-wizard-authentication-method-choice");
}
get nextButton() {
return $(">>>ak-wizard-frame footer button.pf-m-primary");
async nextButton() {
return await $("ak-wizard-frame").$("footer button.pf-m-primary");
}
async getProviderType(type: string) {
return await this.providerList.$(`>>>input[value="${type}"]`);
return await this.providerList().$(`input[value="${type}"]`);
}
get successMessage() {
return $('>>>[data-commit-state="success"]');
async successMessage() {
return await $('[data-commit-state="success"]');
}
}
@ -65,8 +65,10 @@ const providerValues: Pair[] = [
providerValues.forEach(([value, name]: Pair) => {
Object.defineProperties(ApplicationWizardView.prototype, {
[name]: {
get: function () {
return this.providerList.$(`>>>input[value="${value}"]`);
get: async function () {
return await (
await this.providerList()
).$(`div[data-ouid-component-name="${value}"]`);
},
},
});

View File

@ -9,8 +9,8 @@ class ApplicationsListPage extends AdminPage {
* define selectors using getter methods
*/
get startWizardButton() {
return $('>>>ak-wizard-frame button[slot="trigger"]');
async startWizardButton() {
return await $("ak-application-wizard").$('button[slot="trigger"]');
}
async open() {

View File

@ -2,16 +2,16 @@ import Page from "../page.js";
import { $ } from "@wdio/globals";
export class ApplicationForm extends Page {
get name() {
return $('>>>ak-form-element-horizontal input[name="name"]');
async name() {
return await $('ak-text-input[name="name"]').$("input");
}
get uiSettings() {
return $('>>>ak-form-group button[aria-label="UI Settings"]');
async uiSettings() {
return await $("ak-form-group").$('button[aria-label="UI Settings"]');
}
get launchUrl() {
return $('>>>input[name="metaLaunchUrl"]');
async launchUrl() {
return await $('input[name="metaLaunchUrl"]');
}
}

View File

@ -4,14 +4,14 @@ import { $ } from "@wdio/globals";
export class ForwardProxyForm extends Page {
async setAuthorizationFlow(selector: string) {
await this.searchSelect(
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
'ak-flow-search[name="authorizationFlow"]',
"authorizationFlow",
`button*=${selector}`,
selector,
);
}
get externalHost() {
return $('>>>input[name="externalHost"]');
return $('input[name="externalHost"]');
}
}

View File

@ -1,11 +1,11 @@
import Page from "../page.js";
export class LdapForm extends Page {
async setBindFlow(selector: string) {
async setBindFlow(_selector: string) {
await this.searchSelect(
'>>>ak-branded-flow-search[name="authorizationFlow"] input[type="text"]',
'ak-search-select-view[name="authorizationFlow"]',
"authorizationFlow",
`button*=${selector}`,
"default-authentication-flow",
);
}
}

View File

@ -4,14 +4,14 @@ import { $ } from "@wdio/globals";
export class OauthForm extends Page {
async setAuthorizationFlow(selector: string) {
await this.searchSelect(
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
'ak-flow-search[name="authorizationFlow"]',
"authorizationFlow",
`button*=${selector}`,
`${selector}`,
);
}
get providerName() {
return $('>>>ak-form-element-horizontal[name="name"] input');
async providerName() {
return await $('ak-form-element-horizontal[name="name"]').$("input");
}
}

View File

@ -3,9 +3,9 @@ import Page from "../page.js";
export class RadiusForm extends Page {
async setAuthenticationFlow(selector: string) {
await this.searchSelect(
'>>>ak-branded-flow-search[name="authorizationFlow"] input[type="text"]',
'ak-branded-flow-search[name="authorizationFlow"]',
"authorizationFlow",
`button*=${selector}`,
selector,
);
}
}

View File

@ -4,14 +4,14 @@ import { $ } from "@wdio/globals";
export class SamlForm extends Page {
async setAuthorizationFlow(selector: string) {
await this.searchSelect(
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
'ak-flow-search[name="authorizationFlow"]',
"authorizationFlow",
`button*=${selector}`,
selector,
);
}
get acsUrl() {
return $('>>>input[name="acsUrl"]');
return $('input[name="acsUrl"]');
}
}

View File

@ -2,11 +2,11 @@ import Page from "../page.js";
export class ScimForm extends Page {
get url() {
return $('>>>input[name="url"]');
return $('input[name="url"]');
}
get token() {
return $('>>>input[name="token"]');
return $('input[name="token"]');
}
}

View File

@ -4,18 +4,18 @@ import { $ } from "@wdio/globals";
export class TransparentProxyForm extends Page {
async setAuthorizationFlow(selector: string) {
await this.searchSelect(
'>>>ak-flow-search[name="authorizationFlow"] input[type="text"]',
'ak-flow-search[name="authorizationFlow"]',
"authorizationFlow",
`button*=${selector}`,
selector,
);
}
get externalHost() {
return $('>>>input[name="externalHost"]');
return $('input[name="externalHost"]');
}
get internalHost() {
return $('>>>input[name="internalHost"]');
return $('input[name="internalHost"]');
}
}

View File

@ -9,20 +9,20 @@ class LoginPage extends Page {
/**
* Selectors
*/
get inputUsername() {
return $('>>>input[name="uidField"]');
async inputUsername() {
return await $('input[name="uidField"]');
}
get inputPassword() {
return $('>>>input[name="password"]');
async inputPassword() {
return await $('input[name="password"]');
}
get btnSubmit() {
return $('>>>button[type="submit"]');
async btnSubmit() {
return await $('button[type="submit"]');
}
get authFailure() {
return $(">>>h4.pf-c-alert__title");
async authFailure() {
return await $(".pf-m-error");
}
/**
@ -30,17 +30,15 @@ class LoginPage extends Page {
*/
async username(username: string) {
await this.inputUsername.waitForClickable();
await this.inputUsername.setValue(username);
await this.btnSubmit.waitForEnabled();
await this.btnSubmit.click();
await (await this.inputUsername()).setValue(username);
await (await this.btnSubmit()).waitForEnabled();
await (await this.btnSubmit()).click();
}
async password(password: string) {
await this.inputPassword.waitForClickable();
await this.inputPassword.setValue(password);
await this.btnSubmit.waitForEnabled();
await this.btnSubmit.click();
await (await this.inputPassword()).setValue(password);
await (await this.btnSubmit()).waitForEnabled();
await (await this.btnSubmit()).click();
}
async login(username: string, password: string) {
@ -48,7 +46,7 @@ class LoginPage extends Page {
await this.pause();
await this.password(password);
await this.pause();
await this.pause(">>>div.header h1");
await this.pause("div.header h1");
return UserLibraryPage;
}

View File

@ -1,4 +1,5 @@
import { browser } from "@wdio/globals";
import { Key } from "webdriverio";
const CLICK_TIME_DELAY = 250;
@ -11,15 +12,15 @@ export default class Page {
* Opens a sub page of the page
* @param path path of the sub page (e.g. /path/to/page.html)
*/
public open(path: string) {
return browser.url(`http://localhost:9000/${path}`);
public async open(path: string) {
return await browser.url(`http://localhost:9000/${path}`);
}
public pause(selector?: string) {
public async pause(selector?: string) {
if (selector) {
return $(selector).waitForDisplayed();
return await $(selector).waitForDisplayed();
}
return browser.pause(CLICK_TIME_DELAY);
return await browser.pause(CLICK_TIME_DELAY);
}
/**
@ -33,10 +34,20 @@ export default class Page {
async searchSelect(searchSelector: string, managedSelector: string, buttonSelector: string) {
const inputBind = await $(searchSelector);
await inputBind.click();
const searchBlock = await $(`>>>div[data-managed-for="${managedSelector}"]`);
const target = searchBlock.$(buttonSelector);
return await target.click();
const inputMain = await inputBind.$('input[type="text"]');
await inputMain.click();
const searchBlock = await (
await $(`div[data-managed-for="${managedSelector}"]`).$("ak-list-select")
).shadow$$("button");
let target: WebdriverIO.Element;
for (const button of searchBlock) {
if ((await button.getText()).includes(buttonSelector)) {
target = button;
break;
}
}
await (await target).click();
await browser.keys(Key.Tab);
}
public async logout() {

View File

@ -9,13 +9,13 @@ class UserLibraryPage extends Page {
* define selectors using getter methods
*/
public get pageHeader() {
return $('>>>h1[aria-level="1"]');
public async pageHeader() {
return await $('h1[aria-level="1"]');
}
public async goToAdmin() {
await $('>>>a[href="/if/admin"]').click();
await $(">>>ak-admin-overview").waitForDisplayed();
await $('a[href="/if/admin"]').click();
return await $("ak-admin-overview").waitForDisplayed();
}
}

View File

@ -0,0 +1,15 @@
import LoginPage from "../pageobjects/login.page.js";
import { BAD_PASSWORD, GOOD_USERNAME } from "../utils/constants.js";
import { expect } from "@wdio/globals";
describe("Log into authentik", () => {
it("should fail on a bad password", async () => {
await LoginPage.open();
await LoginPage.username(GOOD_USERNAME);
await LoginPage.pause();
await LoginPage.password(BAD_PASSWORD);
const failure = await LoginPage.authFailure();
await expect(failure).toBeDisplayedInViewport();
await expect(failure).toHaveText("Invalid password");
});
});

View File

@ -1,21 +1,15 @@
import LoginPage from "../pageobjects/login.page.js";
import { BAD_PASSWORD, BAD_USERNAME, GOOD_USERNAME } from "../utils/constants.js";
import { BAD_USERNAME, GOOD_PASSWORD } from "../utils/constants.js";
import { expect } from "@wdio/globals";
describe("Log into authentik", () => {
it("should fail on a bad username", async () => {
await LoginPage.open();
await LoginPage.username(BAD_USERNAME);
const failure = await LoginPage.authFailure;
expect(failure).toHaveText("Failed to authenticate.");
});
it("should fail on a bad password", async () => {
await LoginPage.open();
await LoginPage.username(GOOD_USERNAME);
await LoginPage.pause();
await LoginPage.password(BAD_PASSWORD);
const failure = await LoginPage.authFailure;
expect(failure).toHaveText("Failed to authenticate.");
await LoginPage.password(GOOD_PASSWORD);
const failure = await LoginPage.authFailure();
await expect(failure).toBeDisplayedInViewport();
await expect(failure).toHaveText("Invalid password");
});
});

View File

@ -10,25 +10,27 @@ async function reachTheProvider(title: string) {
await ApplicationsListPage.logout();
await login();
await ApplicationsListPage.open();
await expect(await ApplicationsListPage.pageHeader).toHaveText("Applications");
await ApplicationsListPage.pause("ak-page-header");
await expect(await ApplicationsListPage.pageHeader()).toBeDisplayed();
await expect(await ApplicationsListPage.pageHeader()).toHaveText("Applications");
await ApplicationsListPage.startWizardButton.click();
await ApplicationWizardView.wizardTitle.waitForDisplayed();
await expect(await ApplicationWizardView.wizardTitle).toHaveText("New application");
await (await ApplicationsListPage.startWizardButton()).click();
await (await ApplicationWizardView.wizardTitle()).waitForDisplayed();
await expect(await ApplicationWizardView.wizardTitle()).toHaveText("New application");
await ApplicationWizardView.app.name.setValue(`${title} - ${newPrefix}`);
await ApplicationWizardView.app.uiSettings.scrollIntoView();
await ApplicationWizardView.app.uiSettings.click();
await ApplicationWizardView.app.launchUrl.scrollIntoView();
await ApplicationWizardView.app.launchUrl.setValue("http://example.goauthentik.io");
await (await ApplicationWizardView.app.name()).setValue(`${title} - ${newPrefix}`);
await (await ApplicationWizardView.app.uiSettings()).scrollIntoView();
await (await ApplicationWizardView.app.uiSettings()).click();
await (await ApplicationWizardView.app.launchUrl()).scrollIntoView();
await (await ApplicationWizardView.app.launchUrl()).setValue("http://example.goauthentik.io");
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
return await ApplicationWizardView.pause();
}
async function getCommitMessage() {
await ApplicationWizardView.successMessage.waitForDisplayed();
return await ApplicationWizardView.successMessage;
await (await ApplicationWizardView.successMessage()).waitForDisplayed();
return await ApplicationWizardView.successMessage();
}
const SUCCESS_MESSAGE = "Your application has been saved";
@ -38,97 +40,97 @@ describe("Configure Applications with the Application Wizard", () => {
it("Should configure a simple LDAP Application", async () => {
await reachTheProvider("New LDAP Application");
await ApplicationWizardView.providerList.waitForDisplayed();
await ApplicationWizardView.ldapProvider.scrollIntoView();
await ApplicationWizardView.ldapProvider.click();
await (await ApplicationWizardView.providerList()).waitForDisplayed();
await (await ApplicationWizardView.ldapProvider).scrollIntoView();
await (await ApplicationWizardView.ldapProvider).click();
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await ApplicationWizardView.ldap.setBindFlow("default-authentication-flow");
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
});
it("Should configure a simple Oauth2 Application", async () => {
await reachTheProvider("New Oauth2 Application");
await ApplicationWizardView.providerList.waitForDisplayed();
await ApplicationWizardView.oauth2Provider.scrollIntoView();
await ApplicationWizardView.oauth2Provider.click();
await (await ApplicationWizardView.providerList()).waitForDisplayed();
await (await ApplicationWizardView.oauth2Provider).scrollIntoView();
await (await ApplicationWizardView.oauth2Provider).click();
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await ApplicationWizardView.oauth.setAuthorizationFlow(EXPLICIT_CONSENT);
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
});
it("Should configure a simple SAML Application", async () => {
await reachTheProvider("New SAML Application");
await ApplicationWizardView.providerList.waitForDisplayed();
await ApplicationWizardView.samlProvider.scrollIntoView();
await ApplicationWizardView.samlProvider.click();
await (await ApplicationWizardView.providerList()).waitForDisplayed();
await (await ApplicationWizardView.samlProvider).scrollIntoView();
await (await ApplicationWizardView.samlProvider).click();
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await ApplicationWizardView.saml.setAuthorizationFlow(EXPLICIT_CONSENT);
await ApplicationWizardView.saml.acsUrl.setValue("http://example.com:8000/");
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
});
it("Should configure a simple SCIM Application", async () => {
await reachTheProvider("New SCIM Application");
await ApplicationWizardView.providerList.waitForDisplayed();
await ApplicationWizardView.scimProvider.scrollIntoView();
await ApplicationWizardView.scimProvider.click();
await (await ApplicationWizardView.providerList()).waitForDisplayed();
await (await ApplicationWizardView.scimProvider).scrollIntoView();
await (await ApplicationWizardView.scimProvider).click();
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await ApplicationWizardView.scim.url.setValue("http://example.com:8000/");
await ApplicationWizardView.scim.token.setValue("a-very-basic-token");
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
});
it("Should configure a simple Radius Application", async () => {
await reachTheProvider("New Radius Application");
await ApplicationWizardView.providerList.waitForDisplayed();
await ApplicationWizardView.radiusProvider.scrollIntoView();
await ApplicationWizardView.radiusProvider.click();
await (await ApplicationWizardView.providerList()).waitForDisplayed();
await (await ApplicationWizardView.radiusProvider).scrollIntoView();
await (await ApplicationWizardView.radiusProvider).click();
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await ApplicationWizardView.radius.setAuthenticationFlow("default-authentication-flow");
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
});
it("Should configure a simple Transparent Proxy Application", async () => {
await reachTheProvider("New Transparent Proxy Application");
await ApplicationWizardView.providerList.waitForDisplayed();
await ApplicationWizardView.proxyProviderProxy.scrollIntoView();
await ApplicationWizardView.proxyProviderProxy.click();
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.providerList()).waitForDisplayed();
await (await ApplicationWizardView.proxyProviderProxy).scrollIntoView();
await (await ApplicationWizardView.proxyProviderProxy).click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await ApplicationWizardView.transparentProxy.setAuthorizationFlow(EXPLICIT_CONSENT);
@ -139,19 +141,19 @@ describe("Configure Applications with the Application Wizard", () => {
"http://internal.example.com",
);
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
});
it("Should configure a simple Forward Proxy Application", async () => {
await reachTheProvider("New Forward Proxy Application");
await ApplicationWizardView.providerList.waitForDisplayed();
await ApplicationWizardView.proxyProviderForwardsingle.scrollIntoView();
await ApplicationWizardView.proxyProviderForwardsingle.click();
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.providerList()).waitForDisplayed();
await (await ApplicationWizardView.proxyProviderForwardsingle).scrollIntoView();
await (await ApplicationWizardView.proxyProviderForwardsingle).click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await ApplicationWizardView.forwardProxy.setAuthorizationFlow(EXPLICIT_CONSENT);
@ -159,9 +161,9 @@ describe("Configure Applications with the Application Wizard", () => {
"http://external.example.com",
);
await ApplicationWizardView.nextButton.click();
await (await ApplicationWizardView.nextButton()).click();
await ApplicationWizardView.pause();
await expect(getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
await expect(await getCommitMessage()).toHaveText(SUCCESS_MESSAGE);
});
});

View File

@ -6,5 +6,5 @@ import { expect } from "@wdio/globals";
export const login = async () => {
await LoginPage.open();
await LoginPage.login(GOOD_USERNAME, GOOD_PASSWORD);
await expect(UserLibraryPage.pageHeader).toHaveText("My applications");
await expect(await UserLibraryPage.pageHeader()).toHaveText("My applications");
};

View File

@ -3,7 +3,7 @@
"moduleResolution": "node",
"module": "ESNext",
"target": "es2022",
"types": ["node", "@wdio/globals/types", "expect-webdriverio", "@wdio/mocha-framework"],
"types": ["node", "@wdio/globals/types", "expect-webdriverio", "@wdio/mocha-framework", "@types/mocha"],
"skipLibCheck": true,
"noEmit": true,
"allowImportingTsExtensions": true,

View File

@ -41,6 +41,7 @@ const definitions = {
const otherFiles = [
["node_modules/@patternfly/patternfly/patternfly.min.css", "."],
["node_modules/@patternfly/patternfly/patternfly-base.css", "."],
["node_modules/@patternfly/patternfly/assets/**", ".", "node_modules/@patternfly/patternfly/"],
["src/custom.css", "."],
["src/common/styles/**", "."],
@ -79,6 +80,12 @@ const interfaces = [
["polyfill/poly.ts", "."],
];
const extraTargets = [
["sdk/index.ts", "sdk", { entryNames: "[dir]/[name]" }],
["sdk/user-settings.ts", "sdk/user-settings", { entryNames: "[dir]/[name]" }],
["sdk/flow.ts", "sdk/flow", { entryNames: "[dir]/[name]" }],
];
const baseArgs = {
bundle: true,
write: true,
@ -101,7 +108,11 @@ function getVersion() {
return version;
}
async function buildOneSource(source, dest) {
function getAllTargets() {
return [...interfaces, ...extraTargets];
}
async function buildSingleTarget(source, dest, options) {
const DIST = path.join(__dirname, "./dist", dest);
console.log(`[${new Date(Date.now()).toISOString()}] Starting build for target ${source}`);
@ -112,6 +123,7 @@ async function buildOneSource(source, dest) {
entryPoints: [`./src/${source}`],
entryNames: `[dir]/[name]-${getVersion()}`,
outdir: DIST,
...options,
});
const end = Date.now();
console.log(
@ -124,8 +136,10 @@ async function buildOneSource(source, dest) {
}
}
async function buildAuthentik(interfaces) {
await Promise.allSettled(interfaces.map(([source, dest]) => buildOneSource(source, dest)));
async function buildTargets(targets) {
await Promise.allSettled(
targets.map(([source, dest, options]) => buildSingleTarget(source, dest, options)),
);
}
let timeoutId = null;
@ -135,7 +149,7 @@ function debouncedBuild() {
}
timeoutId = setTimeout(() => {
console.clear();
buildAuthentik(interfaces);
buildTargets(getAllTargets());
}, 250);
}
@ -143,7 +157,7 @@ if (process.argv.length > 2 && (process.argv[2] === "-h" || process.argv[2] ===
console.log(`Build the authentikUI
options:
-w, --watch: Build all ${interfaces.length} interfaces
-w, --watch: Build all ${getAllTargets().length} interfaces
-p, --proxy: Build only the polyfills and the loading application
-h, --help: This help message
`);
@ -163,11 +177,11 @@ if (process.argv.length > 2 && (process.argv[2] === "-w" || process.argv[2] ===
});
} else if (process.argv.length > 2 && (process.argv[2] === "-p" || process.argv[2] === "--proxy")) {
// There's no watch-for-proxy, sorry.
await buildAuthentik(
await buildTargets(
interfaces.filter(([_, dest]) => ["standalone/loading", "."].includes(dest)),
);
process.exit(0);
} else {
// And the fallback: just build it.
await buildAuthentik(interfaces);
await buildTargets(interfaces);
}

1788
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -11,15 +11,15 @@
"@floating-ui/dom": "^1.6.9",
"@formatjs/intl-listformat": "^7.5.7",
"@fortawesome/fontawesome-free": "^6.6.0",
"@goauthentik/api": "^2024.6.3-1724414734",
"@goauthentik/api": "^2024.8.0-1725367323",
"@lit/context": "^1.1.2",
"@lit/localize": "^0.12.2",
"@lit/reactive-element": "^2.0.4",
"@lit/task": "^1.0.1",
"@open-wc/lit-helpers": "^0.7.0",
"@patternfly/elements": "^4.0.0",
"@patternfly/elements": "^4.0.1",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^8.26.0",
"@sentry/browser": "^8.27.0",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"chart.js": "^4.4.4",
@ -32,7 +32,7 @@
"guacamole-common-js": "^1.5.0",
"lit": "^3.2.0",
"md-front-matter": "^1.0.4",
"mermaid": "^10.9.1",
"mermaid": "^11.1.0",
"rapidoc": "^9.3.4",
"showdown": "^2.1.0",
"style-mod": "^4.1.2",
@ -51,13 +51,13 @@
"@babel/preset-typescript": "^7.24.7",
"@changesets/cli": "^2.27.5",
"@custom-elements-manifest/analyzer": "^0.10.2",
"@eslint/js": "^9.9.0",
"@eslint/js": "^9.9.1",
"@genesiscommunitysuccess/custom-elements-lsp": "^5.0.3",
"@hcaptcha/types": "^1.0.4",
"@jeysal/storybook-addon-css-user-preferences": "^0.2.0",
"@lit/localize-tools": "^0.8.0",
"@rollup/plugin-replace": "^5.0.7",
"@spotlightjs/spotlight": "^2.3.0",
"@spotlightjs/spotlight": "^2.3.2",
"@storybook/addon-essentials": "^8.2.9",
"@storybook/addon-links": "^8.2.9",
"@storybook/api": "^7.6.17",
@ -71,6 +71,7 @@
"@types/eslint__js": "^8.42.3",
"@types/grecaptcha": "^3.0.9",
"@types/guacamole-common-js": "1.5.2",
"@types/node": "^22.5.0",
"@types/showdown": "^2.0.6",
"@typescript-eslint/eslint-plugin": "^8.0.1",
"@typescript-eslint/parser": "^8.0.1",
@ -90,6 +91,7 @@
"github-slugger": "^2.0.0",
"glob": "^11.0.0",
"globals": "^15.9.0",
"knip": "^5.27.4",
"lit-analyzer": "^2.0.3",
"lockfile-lint": "^4.14.0",
"npm-run-all": "^4.1.5",
@ -101,13 +103,13 @@
"rollup-plugin-postcss-lit": "^2.1.0",
"storybook": "^8.1.11",
"storybook-addon-mock": "^5.0.0",
"syncpack": "^12.3.3",
"syncpack": "^13.0.0",
"ts-lit-plugin": "^2.0.2",
"ts-node": "^10.9.2",
"tslib": "^2.6.3",
"tslib": "^2.7.0",
"turnstile-types": "^1.2.2",
"typescript": "^5.5.4",
"typescript-eslint": "^8.2.0",
"typescript-eslint": "^8.4.0",
"vite-tsconfig-paths": "^5.0.1",
"wdio-wait-for": "^3.0.11",
"wireit": "^0.14.8"
@ -120,9 +122,9 @@
"@esbuild/darwin-arm64": "^0.23.0",
"@esbuild/linux-amd64": "^0.18.11",
"@esbuild/linux-arm64": "^0.23.0",
"@rollup/rollup-darwin-arm64": "4.21.0",
"@rollup/rollup-linux-arm64-gnu": "4.21.0",
"@rollup/rollup-linux-x64-gnu": "4.21.0"
"@rollup/rollup-darwin-arm64": "4.21.2",
"@rollup/rollup-linux-arm64-gnu": "4.21.2",
"@rollup/rollup-linux-x64-gnu": "4.21.2"
},
"private": true,
"scripts": {
@ -135,6 +137,7 @@
"extract-locales": "wireit",
"format": "wireit",
"lint": "wireit",
"lint:imports": "wireit",
"lint:lockfile": "wireit",
"lint:nightmare": "wireit",
"lint:package": "wireit",
@ -149,8 +152,7 @@
"storybook:build": "wireit",
"storybook:build-import-map": "wireit",
"test": "wireit",
"test-view": "wireit",
"test-watch": "npx wdio run ./wdio.conf.ts --autoCompileOpts.tsNodeOpts.project=tsconfig.test.json --watch",
"test-watch": "wireit",
"tsc": "wireit",
"watch": "run-s build-locales esbuild:watch"
},
@ -250,6 +252,9 @@
"lint:components": {
"command": "lit-analyzer src"
},
"lint:imports": {
"command": "knip --config scripts/knip.config.ts"
},
"lint:types": {
"command": "tsc --noEmit -p .",
"dependencies": [
@ -330,7 +335,7 @@
"TS_NODE_PROJECT": "tsconfig.test.json"
}
},
"test-view": {
"test-watch": {
"command": "wdio run ./wdio.conf.ts",
"env": {
"TS_NODE_PROJECT": "tsconfig.test.json"

View File

@ -14,18 +14,18 @@
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-swc": "^0.3.1",
"@swc/cli": "^0.4.0",
"@swc/core": "^1.7.14",
"@swc/core": "^1.7.23",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/jquery": "^3.5.30",
"lockfile-lint": "^4.14.0",
"prettier": "^3.3.2",
"rollup": "^4.21.0",
"rollup": "^4.21.2",
"rollup-plugin-copy": "^3.5.0",
"wireit": "^0.14.8"
},
"license": "MIT",
"optionalDependencies": {
"@swc/core": "^1.7.14",
"@swc/core": "^1.7.23",
"@swc/core-darwin-arm64": "^1.6.13",
"@swc/core-darwin-x64": "^1.6.13",
"@swc/core-linux-arm-gnueabihf": "^1.6.13",

View File

@ -0,0 +1,48 @@
import { type KnipConfig } from "knip";
const config: KnipConfig = {
"entry": [
"./src/admin/AdminInterface/AdminInterface.ts",
"./src/user/UserInterface.ts",
"./src/flow/FlowInterface.ts",
"./src/standalone/api-browser/index.ts",
"./src/enterprise/rac/index.ts",
"./src/standalone/loading/index.ts",
"./src/polyfill/poly.ts",
],
"project": ["src/**/*.ts", "src/**/*.js", "./scripts/*.mjs", ".storybook/*.ts"],
// "ignore": ["src/**/*.test.ts", "src/**/*.stories.ts"],
// Prevent Knip from complaining about web components, which export their classes but also
// export their registration, and we don't always use both.
"ignoreExportsUsedInFile": true,
"typescript": {
config: ["tsconfig.json"],
},
"wireit": {
config: ["package.json"],
},
"storybook": {
config: [".storybook/{main,test-runner}.{js,ts}"],
entry: [
".storybook/{manager,preview}.{js,jsx,ts,tsx}",
"**/*.@(mdx|stories.@(mdx|js|jsx|mjs|ts|tsx))",
],
project: [".storybook/**/*.{js,jsx,ts,tsx}"],
},
"eslint": {
entry: [
"eslint.config.mjs",
"scripts/eslint.precommit.mjs",
"scripts/eslint.nightmare.mjs",
"scripts/eslint-precommit.mjs",
"scripts/eslint-nightmare.mjs",
"scripts/eslint.mjs",
],
config: ["package.json"],
},
"webdriver-io": {
config: ["wdio.conf.js"],
},
};
export default config;

3057
web/sfe/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +0,0 @@
{
"name": "@goauthentik/web-sfe",
"version": "0.0.0",
"private": true,
"license": "MIT",
"dependencies": {
"@goauthentik/api": "^2024.6.3-1724337552",
"base64-js": "^1.5.1",
"bootstrap": "^4.6.1",
"formdata-polyfill": "^4.0.10",
"jquery": "^3.7.1",
"weakmap-polyfill": "^2.0.4"
},
"scripts": {
"build": "rollup -c rollup.config.js --bundleConfigAsCjs",
"watch": "rollup -w -c rollup.config.js --bundleConfigAsCjs"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^26.0.1",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-swc": "^0.3.1",
"@swc/cli": "^0.4.0",
"@swc/core": "^1.7.14",
"@types/jquery": "^3.5.30",
"rollup": "^4.21.0",
"rollup-plugin-copy": "^3.5.0"
}
}

View File

@ -21,10 +21,20 @@ export class ApplicationWizardAuthenticationMethodChoice extends WithLicenseSumm
const selectedTypes = providerModelsList.filter(
(t) => t.formName === this.wizard.providerModel,
);
// As a hack, the Application wizard has separate provider paths for our three types of
// proxy providers. This patch swaps the form we want to be directed to on page 3 from the
// modelName to the formName, so we get the right one. This information isn't modified
// or forwarded, so the proxy-plus-subtype is correctly mapped on submission.
const typesForWizard = providerModelsList.map((provider) => ({
...provider,
modelName: provider.formName,
}));
return providerModelsList.length > 0
? html`<form class="pf-c-form pf-m-horizontal">
<ak-wizard-page-type-create
.types=${providerModelsList}
.types=${typesForWizard}
layout=${TypeCreateWizardPageLayouts.grid}
.selectedType=${selectedTypes.length > 0 ? selectedTypes[0] : undefined}
@select=${(ev: CustomEvent<LocalTypeCreate>) => {

View File

@ -265,7 +265,7 @@ export class ApplicationWizardAuthenticationByOauth extends BaseProviderPanel {
>
<ak-dual-select-provider
.provider=${oauth2SourcesProvider}
.selected=${provider?.jwksSources}
.selected=${provider?.jwksSources ?? []}
available-label=${msg("Available Sources")}
selected-label=${msg("Selected Sources")}
></ak-dual-select-provider>

View File

@ -230,7 +230,7 @@ export class AkTypeProxyApplicationWizardPage extends BaseProviderPanel {
>
<ak-dual-select-provider
.provider=${oauth2SourcesProvider}
.selected=${this.instance?.jwksSources}
.selected=${this.instance?.jwksSources ?? []}
available-label=${msg("Available Sources")}
selected-label=${msg("Selected Sources")}
></ak-dual-select-provider>

View File

@ -97,7 +97,8 @@ export class OutpostForm extends ModelForm<Outpost, string> {
embedded = false;
@state()
providers?: DataProvider;
providers: DataProvider = providerProvider(this.type);
defaultConfig?: OutpostDefaultConfig;
async loadInstance(pk: string): Promise<Outpost> {
@ -113,6 +114,7 @@ export class OutpostForm extends ModelForm<Outpost, string> {
this.defaultConfig = await new OutpostsApi(
DEFAULT_CONFIG,
).outpostsInstancesDefaultSettingsRetrieve();
this.providers = providerProvider(this.type);
}
getSuccessMessage(): string {

View File

@ -117,7 +117,7 @@ export class EventMatcherPolicyForm extends BasePolicyForm<EventMatcherPolicy> {
/>
<p class="pf-c-form__helper-text">
${msg(
"Matches Event's Client IP (strict matching, for network matching use an Expression Policy.",
"Matches Event's Client IP (strict matching, for network matching use an Expression Policy).",
)}
</p>
</ak-form-element-horizontal>

View File

@ -7,6 +7,9 @@ export function renderSourceIcon(name: string, iconUrl: string | undefined | nul
const url = iconUrl.replaceAll("fa://", "");
return html`<i class="fas ${url}" title="${name}"></i>`;
}
if (window.authentik_sdk?.base) {
return html`<img src="${window.authentik_sdk?.base}${iconUrl}" alt="${name}" />`;
}
return html`<img src="${iconUrl}" alt="${name}" />`;
}
return icon;

View File

@ -21,7 +21,6 @@ import {
SourcesApi,
Stage,
StagesApi,
StagesCaptchaListRequest,
StagesPasswordListRequest,
UserFieldsEnum,
} from "@goauthentik/api";
@ -47,7 +46,8 @@ async function makeSourcesSelector(instanceSources: string[] | undefined) {
return localSources
? ([pk, _]: DualSelectPair) => localSources.has(pk)
: ([_0, _1, _2, source]: DualSelectPair<Source>) =>
: // Creating a new instance, auto-select built-in source only when no other sources exist
([_0, _1, _2, source]: DualSelectPair<Source>) =>
source !== undefined && source.component === "";
}
@ -76,11 +76,11 @@ export class IdentificationStageForm extends BaseStageForm<IdentificationStage>
stageUuid: this.instance.pk || "",
identificationStageRequest: data,
});
} else {
return new StagesApi(DEFAULT_CONFIG).stagesIdentificationCreate({
identificationStageRequest: data,
});
}
return new StagesApi(DEFAULT_CONFIG).stagesIdentificationCreate({
identificationStageRequest: data,
});
}
isUserFieldSelected(field: UserFieldsEnum): boolean {
@ -161,37 +161,6 @@ export class IdentificationStageForm extends BaseStageForm<IdentificationStage>
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${msg("Captcha stage")} name="captchaStage">
<ak-search-select
.fetchObjects=${async (query?: string): Promise<Stage[]> => {
const args: StagesCaptchaListRequest = {
ordering: "name",
};
if (query !== undefined) {
args.search = query;
}
const stages = await new StagesApi(
DEFAULT_CONFIG,
).stagesCaptchaList(args);
return stages.results;
}}
.groupBy=${(items: Stage[]) => {
return groupBy(items, (stage) => stage.verboseNamePlural);
}}
.renderElement=${(stage: Stage): string => {
return stage.name;
}}
.value=${(stage: Stage | undefined): string | undefined => {
return stage?.pk;
}}
.selected=${(stage: Stage): boolean => {
return stage.pk === this.instance?.captchaStage;
}}
?blankable=${true}
>
</ak-search-select>
<p class="pf-c-form__helper-text">${msg("TODO.")}</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="caseInsensitiveMatching">
<label class="pf-c-switch">
<input
@ -264,12 +233,12 @@ export class IdentificationStageForm extends BaseStageForm<IdentificationStage>
?required=${true}
name="sources"
>
<ak-dual-select-provider-dynamic-selected
<ak-dual-select-dynamic-selected
.provider=${sourcesProvider}
.selected=${makeSourcesSelector(this.instance?.sources)}
.selector=${makeSourcesSelector(this.instance?.sources)}
available-label="${msg("Available Stages")}"
selected-label="${msg("Selected Stages")}"
></ak-dual-select-provider-dynamic-selected>
></ak-dual-select-dynamic-selected>
<p class="pf-c-form__helper-text">
${msg(
"Select sources should be shown for users to authenticate with. This only affects web-based sources, not LDAP.",

View File

@ -2,6 +2,7 @@ import {
CSRFMiddleware,
EventMiddleware,
LoggingMiddleware,
SDKMiddleware,
} from "@goauthentik/common/api/middleware";
import { EVENT_LOCALE_REQUEST, VERSION } from "@goauthentik/common/constants";
import { globalAK } from "@goauthentik/common/global";
@ -67,8 +68,18 @@ export function getMetaContent(key: string): string {
return metaEl.content;
}
export function apiBase(): string {
if (process.env.AK_API_BASE_PATH) {
return process.env.AK_API_BASE_PATH;
}
if (window.authentik_sdk?.base) {
return window.authentik_sdk?.base;
}
return window.location.origin;
}
export const DEFAULT_CONFIG = new Configuration({
basePath: (process.env.AK_API_BASE_PATH || window.location.origin) + "/api/v3",
basePath: `${apiBase()}/api/v3`,
headers: {
"sentry-trace": getMetaContent("sentry-trace"),
},
@ -76,6 +87,7 @@ export const DEFAULT_CONFIG = new Configuration({
new CSRFMiddleware(),
new EventMiddleware(),
new LoggingMiddleware(globalAK().brand),
new SDKMiddleware(),
],
});

View File

@ -44,6 +44,21 @@ export class CSRFMiddleware implements Middleware {
}
}
export class SDKMiddleware implements Middleware {
token?: string;
constructor() {
this.token = window.authentik_sdk?.token;
}
pre?(context: RequestContext): Promise<FetchParams | void> {
if (this.token) {
context.init.credentials = "include";
// @ts-ignore
context.init.headers["Authorization"] = `Bearer ${this.token}`;
}
return Promise.resolve(context);
}
}
export class EventMiddleware implements Middleware {
post?(context: ResponseContext): Promise<Response | void> {
const request: RequestInfo = {

View File

@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
export const ERROR_CLASS = "pf-m-danger";
export const PROGRESS_CLASS = "pf-m-in-progress";
export const CURRENT_CLASS = "pf-m-current";
export const VERSION = "2024.6.4";
export const VERSION = "2024.8.0";
export const TITLE_DEFAULT = "authentik";
export const ROUTE_SEPARATOR = ";";

View File

@ -1,4 +1,11 @@
import { Config, ConfigFromJSON, CurrentBrand, CurrentBrandFromJSON } from "@goauthentik/api";
import {
Config,
ConfigFromJSON,
CurrentBrand,
CurrentBrandFromJSON,
ErrorReportingConfigFromJSON,
UiThemeEnum,
} from "@goauthentik/api";
export interface GlobalAuthentik {
_converted?: boolean;
@ -28,9 +35,12 @@ export function globalAK(): GlobalAuthentik {
return {
config: ConfigFromJSON({
capabilities: [],
error_reporting: ErrorReportingConfigFromJSON({}),
}),
brand: CurrentBrandFromJSON({
matched_domain: window.location.host,
ui_footer_links: [],
ui_theme: window.authentik_sdk?.forceTheme ?? UiThemeEnum.Automatic,
}),
versionFamily: "",
versionSubdomain: "",
@ -40,6 +50,10 @@ export function globalAK(): GlobalAuthentik {
return ak;
}
export function isEmbedded() {
return !!window.authentik_sdk;
}
export function docLink(path: string): string {
const ak = globalAK();
// Default case or beta build which should always point to latest

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