Compare commits
32 Commits
workspace-
...
channels-p
Author | SHA1 | Date | |
---|---|---|---|
44f4ba3385 | |||
bfbe8b8038 | |||
36ba8bc4e7 | |||
dd5edf7fd9 | |||
da1b252f3b | |||
a8e543972a | |||
6e03045d1f | |||
f4b39e7465 | |||
e7cd5880b5 | |||
d8c6a2417d | |||
a1fe471a59 | |||
054dfda73f | |||
2e5e8f5c58 | |||
c28b65a3f2 | |||
afc9847e36 | |||
620c95dfa1 | |||
15c7a0a9be | |||
5fed8ca575 | |||
f471ddfb29 | |||
1b1f06c9f7 | |||
67c31a8ac3 | |||
638180d246 | |||
a3be1bbb57 | |||
fbd0ba2865 | |||
182ad912cb | |||
e850b2ba1a | |||
b4ce7f9ab0 | |||
5f0bd6f5ea | |||
f5944ccb95 | |||
9bd3bad605 | |||
dff60ee9fb | |||
9cf2f89bf6 |
6
.github/actions/setup/action.yml
vendored
6
.github/actions/setup/action.yml
vendored
@ -28,9 +28,9 @@ runs:
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
cache-dependency-path: web/package-lock.json
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
@ -44,7 +44,7 @@ runs:
|
||||
run: |
|
||||
export PSQL_TAG=${{ inputs.postgresql_version }}
|
||||
docker compose -f .github/actions/setup/docker-compose.yml up -d
|
||||
npm ci
|
||||
cd web && npm ci
|
||||
- name: Generate config
|
||||
shell: uv run python {0}
|
||||
run: |
|
||||
|
15
.github/workflows/api-ts-publish.yml
vendored
15
.github/workflows/api-ts-publish.yml
vendored
@ -20,11 +20,8 @@ jobs:
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
node-version-file: web/package.json
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- name: Prepare Dependencies
|
||||
run: |
|
||||
npm ci
|
||||
- name: Generate API Client
|
||||
run: make gen-client-ts
|
||||
- name: Publish package
|
||||
@ -35,13 +32,15 @@ jobs:
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
||||
- name: Upgrade /web
|
||||
working-directory: web
|
||||
run: |
|
||||
export VERSION=`node -e 'console.log(require("./gen-ts-api/package.json").version)'`
|
||||
npm i @goauthentik/api@$VERSION -w @goauthentik/web
|
||||
export VERSION=`node -e 'console.log(require("../gen-ts-api/package.json").version)'`
|
||||
npm i @goauthentik/api@$VERSION
|
||||
- name: Upgrade /web/packages/sfe
|
||||
working-directory: web/packages/sfe
|
||||
run: |
|
||||
export VERSION=`node -e 'console.log(require("./gen-ts-api/package.json").version)'`
|
||||
npm i @goauthentik/api@$VERSION -w @goauthentik/web-sfe
|
||||
export VERSION=`node -e 'console.log(require("../gen-ts-api/package.json").version)'`
|
||||
npm i @goauthentik/api@$VERSION
|
||||
- uses: peter-evans/create-pull-request@v7
|
||||
id: cpr
|
||||
with:
|
||||
|
15
.github/workflows/ci-main.yml
vendored
15
.github/workflows/ci-main.yml
vendored
@ -193,22 +193,23 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
- name: Setup E2E environment (Chrome, etc)
|
||||
- name: Setup e2e env (chrome, etc)
|
||||
run: |
|
||||
docker compose -f tests/e2e/docker-compose.yml up -d --quiet-pull
|
||||
- id: cache-web
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: web/dist
|
||||
key: ${{ runner.os }}-web-${{ hashFiles('package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b
|
||||
- name: Prepare Web UI
|
||||
key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b
|
||||
- name: prepare web ui
|
||||
if: steps.cache-web.outputs.cache-hit != 'true'
|
||||
working-directory: web
|
||||
run: |
|
||||
npm ci
|
||||
make gen-client-ts
|
||||
npm run build -w @goauthentik/web
|
||||
npm run build -w @goauthentik/web-sfe
|
||||
- name: Run E2E
|
||||
make -C .. gen-client-ts
|
||||
npm run build
|
||||
npm run build:sfe
|
||||
- name: run e2e
|
||||
run: |
|
||||
uv run coverage run manage.py test ${{ matrix.job.glob }}
|
||||
uv run coverage xml
|
||||
|
19
.github/workflows/ci-outpost.yml
vendored
19
.github/workflows/ci-outpost.yml
vendored
@ -26,7 +26,7 @@ jobs:
|
||||
mkdir -p web/dist
|
||||
mkdir -p website/help
|
||||
touch web/dist/test website/help/test
|
||||
- name: Generate Golang API Client
|
||||
- name: Generate API
|
||||
run: make gen-client-go
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v8
|
||||
@ -43,7 +43,7 @@ jobs:
|
||||
go-version-file: "go.mod"
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
- name: Generate Golang API Client
|
||||
- name: Generate API
|
||||
run: make gen-client-go
|
||||
- name: Go unittests
|
||||
run: |
|
||||
@ -99,7 +99,7 @@ jobs:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Generate Golang API Client
|
||||
- name: Generate API
|
||||
run: make gen-client-go
|
||||
- name: Build Docker Image
|
||||
id: push
|
||||
@ -145,17 +145,16 @@ jobs:
|
||||
go-version-file: "go.mod"
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Generate Golang API Client
|
||||
cache-dependency-path: web/package-lock.json
|
||||
- name: Generate API
|
||||
run: make gen-client-go
|
||||
- name: Prepare Dependencies
|
||||
- name: Build web
|
||||
working-directory: web/
|
||||
run: |
|
||||
npm ci
|
||||
- name: Run ESBuild
|
||||
run: |
|
||||
npm run build-proxy -w @goauthentik/web
|
||||
npm run build-proxy
|
||||
- name: Build outpost
|
||||
run: |
|
||||
set -x
|
||||
|
43
.github/workflows/ci-web.yml
vendored
43
.github/workflows/ci-web.yml
vendored
@ -19,45 +19,47 @@ jobs:
|
||||
matrix:
|
||||
command:
|
||||
- lint
|
||||
- lint:lockfile
|
||||
- tsc
|
||||
- prettier-check
|
||||
project:
|
||||
- web
|
||||
include:
|
||||
- command: tsc
|
||||
project: web
|
||||
- command: lit-analyse
|
||||
project: web
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
node-version-file: ${{ matrix.project }}/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Prepare Dependencies
|
||||
cache-dependency-path: ${{ matrix.project }}/package-lock.json
|
||||
- working-directory: ${{ matrix.project }}/
|
||||
run: |
|
||||
npm ci
|
||||
- name: Generate TypeScript API
|
||||
- name: Generate API
|
||||
run: make gen-client-ts
|
||||
- name: Lint Project
|
||||
run: |
|
||||
npm run build-locales -w @goauthentik/web
|
||||
npm run lint:types
|
||||
- name: Lint Web
|
||||
run: npm run ${{ matrix.command }} -w @goauthentik/web
|
||||
- name: Lint
|
||||
working-directory: ${{ matrix.project }}/
|
||||
run: npm run ${{ matrix.command }}
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Prepare Dependencies
|
||||
cache-dependency-path: web/package-lock.json
|
||||
- working-directory: web/
|
||||
run: npm ci
|
||||
- name: Generate TypeScript API
|
||||
- name: Generate API
|
||||
run: make gen-client-ts
|
||||
- name: build
|
||||
run: npm run build -w @goauthentik/web
|
||||
working-directory: web/
|
||||
run: npm run build
|
||||
ci-web-mark:
|
||||
if: always()
|
||||
needs:
|
||||
@ -76,12 +78,13 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Prepare Dependencies
|
||||
cache-dependency-path: web/package-lock.json
|
||||
- working-directory: web/
|
||||
run: npm ci
|
||||
- name: Generate TypeScript API
|
||||
- name: Generate API
|
||||
run: make gen-client-ts
|
||||
- name: test
|
||||
run: npm run test -w @goauthentik/web || exit 0
|
||||
working-directory: web/
|
||||
run: npm run test || exit 0
|
||||
|
43
.github/workflows/ci-website.yml
vendored
43
.github/workflows/ci-website.yml
vendored
@ -14,44 +14,53 @@ on:
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
command:
|
||||
- lint:lockfile
|
||||
- prettier-check
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Prepare Dependencies
|
||||
- working-directory: website/
|
||||
run: npm ci
|
||||
- name: Lint
|
||||
run: npm run prettier-check -w @goauthentik/docs
|
||||
working-directory: website/
|
||||
run: npm run ${{ matrix.command }}
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
node-version-file: website/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Prepare Dependencies
|
||||
cache-dependency-path: website/package-lock.json
|
||||
- working-directory: website/
|
||||
run: npm ci
|
||||
- name: test
|
||||
run: npm test -w @goauthentik/docs
|
||||
working-directory: website/
|
||||
run: npm test
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: ${{ matrix.job }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job:
|
||||
- build
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
node-version-file: website/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Prepare Dependencies
|
||||
cache-dependency-path: website/package-lock.json
|
||||
- working-directory: website/
|
||||
run: npm ci
|
||||
- name: Run Docusaurus
|
||||
run: npm run build -w @goauthentik/docs
|
||||
- name: build
|
||||
working-directory: website/
|
||||
run: npm run ${{ matrix.job }}
|
||||
ci-website-mark:
|
||||
if: always()
|
||||
needs:
|
||||
|
12
.github/workflows/release-publish.yml
vendored
12
.github/workflows/release-publish.yml
vendored
@ -106,14 +106,14 @@ jobs:
|
||||
go-version-file: "go.mod"
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Prepare Dependencies
|
||||
run: npm ci
|
||||
- name: Run ESBuild (Proxy)
|
||||
cache-dependency-path: web/package-lock.json
|
||||
- name: Build web
|
||||
working-directory: web/
|
||||
run: |
|
||||
npm run build-proxy -w @goauthentik/web
|
||||
npm ci
|
||||
npm run build-proxy
|
||||
- name: Build outpost
|
||||
run: |
|
||||
set -x
|
||||
|
@ -32,25 +32,15 @@ jobs:
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Prepare Dependencies
|
||||
run: npm ci
|
||||
- name: Generate TypeScript API
|
||||
- name: Generate API
|
||||
run: make gen-client-ts
|
||||
- name: Run extract
|
||||
- name: run extract
|
||||
run: |
|
||||
uv run make i18n-extract
|
||||
- name: Run UV compile
|
||||
- name: run compile
|
||||
run: |
|
||||
uv run ak compilemessages
|
||||
- name: Lint Project
|
||||
run: |
|
||||
npm run build-locales -w @goauthentik/web
|
||||
npm run lint:types
|
||||
make web-check-compile
|
||||
- name: Create Pull Request
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
|
@ -36,19 +36,12 @@ coverage
|
||||
*.mdx
|
||||
*.md
|
||||
|
||||
## Import order matters
|
||||
poly.ts
|
||||
src/locale-codes.ts
|
||||
src/locales/
|
||||
|
||||
# Storybook
|
||||
storybook-static/
|
||||
.storybook/css-import-maps*
|
||||
|
||||
# JSON Schemas
|
||||
schemas/**/*.json
|
||||
blueprints/**/*.json
|
||||
authentik/**/*.json
|
||||
lifecycle/**/*.json
|
||||
|
||||
# Locales
|
||||
web/src/locale-codes.ts
|
||||
web/src/locales/
|
||||
|
||||
# Wireit's cache
|
||||
.wireit
|
||||
|
2
.vscode/extensions.json
vendored
2
.vscode/extensions.json
vendored
@ -17,6 +17,6 @@
|
||||
"ms-python.vscode-pylance",
|
||||
"redhat.vscode-yaml",
|
||||
"Tobermory.es6-string-html",
|
||||
"unifiedjs.vscode-mdx"
|
||||
"unifiedjs.vscode-mdx",
|
||||
]
|
||||
}
|
||||
|
40
.vscode/tasks.json
vendored
40
.vscode/tasks.json
vendored
@ -4,7 +4,12 @@
|
||||
{
|
||||
"label": "authentik/core: make",
|
||||
"command": "uv",
|
||||
"args": ["run", "make", "lint-fix", "lint"],
|
||||
"args": [
|
||||
"run",
|
||||
"make",
|
||||
"lint-fix",
|
||||
"lint"
|
||||
],
|
||||
"presentation": {
|
||||
"panel": "new"
|
||||
},
|
||||
@ -13,7 +18,11 @@
|
||||
{
|
||||
"label": "authentik/core: run",
|
||||
"command": "uv",
|
||||
"args": ["run", "ak", "server"],
|
||||
"args": [
|
||||
"run",
|
||||
"ak",
|
||||
"server"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
@ -23,13 +32,17 @@
|
||||
{
|
||||
"label": "authentik/web: make",
|
||||
"command": "make",
|
||||
"args": ["web"],
|
||||
"args": [
|
||||
"web"
|
||||
],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "authentik/web: watch",
|
||||
"command": "make",
|
||||
"args": ["web-watch"],
|
||||
"args": [
|
||||
"web-watch"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
@ -39,19 +52,26 @@
|
||||
{
|
||||
"label": "authentik: install",
|
||||
"command": "make",
|
||||
"args": ["install", "-j4"],
|
||||
"args": [
|
||||
"install",
|
||||
"-j4"
|
||||
],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "authentik/website: make",
|
||||
"command": "make",
|
||||
"args": ["website"],
|
||||
"args": [
|
||||
"website"
|
||||
],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "authentik/website: watch",
|
||||
"command": "make",
|
||||
"args": ["website-watch"],
|
||||
"args": [
|
||||
"website-watch"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
@ -61,7 +81,11 @@
|
||||
{
|
||||
"label": "authentik/api: generate",
|
||||
"command": "uv",
|
||||
"args": ["run", "make", "gen"],
|
||||
"args": [
|
||||
"run",
|
||||
"make",
|
||||
"gen"
|
||||
],
|
||||
"group": "build"
|
||||
}
|
||||
]
|
||||
|
92
Dockerfile
92
Dockerfile
@ -1,41 +1,49 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Stage 1: Build Node packages
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24-slim AS node-packages
|
||||
|
||||
ARG GIT_BUILD_HASH
|
||||
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
||||
|
||||
WORKDIR /work
|
||||
|
||||
COPY ./SECURITY.md /work
|
||||
COPY ./schema.yml /work
|
||||
COPY ./docker-compose.yml /work
|
||||
COPY ./blueprints /work/blueprints/
|
||||
COPY ./package.json /work
|
||||
COPY ./package-lock.json /work
|
||||
COPY ./tsconfig.json /work
|
||||
COPY ./packages/ /work/packages/
|
||||
COPY ./web /work/web/
|
||||
COPY ./website /work/website/
|
||||
COPY ./gen-ts-api /work/gen-ts-api/
|
||||
|
||||
RUN --mount=type=cache,id=npm-node,sharing=shared,target=/root/.npm \
|
||||
npm ci
|
||||
|
||||
RUN cd ./gen-ts-api && npm link
|
||||
|
||||
RUN npm link @goauthentik/api -w @goauthentik/web
|
||||
# Stage 1: Build website
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24 AS website-builder
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
RUN npm run build -w @goauthentik/web
|
||||
RUN npm run build -w @goauthentik/web-sfe
|
||||
WORKDIR /work/website
|
||||
|
||||
RUN npm run build:api -w @goauthentik/docs
|
||||
RUN npm run build:docusaurus -w @goauthentik/docs
|
||||
RUN --mount=type=bind,target=/work/website/package.json,src=./website/package.json \
|
||||
--mount=type=bind,target=/work/website/package-lock.json,src=./website/package-lock.json \
|
||||
--mount=type=cache,id=npm-website,sharing=shared,target=/root/.npm \
|
||||
npm ci --include=dev
|
||||
|
||||
# Stage 2: Build go proxy
|
||||
COPY ./website /work/website/
|
||||
COPY ./blueprints /work/blueprints/
|
||||
COPY ./schema.yml /work/
|
||||
COPY ./SECURITY.md /work/
|
||||
|
||||
RUN npm run build-bundled
|
||||
|
||||
# Stage 2: Build webui
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24 AS web-builder
|
||||
|
||||
ARG GIT_BUILD_HASH
|
||||
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
||||
ENV NODE_ENV=production
|
||||
|
||||
WORKDIR /work/web
|
||||
|
||||
RUN --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
|
||||
--mount=type=bind,target=/work/web/package-lock.json,src=./web/package-lock.json \
|
||||
--mount=type=bind,target=/work/web/packages/sfe/package.json,src=./web/packages/sfe/package.json \
|
||||
--mount=type=bind,target=/work/web/scripts,src=./web/scripts \
|
||||
--mount=type=cache,id=npm-web,sharing=shared,target=/root/.npm \
|
||||
npm ci --include=dev
|
||||
|
||||
COPY ./package.json /work
|
||||
COPY ./web /work/web/
|
||||
COPY ./website /work/website/
|
||||
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
|
||||
|
||||
RUN npm run build && \
|
||||
npm run build:sfe
|
||||
|
||||
# Stage 3: Build go proxy
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder
|
||||
|
||||
ARG TARGETOS
|
||||
@ -60,8 +68,8 @@ RUN --mount=type=bind,target=/go/src/goauthentik.io/go.mod,src=./go.mod \
|
||||
COPY ./cmd /go/src/goauthentik.io/cmd
|
||||
COPY ./authentik/lib /go/src/goauthentik.io/authentik/lib
|
||||
COPY ./web/static.go /go/src/goauthentik.io/web/static.go
|
||||
COPY --from=node-packages /work/web/robots.txt /go/src/goauthentik.io/web/robots.txt
|
||||
COPY --from=node-packages /work/web/security.txt /go/src/goauthentik.io/web/security.txt
|
||||
COPY --from=web-builder /work/web/robots.txt /go/src/goauthentik.io/web/robots.txt
|
||||
COPY --from=web-builder /work/web/security.txt /go/src/goauthentik.io/web/security.txt
|
||||
COPY ./internal /go/src/goauthentik.io/internal
|
||||
COPY ./go.mod /go/src/goauthentik.io/go.mod
|
||||
COPY ./go.sum /go/src/goauthentik.io/go.sum
|
||||
@ -72,7 +80,7 @@ RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
|
||||
CGO_ENABLED=1 GOFIPS140=latest GOARM="${TARGETVARIANT#v}" \
|
||||
go build -o /go/authentik ./cmd/server
|
||||
|
||||
# Stage 3: MaxMind GeoIP
|
||||
# Stage 4: MaxMind GeoIP
|
||||
FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.1.0 AS geoip
|
||||
|
||||
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN"
|
||||
@ -85,9 +93,9 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
|
||||
mkdir -p /usr/share/GeoIP && \
|
||||
/bin/sh -c "GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/GEOIPUPDATE_LICENSE_KEY /usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
|
||||
|
||||
# Stage 4: Download uv
|
||||
FROM ghcr.io/astral-sh/uv:0.7.6 AS uv
|
||||
# Stage 5: Base python image
|
||||
# Stage 5: Download uv
|
||||
FROM ghcr.io/astral-sh/uv:0.7.8 AS uv
|
||||
# Stage 6: Base python image
|
||||
FROM ghcr.io/goauthentik/fips-python:3.13.3-slim-bookworm-fips AS python-base
|
||||
|
||||
ENV VENV_PATH="/ak-root/.venv" \
|
||||
@ -101,7 +109,7 @@ WORKDIR /ak-root/
|
||||
|
||||
COPY --from=uv /uv /uvx /bin/
|
||||
|
||||
# Stage 6: Python dependencies
|
||||
# Stage 7: Python dependencies
|
||||
FROM python-base AS python-deps
|
||||
|
||||
ARG TARGETARCH
|
||||
@ -136,7 +144,7 @@ RUN --mount=type=bind,target=pyproject.toml,src=pyproject.toml \
|
||||
--mount=type=cache,target=/root/.cache/uv \
|
||||
uv sync --frozen --no-install-project --no-dev
|
||||
|
||||
# Stage 7: Run
|
||||
# Stage 8: Run
|
||||
FROM python-base AS final-image
|
||||
|
||||
ARG VERSION
|
||||
@ -179,9 +187,9 @@ COPY ./lifecycle/ /lifecycle
|
||||
COPY ./authentik/sources/kerberos/krb5.conf /etc/krb5.conf
|
||||
COPY --from=go-builder /go/authentik /bin/authentik
|
||||
COPY --from=python-deps /ak-root/.venv /ak-root/.venv
|
||||
COPY --from=node-packages /work/web/dist/ /web/dist/
|
||||
COPY --from=node-packages /work/web/authentik/ /web/authentik/
|
||||
COPY --from=node-packages /work/website/build/ /website/help/
|
||||
COPY --from=web-builder /work/web/dist/ /web/dist/
|
||||
COPY --from=web-builder /work/web/authentik/ /web/authentik/
|
||||
COPY --from=website-builder /work/website/build/ /website/help/
|
||||
COPY --from=geoip /usr/share/GeoIP /geoip
|
||||
|
||||
USER 1000
|
||||
|
44
Makefile
44
Makefile
@ -1,6 +1,6 @@
|
||||
.PHONY: gen dev-reset all clean test web website
|
||||
|
||||
SHELL := /bin/bash
|
||||
SHELL := /usr/bin/env bash
|
||||
.SHELLFLAGS += ${SHELLFLAGS} -e -o pipefail
|
||||
PWD = $(shell pwd)
|
||||
UID = $(shell id -u)
|
||||
@ -73,7 +73,7 @@ core-i18n-extract:
|
||||
--ignore website \
|
||||
-l en
|
||||
|
||||
install: npm-install core-install ## Install all requires dependencies for `web`, `website` and `core`
|
||||
install: web-install website-install core-install ## Install all requires dependencies for `web`, `website` and `core`
|
||||
|
||||
dev-drop-db:
|
||||
dropdb -U ${pg_user} -h ${pg_host} ${pg_name}
|
||||
@ -146,8 +146,9 @@ gen-client-ts: gen-clean-ts ## Build and install the authentik API for Typescri
|
||||
--additional-properties=npmVersion=${NPM_VERSION} \
|
||||
--git-repo-id authentik \
|
||||
--git-user-id goauthentik
|
||||
cd ./${GEN_API_TS} && npm link
|
||||
npm link @goauthentik/api -w @goauthentik/web
|
||||
mkdir -p web/node_modules/@goauthentik/api
|
||||
cd ${PWD}/${GEN_API_TS} && npm i
|
||||
\cp -rf ${PWD}/${GEN_API_TS}/* web/node_modules/@goauthentik/api
|
||||
|
||||
gen-client-py: gen-clean-py ## Build and install the authentik API for Python
|
||||
docker run \
|
||||
@ -182,34 +183,38 @@ gen: gen-build gen-client-ts
|
||||
## Web
|
||||
#########################
|
||||
|
||||
web-build: npm-install ## Build the Authentik UI
|
||||
npm run build -w @goauthentik/web
|
||||
web-build: web-install ## Build the Authentik UI
|
||||
cd web && npm run build
|
||||
|
||||
web: web-lint-fix web-lint web-check-compile ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it
|
||||
|
||||
npm-install: ## Install the necessary libraries to build the Authentik UI
|
||||
npm ci
|
||||
web-install: ## Install the necessary libraries to build the Authentik UI
|
||||
cd web && npm ci
|
||||
|
||||
web-test: ## Run tests for the Authentik UI
|
||||
npm run test -w @goauthentik/web
|
||||
cd web && npm run test
|
||||
|
||||
web-watch: ## Build and watch the Authentik UI for changes, updating automatically
|
||||
npm run watch -w @goauthentik/web
|
||||
rm -rf web/dist/
|
||||
mkdir web/dist/
|
||||
touch web/dist/.gitkeep
|
||||
cd web && npm run watch
|
||||
|
||||
web-storybook-watch: ## Build and run the storybook documentation server
|
||||
npm run storybook -w @goauthentik/web
|
||||
cd web && npm run storybook
|
||||
|
||||
web-lint-fix:
|
||||
npm run prettier -w @goauthentik/web
|
||||
cd web && npm run prettier
|
||||
|
||||
web-lint:
|
||||
npm run lint -w @goauthentik/web
|
||||
cd web && npm run lint
|
||||
cd web && npm run lit-analyse
|
||||
|
||||
web-check-compile:
|
||||
npm run lint:types
|
||||
cd web && npm run tsc
|
||||
|
||||
web-i18n-extract:
|
||||
npm run extract-locales -w @goauthentik/web
|
||||
cd web && npm run extract-locales
|
||||
|
||||
#########################
|
||||
## Website
|
||||
@ -217,14 +222,17 @@ web-i18n-extract:
|
||||
|
||||
website: website-lint-fix website-build ## Automatically fix formatting issues in the Authentik website/docs source code, lint the code, and compile it
|
||||
|
||||
website-install:
|
||||
cd website && npm ci
|
||||
|
||||
website-lint-fix: lint-codespell
|
||||
npm run prettier --prefix website
|
||||
cd website && npm run prettier
|
||||
|
||||
website-build:
|
||||
npm run build --prefix website
|
||||
cd website && npm run build
|
||||
|
||||
website-watch: ## Build and watch the documentation website, updating automatically
|
||||
npm run watch --prefix website
|
||||
cd website && npm run watch
|
||||
|
||||
#########################
|
||||
## Docker
|
||||
|
@ -5,7 +5,6 @@ from typing import Any
|
||||
|
||||
from billiard.exceptions import SoftTimeLimitExceeded, WorkerLostError
|
||||
from celery.exceptions import CeleryError
|
||||
from channels_redis.core import ChannelFull
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation, ValidationError
|
||||
from django.db import DatabaseError, InternalError, OperationalError, ProgrammingError
|
||||
@ -127,7 +126,6 @@ def before_send(event: dict, hint: dict) -> dict | None:
|
||||
RedisError,
|
||||
ResponseError,
|
||||
# websocket errors
|
||||
ChannelFull,
|
||||
WebSocketException,
|
||||
LocalProtocolError,
|
||||
# rest_framework error
|
||||
|
@ -65,6 +65,7 @@ SHARED_APPS = [
|
||||
"pgactivity",
|
||||
"pglock",
|
||||
"channels",
|
||||
"channels_postgres",
|
||||
]
|
||||
TENANT_APPS = [
|
||||
"django.contrib.auth",
|
||||
@ -278,16 +279,6 @@ TEMPLATES = [
|
||||
|
||||
ASGI_APPLICATION = "authentik.root.asgi.application"
|
||||
|
||||
CHANNEL_LAYERS = {
|
||||
"default": {
|
||||
"BACKEND": "channels_redis.pubsub.RedisPubSubChannelLayer",
|
||||
"CONFIG": {
|
||||
"hosts": [CONFIG.get("channel.url") or redis_url(CONFIG.get("redis.db"))],
|
||||
"prefix": "authentik_channels_",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
|
||||
@ -300,6 +291,16 @@ DATABASE_ROUTERS = (
|
||||
"django_tenants.routers.TenantSyncRouter",
|
||||
)
|
||||
|
||||
CHANNEL_LAYERS = {
|
||||
"default": {
|
||||
"BACKEND": "channels_postgres.core.PostgresChannelLayer",
|
||||
"CONFIG": {
|
||||
**DATABASES["default"],
|
||||
"TIME_ZONE": None,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# Email
|
||||
# These values should never actually be used, emails are only sent from email stages, which
|
||||
# loads the config directly from CONFIG
|
||||
|
@ -97,7 +97,8 @@ class GroupsView(SCIMObjectView):
|
||||
self.logger.warning("Invalid group member", exc=exc)
|
||||
continue
|
||||
query |= Q(uuid=member.value)
|
||||
group.users.set(User.objects.filter(query))
|
||||
if query:
|
||||
group.users.set(User.objects.filter(query))
|
||||
if not connection:
|
||||
connection, _ = SCIMSourceGroup.objects.get_or_create(
|
||||
source=self.source,
|
||||
|
@ -1,10 +0,0 @@
|
||||
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
|
||||
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* ESLint configuration for authentik's monorepo.
|
||||
*/
|
||||
const ESLintConfig = createESLintPackageConfig();
|
||||
|
||||
export default ESLintConfig;
|
Binary file not shown.
Binary file not shown.
44353
package-lock.json
generated
44353
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
29
package.json
29
package.json
@ -2,33 +2,14 @@
|
||||
"name": "@goauthentik/authentik",
|
||||
"version": "2025.4.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"lint": "eslint --fix .",
|
||||
"lint-check": "eslint --max-warnings 0 .",
|
||||
"lint:types": "NODE_OPTIONS=\"--max-old-space-size=3000\" tsc -b .",
|
||||
"prettier": "prettier --cache --write -u .",
|
||||
"prettier-check": "prettier --cache --check -u ."
|
||||
},
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.11.1",
|
||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
||||
"@typescript-eslint/parser": "^8.28.0",
|
||||
"eslint": "^9.23.0",
|
||||
"eslint-plugin-lit": "^2.0.0",
|
||||
"eslint-plugin-wc": "^3.0.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-packagejson": "^2.5.13",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.29.0"
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"prettier-plugin-packagejson": "^2.5.10",
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"workspaces": [
|
||||
"./packages/*",
|
||||
"./web/packages/*",
|
||||
"./web",
|
||||
"./website"
|
||||
],
|
||||
"workspaces": [],
|
||||
"prettier": "./packages/prettier-config/index.js"
|
||||
}
|
||||
|
8
packages/docusaurus-config/package-lock.json
generated
8
packages/docusaurus-config/package-lock.json
generated
@ -3710,9 +3710,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/prettier-config": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.4.tgz",
|
||||
"integrity": "sha512-CgUVAThlJHif7ZRXUPMbR/7/YLGzkJw7YbqEcleUjjKkvID0aykrypXx04td6cG76zigspTCgJKoXimKT41E7g==",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.5.tgz",
|
||||
"integrity": "sha512-3W1uJvhzBPerDao53hSXhNzB7Ev8DbGYh+gVkuku1FaUZGBpiwD/6U3ah4sny8NoRiObGQ1geF4dhNLtlRbC/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -3722,7 +3722,7 @@
|
||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"prettier-plugin-packagejson": "^2.5.10"
|
||||
"prettier-plugin-packagejson": "^2.5.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/tsconfig": {
|
||||
|
@ -23,7 +23,6 @@ export const DefaultIgnorePatterns = [
|
||||
"**/out",
|
||||
"**/dist",
|
||||
"**/.wireit",
|
||||
"**/.venv",
|
||||
"website/build/**",
|
||||
"website/.docusaurus/**",
|
||||
"**/node_modules",
|
||||
@ -59,44 +58,16 @@ export function createESLintPackageConfig({ ignorePatterns = DefaultIgnorePatter
|
||||
|
||||
...reactConfig,
|
||||
|
||||
//#region TODO Incomplete Rules
|
||||
{
|
||||
// The following rules are disabled because the changes needed to satisfy them are
|
||||
// are large enough to warrant several follow-up PRs.
|
||||
rules: {
|
||||
// TODO: High priority, common and easy to fix.
|
||||
"eqeqeq": "off",
|
||||
// TODO: High priority, common and easy to fix.
|
||||
"no-sparse-arrays": "off",
|
||||
// TODO: High priority, common and easy to fix.
|
||||
"no-lonely-if": "off",
|
||||
// TODO: Reconsider this rule.
|
||||
"dot-notation": "off",
|
||||
// TODO: Reconsider this rule.
|
||||
"no-implicit-coercion": "off",
|
||||
// TODO: Reconsider this rule.
|
||||
"prefer-template": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/no-use-before-define": "off",
|
||||
"array-callback-return": "off",
|
||||
"block-scoped-var": "off",
|
||||
"consistent-return": "off",
|
||||
"func-names": "off",
|
||||
"guard-for-in": "off",
|
||||
"no-bitwise": "off",
|
||||
"no-div-regex": "off",
|
||||
"no-else-return": "off",
|
||||
"no-empty-function": "off",
|
||||
"no-param-reassign": "off",
|
||||
"no-throw-literal": "off",
|
||||
"no-var": "error",
|
||||
"prefer-arrow-callback": "off",
|
||||
"react/jsx-no-leaked-render": "off",
|
||||
"vars-on-top": "off",
|
||||
"no-console": "off",
|
||||
},
|
||||
files: [
|
||||
// ---
|
||||
"**/scripts/**/*",
|
||||
"**/test/**/*",
|
||||
"**/tests/**/*",
|
||||
],
|
||||
},
|
||||
|
||||
//#endregion
|
||||
);
|
||||
}
|
||||
|
@ -116,6 +116,7 @@ export const javaScriptConfig = tseslint.config({
|
||||
"no-useless-call": "error",
|
||||
"no-dupe-class-members": "error",
|
||||
"no-var": "error",
|
||||
"no-void": "error",
|
||||
"no-with": "error",
|
||||
"prefer-arrow-callback": "error",
|
||||
"prefer-const": "error",
|
||||
@ -130,6 +131,7 @@ export const javaScriptConfig = tseslint.config({
|
||||
"vars-on-top": "error",
|
||||
"yoda": ["error", "never"],
|
||||
|
||||
"no-console": ["error", { allow: ["debug", "warn", "error"] }],
|
||||
// SonarJS is not yet compatible with ESLint 9. Commenting these out
|
||||
// until it is.
|
||||
// "sonarjs/cognitive-complexity": ["off", MAX_COGNITIVE_COMPLEXITY],
|
||||
|
106
packages/eslint-config/package-lock.json
generated
106
packages/eslint-config/package-lock.json
generated
@ -308,9 +308,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/prettier-config": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.1.tgz",
|
||||
"integrity": "sha512-6N0cCG3Uw3Nt+gTxRJ/FYFi/NfuL849CrQkrx307PvEBaG66OjxFFee4bhS/si4XvLdxFdog7oQsPwYmqZeZ+w==",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.5.tgz",
|
||||
"integrity": "sha512-3W1uJvhzBPerDao53hSXhNzB7Ev8DbGYh+gVkuku1FaUZGBpiwD/6U3ah4sny8NoRiObGQ1geF4dhNLtlRbC/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -320,13 +320,13 @@
|
||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"prettier-plugin-packagejson": "^2.5.10"
|
||||
"prettier-plugin-packagejson": "^2.5.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/tsconfig": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.1.tgz",
|
||||
"integrity": "sha512-kxMDkgUHhAmQ2iIhUZJjrx/CgDb1AwvRoPtU4vrjAZu7x66+qczCjRTK+GzIGCeqB97GEpvCCjU8CThmozVFqA==",
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.4.tgz",
|
||||
"integrity": "sha512-BTGVpGh8SbCRHTULBf+2WTcw6OHJ8Ws9VtVfAMUUgcq8whbH/A7Q/n8WbkDaEeihzHUFkLk3JBenHKzEKAZWlw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -491,9 +491,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgr/core": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz",
|
||||
"integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==",
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz",
|
||||
"integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
@ -501,7 +501,7 @@
|
||||
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/unts"
|
||||
"url": "https://opencollective.com/pkgr"
|
||||
}
|
||||
},
|
||||
"node_modules/@rtsao/scc": {
|
||||
@ -2045,20 +2045,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stdin": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz",
|
||||
"integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/get-symbol-description": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
|
||||
@ -2077,9 +2063,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/git-hooks-list": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.2.0.tgz",
|
||||
"integrity": "sha512-ZHG9a1gEhUMX1TvGrLdyWb9kDopCBbTnI8z4JgRMYxsijWipgjSEYoPWqBuIB0DnRnvqlQSEeVmzpeuPm7NdFQ==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-4.1.1.tgz",
|
||||
"integrity": "sha512-cmP497iLq54AZnv4YRAEMnEyQ1eIn4tGKbmswqwmFV4GBnAqE8NLtWxxdXa++AalfgL5EBH4IxTPyquEuGY/jA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
@ -3219,15 +3205,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-packagejson": {
|
||||
"version": "2.5.10",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.10.tgz",
|
||||
"integrity": "sha512-LUxATI5YsImIVSaaLJlJ3aE6wTD+nvots18U3GuQMJpUyClChaZlQrqx3dBnbhF20OnKWZyx8EgyZypQtBDtgQ==",
|
||||
"version": "2.5.14",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.14.tgz",
|
||||
"integrity": "sha512-h+3tSpr2nVpp+YOK1MDIYtYhHVXr8/0V59UUbJpIJFaqi3w4fvUokJo6eV8W+vELrUXIZzJ+DKm5G7lYzrMcKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"sort-package-json": "2.15.1",
|
||||
"synckit": "0.9.2"
|
||||
"sort-package-json": "3.2.1",
|
||||
"synckit": "0.11.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prettier": ">= 1.16.0"
|
||||
@ -3633,30 +3619,29 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/sort-package-json": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.15.1.tgz",
|
||||
"integrity": "sha512-9x9+o8krTT2saA9liI4BljNjwAbvUnWf11Wq+i/iZt8nl2UGYnf3TH5uBydE7VALmP7AGwlfszuEeL8BDyb0YA==",
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.2.1.tgz",
|
||||
"integrity": "sha512-rTfRdb20vuoAn7LDlEtCqOkYfl2X+Qze6cLbNOzcDpbmKEhJI30tTN44d5shbKJnXsvz24QQhlCm81Bag7EOKg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"detect-indent": "^7.0.1",
|
||||
"detect-newline": "^4.0.0",
|
||||
"get-stdin": "^9.0.0",
|
||||
"git-hooks-list": "^3.0.0",
|
||||
"detect-newline": "^4.0.1",
|
||||
"git-hooks-list": "^4.0.0",
|
||||
"is-plain-obj": "^4.1.0",
|
||||
"semver": "^7.6.0",
|
||||
"semver": "^7.7.1",
|
||||
"sort-object-keys": "^1.1.3",
|
||||
"tinyglobby": "^0.2.9"
|
||||
"tinyglobby": "^0.2.12"
|
||||
},
|
||||
"bin": {
|
||||
"sort-package-json": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/sort-package-json/node_modules/semver": {
|
||||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
@ -3806,32 +3791,31 @@
|
||||
}
|
||||
},
|
||||
"node_modules/synckit": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
|
||||
"integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
|
||||
"version": "0.11.6",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.6.tgz",
|
||||
"integrity": "sha512-2pR2ubZSV64f/vqm9eLPz/KOvR9Dm+Co/5ChLgeHl0yEDRc6h5hXHoxEQH8Y5Ljycozd3p1k5TTSVdzYGkPvLw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@pkgr/core": "^0.1.0",
|
||||
"tslib": "^2.6.2"
|
||||
"@pkgr/core": "^0.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/unts"
|
||||
"url": "https://opencollective.com/synckit"
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.12",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz",
|
||||
"integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==",
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
|
||||
"integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fdir": "^6.4.3",
|
||||
"fdir": "^6.4.4",
|
||||
"picomatch": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
@ -3842,9 +3826,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby/node_modules/fdir": {
|
||||
"version": "6.4.3",
|
||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz",
|
||||
"integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==",
|
||||
"version": "6.4.4",
|
||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
|
||||
"integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
@ -3909,14 +3893,6 @@
|
||||
"strip-bom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"dev": true,
|
||||
"license": "0BSD",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
|
@ -31,8 +31,33 @@ export const AuthentikPrettierConfig = {
|
||||
trailingComma: "all",
|
||||
useTabs: false,
|
||||
vueIndentScriptAndStyle: false,
|
||||
plugins: ["prettier-plugin-packagejson", "@trivago/prettier-plugin-sort-imports"],
|
||||
importOrder: ["^(@?)lit(.*)$", "\\.css$", "^@goauthentik/api$", "^[./]"],
|
||||
plugins: [
|
||||
// ---
|
||||
"prettier-plugin-packagejson",
|
||||
"@trivago/prettier-plugin-sort-imports",
|
||||
],
|
||||
importOrder: [
|
||||
// ---
|
||||
|
||||
"^(@goauthentik/|#)common.+",
|
||||
"^(@goauthentik/|#)elements.+",
|
||||
"^(@goauthentik/|#)components.+",
|
||||
"^(@goauthentik/|#)user.+",
|
||||
"^(@goauthentik/|#)admin.+",
|
||||
"^(@goauthentik/|#)flow.+",
|
||||
"^(@goauthentik/|#)flow.+",
|
||||
|
||||
"^#.+",
|
||||
"^@goauthentik.+",
|
||||
|
||||
"<THIRD_PARTY_MODULES>",
|
||||
|
||||
"^(@?)lit(.*)$",
|
||||
"\\.css$",
|
||||
"^@goauthentik/api$",
|
||||
"^[./]",
|
||||
],
|
||||
importOrderSideEffects: false,
|
||||
importOrderSeparation: true,
|
||||
importOrderSortSpecifiers: true,
|
||||
importOrderParserPlugins: ["typescript", "jsx", "classProperties", "decorators-legacy"],
|
||||
|
10
packages/prettier-config/package-lock.json
generated
10
packages/prettier-config/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "1.0.4",
|
||||
"version": "2.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "1.0.4",
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@goauthentik/tsconfig": "^1.0.1",
|
||||
@ -143,9 +143,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/tsconfig": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.1.tgz",
|
||||
"integrity": "sha512-kxMDkgUHhAmQ2iIhUZJjrx/CgDb1AwvRoPtU4vrjAZu7x66+qczCjRTK+GzIGCeqB97GEpvCCjU8CThmozVFqA==",
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.4.tgz",
|
||||
"integrity": "sha512-BTGVpGh8SbCRHTULBf+2WTcw6OHJ8Ws9VtVfAMUUgcq8whbH/A7Q/n8WbkDaEeihzHUFkLk3JBenHKzEKAZWlw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "1.0.5",
|
||||
"version": "2.0.0",
|
||||
"description": "authentik's Prettier config",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
@ -2,19 +2,19 @@
|
||||
"name": "@goauthentik/tsconfig",
|
||||
"version": "1.0.4",
|
||||
"description": "authentik's base TypeScript configuration.",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": ""
|
||||
},
|
||||
"main": "tsconfig.json",
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">=20.11"
|
||||
},
|
||||
"keywords": [
|
||||
"tsconfig",
|
||||
"typescript"
|
||||
],
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": ""
|
||||
},
|
||||
"type": "module",
|
||||
"main": "tsconfig.json",
|
||||
"engines": {
|
||||
"node": ">=20.11"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
@ -1,22 +1,20 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Stage 1: Build web
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24-slim AS web-builder
|
||||
|
||||
WORKDIR /work
|
||||
|
||||
COPY ./package.json /work
|
||||
COPY ./package-lock.json /work
|
||||
COPY ./tsconfig.json /work
|
||||
COPY ./packages/ /work/packages/
|
||||
COPY ./web /work/web/
|
||||
|
||||
RUN --mount=type=cache,id=npm-node,sharing=shared,target=/root/.npm \
|
||||
npm ci
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24 AS web-builder
|
||||
|
||||
ENV NODE_ENV=production
|
||||
WORKDIR /static
|
||||
|
||||
RUN npm run build-proxy -w @goauthentik/web
|
||||
COPY package.json /
|
||||
RUN --mount=type=bind,target=/static/package.json,src=./web/package.json \
|
||||
--mount=type=bind,target=/static/package-lock.json,src=./web/package-lock.json \
|
||||
--mount=type=bind,target=/static/scripts,src=./web/scripts \
|
||||
--mount=type=cache,target=/root/.npm \
|
||||
npm ci --include=dev
|
||||
|
||||
COPY web .
|
||||
RUN npm run build-proxy
|
||||
|
||||
# Stage 2: Build
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS builder
|
||||
@ -67,10 +65,10 @@ RUN apt-get update && \
|
||||
rm -rf /tmp/* /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=builder /go/proxy /
|
||||
COPY --from=web-builder /work/web/robots.txt /web/robots.txt
|
||||
COPY --from=web-builder /work/web/security.txt /web/security.txt
|
||||
COPY --from=web-builder /work/web/dist/ /web/dist/
|
||||
COPY --from=web-builder /work/web/authentik/ /web/authentik/
|
||||
COPY --from=web-builder /static/robots.txt /web/robots.txt
|
||||
COPY --from=web-builder /static/security.txt /web/security.txt
|
||||
COPY --from=web-builder /static/dist/ /web/dist/
|
||||
COPY --from=web-builder /static/authentik/ /web/authentik/
|
||||
|
||||
HEALTHCHECK --interval=5s --retries=20 --start-period=3s CMD [ "/proxy", "healthcheck" ]
|
||||
|
||||
|
@ -8,8 +8,8 @@ dependencies = [
|
||||
"argon2-cffi==23.1.0",
|
||||
"celery==5.5.2",
|
||||
"channels==4.2.2",
|
||||
"channels-redis==4.2.1",
|
||||
"cryptography==44.0.3",
|
||||
"channels-postgres==1.1.2",
|
||||
"cryptography==45.0.3",
|
||||
"dacite==1.9.2",
|
||||
"deepmerge==2.0",
|
||||
"defusedxml==0.7.1",
|
||||
@ -23,7 +23,7 @@ dependencies = [
|
||||
"django-prometheus==2.3.1",
|
||||
"django-redis==5.4.0",
|
||||
"django-storages[s3]==1.14.6",
|
||||
"django-tenants==3.7.0",
|
||||
"django-tenants==3.8.0",
|
||||
"djangorestframework==3.16.0",
|
||||
"djangorestframework-guardian==0.3.0",
|
||||
"docker==7.1.0",
|
||||
@ -35,7 +35,7 @@ dependencies = [
|
||||
"flower==2.0.1",
|
||||
"geoip2==5.1.0",
|
||||
"geopy==2.4.1",
|
||||
"google-api-python-client==2.169.0",
|
||||
"google-api-python-client==2.170.0",
|
||||
"gssapi==1.9.0",
|
||||
"gunicorn==23.0.0",
|
||||
"jsonpatch==1.33",
|
||||
@ -48,7 +48,7 @@ dependencies = [
|
||||
"packaging==25.0",
|
||||
"paramiko==3.5.1",
|
||||
"psycopg[c,pool]==3.2.9",
|
||||
"pydantic==2.11.4",
|
||||
"pydantic==2.11.5",
|
||||
"pydantic-scim==0.0.8",
|
||||
"pyjwt==2.10.1",
|
||||
"pyrad==2.4",
|
||||
@ -114,7 +114,6 @@ no-binary-package = [
|
||||
]
|
||||
|
||||
[tool.uv.sources]
|
||||
django-tenants = { git = "https://github.com/goauthentik/django-tenants.git", branch = "authentik-fixes" }
|
||||
opencontainers = { git = "https://github.com/vsoch/oci-python", rev = "ceb4fcc090851717a3069d78e85ceb1e86c2740c" }
|
||||
djangorestframework = { git = "https://github.com/goauthentik/django-rest-framework", rev = "896722bab969fabc74a08b827da59409cf9f1a4e" }
|
||||
|
||||
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist/esm",
|
||||
},
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"isolatedModules": true,
|
||||
"incremental": true,
|
||||
"baseUrl": ".",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"newLine": "lf",
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"outDir": "dist",
|
||||
"skipDefaultLibCheck": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
},
|
||||
"exclude": ["node_modules", "./out/**/*", "./dist/**/*"],
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
set -e -x -o pipefail
|
||||
hash="$(git rev-parse HEAD || openssl rand -base64 36 | sha256sum)"
|
||||
|
||||
|
@ -6,7 +6,7 @@ services:
|
||||
network_mode: host
|
||||
restart: always
|
||||
mailpit:
|
||||
image: docker.io/axllent/mailpit:v1.25.0
|
||||
image: docker.io/axllent/mailpit:v1.25.1
|
||||
ports:
|
||||
- 1025:1025
|
||||
- 8025:8025
|
||||
|
@ -23,8 +23,6 @@
|
||||
"files": [],
|
||||
"references": [
|
||||
// Note that references are in the order we want them to be built.
|
||||
{
|
||||
"path": "./web"
|
||||
}
|
||||
// TODO: Left blank until TypeScript workspaces are complete.
|
||||
]
|
||||
}
|
||||
|
97
uv.lock
generated
97
uv.lock
generated
@ -170,7 +170,7 @@ dependencies = [
|
||||
{ name = "argon2-cffi" },
|
||||
{ name = "celery" },
|
||||
{ name = "channels" },
|
||||
{ name = "channels-redis" },
|
||||
{ name = "channels-postgres" },
|
||||
{ name = "cryptography" },
|
||||
{ name = "dacite" },
|
||||
{ name = "deepmerge" },
|
||||
@ -268,8 +268,8 @@ requires-dist = [
|
||||
{ name = "argon2-cffi", specifier = "==23.1.0" },
|
||||
{ name = "celery", specifier = "==5.5.2" },
|
||||
{ name = "channels", specifier = "==4.2.2" },
|
||||
{ name = "channels-redis", specifier = "==4.2.1" },
|
||||
{ name = "cryptography", specifier = "==44.0.3" },
|
||||
{ name = "channels-postgres", specifier = "==1.1.2" },
|
||||
{ name = "cryptography", specifier = "==45.0.3" },
|
||||
{ name = "dacite", specifier = "==1.9.2" },
|
||||
{ name = "deepmerge", specifier = "==2.0" },
|
||||
{ name = "defusedxml", specifier = "==0.7.1" },
|
||||
@ -283,7 +283,7 @@ requires-dist = [
|
||||
{ name = "django-prometheus", specifier = "==2.3.1" },
|
||||
{ name = "django-redis", specifier = "==5.4.0" },
|
||||
{ name = "django-storages", extras = ["s3"], specifier = "==1.14.6" },
|
||||
{ name = "django-tenants", git = "https://github.com/goauthentik/django-tenants.git?branch=authentik-fixes" },
|
||||
{ name = "django-tenants", specifier = "==3.8.0" },
|
||||
{ name = "djangorestframework", git = "https://github.com/goauthentik/django-rest-framework?rev=896722bab969fabc74a08b827da59409cf9f1a4e" },
|
||||
{ name = "djangorestframework-guardian", specifier = "==0.3.0" },
|
||||
{ name = "docker", specifier = "==7.1.0" },
|
||||
@ -295,7 +295,7 @@ requires-dist = [
|
||||
{ name = "flower", specifier = "==2.0.1" },
|
||||
{ name = "geoip2", specifier = "==5.1.0" },
|
||||
{ name = "geopy", specifier = "==2.4.1" },
|
||||
{ name = "google-api-python-client", specifier = "==2.169.0" },
|
||||
{ name = "google-api-python-client", specifier = "==2.170.0" },
|
||||
{ name = "gssapi", specifier = "==1.9.0" },
|
||||
{ name = "gunicorn", specifier = "==23.0.0" },
|
||||
{ name = "jsonpatch", specifier = "==1.33" },
|
||||
@ -308,7 +308,7 @@ requires-dist = [
|
||||
{ name = "packaging", specifier = "==25.0" },
|
||||
{ name = "paramiko", specifier = "==3.5.1" },
|
||||
{ name = "psycopg", extras = ["c", "pool"], specifier = "==3.2.9" },
|
||||
{ name = "pydantic", specifier = "==2.11.4" },
|
||||
{ name = "pydantic", specifier = "==2.11.5" },
|
||||
{ name = "pydantic-scim", specifier = "==0.0.8" },
|
||||
{ name = "pyjwt", specifier = "==2.10.1" },
|
||||
{ name = "pyrad", specifier = "==2.4" },
|
||||
@ -712,18 +712,18 @@ daphne = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "channels-redis"
|
||||
version = "4.2.1"
|
||||
name = "channels-postgres"
|
||||
version = "1.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "asgiref" },
|
||||
{ name = "channels" },
|
||||
{ name = "msgpack" },
|
||||
{ name = "redis" },
|
||||
{ name = "psycopg", extra = ["pool"] },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c7/6d/c379c9feea4522cbdb4eba9b3d23a6270ba8cbd94e847b21834d898109d6/channels_redis-4.2.1.tar.gz", hash = "sha256:8375e81493e684792efe6e6eca60ef3d7782ef76c6664057d2e5c31e80d636dd", size = 31152, upload-time = "2024-11-15T12:58:49.836Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f5/21/c74be89ec2f93fa832f9c5b47f08c73e5e07279aab176a1f7ef4a240722d/channels_postgres-1.1.2.tar.gz", hash = "sha256:bfdf580ba65aab0d5e944d38ddd807d3521939153b786b53d6f932b6f3defd8e", size = 19696, upload-time = "2025-04-20T16:09:01.83Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/aa/981d08ae9627c3b9d8dd150f0fe644122a351abc1f47bcf53d2bfff80d91/channels_redis-4.2.1-py3-none-any.whl", hash = "sha256:2ca33105b3a04b5a327a9c47dd762b546f30b76a0cd3f3f593a23d91d346b6f4", size = 20487, upload-time = "2024-11-15T12:58:47.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/0b/1ec2c7357ebff7ff457f39d51ccb74be56ac796595dfc228658ba23974a1/channels_postgres-1.1.2-py3-none-any.whl", hash = "sha256:301e1980f23e325e289ac93265baf54ceae289c19f1893d1b55e40fe73149f67", size = 16176, upload-time = "2025-04-20T16:09:00.383Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -869,37 +869,37 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "44.0.3"
|
||||
version = "45.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/53/d6/1411ab4d6108ab167d06254c5be517681f1e331f90edf1379895bcb87020/cryptography-44.0.3.tar.gz", hash = "sha256:fe19d8bc5536a91a24a8133328880a41831b6c5df54599a8417b62fe015d3053", size = 711096, upload-time = "2025-05-02T19:36:04.667Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/13/1f/9fa001e74a1993a9cadd2333bb889e50c66327b8594ac538ab8a04f915b7/cryptography-45.0.3.tar.gz", hash = "sha256:ec21313dd335c51d7877baf2972569f40a4291b76a0ce51391523ae358d05899", size = 744738, upload-time = "2025-05-25T14:17:24.777Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/08/53/c776d80e9d26441bb3868457909b4e74dd9ccabd182e10b2b0ae7a07e265/cryptography-44.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:962bc30480a08d133e631e8dfd4783ab71cc9e33d5d7c1e192f0b7c06397bb88", size = 6670281, upload-time = "2025-05-02T19:34:50.665Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/06/af2cf8d56ef87c77319e9086601bef621bedf40f6f59069e1b6d1ec498c5/cryptography-44.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffc61e8f3bf5b60346d89cd3d37231019c17a081208dfbbd6e1605ba03fa137", size = 3959305, upload-time = "2025-05-02T19:34:53.042Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/01/80de3bec64627207d030f47bf3536889efee8913cd363e78ca9a09b13c8e/cryptography-44.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58968d331425a6f9eedcee087f77fd3c927c88f55368f43ff7e0a19891f2642c", size = 4171040, upload-time = "2025-05-02T19:34:54.675Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/48/bb16b7541d207a19d9ae8b541c70037a05e473ddc72ccb1386524d4f023c/cryptography-44.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e28d62e59a4dbd1d22e747f57d4f00c459af22181f0b2f787ea83f5a876d7c76", size = 3963411, upload-time = "2025-05-02T19:34:56.61Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/b2/7d31f2af5591d217d71d37d044ef5412945a8a8e98d5a2a8ae4fd9cd4489/cryptography-44.0.3-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af653022a0c25ef2e3ffb2c673a50e5a0d02fecc41608f4954176f1933b12359", size = 3689263, upload-time = "2025-05-02T19:34:58.591Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/50/c0dfb9d87ae88ccc01aad8eb93e23cfbcea6a6a106a9b63a7b14c1f93c75/cryptography-44.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:157f1f3b8d941c2bd8f3ffee0af9b049c9665c39d3da9db2dc338feca5e98a43", size = 4196198, upload-time = "2025-05-02T19:35:00.988Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/c9/55c6b8794a74da652690c898cb43906310a3e4e4f6ee0b5f8b3b3e70c441/cryptography-44.0.3-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:c6cd67722619e4d55fdb42ead64ed8843d64638e9c07f4011163e46bc512cf01", size = 3966502, upload-time = "2025-05-02T19:35:03.091Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/f7/7cb5488c682ca59a02a32ec5f975074084db4c983f849d47b7b67cc8697a/cryptography-44.0.3-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b424563394c369a804ecbee9b06dfb34997f19d00b3518e39f83a5642618397d", size = 4196173, upload-time = "2025-05-02T19:35:05.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/0b/2f789a8403ae089b0b121f8f54f4a3e5228df756e2146efdf4a09a3d5083/cryptography-44.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c91fc8e8fd78af553f98bc7f2a1d8db977334e4eea302a4bfd75b9461c2d8904", size = 4087713, upload-time = "2025-05-02T19:35:07.187Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/aa/330c13655f1af398fc154089295cf259252f0ba5df93b4bc9d9c7d7f843e/cryptography-44.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:25cd194c39fa5a0aa4169125ee27d1172097857b27109a45fadc59653ec06f44", size = 4299064, upload-time = "2025-05-02T19:35:08.879Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/a8/8c540a421b44fd267a7d58a1fd5f072a552d72204a3f08194f98889de76d/cryptography-44.0.3-cp37-abi3-win32.whl", hash = "sha256:3be3f649d91cb182c3a6bd336de8b61a0a71965bd13d1a04a0e15b39c3d5809d", size = 2773887, upload-time = "2025-05-02T19:35:10.41Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/0d/c4b1657c39ead18d76bbd122da86bd95bdc4095413460d09544000a17d56/cryptography-44.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:3883076d5c4cc56dbef0b898a74eb6992fdac29a7b9013870b34efe4ddb39a0d", size = 3209737, upload-time = "2025-05-02T19:35:12.12Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/a3/ad08e0bcc34ad436013458d7528e83ac29910943cea42ad7dd4141a27bbb/cryptography-44.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:5639c2b16764c6f76eedf722dbad9a0914960d3489c0cc38694ddf9464f1bb2f", size = 6673501, upload-time = "2025-05-02T19:35:13.775Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/f0/7491d44bba8d28b464a5bc8cc709f25a51e3eac54c0a4444cf2473a57c37/cryptography-44.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ffef566ac88f75967d7abd852ed5f182da252d23fac11b4766da3957766759", size = 3960307, upload-time = "2025-05-02T19:35:15.917Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/c8/e5c5d0e1364d3346a5747cdcd7ecbb23ca87e6dea4f942a44e88be349f06/cryptography-44.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:192ed30fac1728f7587c6f4613c29c584abdc565d7417c13904708db10206645", size = 4170876, upload-time = "2025-05-02T19:35:18.138Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/96/025cb26fc351d8c7d3a1c44e20cf9a01e9f7cf740353c9c7a17072e4b264/cryptography-44.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7d5fe7195c27c32a64955740b949070f21cba664604291c298518d2e255931d2", size = 3964127, upload-time = "2025-05-02T19:35:19.864Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/44/eb6522db7d9f84e8833ba3bf63313f8e257729cf3a8917379473fcfd6601/cryptography-44.0.3-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3f07943aa4d7dad689e3bb1638ddc4944cc5e0921e3c227486daae0e31a05e54", size = 3689164, upload-time = "2025-05-02T19:35:21.449Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/fb/d61a4defd0d6cee20b1b8a1ea8f5e25007e26aeb413ca53835f0cae2bcd1/cryptography-44.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cb90f60e03d563ca2445099edf605c16ed1d5b15182d21831f58460c48bffb93", size = 4198081, upload-time = "2025-05-02T19:35:23.187Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/50/457f6911d36432a8811c3ab8bd5a6090e8d18ce655c22820994913dd06ea/cryptography-44.0.3-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ab0b005721cc0039e885ac3503825661bd9810b15d4f374e473f8c89b7d5460c", size = 3967716, upload-time = "2025-05-02T19:35:25.426Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/6e/dca39d553075980ccb631955c47b93d87d27f3596da8d48b1ae81463d915/cryptography-44.0.3-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:3bb0847e6363c037df8f6ede57d88eaf3410ca2267fb12275370a76f85786a6f", size = 4197398, upload-time = "2025-05-02T19:35:27.678Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/9d/d1f2fe681eabc682067c66a74addd46c887ebacf39038ba01f8860338d3d/cryptography-44.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b0cc66c74c797e1db750aaa842ad5b8b78e14805a9b5d1348dc603612d3e3ff5", size = 4087900, upload-time = "2025-05-02T19:35:29.312Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/f5/3599e48c5464580b73b236aafb20973b953cd2e7b44c7c2533de1d888446/cryptography-44.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6866df152b581f9429020320e5eb9794c8780e90f7ccb021940d7f50ee00ae0b", size = 4301067, upload-time = "2025-05-02T19:35:31.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/6c/d2c48c8137eb39d0c193274db5c04a75dab20d2f7c3f81a7dcc3a8897701/cryptography-44.0.3-cp39-abi3-win32.whl", hash = "sha256:c138abae3a12a94c75c10499f1cbae81294a6f983b3af066390adee73f433028", size = 2775467, upload-time = "2025-05-02T19:35:33.805Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/ad/51f212198681ea7b0deaaf8846ee10af99fba4e894f67b353524eab2bbe5/cryptography-44.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:5d186f32e52e66994dce4f766884bcb9c68b8da62d61d9d215bfe5fb56d21334", size = 3210375, upload-time = "2025-05-02T19:35:35.369Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/b2/2345dc595998caa6f68adf84e8f8b50d18e9fc4638d32b22ea8daedd4b7a/cryptography-45.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:7573d9eebaeceeb55285205dbbb8753ac1e962af3d9640791d12b36864065e71", size = 7056239, upload-time = "2025-05-25T14:16:12.22Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/3d/ac361649a0bfffc105e2298b720d8b862330a767dab27c06adc2ddbef96a/cryptography-45.0.3-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d377dde61c5d67eb4311eace661c3efda46c62113ff56bf05e2d679e02aebb5b", size = 4205541, upload-time = "2025-05-25T14:16:14.333Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/3e/c02a043750494d5c445f769e9c9f67e550d65060e0bfce52d91c1362693d/cryptography-45.0.3-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fae1e637f527750811588e4582988932c222f8251f7b7ea93739acb624e1487f", size = 4433275, upload-time = "2025-05-25T14:16:16.421Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/7a/9af0bfd48784e80eef3eb6fd6fde96fe706b4fc156751ce1b2b965dada70/cryptography-45.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ca932e11218bcc9ef812aa497cdf669484870ecbcf2d99b765d6c27a86000942", size = 4209173, upload-time = "2025-05-25T14:16:18.163Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/5f/d6f8753c8708912df52e67969e80ef70b8e8897306cd9eb8b98201f8c184/cryptography-45.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af3f92b1dc25621f5fad065288a44ac790c5798e986a34d393ab27d2b27fcff9", size = 3898150, upload-time = "2025-05-25T14:16:20.34Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/50/f256ab79c671fb066e47336706dc398c3b1e125f952e07d54ce82cf4011a/cryptography-45.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2f8f8f0b73b885ddd7f3d8c2b2234a7d3ba49002b0223f58cfde1bedd9563c56", size = 4466473, upload-time = "2025-05-25T14:16:22.605Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/e7/312428336bb2df0848d0768ab5a062e11a32d18139447a76dfc19ada8eed/cryptography-45.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9cc80ce69032ffa528b5e16d217fa4d8d4bb7d6ba8659c1b4d74a1b0f4235fca", size = 4211890, upload-time = "2025-05-25T14:16:24.738Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/53/8a130e22c1e432b3c14896ec5eb7ac01fb53c6737e1d705df7e0efb647c6/cryptography-45.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c824c9281cb628015bfc3c59335163d4ca0540d49de4582d6c2637312907e4b1", size = 4466300, upload-time = "2025-05-25T14:16:26.768Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/75/6bb6579688ef805fd16a053005fce93944cdade465fc92ef32bbc5c40681/cryptography-45.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5833bb4355cb377ebd880457663a972cd044e7f49585aee39245c0d592904578", size = 4332483, upload-time = "2025-05-25T14:16:28.316Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/11/2538f4e1ce05c6c4f81f43c1ef2bd6de7ae5e24ee284460ff6c77e42ca77/cryptography-45.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9bb5bf55dcb69f7067d80354d0a348368da907345a2c448b0babc4215ccd3497", size = 4573714, upload-time = "2025-05-25T14:16:30.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/bb/e86e9cf07f73a98d84a4084e8fd420b0e82330a901d9cac8149f994c3417/cryptography-45.0.3-cp311-abi3-win32.whl", hash = "sha256:3ad69eeb92a9de9421e1f6685e85a10fbcfb75c833b42cc9bc2ba9fb00da4710", size = 2934752, upload-time = "2025-05-25T14:16:32.204Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/75/063bc9ddc3d1c73e959054f1fc091b79572e716ef74d6caaa56e945b4af9/cryptography-45.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:97787952246a77d77934d41b62fb1b6f3581d83f71b44796a4158d93b8f5c490", size = 3412465, upload-time = "2025-05-25T14:16:33.888Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/9b/04ead6015229a9396890d7654ee35ef630860fb42dc9ff9ec27f72157952/cryptography-45.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:c92519d242703b675ccefd0f0562eb45e74d438e001f8ab52d628e885751fb06", size = 7031892, upload-time = "2025-05-25T14:16:36.214Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/c7/c7d05d0e133a09fc677b8a87953815c522697bdf025e5cac13ba419e7240/cryptography-45.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5edcb90da1843df85292ef3a313513766a78fbbb83f584a5a58fb001a5a9d57", size = 4196181, upload-time = "2025-05-25T14:16:37.934Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/7a/6ad3aa796b18a683657cef930a986fac0045417e2dc428fd336cfc45ba52/cryptography-45.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38deed72285c7ed699864f964a3f4cf11ab3fb38e8d39cfcd96710cd2b5bb716", size = 4423370, upload-time = "2025-05-25T14:16:39.502Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/58/ec1461bfcb393525f597ac6a10a63938d18775b7803324072974b41a926b/cryptography-45.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5555365a50efe1f486eed6ac7062c33b97ccef409f5970a0b6f205a7cfab59c8", size = 4197839, upload-time = "2025-05-25T14:16:41.322Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/3d/5185b117c32ad4f40846f579369a80e710d6146c2baa8ce09d01612750db/cryptography-45.0.3-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9e4253ed8f5948a3589b3caee7ad9a5bf218ffd16869c516535325fece163dcc", size = 3886324, upload-time = "2025-05-25T14:16:43.041Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/85/caba91a57d291a2ad46e74016d1f83ac294f08128b26e2a81e9b4f2d2555/cryptography-45.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cfd84777b4b6684955ce86156cfb5e08d75e80dc2585e10d69e47f014f0a5342", size = 4450447, upload-time = "2025-05-25T14:16:44.759Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/d1/164e3c9d559133a38279215c712b8ba38e77735d3412f37711b9f8f6f7e0/cryptography-45.0.3-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:a2b56de3417fd5f48773ad8e91abaa700b678dc7fe1e0c757e1ae340779acf7b", size = 4200576, upload-time = "2025-05-25T14:16:46.438Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/7a/e002d5ce624ed46dfc32abe1deff32190f3ac47ede911789ee936f5a4255/cryptography-45.0.3-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:57a6500d459e8035e813bd8b51b671977fb149a8c95ed814989da682314d0782", size = 4450308, upload-time = "2025-05-25T14:16:48.228Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/ad/3fbff9c28cf09b0a71e98af57d74f3662dea4a174b12acc493de00ea3f28/cryptography-45.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f22af3c78abfbc7cbcdf2c55d23c3e022e1a462ee2481011d518c7fb9c9f3d65", size = 4325125, upload-time = "2025-05-25T14:16:49.844Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/b4/51417d0cc01802304c1984d76e9592f15e4801abd44ef7ba657060520bf0/cryptography-45.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:232954730c362638544758a8160c4ee1b832dc011d2c41a306ad8f7cccc5bb0b", size = 4560038, upload-time = "2025-05-25T14:16:51.398Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/38/d572f6482d45789a7202fb87d052deb7a7b136bf17473ebff33536727a2c/cryptography-45.0.3-cp37-abi3-win32.whl", hash = "sha256:cb6ab89421bc90e0422aca911c69044c2912fc3debb19bb3c1bfe28ee3dff6ab", size = 2924070, upload-time = "2025-05-25T14:16:53.472Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/5a/61f39c0ff4443651cc64e626fa97ad3099249152039952be8f344d6b0c86/cryptography-45.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:d54ae41e6bd70ea23707843021c778f151ca258081586f0cfa31d936ae43d1b2", size = 3395005, upload-time = "2025-05-25T14:16:55.134Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1118,11 +1118,12 @@ s3 = [
|
||||
|
||||
[[package]]
|
||||
name = "django-tenants"
|
||||
version = "3.7.0"
|
||||
source = { git = "https://github.com/goauthentik/django-tenants.git?branch=authentik-fixes#156e53a6f5902d74b73dd9d0192fffaa2587a740" }
|
||||
version = "3.8.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "django" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/7b/22e3bb79d48e5a4fdcacdcdc27bbc5c2523a2b7892b440bfe229f313d823/django_tenants-3.8.0.tar.gz", hash = "sha256:07d009d5d01be2d65c3f5ddbf323d58d1228838fc1a64fded15c8e5c6f41cf8f", size = 154307, upload-time = "2025-05-23T16:07:24.307Z" }
|
||||
|
||||
[[package]]
|
||||
name = "djangorestframework"
|
||||
@ -1396,7 +1397,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "google-api-python-client"
|
||||
version = "2.169.0"
|
||||
version = "2.170.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "google-api-core" },
|
||||
@ -1405,9 +1406,9 @@ dependencies = [
|
||||
{ name = "httplib2" },
|
||||
{ name = "uritemplate" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4f/e6/787c24738fc7c99de9289abe60bd64591800ae1cdf60db7b87e0e6ef9cdd/google_api_python_client-2.169.0.tar.gz", hash = "sha256:0585bb97bd5f5bf3ed8d4bf624593e4c5a14d06c811d1952b07a1f94b4d12c51", size = 12811341, upload-time = "2025-04-29T15:46:05.603Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/db/86/1bd09aea2664a46bc65713cb7876381ec8949a4b1e71be97dfc359c79781/google_api_python_client-2.170.0.tar.gz", hash = "sha256:75f3a1856f11418ea3723214e0abc59d9b217fd7ed43dcf743aab7f06ab9e2b1", size = 12971933, upload-time = "2025-05-22T20:39:52.802Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/bd/6aa93c38756cc9fc63262e0dc3d3f1ff7241ce6f413a25ad6e4a9c98b473/google_api_python_client-2.169.0-py3-none-any.whl", hash = "sha256:dae3e882dc0e6f28e60cf09c1f13fedfd881db84f824dd418aa9e44def2fe00d", size = 13323742, upload-time = "2025-04-29T15:46:02.521Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/ab/928fb4551ce9c791de96b0681924d46de9a5b50931394fd19850383a08a1/google_api_python_client-2.170.0-py3-none-any.whl", hash = "sha256:7bf518a0527ad23322f070fa69f4f24053170d5c766821dc970ff0571ec22748", size = 13490660, upload-time = "2025-05-22T20:39:49.834Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2473,7 +2474,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.11.4"
|
||||
version = "2.11.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
@ -2481,9 +2482,9 @@ dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/77/ab/5250d56ad03884ab5efd07f734203943c8a8ab40d551e208af81d0257bf2/pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d", size = 786540, upload-time = "2025-04-29T20:38:55.02Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f0/86/8ce9040065e8f924d642c58e4a344e33163a07f6b57f836d0d734e0ad3fb/pydantic-2.11.5.tar.gz", hash = "sha256:7f853db3d0ce78ce8bbb148c401c2cdd6431b3473c0cdff2755c7690952a7b7a", size = 787102, upload-time = "2025-05-22T21:18:08.761Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/12/46b65f3534d099349e38ef6ec98b1a5a81f42536d17e0ba382c28c67ba67/pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb", size = 443900, upload-time = "2025-04-29T20:38:52.724Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/69/831ed22b38ff9b4b64b66569f0e5b7b97cf3638346eb95a2147fdb49ad5f/pydantic-2.11.5-py3-none-any.whl", hash = "sha256:f9c26ba06f9747749ca1e5c94d6a85cb84254577553c8785576fd38fa64dc0f7", size = 444229, upload-time = "2025-05-22T21:18:06.329Z" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
@ -2576,14 +2577,14 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pyopenssl"
|
||||
version = "25.0.0"
|
||||
version = "25.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cryptography" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9f/26/e25b4a374b4639e0c235527bbe31c0524f26eda701d79456a7e1877f4cc5/pyopenssl-25.0.0.tar.gz", hash = "sha256:cd2cef799efa3936bb08e8ccb9433a575722b9dd986023f1cabc4ae64e9dac16", size = 179573, upload-time = "2025-01-12T17:22:48.897Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/04/8c/cd89ad05804f8e3c17dea8f178c3f40eeab5694c30e0c9f5bcd49f576fc3/pyopenssl-25.1.0.tar.gz", hash = "sha256:8d031884482e0c67ee92bf9a4d8cceb08d92aba7136432ffb0703c5280fc205b", size = 179937, upload-time = "2025-05-17T16:28:31.31Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/d7/eb76863d2060dcbe7c7e6cccfd95ac02ea0b9acc37745a0d99ff6457aefb/pyOpenSSL-25.0.0-py3-none-any.whl", hash = "sha256:424c247065e46e76a37411b9ab1782541c23bb658bf003772c3405fbaa128e90", size = 56453, upload-time = "2025-01-12T17:22:43.44Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/28/2659c02301b9500751f8d42f9a6632e1508aa5120de5e43042b8b30f8d5d/pyopenssl-25.1.0-py3-none-any.whl", hash = "sha256:2b11f239acc47ac2e5aca04fd7fa829800aeee22a2eb30d744572a157bd8a1ab", size = 56771, upload-time = "2025-05-17T16:28:29.197Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4,30 +4,27 @@
|
||||
* @import {
|
||||
* OnLoadArgs,
|
||||
* OnLoadResult,
|
||||
* OnResolveArgs,
|
||||
* OnResolveResult,
|
||||
* Plugin,
|
||||
* PluginBuild
|
||||
* } from "esbuild"
|
||||
*/
|
||||
import { MonoRepoRoot } from "@goauthentik/core/paths/node";
|
||||
import * as fs from "node:fs/promises";
|
||||
import * as path from "node:path";
|
||||
|
||||
/**
|
||||
* @typedef {Omit<OnLoadArgs, 'pluginData'> & LoadDataFields} LoadData
|
||||
* Data passed to `onload`.
|
||||
* @typedef {Omit<OnLoadArgs, 'pluginData'> & LoadDataFields} LoadData Data passed to `onload`.
|
||||
*
|
||||
* @typedef LoadDataFields
|
||||
* Extra fields given in `data` to `onload`.
|
||||
* @property {PluginData | null | undefined} [pluginData]
|
||||
* Plugin data.
|
||||
* @typedef LoadDataFields Extra fields given in `data` to `onload`.
|
||||
* @property {PluginData | null | undefined} [pluginData] Plugin data.
|
||||
*
|
||||
*
|
||||
* @typedef PluginData
|
||||
* Extra data passed.
|
||||
* @property {Buffer | string | null | undefined} [contents]
|
||||
* File contents.
|
||||
* @typedef PluginData Extra data passed.
|
||||
* @property {Buffer | string | null | undefined} [contents] File contents.
|
||||
*/
|
||||
|
||||
const name = "mdx-plugin";
|
||||
const pluginName = "mdx-plugin";
|
||||
|
||||
/**
|
||||
* @typedef MDXPluginOptions
|
||||
@ -38,28 +35,35 @@ const name = "mdx-plugin";
|
||||
/**
|
||||
* Bundle MDX into JSON modules.
|
||||
*
|
||||
* @param {MDXPluginOptions} options Options.
|
||||
* @returns {Plugin} Plugin.
|
||||
* @param {MDXPluginOptions} options
|
||||
* @returns {Plugin}
|
||||
*/
|
||||
export function mdxPlugin({ root }) {
|
||||
return { name, setup };
|
||||
// TODO: Replace with `resolvePackage` after NPM Workspaces support is added.
|
||||
const docsPackageRoot = path.resolve(MonoRepoRoot, "website");
|
||||
|
||||
/**
|
||||
* @param {PluginBuild} build
|
||||
* Build.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function setup(build) {
|
||||
build.onLoad({ filter: /\.mdx?$/ }, onload);
|
||||
/**
|
||||
* @param {OnResolveArgs} args
|
||||
* @returns {Promise<OnResolveResult>}
|
||||
*/
|
||||
async function resolveListener(args) {
|
||||
if (!args.path.startsWith("~")) return args;
|
||||
|
||||
return {
|
||||
path: path.resolve(docsPackageRoot, args.path.slice(1)),
|
||||
pluginName,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LoadData} data
|
||||
* Data.
|
||||
* @returns {Promise<OnLoadResult>}
|
||||
* Result.
|
||||
*/
|
||||
async function onload(data) {
|
||||
async function loadListener(data) {
|
||||
const content = String(
|
||||
data.pluginData &&
|
||||
data.pluginData.contents !== null &&
|
||||
@ -77,7 +81,16 @@ export function mdxPlugin({ root }) {
|
||||
return {
|
||||
contents: JSON.stringify({ content, publicPath, publicDirectory }),
|
||||
loader: "file",
|
||||
pluginName,
|
||||
};
|
||||
}
|
||||
|
||||
build.onResolve({ filter: /\.mdx?$/ }, resolveListener);
|
||||
build.onLoad({ filter: /\.mdx?$/ }, loadListener);
|
||||
}
|
||||
|
||||
return {
|
||||
name: pluginName,
|
||||
setup,
|
||||
};
|
||||
}
|
||||
|
@ -24,12 +24,13 @@ export default tseslint.config(
|
||||
...ESLintConfig,
|
||||
{
|
||||
rules: {
|
||||
"no-console": ["error", { allow: ["debug", "warn", "error"] }],
|
||||
"no-console": "off",
|
||||
},
|
||||
files: ["src/**/*"],
|
||||
files: ["packages/**/*"],
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
"no-void": "off",
|
||||
"no-implicit-coercion": "off",
|
||||
"prefer-template": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
@ -46,6 +47,7 @@ export default tseslint.config(
|
||||
"no-empty-function": "off",
|
||||
"no-param-reassign": "off",
|
||||
"no-throw-literal": "off",
|
||||
// "no-var": "off",
|
||||
"prefer-arrow-callback": "off",
|
||||
"react/jsx-no-leaked-render": "off",
|
||||
"vars-on-top": "off",
|
||||
|
29272
web/package-lock.json
generated
Normal file
29272
web/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -67,6 +67,7 @@
|
||||
"#admin/*": "./src/admin/*.js",
|
||||
"#flow/*.css": "./src/flow/*.css",
|
||||
"#flow/*": "./src/flow/*.js",
|
||||
"#locales/*": "./src/locales/*.js",
|
||||
"#stories/*": "./src/stories/*.js",
|
||||
"#*/browser": {
|
||||
"types": "./out/*/browser.d.ts",
|
||||
@ -84,13 +85,13 @@
|
||||
"dependencies": {
|
||||
"@codemirror/lang-css": "^6.3.1",
|
||||
"@codemirror/lang-html": "^6.4.9",
|
||||
"@codemirror/lang-javascript": "^6.2.2",
|
||||
"@codemirror/lang-javascript": "^6.2.4",
|
||||
"@codemirror/lang-python": "^6.1.6",
|
||||
"@codemirror/lang-xml": "^6.1.0",
|
||||
"@codemirror/legacy-modes": "^6.4.1",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@floating-ui/dom": "^1.6.11",
|
||||
"@formatjs/intl-listformat": "^7.5.7",
|
||||
"@formatjs/intl-listformat": "^7.7.11",
|
||||
"@fortawesome/fontawesome-free": "^6.6.0",
|
||||
"@goauthentik/api": "^2025.4.1-1747687715",
|
||||
"@lit/context": "^1.1.2",
|
||||
@ -106,16 +107,16 @@
|
||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"change-case": "^5.4.4",
|
||||
"chart.js": "^4.4.4",
|
||||
"chart.js": "^4.4.9",
|
||||
"chartjs-adapter-date-fns": "^3.0.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"construct-style-sheets-polyfill": "^3.1.0",
|
||||
"core-js": "^3.38.1",
|
||||
"country-flag-icons": "^1.5.13",
|
||||
"country-flag-icons": "^1.5.19",
|
||||
"date-fns": "^4.1.0",
|
||||
"deepmerge-ts": "^7.1.5",
|
||||
"dompurify": "^3.2.4",
|
||||
"fuse.js": "^7.0.0",
|
||||
"dompurify": "^3.2.6",
|
||||
"fuse.js": "^7.1.0",
|
||||
"guacamole-common-js": "^1.5.0",
|
||||
"hastscript": "^9.0.1",
|
||||
"lit": "^3.2.0",
|
||||
@ -168,9 +169,9 @@
|
||||
"@types/react-dom": "^19.1.5",
|
||||
"@typescript-eslint/eslint-plugin": "^8.8.0",
|
||||
"@typescript-eslint/parser": "^8.8.0",
|
||||
"@wdio/browser-runner": "^9.14.0",
|
||||
"@wdio/cli": "^9.14.0",
|
||||
"@wdio/spec-reporter": "^9.14.0",
|
||||
"@wdio/browser-runner": "9.4",
|
||||
"@wdio/cli": "9.4",
|
||||
"@wdio/spec-reporter": "^9.1.2",
|
||||
"@web/test-runner": "^0.20.2",
|
||||
"chromedriver": "^136.0.3",
|
||||
"esbuild": "^0.25.4",
|
||||
@ -182,10 +183,10 @@
|
||||
"eslint-plugin-wc": "^3.0.1",
|
||||
"github-slugger": "^2.0.0",
|
||||
"globals": "^15.10.0",
|
||||
"knip": "^5.30.6",
|
||||
"knip": "^5.58.0",
|
||||
"lit-analyzer": "^2.0.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier": "^3.3.3",
|
||||
"pseudolocale": "^2.1.0",
|
||||
"rollup-plugin-postcss-lit": "^2.2.0",
|
||||
"storybook": "^8.6.14",
|
||||
@ -195,7 +196,7 @@
|
||||
"typescript-eslint": "^8.32.1",
|
||||
"vite-plugin-lit-css": "^2.0.0",
|
||||
"vite-tsconfig-paths": "^5.0.1",
|
||||
"wireit": "^0.14.9"
|
||||
"wireit": "^0.14.12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/darwin-arm64": "^0.25.4",
|
||||
|
@ -45,11 +45,11 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@goauthentik/prettier-config": "^1.0.4",
|
||||
"@goauthentik/prettier-config": "^1.0.5",
|
||||
"@goauthentik/tsconfig": "^1.0.4",
|
||||
"@types/node": "^22.15.21",
|
||||
"prettier": "^3.5.3",
|
||||
"typescript": "^5.8.3"
|
||||
"prettier": "^3.3.3",
|
||||
"typescript": "^5.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.11"
|
||||
|
19
web/paths/index.js
Normal file
19
web/paths/index.js
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @file Paths used by the web package.
|
||||
*
|
||||
* @runtime common
|
||||
*/
|
||||
|
||||
/**
|
||||
* The name of the distribution directory.
|
||||
*
|
||||
* @runtime common
|
||||
*/
|
||||
export const DistDirectoryName = "dist";
|
||||
|
||||
/**
|
||||
* The name of the static file directory.
|
||||
*
|
||||
* @runtime common
|
||||
*/
|
||||
export const StaticDirectoryName = "static";
|
@ -1,3 +1,9 @@
|
||||
/**
|
||||
* @file Paths used by the web package.
|
||||
*
|
||||
* @runtime node
|
||||
*/
|
||||
import { DistDirectoryName } from "#paths";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
@ -11,18 +17,17 @@ const relativeDirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
/**
|
||||
* The root of the web package.
|
||||
*
|
||||
* @runtime node
|
||||
*/
|
||||
export const PackageRoot = /** @type {WebPackageIdentifier} */ (resolve(relativeDirname, ".."));
|
||||
|
||||
/**
|
||||
* The name of the distribution directory.
|
||||
*/
|
||||
export const DistDirectoryName = "dist";
|
||||
|
||||
/**
|
||||
* Path to the web package's distribution directory.
|
||||
*
|
||||
* This is where the built files are located after running the build process.
|
||||
*
|
||||
* @runtime node
|
||||
*/
|
||||
export const DistDirectory = /** @type {`${WebPackageIdentifier}/${DistDirectoryName}`} */ (
|
||||
resolve(PackageRoot, DistDirectoryName)
|
||||
@ -43,6 +48,8 @@ export const DistDirectory = /** @type {`${WebPackageIdentifier}/${DistDirectory
|
||||
* Entry points available for building.
|
||||
*
|
||||
* @satisfies {Record<string, EntryPointTarget>}
|
||||
*
|
||||
* @runtime node
|
||||
*/
|
||||
export const EntryPoint = /** @type {const} */ ({
|
||||
Admin: {
|
||||
|
@ -6,7 +6,8 @@
|
||||
*/
|
||||
import { mdxPlugin } from "#bundler/mdx-plugin/node";
|
||||
import { createBundleDefinitions } from "#bundler/utils/node";
|
||||
import { DistDirectory, DistDirectoryName, EntryPoint, PackageRoot } from "#paths/node";
|
||||
import { DistDirectoryName } from "#paths";
|
||||
import { DistDirectory, EntryPoint, PackageRoot } from "#paths/node";
|
||||
import { NodeEnvironment } from "@goauthentik/core/environment/node";
|
||||
import { MonoRepoRoot, resolvePackage } from "@goauthentik/core/paths/node";
|
||||
import { readBuildIdentifier } from "@goauthentik/core/version/node";
|
||||
@ -26,7 +27,7 @@ const patternflyPath = resolvePackage("@patternfly/patternfly", import.meta);
|
||||
*/
|
||||
const BASE_ESBUILD_OPTIONS = {
|
||||
entryNames: `[dir]/[name]-${readBuildIdentifier()}`,
|
||||
chunkNames: "[dir]/chunks/[name]-[hash]",
|
||||
chunkNames: "[dir]/chunks/[hash]",
|
||||
assetNames: "assets/[dir]/[name]-[hash]",
|
||||
publicPath: path.join("/static", DistDirectoryName),
|
||||
outdir: DistDirectory,
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { WithBrandConfig } from "#elements/mixins/branding";
|
||||
import { WithLicenseSummary } from "#elements/mixins/license";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { globalAK } from "@goauthentik/common/global";
|
||||
import { DefaultBrand } from "@goauthentik/common/ui/config";
|
||||
import "@goauthentik/elements/EmptyState";
|
||||
import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider";
|
||||
import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider";
|
||||
import { ModalButton } from "@goauthentik/elements/buttons/ModalButton";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
@ -57,7 +56,8 @@ export class AboutModal extends WithLicenseSummary(WithBrandConfig(ModalButton))
|
||||
}
|
||||
|
||||
renderModal() {
|
||||
let product = globalAK().brand.brandingTitle || DefaultBrand.brandingTitle;
|
||||
let product = this.brandingTitle;
|
||||
|
||||
if (this.licenseSummary.status !== LicenseSummaryStatusEnum.Unlicensed) {
|
||||
product += ` ${msg("Enterprise")}`;
|
||||
}
|
||||
@ -73,7 +73,7 @@ export class AboutModal extends WithLicenseSummary(WithBrandConfig(ModalButton))
|
||||
<div class="pf-c-about-modal-box__brand">
|
||||
<img
|
||||
class="pf-c-about-modal-box__brand-image"
|
||||
src=${this.brand?.brandingFavicon ?? DefaultBrand.brandingFavicon}
|
||||
src=${this.brandingFavicon}
|
||||
alt="${msg("authentik Logo")}"
|
||||
/>
|
||||
</div>
|
||||
|
@ -1,9 +1,12 @@
|
||||
import "#admin/AdminInterface/AboutModal";
|
||||
import type { AboutModal } from "#admin/AdminInterface/AboutModal";
|
||||
import { ROUTES } from "#admin/Routes";
|
||||
import { EVENT_API_DRAWER_TOGGLE, EVENT_NOTIFICATION_DRAWER_TOGGLE } from "#common/constants";
|
||||
import { configureSentry } from "#common/sentry/index";
|
||||
import { me } from "#common/users";
|
||||
import { WebsocketClient } from "#common/ws";
|
||||
import { AuthenticatedInterface } from "#elements/Interface/Interface";
|
||||
import { WithLicenseSummary } from "#elements/Interface/licenseSummaryProvider";
|
||||
import { SidebarToggleEventDetail } from "#components/ak-page-header";
|
||||
import { AuthenticatedInterface } from "#elements/AuthenticatedInterface";
|
||||
import "#elements/ak-locale-context/ak-locale-context";
|
||||
import "#elements/banner/EnterpriseStatusBanner";
|
||||
import "#elements/banner/EnterpriseStatusBanner";
|
||||
@ -11,16 +14,13 @@ import "#elements/banner/VersionBanner";
|
||||
import "#elements/banner/VersionBanner";
|
||||
import "#elements/messages/MessageContainer";
|
||||
import "#elements/messages/MessageContainer";
|
||||
import { WithCapabilitiesConfig } from "#elements/mixins/capabilities";
|
||||
import "#elements/notifications/APIDrawer";
|
||||
import "#elements/notifications/NotificationDrawer";
|
||||
import { getURLParam, updateURLParams } from "#elements/router/RouteMatch";
|
||||
import "#elements/router/RouterOutlet";
|
||||
import "#elements/sidebar/Sidebar";
|
||||
import "#elements/sidebar/SidebarItem";
|
||||
import "@goauthentik/admin/AdminInterface/AboutModal";
|
||||
import type { AboutModal } from "@goauthentik/admin/AdminInterface/AboutModal";
|
||||
import { ROUTES } from "@goauthentik/admin/Routes";
|
||||
import { SidebarToggleEventDetail } from "@goauthentik/components/ak-page-header.js";
|
||||
|
||||
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
|
||||
import { customElement, eventOptions, property, query } from "lit/decorators.js";
|
||||
@ -45,7 +45,7 @@ if (process.env.NODE_ENV === "development") {
|
||||
}
|
||||
|
||||
@customElement("ak-interface-admin")
|
||||
export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
|
||||
export class AdminInterface extends WithCapabilitiesConfig(AuthenticatedInterface) {
|
||||
//#region Properties
|
||||
|
||||
@property({ type: Boolean })
|
||||
@ -202,7 +202,7 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
|
||||
|
||||
<ak-sidebar class="${classMap(sidebarClasses)}">
|
||||
${renderSidebarItems(AdminSidebarEntries)}
|
||||
${this.config?.capabilities.includes(CapabilitiesEnum.IsEnterprise)
|
||||
${this.can(CapabilitiesEnum.IsEnterprise)
|
||||
? renderSidebarItems(AdminSidebarEnterpriseEntries)
|
||||
: nothing}
|
||||
</ak-sidebar>
|
||||
|
@ -11,10 +11,10 @@ import "#admin/admin-overview/charts/SyncStatusChart";
|
||||
import { me } from "#common/users";
|
||||
import "#components/ak-page-header";
|
||||
import { AKElement } from "#elements/Base";
|
||||
import { WithLicenseSummary } from "#elements/Interface/licenseSummaryProvider";
|
||||
import "#elements/cards/AggregatePromiseCard";
|
||||
import type { QuickAction } from "#elements/cards/QuickActionsCard";
|
||||
import "#elements/cards/QuickActionsCard";
|
||||
import { WithLicenseSummary } from "#elements/mixins/license";
|
||||
import { paramURL } from "#elements/router/RouterOutlet";
|
||||
import { createReleaseNotesURL } from "@goauthentik/core/version";
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { CapabilitiesEnum, WithCapabilitiesConfig } from "#elements/mixins/capabilities";
|
||||
import "@goauthentik/admin/applications/ProviderSelectModal";
|
||||
import { iconHelperText } from "@goauthentik/admin/helperText";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
@ -6,18 +7,14 @@ import "@goauthentik/components/ak-radio-input";
|
||||
import "@goauthentik/components/ak-switch-input";
|
||||
import "@goauthentik/components/ak-text-input";
|
||||
import "@goauthentik/components/ak-textarea-input";
|
||||
import "@goauthentik/elements/Alert.js";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
WithCapabilitiesConfig,
|
||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||
import "@goauthentik/elements/Alert";
|
||||
import "@goauthentik/elements/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import "@goauthentik/elements/forms/ModalForm";
|
||||
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
||||
import "@goauthentik/elements/forms/ProxyForm";
|
||||
import "@goauthentik/elements/forms/Radio";
|
||||
import "@goauthentik/elements/forms/SearchSelect";
|
||||
import "@goauthentik/elements/forms/SearchSelect/ak-search-select";
|
||||
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
|
@ -1,17 +1,17 @@
|
||||
import "@goauthentik/admin/applications/ApplicationForm";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import MDApplication from "@goauthentik/docs/add-secure-apps/applications/index.md";
|
||||
import "@goauthentik/elements/AppIcon.js";
|
||||
import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider";
|
||||
import "@goauthentik/elements/ak-mdx";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
import "@goauthentik/elements/forms/ModalForm";
|
||||
import { getURLParam } from "@goauthentik/elements/router/RouteMatch";
|
||||
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
|
||||
import { TableColumn } from "@goauthentik/elements/table/Table";
|
||||
import { TablePage } from "@goauthentik/elements/table/TablePage";
|
||||
import "#admin/applications/ApplicationForm";
|
||||
import { DEFAULT_CONFIG } from "#common/api/config";
|
||||
import "#elements/AppIcon";
|
||||
import "#elements/ak-mdx/ak-mdx";
|
||||
import "#elements/buttons/SpinnerButton/ak-spinner-button";
|
||||
import "#elements/forms/DeleteBulkForm";
|
||||
import "#elements/forms/ModalForm";
|
||||
import { WithBrandConfig } from "#elements/mixins/branding";
|
||||
import { getURLParam } from "#elements/router/RouteMatch";
|
||||
import { PaginatedResponse } from "#elements/table/Table";
|
||||
import { TableColumn } from "#elements/table/Table";
|
||||
import { TablePage } from "#elements/table/TablePage";
|
||||
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||
import MDApplication from "~docs/add-secure-apps/applications/index.md";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||
@ -22,7 +22,7 @@ import PFCard from "@patternfly/patternfly/components/Card/card.css";
|
||||
|
||||
import { Application, CoreApi, PoliciesApi } from "@goauthentik/api";
|
||||
|
||||
import "./ApplicationWizardHint";
|
||||
import "./ApplicationWizardHint.js";
|
||||
|
||||
export const applicationListStyle = css`
|
||||
/* Fix alignment issues with images in tables */
|
||||
@ -50,7 +50,7 @@ export class ApplicationListPage extends WithBrandConfig(TablePage<Application>)
|
||||
}
|
||||
pageDescription(): string {
|
||||
return msg(
|
||||
str`External applications that use ${this.brand?.brandingTitle ?? "authentik"} as an identity provider via protocols like OAuth2 and SAML. All applications are shown here, even ones you cannot access.`,
|
||||
str`External applications that use ${this.brandingTitle} as an identity provider via protocols like OAuth2 and SAML. All applications are shown here, even ones you cannot access.`,
|
||||
);
|
||||
}
|
||||
pageIcon(): string {
|
||||
|
@ -3,5 +3,5 @@ import { createContext } from "@lit/context";
|
||||
import { LocalTypeCreate } from "./steps/ProviderChoices.js";
|
||||
|
||||
export const applicationWizardProvidersContext = createContext<LocalTypeCreate[]>(
|
||||
Symbol("ak-application-wizard-providers-context"),
|
||||
Symbol.for("ak-application-wizard-providers-context"),
|
||||
);
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { WithLicenseSummary } from "#elements/mixins/license";
|
||||
import { ApplicationWizardStep } from "@goauthentik/admin/applications/wizard/ApplicationWizardStep.js";
|
||||
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
|
||||
import type { NavigableButton, WizardButton } from "@goauthentik/components/ak-wizard/types";
|
||||
import "@goauthentik/elements/EmptyState.js";
|
||||
import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider.js";
|
||||
import { bound } from "@goauthentik/elements/decorators/bound.js";
|
||||
import "@goauthentik/elements/forms/FormGroup.js";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement.js";
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { WithBrandConfig } from "#elements/mixins/branding";
|
||||
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
|
||||
import { ValidationRecord } from "@goauthentik/admin/applications/wizard/types";
|
||||
import { renderForm } from "@goauthentik/admin/providers/ldap/LDAPProviderFormForm.js";
|
||||
import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider.js";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { html } from "lit";
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { WithBrandConfig } from "#elements/mixins/branding";
|
||||
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
|
||||
import { ValidationRecord } from "@goauthentik/admin/applications/wizard/types";
|
||||
import { renderForm } from "@goauthentik/admin/providers/radius/RadiusProviderFormForm.js";
|
||||
import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { customElement } from "@lit/reactive-element/decorators.js";
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { WithLicenseSummary } from "#elements/mixins/license";
|
||||
import "@goauthentik/elements/Alert";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { html, nothing } from "lit";
|
||||
|
@ -1,10 +1,7 @@
|
||||
import { CapabilitiesEnum, WithCapabilitiesConfig } from "#elements/mixins/capabilities";
|
||||
import { DesignationToLabel, LayoutToLabel } from "@goauthentik/admin/flows/utils";
|
||||
import { AuthenticationEnum } from "@goauthentik/api/dist/models/AuthenticationEnum";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
WithCapabilitiesConfig,
|
||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||
import "@goauthentik/elements/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { WithBrandConfig } from "#elements/mixins/branding";
|
||||
import { CapabilitiesEnum, WithCapabilitiesConfig } from "#elements/mixins/capabilities";
|
||||
import "@goauthentik/admin/users/ServiceAccountForm";
|
||||
import "@goauthentik/admin/users/UserActiveForm";
|
||||
import "@goauthentik/admin/users/UserForm";
|
||||
@ -11,11 +13,6 @@ import { MessageLevel } from "@goauthentik/common/messages";
|
||||
import { formatElapsedTime } from "@goauthentik/common/temporal";
|
||||
import { me } from "@goauthentik/common/users";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
WithCapabilitiesConfig,
|
||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||
import "@goauthentik/elements/buttons/ActionButton";
|
||||
import "@goauthentik/elements/buttons/Dropdown";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
@ -295,7 +292,7 @@ export class RelatedUserList extends WithBrandConfig(WithCapabilitiesConfig(Tabl
|
||||
${msg("Set password")}
|
||||
</button>
|
||||
</ak-forms-modal>
|
||||
${this.brand?.flowRecovery
|
||||
${this.brand.flowRecovery
|
||||
? html`
|
||||
<ak-action-button
|
||||
class="pf-m-secondary"
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { WithBrandConfig } from "#elements/mixins/branding";
|
||||
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||
import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search";
|
||||
import { BaseProviderForm } from "@goauthentik/admin/providers/BaseProviderForm";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider";
|
||||
|
||||
import { customElement } from "lit/decorators.js";
|
||||
|
||||
|
@ -4,7 +4,6 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import renderDescriptionList from "@goauthentik/components/DescriptionList";
|
||||
import "@goauthentik/components/events/ObjectChangelog";
|
||||
import MDProviderOAuth2 from "@goauthentik/docs/add-secure-apps/providers/oauth2/index.mdx";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/CodeMirror";
|
||||
import "@goauthentik/elements/EmptyState";
|
||||
@ -12,6 +11,7 @@ import "@goauthentik/elements/Tabs";
|
||||
import "@goauthentik/elements/ak-mdx";
|
||||
import "@goauthentik/elements/buttons/ModalButton";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import MDProviderOAuth2 from "~docs/add-secure-apps/providers/oauth2/index.mdx";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, TemplateResult, html } from "lit";
|
||||
|
@ -5,14 +5,6 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/components/events/ObjectChangelog";
|
||||
import MDCaddyStandalone from "@goauthentik/docs/add-secure-apps/providers/proxy/_caddy_standalone.md";
|
||||
import MDNginxIngress from "@goauthentik/docs/add-secure-apps/providers/proxy/_nginx_ingress.md";
|
||||
import MDNginxPM from "@goauthentik/docs/add-secure-apps/providers/proxy/_nginx_proxy_manager.md";
|
||||
import MDNginxStandalone from "@goauthentik/docs/add-secure-apps/providers/proxy/_nginx_standalone.md";
|
||||
import MDTraefikCompose from "@goauthentik/docs/add-secure-apps/providers/proxy/_traefik_compose.md";
|
||||
import MDTraefikIngress from "@goauthentik/docs/add-secure-apps/providers/proxy/_traefik_ingress.md";
|
||||
import MDTraefikStandalone from "@goauthentik/docs/add-secure-apps/providers/proxy/_traefik_standalone.md";
|
||||
import MDHeaderAuthentication from "@goauthentik/docs/add-secure-apps/providers/proxy/header_authentication.mdx";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/CodeMirror";
|
||||
import "@goauthentik/elements/Tabs";
|
||||
@ -22,6 +14,14 @@ import "@goauthentik/elements/buttons/ModalButton";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import { getURLParam } from "@goauthentik/elements/router/RouteMatch";
|
||||
import { formatSlug } from "@goauthentik/elements/router/utils.js";
|
||||
import MDCaddyStandalone from "~docs/add-secure-apps/providers/proxy/_caddy_standalone.md";
|
||||
import MDNginxIngress from "~docs/add-secure-apps/providers/proxy/_nginx_ingress.md";
|
||||
import MDNginxPM from "~docs/add-secure-apps/providers/proxy/_nginx_proxy_manager.md";
|
||||
import MDNginxStandalone from "~docs/add-secure-apps/providers/proxy/_nginx_standalone.md";
|
||||
import MDTraefikCompose from "~docs/add-secure-apps/providers/proxy/_traefik_compose.md";
|
||||
import MDTraefikIngress from "~docs/add-secure-apps/providers/proxy/_traefik_ingress.md";
|
||||
import MDTraefikStandalone from "~docs/add-secure-apps/providers/proxy/_traefik_standalone.md";
|
||||
import MDHeaderAuthentication from "~docs/add-secure-apps/providers/proxy/header_authentication.mdx";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, PropertyValues, TemplateResult, css, html } from "lit";
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { WithBrandConfig } from "#elements/mixins/branding";
|
||||
import { BaseProviderForm } from "@goauthentik/admin/providers/BaseProviderForm";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider";
|
||||
|
||||
import { customElement } from "lit/decorators.js";
|
||||
|
||||
|
@ -7,13 +7,13 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import "@goauthentik/components/events/ObjectChangelog";
|
||||
import MDSCIMProvider from "@goauthentik/docs/add-secure-apps/providers/scim/index.md";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/Tabs";
|
||||
import "@goauthentik/elements/ak-mdx";
|
||||
import "@goauthentik/elements/buttons/ActionButton";
|
||||
import "@goauthentik/elements/buttons/ModalButton";
|
||||
import "@goauthentik/elements/sync/SyncStatusCard";
|
||||
import MDSCIMProvider from "~docs/add-secure-apps/providers/scim/index.md";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, PropertyValues, TemplateResult, html } from "lit";
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { CapabilitiesEnum, WithCapabilitiesConfig } from "#elements/mixins/capabilities";
|
||||
import "@goauthentik/admin/common/ak-flow-search/ak-source-flow-search";
|
||||
import { iconHelperText, placeholderHelperText } from "@goauthentik/admin/helperText";
|
||||
import { BaseSourceForm } from "@goauthentik/admin/sources/BaseSourceForm";
|
||||
@ -9,10 +10,6 @@ import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config";
|
||||
import "@goauthentik/components/ak-switch-input";
|
||||
import "@goauthentik/components/ak-text-input";
|
||||
import "@goauthentik/components/ak-textarea-input";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
WithCapabilitiesConfig,
|
||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
|
||||
import "@goauthentik/elements/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
|
@ -4,7 +4,6 @@ import "@goauthentik/admin/sources/kerberos/KerberosSourceForm";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import "@goauthentik/components/events/ObjectChangelog";
|
||||
import MDSourceKerberosBrowser from "@goauthentik/docs/users-sources/sources/protocols/kerberos/browser.md";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/CodeMirror";
|
||||
import "@goauthentik/elements/Tabs";
|
||||
@ -13,6 +12,7 @@ import "@goauthentik/elements/buttons/ActionButton";
|
||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||
import "@goauthentik/elements/forms/ModalForm";
|
||||
import "@goauthentik/elements/sync/SyncStatusCard";
|
||||
import MDSourceKerberosBrowser from "~docs/users-sources/sources/protocols/kerberos/browser.md";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, TemplateResult, html } from "lit";
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { CapabilitiesEnum, WithCapabilitiesConfig } from "#elements/mixins/capabilities";
|
||||
import "@goauthentik/admin/common/ak-flow-search/ak-source-flow-search";
|
||||
import { iconHelperText, placeholderHelperText } from "@goauthentik/admin/helperText";
|
||||
import { BaseSourceForm } from "@goauthentik/admin/sources/BaseSourceForm";
|
||||
@ -9,10 +10,6 @@ import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config";
|
||||
import "@goauthentik/components/ak-radio-input";
|
||||
import "@goauthentik/elements/CodeMirror";
|
||||
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
WithCapabilitiesConfig,
|
||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
|
||||
import "@goauthentik/elements/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { CapabilitiesEnum, WithCapabilitiesConfig } from "#elements/mixins/capabilities";
|
||||
import "@goauthentik/admin/common/ak-flow-search/ak-source-flow-search";
|
||||
import { iconHelperText, placeholderHelperText } from "@goauthentik/admin/helperText";
|
||||
import { BaseSourceForm } from "@goauthentik/admin/sources/BaseSourceForm";
|
||||
@ -8,10 +9,6 @@ import {
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { PlexAPIClient, PlexResource, popupCenterScreen } from "@goauthentik/common/helpers/plex";
|
||||
import { ascii_letters, digits, randomString } from "@goauthentik/common/utils";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
WithCapabilitiesConfig,
|
||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider.js";
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { CapabilitiesEnum, WithCapabilitiesConfig } from "#elements/mixins/capabilities";
|
||||
import "@goauthentik/admin/common/ak-crypto-certificate-search";
|
||||
import "@goauthentik/admin/common/ak-flow-search/ak-source-flow-search";
|
||||
import { iconHelperText, placeholderHelperText } from "@goauthentik/admin/helperText";
|
||||
@ -7,10 +8,6 @@ import {
|
||||
UserMatchingModeToLabel,
|
||||
} from "@goauthentik/admin/sources/oauth/utils";
|
||||
import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
WithCapabilitiesConfig,
|
||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
|
||||
import "@goauthentik/elements/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { WithBrandConfig } from "#elements/mixins/branding";
|
||||
import { CapabilitiesEnum, WithCapabilitiesConfig } from "#elements/mixins/capabilities";
|
||||
import type { AdminInterface } from "@goauthentik/admin/AdminInterface/index.entrypoint.js";
|
||||
import "@goauthentik/admin/users/ServiceAccountForm";
|
||||
import "@goauthentik/admin/users/UserActiveForm";
|
||||
@ -11,15 +13,10 @@ import { parseAPIResponseError } from "@goauthentik/common/errors/network";
|
||||
import { userTypeToLabel } from "@goauthentik/common/labels";
|
||||
import { MessageLevel } from "@goauthentik/common/messages";
|
||||
import { formatElapsedTime } from "@goauthentik/common/temporal";
|
||||
import { rootInterface } from "@goauthentik/common/theme";
|
||||
import { DefaultUIConfig, uiConfig } from "@goauthentik/common/ui/config";
|
||||
import { me } from "@goauthentik/common/users";
|
||||
import "@goauthentik/components/ak-status-label";
|
||||
import { rootInterface } from "@goauthentik/elements/Base";
|
||||
import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
WithCapabilitiesConfig,
|
||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||
import "@goauthentik/elements/TreeView";
|
||||
import "@goauthentik/elements/buttons/ActionButton";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
|
@ -22,11 +22,11 @@ import "#components/events/ObjectChangelog";
|
||||
import "#components/events/UserEvents";
|
||||
import { AKElement } from "#elements/Base";
|
||||
import "#elements/CodeMirror";
|
||||
import { WithCapabilitiesConfig } from "#elements/Interface/capabilitiesProvider";
|
||||
import "#elements/Tabs";
|
||||
import "#elements/buttons/ActionButton/ak-action-button";
|
||||
import "#elements/buttons/SpinnerButton/ak-spinner-button";
|
||||
import "#elements/forms/ModalForm";
|
||||
import { WithCapabilitiesConfig } from "#elements/mixins/capabilities";
|
||||
import "#elements/oauth/UserAccessTokenList";
|
||||
import "#elements/oauth/UserRefreshTokenList";
|
||||
import "#elements/user/SessionList";
|
||||
|
@ -18,7 +18,6 @@ export const CURRENT_CLASS = "pf-m-current";
|
||||
|
||||
//#region Application
|
||||
|
||||
export const TITLE_DEFAULT = "authentik";
|
||||
/**
|
||||
* The delimiter used to parse the URL for the current route.
|
||||
*
|
||||
|
@ -26,8 +26,12 @@ export const HTTPStatusCodeTransformer: Record<number, HTTPErrorJSONTransformer>
|
||||
[HTTPStatusCode.Forbidden]: GenericErrorFromJSON,
|
||||
} as const;
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Type Predicates
|
||||
|
||||
/**
|
||||
* Type guard to check if a response contains a JSON body.
|
||||
* Type predicate to check if a response contains a JSON body.
|
||||
*
|
||||
* This is useful to guard against parsing errors when attempting to read the response body.
|
||||
*/
|
||||
@ -35,6 +39,24 @@ export function isJSONResponse(response: Response): boolean {
|
||||
return Boolean(response.headers.get("content-type")?.includes("application/json"));
|
||||
}
|
||||
|
||||
/**
|
||||
* An error originating from an aborted request.
|
||||
*
|
||||
* @see {@linkcode isAbortError} to check if an error originates from an aborted request.
|
||||
*/
|
||||
export interface AbortErrorLike extends DOMException {
|
||||
name: "AbortError";
|
||||
}
|
||||
|
||||
/**
|
||||
* Type predicate to check if an error originates from an aborted request.
|
||||
*
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort | MDN}
|
||||
*/
|
||||
export function isAbortError(error: unknown): error is AbortErrorLike {
|
||||
return error instanceof DOMException && error.name === "AbortError";
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region API
|
||||
|
@ -2,13 +2,12 @@
|
||||
* @file Theme utilities.
|
||||
*/
|
||||
import { type StyleRoot, createStyleSheetUnsafe, setAdoptedStyleSheets } from "#common/stylesheets";
|
||||
import { UIConfig } from "#common/ui/config";
|
||||
|
||||
import AKBase from "#common/styles/authentik.css";
|
||||
import AKBaseDark from "#common/styles/theme-dark.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
import { Config, CurrentBrand, UiThemeEnum } from "@goauthentik/api";
|
||||
import { UiThemeEnum } from "@goauthentik/api";
|
||||
|
||||
//#region Stylesheet Exports
|
||||
|
||||
@ -259,6 +258,8 @@ export function applyUITheme(
|
||||
export function applyDocumentTheme(hint: CSSColorSchemeValue | UIThemeHint = "auto"): void {
|
||||
const preferredColorScheme = formatColorScheme(hint);
|
||||
|
||||
if (document.documentElement.dataset.theme === preferredColorScheme) return;
|
||||
|
||||
const applyStyleSheets: UIThemeListener = (currentUITheme) => {
|
||||
console.debug(`authentik/theme (document): switching to ${currentUITheme} theme`);
|
||||
|
||||
@ -285,36 +286,20 @@ export function applyDocumentTheme(hint: CSSColorSchemeValue | UIThemeHint = "au
|
||||
applyStyleSheets(preferredColorScheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* An element that can be themed.
|
||||
*/
|
||||
export interface ThemedElement extends HTMLElement {
|
||||
/**
|
||||
* The brand information for the current theme.
|
||||
*/
|
||||
readonly brand?: CurrentBrand;
|
||||
/**
|
||||
* The UI configuration for the current theme,
|
||||
* typically injected through a Lit Mixin.
|
||||
*
|
||||
* @see {@linkcode UIConfig} for details.
|
||||
*/
|
||||
readonly uiConfig?: UIConfig;
|
||||
/**
|
||||
* An authentik configuration initially provided by the server.
|
||||
*/
|
||||
readonly config?: Config;
|
||||
activeTheme: ResolvedUITheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root interface element of the page.
|
||||
*
|
||||
* @todo Can this be handled with a Lit Mixin?
|
||||
*/
|
||||
export function rootInterface<T extends ThemedElement = ThemedElement>(): T | null {
|
||||
export function rootInterface<T extends HTMLElement = HTMLElement>(): T {
|
||||
const element = document.body.querySelector<T>("[data-ak-interface-root]");
|
||||
|
||||
if (!element) {
|
||||
throw new Error(
|
||||
`Could not find root interface element. Was this element added before the parent interface element?`,
|
||||
);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { EVENT_WS_MESSAGE, TITLE_DEFAULT } from "#common/constants";
|
||||
import { EVENT_WS_MESSAGE } from "#common/constants";
|
||||
import { globalAK } from "#common/global";
|
||||
import { UIConfig, UserDisplay, getConfigForUser } from "#common/ui/config";
|
||||
import { DefaultBrand } from "#common/ui/config";
|
||||
import { me } from "#common/users";
|
||||
import "#components/ak-nav-buttons";
|
||||
import type { PageHeaderInit, SidebarToggleEventDetail } from "#components/ak-page-header";
|
||||
import { AKElement } from "#elements/Base";
|
||||
import { WithBrandConfig } from "#elements/Interface/brandProvider";
|
||||
import { WithBrandConfig } from "#elements/mixins/branding";
|
||||
import { isAdminRoute } from "#elements/router/utils";
|
||||
import { themeImage } from "#elements/utils/images";
|
||||
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||
@ -290,7 +289,7 @@ export class AKPageNavbar
|
||||
//#region Private Methods
|
||||
|
||||
#setTitle(header?: string) {
|
||||
let title = this.brand?.brandingTitle || TITLE_DEFAULT;
|
||||
let title = this.brandingTitle;
|
||||
|
||||
if (isAdminRoute()) {
|
||||
title = `${msg("Admin")} - ${title}`;
|
||||
@ -368,9 +367,7 @@ export class AKPageNavbar
|
||||
<a href="#/">
|
||||
<div class="logo">
|
||||
<img
|
||||
src=${themeImage(
|
||||
this.brand?.brandingLogo ?? DefaultBrand.brandingLogo,
|
||||
)}
|
||||
src=${themeImage(this.brandingLogo)}
|
||||
alt="${msg("authentik Logo")}"
|
||||
loading="lazy"
|
||||
/>
|
||||
|
@ -3,5 +3,5 @@ import { createContext } from "@lit/context";
|
||||
import type { WizardStepState } from "./types";
|
||||
|
||||
export const wizardStepContext = createContext<WizardStepState>(
|
||||
Symbol("authentik-wizard-step-labels"),
|
||||
Symbol.for("authentik-wizard-step-labels"),
|
||||
);
|
||||
|
12
web/src/elements/AuthenticatedInterface.ts
Normal file
12
web/src/elements/AuthenticatedInterface.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Interface } from "#elements/Interface";
|
||||
import { LicenseContextController } from "#elements/controllers/EnterpriseContextController";
|
||||
import { VersionContextController } from "#elements/controllers/VersionContextController";
|
||||
|
||||
export class AuthenticatedInterface extends Interface {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.addController(new LicenseContextController(this));
|
||||
this.addController(new VersionContextController(this));
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import { createContext } from "@lit/context";
|
||||
|
||||
import type { Config, CurrentBrand, LicenseSummary, SessionUser, Version } from "@goauthentik/api";
|
||||
|
||||
export const authentikConfigContext = createContext<Config>(Symbol("authentik-config-context"));
|
||||
|
||||
export const authentikUserContext = createContext<SessionUser>(Symbol("authentik-user-context"));
|
||||
|
||||
export const authentikEnterpriseContext = createContext<LicenseSummary>(
|
||||
Symbol("authentik-enterprise-context"),
|
||||
);
|
||||
|
||||
export const authentikBrandContext = createContext<CurrentBrand>(Symbol("authentik-brand-context"));
|
||||
|
||||
export const authentikVersionContext = createContext<Version>(Symbol("authentik-version-context"));
|
||||
|
||||
export default authentikConfigContext;
|
@ -1,19 +1,14 @@
|
||||
import { globalAK } from "@goauthentik/common/global.js";
|
||||
import {
|
||||
StyleRoot,
|
||||
createCSSResult,
|
||||
createStyleSheetUnsafe,
|
||||
} from "@goauthentik/common/stylesheets.js";
|
||||
import { globalAK } from "#common/global";
|
||||
import { StyleRoot, createCSSResult, createStyleSheetUnsafe } from "#common/stylesheets";
|
||||
import {
|
||||
$AKBase,
|
||||
CSSColorSchemeValue,
|
||||
ResolvedUITheme,
|
||||
ThemedElement,
|
||||
applyUITheme,
|
||||
createUIThemeEffect,
|
||||
formatColorScheme,
|
||||
resolveUITheme,
|
||||
} from "@goauthentik/common/theme.js";
|
||||
} from "#common/theme";
|
||||
|
||||
import { localized } from "@lit/localize";
|
||||
import { CSSResult, CSSResultGroup, CSSResultOrNative, LitElement } from "lit";
|
||||
@ -21,11 +16,8 @@ import { property } from "lit/decorators.js";
|
||||
|
||||
import { UiThemeEnum } from "@goauthentik/api";
|
||||
|
||||
// Re-export the theme helpers
|
||||
export { rootInterface } from "@goauthentik/common/theme";
|
||||
|
||||
@localized()
|
||||
export class AKElement extends LitElement implements ThemedElement {
|
||||
export class AKElement extends LitElement {
|
||||
//#region Static Properties
|
||||
|
||||
public static styles?: Array<CSSResult | CSSModule>;
|
||||
|
33
web/src/elements/Interface.ts
Normal file
33
web/src/elements/Interface.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { globalAK } from "#common/global";
|
||||
import { applyDocumentTheme } from "#common/theme";
|
||||
import { AKElement } from "#elements/Base";
|
||||
import { BrandingContextController } from "#elements/controllers/BrandContextController";
|
||||
import { ConfigContextController } from "#elements/controllers/ConfigContextController";
|
||||
import { ModalOrchestrationController } from "#elements/controllers/ModalOrchestrationController";
|
||||
import { WithAuthentikConfig } from "#elements/mixins/config";
|
||||
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
/**
|
||||
* The base interface element for the application.
|
||||
*/
|
||||
export abstract class Interface extends WithAuthentikConfig(AKElement) {
|
||||
static styles = [PFBase];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const { config, brand } = globalAK();
|
||||
|
||||
applyDocumentTheme(brand.uiTheme);
|
||||
|
||||
this.addController(new ConfigContextController(this, config));
|
||||
this.addController(new BrandingContextController(this, brand));
|
||||
this.addController(new ModalOrchestrationController());
|
||||
}
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.dataset.akInterfaceRoot = this.tagName.toLowerCase();
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import { ThemedElement } from "@goauthentik/common/theme";
|
||||
import { authentikBrandContext } from "@goauthentik/elements/AuthentikContexts";
|
||||
import type { ReactiveElementHost } from "@goauthentik/elements/types.js";
|
||||
|
||||
import { ContextProvider } from "@lit/context";
|
||||
import type { ReactiveController } from "lit";
|
||||
|
||||
import type { CurrentBrand } from "@goauthentik/api";
|
||||
import { CoreApi } from "@goauthentik/api";
|
||||
|
||||
export class BrandContextController implements ReactiveController {
|
||||
host!: ReactiveElementHost<ThemedElement>;
|
||||
|
||||
context!: ContextProvider<{ __context__: CurrentBrand | undefined }>;
|
||||
|
||||
constructor(host: ReactiveElementHost<ThemedElement>) {
|
||||
this.host = host;
|
||||
this.context = new ContextProvider(this.host, {
|
||||
context: authentikBrandContext,
|
||||
initialValue: undefined,
|
||||
});
|
||||
this.fetch = this.fetch.bind(this);
|
||||
this.fetch();
|
||||
}
|
||||
|
||||
fetch() {
|
||||
new CoreApi(DEFAULT_CONFIG).coreBrandsCurrentRetrieve().then((brand) => {
|
||||
this.context.setValue(brand);
|
||||
this.host.brand = brand;
|
||||
});
|
||||
}
|
||||
|
||||
hostConnected() {
|
||||
window.addEventListener(EVENT_REFRESH, this.fetch);
|
||||
}
|
||||
|
||||
hostDisconnected() {
|
||||
window.removeEventListener(EVENT_REFRESH, this.fetch);
|
||||
}
|
||||
|
||||
hostUpdate() {
|
||||
// If the Interface changes its brand information for some reason,
|
||||
// we should notify all users of the context of that change. doesn't
|
||||
if (this.host.brand !== this.context.value) {
|
||||
this.context.setValue(this.host.brand);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import { globalAK } from "@goauthentik/common/global";
|
||||
import { ThemedElement } from "@goauthentik/common/theme";
|
||||
import { authentikConfigContext } from "@goauthentik/elements/AuthentikContexts";
|
||||
import type { ReactiveElementHost } from "@goauthentik/elements/types.js";
|
||||
|
||||
import { ContextProvider } from "@lit/context";
|
||||
import type { ReactiveController } from "lit";
|
||||
|
||||
import type { Config } from "@goauthentik/api";
|
||||
import { RootApi } from "@goauthentik/api";
|
||||
|
||||
export class ConfigContextController implements ReactiveController {
|
||||
host!: ReactiveElementHost<ThemedElement>;
|
||||
|
||||
context!: ContextProvider<{ __context__: Config | undefined }>;
|
||||
|
||||
constructor(host: ReactiveElementHost<ThemedElement>) {
|
||||
this.host = host;
|
||||
this.context = new ContextProvider(this.host, {
|
||||
context: authentikConfigContext,
|
||||
initialValue: undefined,
|
||||
});
|
||||
// Pre-hydrate from template-embedded config
|
||||
this.context.setValue(globalAK().config);
|
||||
this.host.config = globalAK().config;
|
||||
this.fetch = this.fetch.bind(this);
|
||||
this.fetch();
|
||||
}
|
||||
|
||||
fetch() {
|
||||
new RootApi(DEFAULT_CONFIG).rootConfigRetrieve().then((config) => {
|
||||
this.context.setValue(config);
|
||||
this.host.config = config;
|
||||
});
|
||||
}
|
||||
|
||||
hostConnected() {
|
||||
window.addEventListener(EVENT_REFRESH, this.fetch);
|
||||
}
|
||||
|
||||
hostDisconnected() {
|
||||
window.removeEventListener(EVENT_REFRESH, this.fetch);
|
||||
}
|
||||
|
||||
hostUpdate() {
|
||||
// If the Interface changes its config information, we should notify all
|
||||
// users of the context of that change, without creating an infinite
|
||||
// loop of resets.
|
||||
if (this.host.config !== this.context.value) {
|
||||
this.context.setValue(this.host.config);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH_ENTERPRISE } from "@goauthentik/common/constants";
|
||||
import { authentikEnterpriseContext } from "@goauthentik/elements/AuthentikContexts";
|
||||
import type { ReactiveElementHost } from "@goauthentik/elements/types.js";
|
||||
|
||||
import { ContextProvider } from "@lit/context";
|
||||
import type { ReactiveController } from "lit";
|
||||
|
||||
import type { LicenseSummary } from "@goauthentik/api";
|
||||
import { EnterpriseApi } from "@goauthentik/api";
|
||||
|
||||
import type { AkAuthenticatedInterface } from "./Interface";
|
||||
|
||||
export class EnterpriseContextController implements ReactiveController {
|
||||
host!: ReactiveElementHost<AkAuthenticatedInterface>;
|
||||
|
||||
context!: ContextProvider<{ __context__: LicenseSummary | undefined }>;
|
||||
|
||||
constructor(host: ReactiveElementHost<AkAuthenticatedInterface>) {
|
||||
this.host = host;
|
||||
this.context = new ContextProvider(this.host, {
|
||||
context: authentikEnterpriseContext,
|
||||
initialValue: undefined,
|
||||
});
|
||||
this.fetch = this.fetch.bind(this);
|
||||
this.fetch();
|
||||
}
|
||||
|
||||
fetch() {
|
||||
new EnterpriseApi(DEFAULT_CONFIG).enterpriseLicenseSummaryRetrieve().then((enterprise) => {
|
||||
this.context.setValue(enterprise);
|
||||
this.host.licenseSummary = enterprise;
|
||||
});
|
||||
}
|
||||
|
||||
hostConnected() {
|
||||
window.addEventListener(EVENT_REFRESH_ENTERPRISE, this.fetch);
|
||||
}
|
||||
|
||||
hostDisconnected() {
|
||||
window.removeEventListener(EVENT_REFRESH_ENTERPRISE, this.fetch);
|
||||
}
|
||||
|
||||
hostUpdate() {
|
||||
// If the Interface changes its config information, we should notify all
|
||||
// users of the context of that change, without creating an infinite
|
||||
// loop of resets.
|
||||
if (this.host.licenseSummary !== this.context.value) {
|
||||
this.context.setValue(this.host.licenseSummary);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
import { globalAK } from "@goauthentik/common/global.js";
|
||||
import { ThemedElement, applyDocumentTheme } from "@goauthentik/common/theme.js";
|
||||
import { UIConfig } from "@goauthentik/common/ui/config.js";
|
||||
import { AKElement } from "@goauthentik/elements/Base.js";
|
||||
import { VersionContextController } from "@goauthentik/elements/Interface/VersionContextController.js";
|
||||
import { ModalOrchestrationController } from "@goauthentik/elements/controllers/ModalOrchestrationController.js";
|
||||
|
||||
import { state } from "lit/decorators.js";
|
||||
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
import {
|
||||
type Config,
|
||||
type CurrentBrand,
|
||||
type LicenseSummary,
|
||||
type Version,
|
||||
} from "@goauthentik/api";
|
||||
|
||||
import { BrandContextController } from "./BrandContextController.js";
|
||||
import { ConfigContextController } from "./ConfigContextController.js";
|
||||
import { EnterpriseContextController } from "./EnterpriseContextController.js";
|
||||
|
||||
const configContext = Symbol("configContext");
|
||||
const modalController = Symbol("modalController");
|
||||
const versionContext = Symbol("versionContext");
|
||||
|
||||
export abstract class LightInterface extends AKElement implements ThemedElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.dataset.akInterfaceRoot = this.tagName.toLowerCase();
|
||||
|
||||
if (!document.documentElement.dataset.theme) {
|
||||
applyDocumentTheme(globalAK().brand.uiTheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class Interface extends LightInterface implements ThemedElement {
|
||||
static styles = [PFBase];
|
||||
protected [configContext]: ConfigContextController;
|
||||
|
||||
protected [modalController]: ModalOrchestrationController;
|
||||
|
||||
@state()
|
||||
public config?: Config;
|
||||
|
||||
@state()
|
||||
public brand?: CurrentBrand;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.addController(new BrandContextController(this));
|
||||
this[configContext] = new ConfigContextController(this);
|
||||
this[modalController] = new ModalOrchestrationController(this);
|
||||
}
|
||||
}
|
||||
|
||||
export interface AkAuthenticatedInterface extends ThemedElement {
|
||||
licenseSummary?: LicenseSummary;
|
||||
version?: Version;
|
||||
}
|
||||
|
||||
const enterpriseContext = Symbol("enterpriseContext");
|
||||
|
||||
export class AuthenticatedInterface extends Interface implements AkAuthenticatedInterface {
|
||||
[enterpriseContext]!: EnterpriseContextController;
|
||||
[versionContext]!: VersionContextController;
|
||||
|
||||
@state()
|
||||
public uiConfig?: UIConfig;
|
||||
|
||||
@state()
|
||||
public licenseSummary?: LicenseSummary;
|
||||
|
||||
@state()
|
||||
public version?: Version;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this[enterpriseContext] = new EnterpriseContextController(this);
|
||||
this[versionContext] = new VersionContextController(this);
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import { authentikVersionContext } from "@goauthentik/elements/AuthentikContexts";
|
||||
import type { ReactiveElementHost } from "@goauthentik/elements/types.js";
|
||||
|
||||
import { ContextProvider } from "@lit/context";
|
||||
import type { ReactiveController } from "lit";
|
||||
|
||||
import type { Version } from "@goauthentik/api";
|
||||
import { AdminApi } from "@goauthentik/api";
|
||||
|
||||
import type { AkAuthenticatedInterface } from "./Interface";
|
||||
|
||||
export class VersionContextController implements ReactiveController {
|
||||
host!: ReactiveElementHost<AkAuthenticatedInterface>;
|
||||
|
||||
context!: ContextProvider<{ __context__: Version | undefined }>;
|
||||
|
||||
constructor(host: ReactiveElementHost<AkAuthenticatedInterface>) {
|
||||
this.host = host;
|
||||
this.context = new ContextProvider(this.host, {
|
||||
context: authentikVersionContext,
|
||||
initialValue: undefined,
|
||||
});
|
||||
this.fetch = this.fetch.bind(this);
|
||||
this.fetch();
|
||||
}
|
||||
|
||||
fetch() {
|
||||
new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve().then((version) => {
|
||||
this.context.setValue(version);
|
||||
this.host.version = version;
|
||||
});
|
||||
}
|
||||
|
||||
hostConnected() {
|
||||
window.addEventListener(EVENT_REFRESH, this.fetch);
|
||||
}
|
||||
|
||||
hostDisconnected() {
|
||||
window.removeEventListener(EVENT_REFRESH, this.fetch);
|
||||
}
|
||||
|
||||
hostUpdate() {
|
||||
// If the Interface changes its version information for some reason,
|
||||
// we should notify all users of the context of that change. doesn't
|
||||
if (this.host.version !== this.context.value) {
|
||||
this.context.setValue(this.host.version);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
import { authentikBrandContext } from "@goauthentik/elements/AuthentikContexts";
|
||||
import { createMixin } from "@goauthentik/elements/types";
|
||||
|
||||
import { consume } from "@lit/context";
|
||||
import { state } from "lit/decorators.js";
|
||||
|
||||
import type { CurrentBrand } from "@goauthentik/api";
|
||||
|
||||
/**
|
||||
* A mixin that provides the current brand to the element.
|
||||
*/
|
||||
export interface StyleBrandMixin {
|
||||
/**
|
||||
* The current style branding configuration.
|
||||
*/
|
||||
brand: CurrentBrand;
|
||||
}
|
||||
|
||||
/**
|
||||
* A mixin that provides the current brand to the element.
|
||||
*
|
||||
* @category Mixin
|
||||
*
|
||||
* @see {@link https://lit.dev/docs/composition/mixins/#mixins-in-typescript | Lit Mixins}
|
||||
*/
|
||||
export const WithBrandConfig = createMixin<StyleBrandMixin>(
|
||||
({
|
||||
/**
|
||||
* The superclass constructor to extend.
|
||||
*/
|
||||
SuperClass,
|
||||
/**
|
||||
* Whether or not to subscribe to the context.
|
||||
*/
|
||||
subscribe = true,
|
||||
}) => {
|
||||
abstract class StyleBrandProvider extends SuperClass implements StyleBrandMixin {
|
||||
@consume({
|
||||
context: authentikBrandContext,
|
||||
subscribe,
|
||||
})
|
||||
@state()
|
||||
public brand!: CurrentBrand;
|
||||
}
|
||||
|
||||
return StyleBrandProvider;
|
||||
},
|
||||
);
|
@ -1,4 +0,0 @@
|
||||
import { AuthenticatedInterface, Interface, LightInterface } from "./Interface";
|
||||
|
||||
export { Interface, AuthenticatedInterface, LightInterface };
|
||||
export default Interface;
|
@ -1,35 +0,0 @@
|
||||
import { authentikVersionContext } from "@goauthentik/elements/AuthentikContexts";
|
||||
|
||||
import { consume } from "@lit/context";
|
||||
import { Constructor } from "@lit/reactive-element/decorators/base.js";
|
||||
import type { LitElement } from "lit";
|
||||
|
||||
import type { Version } from "@goauthentik/api";
|
||||
|
||||
/**
|
||||
* A consumer that provides version information to the element.
|
||||
*/
|
||||
export declare class VersionConsumer {
|
||||
/**
|
||||
* The current version of the application.
|
||||
*/
|
||||
public readonly version: Version;
|
||||
}
|
||||
|
||||
export function WithVersion<T extends Constructor<LitElement>>(
|
||||
/**
|
||||
* The superclass constructor to extend.
|
||||
*/
|
||||
SuperClass: T,
|
||||
/**
|
||||
* Whether or not to subscribe to the context.
|
||||
*/
|
||||
subscribe = true,
|
||||
) {
|
||||
class VersionProvider extends SuperClass {
|
||||
@consume({ context: authentikVersionContext, subscribe })
|
||||
public version!: Version;
|
||||
}
|
||||
|
||||
return VersionProvider as Constructor<VersionConsumer> & T;
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import { type SlottedTemplateResult, type Spread } from "@goauthentik/elements/types";
|
||||
import type { SlottedTemplateResult, Spread } from "@goauthentik/elements/types";
|
||||
import { spread } from "@open-wc/lit-helpers";
|
||||
|
||||
import { html, nothing } from "lit";
|
||||
import { css, html, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { classMap } from "lit/directives/class-map.js";
|
||||
|
||||
@ -44,15 +44,26 @@ export class Label extends AKElement implements ILabel {
|
||||
@property({ type: Boolean })
|
||||
compact = false;
|
||||
|
||||
static get styles() {
|
||||
return [PFBase, PFLabel];
|
||||
}
|
||||
static styles = [
|
||||
PFBase,
|
||||
PFLabel,
|
||||
css`
|
||||
:host([theme="dark"]) {
|
||||
.pf-m-grey {
|
||||
--pf-c-label__icon--Color: var(--ak-dark-background);
|
||||
--pf-c-label__content--Color: var(--ak-dark-background);
|
||||
}
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
get classesAndIcon() {
|
||||
const chrome = chromeList.find(
|
||||
([level, color]) => this.color === level || this.color === color,
|
||||
);
|
||||
|
||||
const [illo, icon] = chrome ? chrome.slice(2) : ["pf-m-grey", "fa-info-circle"];
|
||||
|
||||
return {
|
||||
classes: {
|
||||
"pf-c-label": true,
|
||||
@ -65,6 +76,7 @@ export class Label extends AKElement implements ILabel {
|
||||
|
||||
render() {
|
||||
const { classes, icon } = this.classesAndIcon;
|
||||
|
||||
return html`<span class=${classMap(classes)}>
|
||||
<span class="pf-c-label__content">
|
||||
<span class="pf-c-label__icon">
|
||||
|
@ -5,7 +5,7 @@ import { customEvent } from "@goauthentik/elements/utils/customEvents";
|
||||
import { html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import { WithBrandConfig } from "../Interface/brandProvider";
|
||||
import { WithBrandConfig } from "../mixins/branding";
|
||||
import { initializeLocalization } from "./configureLocale";
|
||||
import type { LocaleGetter, LocaleSetter } from "./configureLocale";
|
||||
import { DEFAULT_LOCALE, autoDetectLanguage, getBestMatchLocale } from "./helpers";
|
||||
@ -70,7 +70,7 @@ export class LocaleContext extends WithBrandConfig(AKElement) {
|
||||
}
|
||||
|
||||
updateLocale(requestedLocale: string | undefined = undefined) {
|
||||
const localeRequest = autoDetectLanguage(requestedLocale, this.brand?.defaultLocale);
|
||||
const localeRequest = autoDetectLanguage(requestedLocale, this.brand.defaultLocale);
|
||||
const locale = getBestMatchLocale(localeRequest);
|
||||
if (!locale) {
|
||||
console.warn(`authentik/locale: failed to find locale for code ${localeRequest}`);
|
||||
|
@ -1,22 +1,5 @@
|
||||
import { createContext, useContext } from "react";
|
||||
|
||||
/**
|
||||
* A parsed JSON module containing MDX content and metadata from ESBuild.
|
||||
*/
|
||||
export interface MDXModule {
|
||||
/**
|
||||
* The Markdown content of the module.
|
||||
*/
|
||||
content: string;
|
||||
/**
|
||||
* The public path of the module, typically identical to the docs page path.
|
||||
*/
|
||||
publicPath?: string;
|
||||
/**
|
||||
* The public directory of the module, used to resolve relative links.
|
||||
*/
|
||||
publicDirectory?: string;
|
||||
}
|
||||
import type { MDXModule } from "~docs/types";
|
||||
|
||||
/**
|
||||
* Fetches an MDX module from a URL or ESBuild static asset.
|
||||
|
@ -1,15 +1,14 @@
|
||||
import "@goauthentik/elements/Alert";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import {
|
||||
MDXModule,
|
||||
MDXModuleContext,
|
||||
fetchMDXModule,
|
||||
} from "@goauthentik/elements/ak-mdx/MDXModuleContext";
|
||||
import { MDXAnchor } from "@goauthentik/elements/ak-mdx/components/MDXAnchor";
|
||||
import { MDXWrapper } from "@goauthentik/elements/ak-mdx/components/MDXWrapper";
|
||||
import { remarkAdmonition } from "@goauthentik/elements/ak-mdx/remark/remark-admonition";
|
||||
import { remarkHeadings } from "@goauthentik/elements/ak-mdx/remark/remark-headings";
|
||||
import { remarkLists } from "@goauthentik/elements/ak-mdx/remark/remark-lists";
|
||||
import { globalAK } from "#common/global";
|
||||
import "#elements/Alert";
|
||||
import { AKElement } from "#elements/Base";
|
||||
import { MDXModuleContext, fetchMDXModule } from "#elements/ak-mdx/MDXModuleContext";
|
||||
import { MDXAnchor } from "#elements/ak-mdx/components/MDXAnchor";
|
||||
import { MDXWrapper } from "#elements/ak-mdx/components/MDXWrapper";
|
||||
import { remarkAdmonition } from "#elements/ak-mdx/remark/remark-admonition";
|
||||
import { remarkHeadings } from "#elements/ak-mdx/remark/remark-headings";
|
||||
import { remarkLists } from "#elements/ak-mdx/remark/remark-lists";
|
||||
import { WithAuthentikConfig } from "#elements/mixins/config";
|
||||
import { DistDirectoryName, StaticDirectoryName } from "#paths";
|
||||
import { compile as compileMDX, run as runMDX } from "@mdx-js/mdx";
|
||||
import apacheGrammar from "highlight.js/lib/languages/apache";
|
||||
import diffGrammar from "highlight.js/lib/languages/diff";
|
||||
@ -26,11 +25,12 @@ import remarkFrontmatter from "remark-frontmatter";
|
||||
import remarkGFM from "remark-gfm";
|
||||
import remarkMdxFrontmatter from "remark-mdx-frontmatter";
|
||||
import remarkParse from "remark-parse";
|
||||
import type { MDXModule } from "~docs/types";
|
||||
|
||||
import { css } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import OneDark from "@goauthentik/common/styles/one-dark.css";
|
||||
import OneDark from "#common/styles/one-dark.css";
|
||||
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
||||
import PFList from "@patternfly/patternfly/components/List/list.css";
|
||||
import PFTable from "@patternfly/patternfly/components/Table/table.css";
|
||||
@ -54,7 +54,7 @@ const highlightThemeOptions: HighlightOptions = {
|
||||
export type Replacer = (input: string) => string;
|
||||
|
||||
@customElement("ak-mdx")
|
||||
export class AKMDX extends AKElement {
|
||||
export class AKMDX extends WithAuthentikConfig(AKElement) {
|
||||
@property({
|
||||
reflect: true,
|
||||
})
|
||||
@ -166,9 +166,17 @@ export class AKMDX extends AKElement {
|
||||
this.#reactRoot = createRoot(this.shadowRoot!);
|
||||
|
||||
let nextMDXModule: MDXModule | undefined;
|
||||
const { relBase } = globalAK().api;
|
||||
|
||||
if (this.url) {
|
||||
nextMDXModule = await fetchMDXModule(this.url);
|
||||
const pathname =
|
||||
relBase +
|
||||
StaticDirectoryName +
|
||||
"/" +
|
||||
DistDirectoryName +
|
||||
this.url.slice(this.url.indexOf("/assets"));
|
||||
|
||||
nextMDXModule = await fetchMDXModule(pathname);
|
||||
} else {
|
||||
nextMDXModule = {
|
||||
content: this.content,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { WithLicenseSummary } from "#elements/mixins/license";
|
||||
import { globalAK } from "@goauthentik/common/global";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { html, nothing } from "lit";
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { WithVersion } from "#elements/mixins/version";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import { WithVersion } from "@goauthentik/elements/Interface/versionProvider";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { html, nothing } from "lit";
|
||||
|
74
web/src/elements/controllers/BrandContextController.ts
Normal file
74
web/src/elements/controllers/BrandContextController.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { DEFAULT_CONFIG } from "#common/api/config";
|
||||
import { EVENT_REFRESH } from "#common/constants";
|
||||
import { isAbortError } from "#common/errors/network";
|
||||
import { BrandingContext, BrandingMixin } from "#elements/mixins/branding";
|
||||
import type { ReactiveElementHost } from "#elements/types";
|
||||
|
||||
import { Context, ContextProvider } from "@lit/context";
|
||||
import type { ReactiveController } from "lit";
|
||||
|
||||
import { CoreApi, CurrentBrand } from "@goauthentik/api";
|
||||
|
||||
export class BrandingContextController implements ReactiveController {
|
||||
#log = console.debug.bind(console, `authentik/controller/branding`);
|
||||
#abortController: null | AbortController = null;
|
||||
|
||||
#host: ReactiveElementHost<BrandingMixin>;
|
||||
#context: ContextProvider<Context<unknown, CurrentBrand>>;
|
||||
|
||||
constructor(host: ReactiveElementHost<BrandingMixin>, initialValue: CurrentBrand) {
|
||||
this.#host = host;
|
||||
this.#context = new ContextProvider(this.#host, {
|
||||
context: BrandingContext,
|
||||
initialValue,
|
||||
});
|
||||
this.#host.brand = initialValue;
|
||||
}
|
||||
|
||||
#fetch = () => {
|
||||
this.#log("Fetching configuration...");
|
||||
|
||||
this.#abortController?.abort();
|
||||
|
||||
this.#abortController = new AbortController();
|
||||
|
||||
return new CoreApi(DEFAULT_CONFIG)
|
||||
.coreBrandsCurrentRetrieve({
|
||||
signal: this.#abortController.signal,
|
||||
})
|
||||
.then((brand) => {
|
||||
this.#context.setValue(brand);
|
||||
this.#host.brand = brand;
|
||||
})
|
||||
|
||||
.catch((error: unknown) => {
|
||||
if (isAbortError(error)) {
|
||||
this.#log("Aborted fetching brand");
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
})
|
||||
.finally(() => {
|
||||
this.#abortController = null;
|
||||
});
|
||||
};
|
||||
|
||||
public hostConnected() {
|
||||
window.addEventListener(EVENT_REFRESH, this.#fetch);
|
||||
this.#fetch();
|
||||
}
|
||||
|
||||
public hostDisconnected() {
|
||||
window.removeEventListener(EVENT_REFRESH, this.#fetch);
|
||||
this.#abortController?.abort();
|
||||
}
|
||||
|
||||
public hostUpdate() {
|
||||
// If the Interface changes its brand information for some reason,
|
||||
// we should notify all users of the context of that change. doesn't
|
||||
if (this.#host.brand && this.#host.brand !== this.#context.value) {
|
||||
this.#context.setValue(this.#host.brand);
|
||||
}
|
||||
}
|
||||
}
|
79
web/src/elements/controllers/ConfigContextController.ts
Normal file
79
web/src/elements/controllers/ConfigContextController.ts
Normal file
@ -0,0 +1,79 @@
|
||||
import { DEFAULT_CONFIG } from "#common/api/config";
|
||||
import { EVENT_REFRESH } from "#common/constants";
|
||||
import { isAbortError } from "#common/errors/network";
|
||||
import { AKConfigMixin, AuthentikConfigContext } from "#elements/mixins/config";
|
||||
import type { ReactiveElementHost } from "#elements/types";
|
||||
|
||||
import { Context, ContextProvider } from "@lit/context";
|
||||
import type { ReactiveController } from "lit";
|
||||
|
||||
import { Config, RootApi } from "@goauthentik/api";
|
||||
|
||||
/**
|
||||
* A controller that provides the application configuration to the element.
|
||||
*/
|
||||
export class ConfigContextController implements ReactiveController {
|
||||
#log = console.debug.bind(console, `authentik/controller/config`);
|
||||
#abortController: null | AbortController = null;
|
||||
|
||||
#host: ReactiveElementHost<AKConfigMixin>;
|
||||
#context: ContextProvider<Context<unknown, Config>>;
|
||||
|
||||
constructor(host: ReactiveElementHost<AKConfigMixin>, initialValue: Config) {
|
||||
this.#host = host;
|
||||
|
||||
this.#context = new ContextProvider(this.#host, {
|
||||
context: AuthentikConfigContext,
|
||||
initialValue,
|
||||
});
|
||||
|
||||
this.#host.authentikConfig = initialValue;
|
||||
}
|
||||
|
||||
#fetch = () => {
|
||||
this.#log("Fetching configuration...");
|
||||
|
||||
this.#abortController?.abort();
|
||||
|
||||
this.#abortController = new AbortController();
|
||||
|
||||
return new RootApi(DEFAULT_CONFIG)
|
||||
.rootConfigRetrieve({
|
||||
signal: this.#abortController.signal,
|
||||
})
|
||||
.then((authentikConfig) => {
|
||||
this.#context.setValue(authentikConfig);
|
||||
this.#host.authentikConfig = authentikConfig;
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
if (isAbortError(error)) {
|
||||
this.#log("Aborted fetching configuration");
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
})
|
||||
.finally(() => {
|
||||
this.#abortController = null;
|
||||
});
|
||||
};
|
||||
|
||||
public hostConnected() {
|
||||
window.addEventListener(EVENT_REFRESH, this.#fetch);
|
||||
this.#fetch();
|
||||
}
|
||||
|
||||
public hostDisconnected() {
|
||||
window.removeEventListener(EVENT_REFRESH, this.#fetch);
|
||||
this.#abortController?.abort();
|
||||
}
|
||||
|
||||
public hostUpdate() {
|
||||
// If the Interface changes its config information, we should notify all
|
||||
// users of the context of that change, without creating an infinite
|
||||
// loop of resets.
|
||||
if (this.#host.authentikConfig && this.#host.authentikConfig !== this.#context.value) {
|
||||
this.#context.setValue(this.#host.authentikConfig);
|
||||
}
|
||||
}
|
||||
}
|
77
web/src/elements/controllers/EnterpriseContextController.ts
Normal file
77
web/src/elements/controllers/EnterpriseContextController.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import { DEFAULT_CONFIG } from "#common/api/config";
|
||||
import { EVENT_REFRESH_ENTERPRISE } from "#common/constants";
|
||||
import { isAbortError } from "#common/errors/network";
|
||||
import { LicenseContext, LicenseMixin } from "#elements/mixins/license";
|
||||
import type { ReactiveElementHost } from "#elements/types";
|
||||
|
||||
import { Context, ContextProvider } from "@lit/context";
|
||||
import type { ReactiveController } from "lit";
|
||||
|
||||
import { EnterpriseApi, LicenseSummary } from "@goauthentik/api";
|
||||
|
||||
export class LicenseContextController implements ReactiveController {
|
||||
#log = console.debug.bind(console, `authentik/controller/license`);
|
||||
#abortController: null | AbortController = null;
|
||||
|
||||
#host: ReactiveElementHost<LicenseMixin>;
|
||||
#context: ContextProvider<Context<unknown, LicenseSummary>>;
|
||||
|
||||
constructor(host: ReactiveElementHost<LicenseMixin>, initialValue?: LicenseSummary) {
|
||||
this.#host = host;
|
||||
this.#context = new ContextProvider(this.#host, {
|
||||
context: LicenseContext,
|
||||
initialValue: initialValue,
|
||||
});
|
||||
}
|
||||
|
||||
#fetch = () => {
|
||||
this.#log("Fetching license summary...");
|
||||
|
||||
this.#abortController?.abort();
|
||||
|
||||
this.#abortController = new AbortController();
|
||||
|
||||
return new EnterpriseApi(DEFAULT_CONFIG)
|
||||
.enterpriseLicenseSummaryRetrieve(
|
||||
{},
|
||||
{
|
||||
signal: this.#abortController.signal,
|
||||
},
|
||||
)
|
||||
.then((enterprise) => {
|
||||
this.#context.setValue(enterprise);
|
||||
this.#host.licenseSummary = enterprise;
|
||||
})
|
||||
|
||||
.catch((error: unknown) => {
|
||||
if (isAbortError(error)) {
|
||||
this.#log("Aborted fetching license summary");
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
})
|
||||
.finally(() => {
|
||||
this.#abortController = null;
|
||||
});
|
||||
};
|
||||
|
||||
public hostConnected() {
|
||||
window.addEventListener(EVENT_REFRESH_ENTERPRISE, this.#fetch);
|
||||
this.#fetch();
|
||||
}
|
||||
|
||||
public hostDisconnected() {
|
||||
window.removeEventListener(EVENT_REFRESH_ENTERPRISE, this.#fetch);
|
||||
this.#abortController?.abort();
|
||||
}
|
||||
|
||||
public hostUpdate() {
|
||||
// If the Interface changes its config information, we should notify all
|
||||
// users of the context of that change, without creating an infinite
|
||||
// loop of resets.
|
||||
if (this.#host.licenseSummary && this.#host.licenseSummary !== this.#context.value) {
|
||||
this.#context.setValue(this.#host.licenseSummary);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,8 @@
|
||||
import { bound } from "@goauthentik/elements/decorators/bound.js";
|
||||
import { LitElement, ReactiveController } from "lit";
|
||||
|
||||
import { LitElement, ReactiveController, ReactiveControllerHost } from "lit";
|
||||
|
||||
type ReactiveElementHost = Partial<ReactiveControllerHost> & LitElement;
|
||||
|
||||
type ModalElement = LitElement & { closeModal(): void | boolean };
|
||||
interface ModalElement extends LitElement {
|
||||
closeModal(): void | boolean;
|
||||
}
|
||||
|
||||
export class ModalShowEvent extends Event {
|
||||
modal: ModalElement;
|
||||
@ -50,75 +48,70 @@ const modalIsLive = (modal: ModalElement) => modal.isConnected && modal.checkVis
|
||||
*/
|
||||
|
||||
export class ModalOrchestrationController implements ReactiveController {
|
||||
host!: ReactiveElementHost;
|
||||
#knownModals: ModalElement[] = [];
|
||||
|
||||
knownModals: ModalElement[] = [];
|
||||
|
||||
constructor(host: ReactiveElementHost) {
|
||||
this.host = host;
|
||||
host.addController(this);
|
||||
}
|
||||
|
||||
hostConnected() {
|
||||
public hostConnected() {
|
||||
window.addEventListener("keyup", this.handleKeyup);
|
||||
window.addEventListener("ak-modal-show", this.addModal);
|
||||
window.addEventListener("ak-modal-show", this.#addModal);
|
||||
window.addEventListener("ak-modal-hide", this.closeModal);
|
||||
}
|
||||
|
||||
hostDisconnected() {
|
||||
public hostDisconnected() {
|
||||
window.removeEventListener("keyup", this.handleKeyup);
|
||||
window.removeEventListener("ak-modal-show", this.addModal);
|
||||
window.removeEventListener("ak-modal-show", this.#addModal);
|
||||
window.removeEventListener("ak-modal-hide", this.closeModal);
|
||||
}
|
||||
|
||||
@bound
|
||||
addModal(e: ModalShowEvent) {
|
||||
this.knownModals = [...this.knownModals, e.modal];
|
||||
}
|
||||
#addModal = (e: ModalShowEvent) => {
|
||||
this.#knownModals = [...this.#knownModals, e.modal];
|
||||
};
|
||||
|
||||
scheduleCleanup(modal: ModalElement) {
|
||||
setTimeout(() => {
|
||||
this.knownModals = this.knownModals.filter((m) => modalIsLive(m) && modal !== m);
|
||||
}, 0);
|
||||
}
|
||||
#cleanupFrameID = -1;
|
||||
|
||||
@bound
|
||||
closeModal(e: ModalHideEvent) {
|
||||
#scheduleCleanup = (modal: ModalElement) => {
|
||||
cancelAnimationFrame(this.#cleanupFrameID);
|
||||
|
||||
this.#cleanupFrameID = requestAnimationFrame(() => {
|
||||
this.#knownModals = this.#knownModals.filter((m) => modalIsLive(m) && modal !== m);
|
||||
});
|
||||
};
|
||||
|
||||
closeModal = (e: ModalHideEvent) => {
|
||||
const modal = e.modal;
|
||||
if (!modalIsLive(modal)) {
|
||||
return;
|
||||
}
|
||||
if (modal.closeModal() !== false) {
|
||||
this.scheduleCleanup(modal);
|
||||
}
|
||||
}
|
||||
|
||||
removeTopmostModal() {
|
||||
const knownModals = [...this.knownModals];
|
||||
if (!modalIsLive(modal)) return;
|
||||
|
||||
if (modal.closeModal() !== false) {
|
||||
this.#scheduleCleanup(modal);
|
||||
}
|
||||
};
|
||||
|
||||
#removeTopmostModal = () => {
|
||||
const knownModals = [...this.#knownModals];
|
||||
|
||||
// Pop off modals until you find the first live one, schedule it to be closed, and make that
|
||||
// cleaned list the current state. Since this is our *only* state object, this has the
|
||||
// effect of creating a new "knownModals" collection with some semantics.
|
||||
while (true) {
|
||||
const modal = knownModals.pop();
|
||||
if (!modal) {
|
||||
break;
|
||||
}
|
||||
if (!modalIsLive(modal)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!modal) break;
|
||||
|
||||
if (!modalIsLive(modal)) continue;
|
||||
|
||||
if (modal.closeModal() !== false) {
|
||||
this.scheduleCleanup(modal);
|
||||
this.#scheduleCleanup(modal);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
this.knownModals = knownModals;
|
||||
}
|
||||
this.#knownModals = knownModals;
|
||||
};
|
||||
|
||||
@bound
|
||||
handleKeyup(e: KeyboardEvent) {
|
||||
handleKeyup = ({ key }: KeyboardEvent) => {
|
||||
// The latter handles Firefox 37 and earlier.
|
||||
if (e.key === "Escape" || e.key === "Esc") {
|
||||
this.removeTopmostModal();
|
||||
if (key === "Escape" || key === "Esc") {
|
||||
this.#removeTopmostModal();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
73
web/src/elements/controllers/VersionContextController.ts
Normal file
73
web/src/elements/controllers/VersionContextController.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import { DEFAULT_CONFIG } from "#common/api/config";
|
||||
import { EVENT_REFRESH } from "#common/constants";
|
||||
import { isAbortError } from "#common/errors/network";
|
||||
import { VersionContext, VersionMixin } from "#elements/mixins/version";
|
||||
import type { ReactiveElementHost } from "#elements/types";
|
||||
|
||||
import { Context, ContextProvider } from "@lit/context";
|
||||
import type { ReactiveController } from "lit";
|
||||
|
||||
import { AdminApi, Version } from "@goauthentik/api";
|
||||
|
||||
export class VersionContextController implements ReactiveController {
|
||||
#log = console.debug.bind(console, `authentik/controller/version`);
|
||||
#abortController: null | AbortController = null;
|
||||
|
||||
#host: ReactiveElementHost<VersionMixin>;
|
||||
#context: ContextProvider<Context<unknown, Version>>;
|
||||
|
||||
constructor(host: ReactiveElementHost<VersionMixin>, initialValue?: Version) {
|
||||
this.#host = host;
|
||||
this.#context = new ContextProvider(this.#host, {
|
||||
context: VersionContext,
|
||||
initialValue,
|
||||
});
|
||||
}
|
||||
|
||||
#fetch = () => {
|
||||
this.#log("Fetching latest version...");
|
||||
|
||||
this.#abortController?.abort();
|
||||
|
||||
this.#abortController = new AbortController();
|
||||
|
||||
return new AdminApi(DEFAULT_CONFIG)
|
||||
.adminVersionRetrieve({
|
||||
signal: this.#abortController.signal,
|
||||
})
|
||||
.then((version) => {
|
||||
this.#context.setValue(version);
|
||||
this.#host.version = version;
|
||||
})
|
||||
|
||||
.catch((error: unknown) => {
|
||||
if (isAbortError(error)) {
|
||||
this.#log("Aborted fetching license summary");
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
})
|
||||
.finally(() => {
|
||||
this.#abortController = null;
|
||||
});
|
||||
};
|
||||
|
||||
public hostConnected() {
|
||||
window.addEventListener(EVENT_REFRESH, this.#fetch);
|
||||
this.#fetch();
|
||||
}
|
||||
|
||||
public hostDisconnected() {
|
||||
window.removeEventListener(EVENT_REFRESH, this.#fetch);
|
||||
this.#abortController?.abort();
|
||||
}
|
||||
|
||||
public hostUpdate() {
|
||||
// If the Interface changes its version information for some reason,
|
||||
// we should notify all users of the context of that change. doesn't
|
||||
if (this.#host.version && this.#host.version !== this.#context.value) {
|
||||
this.#context.setValue(this.#host.version);
|
||||
}
|
||||
}
|
||||
}
|
80
web/src/elements/mixins/branding.ts
Normal file
80
web/src/elements/mixins/branding.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import { DefaultBrand } from "#common/ui/config";
|
||||
import { createMixin } from "#elements/types";
|
||||
|
||||
import { consume, createContext } from "@lit/context";
|
||||
|
||||
import type { CurrentBrand, FooterLink } from "@goauthentik/api";
|
||||
|
||||
/**
|
||||
* The Lit context for application branding.
|
||||
*
|
||||
* @category Context
|
||||
* @see {@linkcode BrandingMixin}
|
||||
* @see {@linkcode WithBrandConfig}
|
||||
*/
|
||||
export const BrandingContext = createContext<CurrentBrand>(
|
||||
Symbol.for("authentik-branding-context"),
|
||||
);
|
||||
|
||||
/**
|
||||
* A mixin that provides the current brand to the element.
|
||||
*
|
||||
* @see {@linkcode WithBrandConfig}
|
||||
*/
|
||||
export interface BrandingMixin {
|
||||
/**
|
||||
* The current style branding configuration.
|
||||
*/
|
||||
readonly brand: Readonly<CurrentBrand>;
|
||||
|
||||
readonly brandingTitle: string;
|
||||
readonly brandingLogo: string;
|
||||
readonly brandingFavicon: string;
|
||||
readonly brandingFooterLinks: FooterLink[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A mixin that provides the current brand to the element.
|
||||
*
|
||||
* @category Mixin
|
||||
*
|
||||
* @see {@link https://lit.dev/docs/composition/mixins/#mixins-in-typescript | Lit Mixins}
|
||||
*/
|
||||
export const WithBrandConfig = createMixin<BrandingMixin>(
|
||||
({
|
||||
/**
|
||||
* The superclass constructor to extend.
|
||||
*/
|
||||
SuperClass,
|
||||
/**
|
||||
* Whether or not to subscribe to the context.
|
||||
*/
|
||||
subscribe = true,
|
||||
}) => {
|
||||
abstract class BrandingProvider extends SuperClass implements BrandingMixin {
|
||||
@consume({
|
||||
context: BrandingContext,
|
||||
subscribe,
|
||||
})
|
||||
public brand!: CurrentBrand;
|
||||
|
||||
public get brandingTitle(): string {
|
||||
return this.brand.brandingTitle ?? DefaultBrand.brandingTitle;
|
||||
}
|
||||
|
||||
public get brandingLogo(): string {
|
||||
return this.brand.brandingLogo ?? DefaultBrand.brandingLogo;
|
||||
}
|
||||
|
||||
public get brandingFavicon(): string {
|
||||
return this.brand.brandingFavicon ?? DefaultBrand.brandingFavicon;
|
||||
}
|
||||
|
||||
public get brandingFooterLinks(): FooterLink[] {
|
||||
return this.brand.uiFooterLinks ?? DefaultBrand.uiFooterLinks;
|
||||
}
|
||||
}
|
||||
|
||||
return BrandingProvider;
|
||||
},
|
||||
);
|
@ -1,10 +1,7 @@
|
||||
import { authentikConfigContext } from "@goauthentik/elements/AuthentikContexts";
|
||||
import { AKConfigMixin } from "#elements/mixins/config";
|
||||
import { createMixin } from "@goauthentik/elements/types";
|
||||
|
||||
import { consume } from "@lit/context";
|
||||
|
||||
import { CapabilitiesEnum } from "@goauthentik/api";
|
||||
import { Config } from "@goauthentik/api";
|
||||
|
||||
/**
|
||||
* A consumer that provides the capability methods to the element.
|
||||
@ -22,13 +19,6 @@ export interface CapabilitiesMixin {
|
||||
): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lexically-scoped symbol for the capabilities configuration.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const kCapabilitiesConfig: unique symbol = Symbol("capabilitiesConfig");
|
||||
|
||||
/**
|
||||
* A mixin that provides the capability methods to the element.
|
||||
*
|
||||
@ -37,14 +27,14 @@ const kCapabilitiesConfig: unique symbol = Symbol("capabilitiesConfig");
|
||||
* After importing, simply mixin this function:
|
||||
*
|
||||
* ```ts
|
||||
* export class AkMyNiftyNewFeature extends withCapabilitiesContext(AKElement) {
|
||||
* export class AkMyNiftyNewFeature extends WithCapabilitiesConfig(AKElement) {
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* And then if you need to check on a capability:
|
||||
*
|
||||
* ```ts
|
||||
* if (this.can(CapabilitiesEnum.IsEnterprise) { ... }
|
||||
* if (this.can(CapabilitiesEnum.IsEnterprise)) { ... }
|
||||
* ```
|
||||
*
|
||||
*
|
||||
@ -53,21 +43,15 @@ const kCapabilitiesConfig: unique symbol = Symbol("capabilitiesConfig");
|
||||
* @category Mixin
|
||||
*
|
||||
*/
|
||||
export const WithCapabilitiesConfig = createMixin<CapabilitiesMixin>(
|
||||
({ SuperClass, subscribe = true }) => {
|
||||
export const WithCapabilitiesConfig = createMixin<CapabilitiesMixin, AKConfigMixin>(
|
||||
({ SuperClass }) => {
|
||||
abstract class CapabilitiesProvider extends SuperClass implements CapabilitiesMixin {
|
||||
@consume({
|
||||
context: authentikConfigContext,
|
||||
subscribe,
|
||||
})
|
||||
private readonly [kCapabilitiesConfig]: Config | undefined;
|
||||
|
||||
public can(capability: CapabilitiesEnum) {
|
||||
const config = this[kCapabilitiesConfig];
|
||||
const config = this.authentikConfig;
|
||||
|
||||
if (!config) {
|
||||
throw new Error(
|
||||
"ConfigContext: Attempted to access site configuration before initialization.",
|
||||
`ConfigContext: Attempted to check capability "${capability}" before initialization. Does the element have the AuthentikConfigMixin applied?`,
|
||||
);
|
||||
}
|
||||
|
@ -1,12 +1,23 @@
|
||||
import { authentikConfigContext } from "@goauthentik/elements/AuthentikContexts";
|
||||
import { createMixin } from "@goauthentik/elements/types";
|
||||
|
||||
import { consume } from "@lit/context";
|
||||
import { consume, createContext } from "@lit/context";
|
||||
|
||||
import type { Config } from "@goauthentik/api";
|
||||
|
||||
/**
|
||||
* The Lit context for the application configuration.
|
||||
*
|
||||
* @category Context
|
||||
* @see {@linkcode AKConfigMixin}
|
||||
* @see {@linkcode WithAuthentikConfig}
|
||||
*/
|
||||
export const AuthentikConfigContext = createContext<Config>(Symbol.for("authentik-config-context"));
|
||||
|
||||
/**
|
||||
* A consumer that provides the application configuration to the element.
|
||||
*
|
||||
* @category Mixin
|
||||
* @see {@linkcode WithAuthentikConfig}
|
||||
*/
|
||||
export interface AKConfigMixin {
|
||||
/**
|
||||
@ -33,7 +44,7 @@ export const WithAuthentikConfig = createMixin<AKConfigMixin>(
|
||||
}) => {
|
||||
abstract class AKConfigProvider extends SuperClass implements AKConfigMixin {
|
||||
@consume({
|
||||
context: authentikConfigContext,
|
||||
context: AuthentikConfigContext,
|
||||
subscribe,
|
||||
})
|
||||
public readonly authentikConfig!: Readonly<Config>;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user