Compare commits
1 Commits
better-ver
...
monorepo-v
Author | SHA1 | Date | |
---|---|---|---|
a4f92f5e30 |
@ -10,6 +10,9 @@ insert_final_newline = true
|
||||
[*.html]
|
||||
indent_size = 2
|
||||
|
||||
[schemas/*.json]
|
||||
indent_size = 2
|
||||
|
||||
[*.{yaml,yml}]
|
||||
indent_size = 2
|
||||
|
||||
|
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: web/package.json
|
||||
node-version-file: package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: web/package-lock.json
|
||||
cache-dependency-path: 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
|
||||
cd web && npm ci
|
||||
npm ci
|
||||
- name: Generate config
|
||||
shell: uv run python {0}
|
||||
run: |
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Re-usable workflow for a single-architecture build
|
||||
name: Single-arch Container build
|
||||
name: "Single-arch Container build"
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
@ -42,7 +42,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: docker/setup-qemu-action@v3.6.0
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- name: prepare variables
|
||||
- name: Prepare variables
|
||||
uses: ./.github/actions/docker-push-variables
|
||||
id: ev
|
||||
env:
|
||||
@ -64,12 +64,12 @@ jobs:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: make empty clients
|
||||
- name: Make empty clients
|
||||
if: ${{ inputs.release }}
|
||||
run: |
|
||||
mkdir -p ./gen-ts-api
|
||||
mkdir -p ./gen-go-api
|
||||
- name: generate ts client
|
||||
- name: Generate TypeScript API Client
|
||||
if: ${{ !inputs.release }}
|
||||
run: make gen-client-ts
|
||||
- name: Build Docker Image
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Re-usable workflow for a multi-architecture build
|
||||
name: Multi-arch container build
|
||||
name: "Multi-arch container build"
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
@ -49,7 +49,7 @@ jobs:
|
||||
shouldPush: ${{ steps.ev.outputs.shouldPush }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: prepare variables
|
||||
- name: Prepare variables
|
||||
uses: ./.github/actions/docker-push-variables
|
||||
id: ev
|
||||
env:
|
||||
@ -69,7 +69,7 @@ jobs:
|
||||
tag: ${{ fromJson(needs.get-tags.outputs.tags) }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: prepare variables
|
||||
- name: Prepare variables
|
||||
uses: ./.github/actions/docker-push-variables
|
||||
id: ev
|
||||
env:
|
||||
|
6
.github/workflows/api-py-publish.yml
vendored
6
.github/workflows/api-py-publish.yml
vendored
@ -1,4 +1,5 @@
|
||||
name: authentik-api-py-publish
|
||||
name: "Python API Publish"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
@ -7,6 +8,7 @@ on:
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
name: "Build and Publish"
|
||||
if: ${{ github.repository != 'goauthentik/authentik-internal' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
@ -30,7 +32,7 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version-file: "pyproject.toml"
|
||||
- name: Generate API Client
|
||||
- name: Generate Python API Client
|
||||
run: make gen-client-py
|
||||
- name: Publish package
|
||||
working-directory: gen-py-api/
|
||||
|
7
.github/workflows/api-ts-publish.yml
vendored
7
.github/workflows/api-ts-publish.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: authentik-api-ts-publish
|
||||
name: "TypeScript API Publish"
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
@ -7,6 +7,7 @@ on:
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
name: "Build and Publish"
|
||||
if: ${{ github.repository != 'goauthentik/authentik-internal' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -20,9 +21,9 @@ jobs:
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
node-version-file: package.json
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- name: Generate API Client
|
||||
- name: Generate TypeScript API Client
|
||||
run: make gen-client-ts
|
||||
- name: Publish package
|
||||
working-directory: gen-ts-api/
|
||||
|
4
.github/workflows/ci-aws-cfn.yml
vendored
4
.github/workflows/ci-aws-cfn.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: authentik-ci-aws-cfn
|
||||
name: "authentik CI AWS CloudFormation"
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -18,6 +18,7 @@ env:
|
||||
|
||||
jobs:
|
||||
check-changes-applied:
|
||||
name: "Check changes applied"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -36,6 +37,7 @@ jobs:
|
||||
uv run make aws-cfn
|
||||
git diff --exit-code
|
||||
ci-aws-cfn-mark:
|
||||
name: "CI AWS CloudFormation Mark"
|
||||
if: always()
|
||||
needs:
|
||||
- check-changes-applied
|
||||
|
3
.github/workflows/ci-main-daily.yml
vendored
3
.github/workflows/ci-main-daily.yml
vendored
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: authentik-ci-main-daily
|
||||
name: "authentik CI Main Daily"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@ -9,6 +9,7 @@ on:
|
||||
|
||||
jobs:
|
||||
test-container:
|
||||
name: "Test Container ${{ matrix.version }}"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
62
.github/workflows/ci-main.yml
vendored
62
.github/workflows/ci-main.yml
vendored
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: authentik-ci-main
|
||||
name: "authentik CI Main"
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -19,6 +19,7 @@ env:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: "Lint"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@ -33,9 +34,10 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
- name: run job
|
||||
- name: Run job ${{ matrix.job }}
|
||||
run: uv run make ci-${{ matrix.job }}
|
||||
test-migrations:
|
||||
name: "Test Migrations"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -44,6 +46,7 @@ jobs:
|
||||
- name: run migrations
|
||||
run: uv run python -m lifecycle.migrate
|
||||
test-make-seed:
|
||||
name: "Test Make Seed"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: seed
|
||||
@ -52,7 +55,7 @@ jobs:
|
||||
outputs:
|
||||
seed: ${{ steps.seed.outputs.seed }}
|
||||
test-migrations-from-stable:
|
||||
name: test-migrations-from-stable - PostgreSQL ${{ matrix.psql }} - Run ${{ matrix.run_id }}/5
|
||||
name: "Test Migrations From Stable - PostgreSQL ${{ matrix.psql }} - Run ${{ matrix.run_id }}/5"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
needs: test-make-seed
|
||||
@ -67,7 +70,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: checkout stable
|
||||
- name: Checkout Stable
|
||||
run: |
|
||||
# Copy current, latest config to local
|
||||
# Temporarly comment the .github backup while migrating to uv
|
||||
@ -84,9 +87,9 @@ jobs:
|
||||
with:
|
||||
postgresql_version: ${{ matrix.psql }}
|
||||
continue-on-error: true
|
||||
- name: run migrations to stable
|
||||
- name: Run migrations to stable
|
||||
run: poetry run python -m lifecycle.migrate
|
||||
- name: checkout current code
|
||||
- name: Checkout current code
|
||||
run: |
|
||||
set -x
|
||||
git fetch
|
||||
@ -97,10 +100,10 @@ jobs:
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
postgresql_version: ${{ matrix.psql }}
|
||||
- name: migrate to latest
|
||||
- name: Migrate to latest
|
||||
run: |
|
||||
uv run python -m lifecycle.migrate
|
||||
- name: run tests
|
||||
- name: Run tests
|
||||
env:
|
||||
# Test in the main database that we just migrated from the previous stable version
|
||||
AUTHENTIK_POSTGRESQL__TEST__NAME: authentik
|
||||
@ -110,7 +113,7 @@ jobs:
|
||||
run: |
|
||||
uv run make ci-test
|
||||
test-unittest:
|
||||
name: test-unittest - PostgreSQL ${{ matrix.psql }} - Run ${{ matrix.run_id }}/5
|
||||
name: "Unit tests - PostgreSQL ${{ matrix.psql }} - Run ${{ matrix.run_id }}/5"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
needs: test-make-seed
|
||||
@ -146,6 +149,7 @@ jobs:
|
||||
file: unittest.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
test-integration:
|
||||
name: "Integration tests"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
@ -154,7 +158,7 @@ jobs:
|
||||
uses: ./.github/actions/setup
|
||||
- name: Create k8s Kind Cluster
|
||||
uses: helm/kind-action@v1.12.0
|
||||
- name: run integration
|
||||
- name: Run integration
|
||||
run: |
|
||||
uv run coverage run manage.py test tests/integration
|
||||
uv run coverage xml
|
||||
@ -170,49 +174,50 @@ jobs:
|
||||
file: unittest.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
test-e2e:
|
||||
name: test-e2e (${{ matrix.job.name }})
|
||||
name: "Test E2E (${{ matrix.job.name }})"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job:
|
||||
- name: proxy
|
||||
- name: Proxy Provider
|
||||
glob: tests/e2e/test_provider_proxy*
|
||||
- name: oauth
|
||||
- name: OAuth2 Provider
|
||||
glob: tests/e2e/test_provider_oauth2* tests/e2e/test_source_oauth*
|
||||
- name: oauth-oidc
|
||||
- name: OIDC Provider
|
||||
glob: tests/e2e/test_provider_oidc*
|
||||
- name: saml
|
||||
- name: SAML Provider
|
||||
glob: tests/e2e/test_provider_saml* tests/e2e/test_source_saml*
|
||||
- name: ldap
|
||||
- name: LDAP Provider
|
||||
glob: tests/e2e/test_provider_ldap* tests/e2e/test_source_ldap*
|
||||
- name: radius
|
||||
- name: RADIUS Provider
|
||||
glob: tests/e2e/test_provider_radius*
|
||||
- name: scim
|
||||
- name: SCIM Source
|
||||
glob: tests/e2e/test_source_scim*
|
||||
- name: flows
|
||||
- name: Flows
|
||||
glob: tests/e2e/test_flows*
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
- name: Setup e2e env (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('web/package-lock.json', 'web/src/**') }}
|
||||
- name: prepare web ui
|
||||
key: ${{ runner.os }}-web-${{ hashFiles('./package-lock.json', 'web/src/**') }}
|
||||
- name: Prepare Web UI
|
||||
if: steps.cache-web.outputs.cache-hit != 'true'
|
||||
working-directory: web
|
||||
run: |
|
||||
npm ci
|
||||
make -C .. gen-client-ts
|
||||
npm run build
|
||||
- name: run e2e
|
||||
make gen-client-ts
|
||||
npm run build -w @goauthentik/web
|
||||
|
||||
npm run typecheck
|
||||
- name: Run E2E tests
|
||||
run: |
|
||||
uv run coverage run manage.py test ${{ matrix.job.glob }}
|
||||
uv run coverage xml
|
||||
@ -228,6 +233,7 @@ jobs:
|
||||
file: unittest.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
ci-core-mark:
|
||||
name: "CI Core Mark"
|
||||
if: always()
|
||||
needs:
|
||||
- lint
|
||||
@ -242,6 +248,7 @@ jobs:
|
||||
with:
|
||||
jobs: ${{ toJSON(needs) }}
|
||||
build:
|
||||
name: "Build"
|
||||
permissions:
|
||||
# Needed to upload container images to ghcr.io
|
||||
packages: write
|
||||
@ -255,6 +262,7 @@ jobs:
|
||||
image_name: ghcr.io/goauthentik/dev-server
|
||||
release: false
|
||||
pr-comment:
|
||||
name: "PR Comment"
|
||||
needs:
|
||||
- build
|
||||
runs-on: ubuntu-latest
|
||||
@ -267,7 +275,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: prepare variables
|
||||
- name: Prepare variables
|
||||
uses: ./.github/actions/docker-push-variables
|
||||
id: ev
|
||||
env:
|
||||
|
32
.github/workflows/ci-outpost.yml
vendored
32
.github/workflows/ci-outpost.yml
vendored
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: authentik-ci-outpost
|
||||
name: "authentik CI Outpost"
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -14,6 +14,7 @@ on:
|
||||
|
||||
jobs:
|
||||
lint-golint:
|
||||
name: "Lint Go"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -26,7 +27,7 @@ jobs:
|
||||
mkdir -p web/dist
|
||||
mkdir -p website/help
|
||||
touch web/dist/test website/help/test
|
||||
- name: Generate API
|
||||
- name: Generate Go API Client
|
||||
run: make gen-client-go
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v7
|
||||
@ -35,6 +36,7 @@ jobs:
|
||||
args: --timeout 5000s --verbose
|
||||
skip-cache: true
|
||||
test-unittest:
|
||||
name: "Unit Test Go"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -43,12 +45,13 @@ jobs:
|
||||
go-version-file: "go.mod"
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
- name: Generate API
|
||||
- name: Generate Go API Client
|
||||
run: make gen-client-go
|
||||
- name: Go unittests
|
||||
run: |
|
||||
go test -timeout 0 -v -race -coverprofile=coverage.out -covermode=atomic -cover ./...
|
||||
ci-outpost-mark:
|
||||
name: "CI Outpost Mark"
|
||||
if: always()
|
||||
needs:
|
||||
- lint-golint
|
||||
@ -59,6 +62,7 @@ jobs:
|
||||
with:
|
||||
jobs: ${{ toJSON(needs) }}
|
||||
build-container:
|
||||
name: "Build Container"
|
||||
timeout-minutes: 120
|
||||
needs:
|
||||
- ci-outpost-mark
|
||||
@ -85,7 +89,7 @@ jobs:
|
||||
uses: docker/setup-qemu-action@v3.6.0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: prepare variables
|
||||
- name: Prepare variables
|
||||
uses: ./.github/actions/docker-push-variables
|
||||
id: ev
|
||||
env:
|
||||
@ -99,7 +103,7 @@ jobs:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Generate API
|
||||
- name: Generate Go API Client
|
||||
run: make gen-client-go
|
||||
- name: Build Docker Image
|
||||
id: push
|
||||
@ -122,6 +126,7 @@ jobs:
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
build-binary:
|
||||
name: "Build Binary"
|
||||
timeout-minutes: 120
|
||||
needs:
|
||||
- ci-outpost-mark
|
||||
@ -140,21 +145,22 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Install Node.js dependencies
|
||||
run: npm ci
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: web/package-lock.json
|
||||
- name: Generate API
|
||||
- name: Generate Go API Client
|
||||
run: make gen-client-go
|
||||
- name: Build web
|
||||
working-directory: web/
|
||||
run: |
|
||||
npm ci
|
||||
npm run build-proxy
|
||||
npm run build-proxy -w @goauthentik/web
|
||||
- name: Build outpost
|
||||
run: |
|
||||
set -x
|
||||
|
88
.github/workflows/ci-web.yml
vendored
88
.github/workflows/ci-web.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: authentik-ci-web
|
||||
name: CI Web UI
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -13,54 +13,50 @@ on:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
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: ${{ matrix.project }}/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: ${{ matrix.project }}/package-lock.json
|
||||
- working-directory: ${{ matrix.project }}/
|
||||
run: |
|
||||
npm ci
|
||||
- name: Generate API
|
||||
run: make gen-client-ts
|
||||
- name: Lint
|
||||
working-directory: ${{ matrix.project }}/
|
||||
run: npm run ${{ matrix.command }}
|
||||
build:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
node-version-file: package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: web/package-lock.json
|
||||
- working-directory: web/
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Install Node.js dependencies
|
||||
run: npm ci
|
||||
- name: Generate API
|
||||
- name: Generate TypeScript API
|
||||
run: make gen-client-ts
|
||||
- name: Build
|
||||
run: |
|
||||
npm run build -w @goauthentik/web
|
||||
- name: Type check
|
||||
run: |
|
||||
npm run typecheck
|
||||
- name: Lint
|
||||
run: |
|
||||
npm run lint -w @goauthentik/web
|
||||
npm run lint:lockfile -w @goauthentik/web
|
||||
npm run lit-analyse -w @goauthentik/web
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
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: Install Node.js dependencies
|
||||
run: npm ci
|
||||
- name: Generate TypeScript API
|
||||
run: make gen-client-ts
|
||||
- name: build
|
||||
working-directory: web/
|
||||
run: npm run build
|
||||
run: |
|
||||
npm run build -w @goauthentik/web
|
||||
npm run typecheck
|
||||
ci-web-mark:
|
||||
name: CI Web Mark
|
||||
if: always()
|
||||
needs:
|
||||
- build
|
||||
@ -71,6 +67,7 @@ jobs:
|
||||
with:
|
||||
jobs: ${{ toJSON(needs) }}
|
||||
test:
|
||||
name: Test
|
||||
needs:
|
||||
- ci-web-mark
|
||||
runs-on: ubuntu-latest
|
||||
@ -78,13 +75,12 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
node-version-file: package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: web/package-lock.json
|
||||
- working-directory: web/
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Install Node.js dependencies
|
||||
run: npm ci
|
||||
- name: Generate API
|
||||
- name: Generate TypeScript API
|
||||
run: make gen-client-ts
|
||||
- name: test
|
||||
working-directory: web/
|
||||
run: npm run test || exit 0
|
||||
- name: Test Web UI
|
||||
run: npm run test -w @goauthentik/web || exit 0
|
||||
|
66
.github/workflows/ci-website.yml
vendored
66
.github/workflows/ci-website.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: authentik-ci-website
|
||||
name: CI Docs Website
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -13,55 +13,59 @@ on:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: "Lint"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
command:
|
||||
- lint:lockfile
|
||||
- prettier-check
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- working-directory: website/
|
||||
run: npm ci
|
||||
- name: Lint
|
||||
working-directory: website/
|
||||
run: npm run ${{ matrix.command }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Install Node.js dependencies
|
||||
run: |
|
||||
npm ci
|
||||
- name: Generate TypeScript API
|
||||
run: make gen-client-ts
|
||||
- name: Lint Docs
|
||||
run: |
|
||||
npm run lint:prettier:check
|
||||
npm run lint:lockfile -w @goauthentik/docs
|
||||
test:
|
||||
name: "Test Docs"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: website/package.json
|
||||
node-version-file: package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: website/package-lock.json
|
||||
- working-directory: website/
|
||||
run: npm ci
|
||||
- name: test
|
||||
working-directory: website/
|
||||
run: npm test
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Install Node.js dependencies
|
||||
run: |
|
||||
npm ci
|
||||
- name: Generate TypeScript API
|
||||
run: make gen-client-ts
|
||||
- name: Test Docs
|
||||
run: |
|
||||
npm run test -w @goauthentik/docs
|
||||
build:
|
||||
name: "Build Docs"
|
||||
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: website/package.json
|
||||
node-version-file: package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: website/package-lock.json
|
||||
- working-directory: website/
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Install Node.js dependencies
|
||||
run: npm ci
|
||||
- name: build
|
||||
working-directory: website/
|
||||
run: npm run ${{ matrix.job }}
|
||||
- name: Build
|
||||
run: |
|
||||
npm run build -w @goauthentik/docs
|
||||
ci-website-mark:
|
||||
name: "CI Website Mark"
|
||||
if: always()
|
||||
needs:
|
||||
- lint
|
||||
|
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@ -10,7 +10,7 @@ on:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
name: "Analyze"
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
|
@ -1,4 +1,4 @@
|
||||
name: authentik-gen-update-webauthn-mds
|
||||
name: "authentik CI Update WebAuthn MDS"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
@ -11,6 +11,7 @@ env:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Update WebAuthn MDS"
|
||||
if: ${{ github.repository != 'goauthentik/authentik-internal' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
3
.github/workflows/gha-cache-cleanup.yml
vendored
3
.github/workflows/gha-cache-cleanup.yml
vendored
@ -1,6 +1,6 @@
|
||||
---
|
||||
# See https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries
|
||||
name: Cleanup cache after PR is closed
|
||||
name: "Post-PR Closed Cache Cleanup"
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
@ -12,6 +12,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
name: "Cleanup Cache"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
|
4
.github/workflows/ghcr-retention.yml
vendored
4
.github/workflows/ghcr-retention.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: ghcr-retention
|
||||
name: "authentik GHCR Retention Policy"
|
||||
|
||||
on:
|
||||
# schedule:
|
||||
@ -8,7 +8,7 @@ on:
|
||||
jobs:
|
||||
clean-ghcr:
|
||||
if: ${{ github.repository != 'goauthentik/authentik-internal' }}
|
||||
name: Delete old unused container images
|
||||
name: "Delete old unused container images"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: generate_token
|
||||
|
4
.github/workflows/image-compress.yml
vendored
4
.github/workflows/image-compress.yml
vendored
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: authentik-compress-images
|
||||
name: "authentik CI Image Compression"
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -20,7 +20,7 @@ on:
|
||||
|
||||
jobs:
|
||||
compress:
|
||||
name: compress
|
||||
name: "Compress Docker images"
|
||||
runs-on: ubuntu-latest
|
||||
# Don't run on forks. Token will not be available. Will run on main and open a PR anyway
|
||||
if: |
|
||||
|
7
.github/workflows/publish-source-docs.yml
vendored
7
.github/workflows/publish-source-docs.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: authentik-publish-source-docs
|
||||
name: "authentik Publish Source Docs"
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -12,6 +12,7 @@ env:
|
||||
|
||||
jobs:
|
||||
publish-source-docs:
|
||||
name: "Publish"
|
||||
if: ${{ github.repository != 'goauthentik/authentik-internal' }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
@ -19,11 +20,11 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
- name: generate docs
|
||||
- name: Generate docs
|
||||
run: |
|
||||
uv run make migrate
|
||||
uv run ak build_source_docs
|
||||
- name: Publish
|
||||
- name: Deploy to Netlify
|
||||
uses: netlify/actions/cli@master
|
||||
with:
|
||||
args: deploy --dir=source_docs --prod
|
||||
|
3
.github/workflows/release-next-branch.yml
vendored
3
.github/workflows/release-next-branch.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: authentik-on-release-next-branch
|
||||
name: "authentik on Release Next Branch"
|
||||
|
||||
on:
|
||||
schedule:
|
||||
@ -11,6 +11,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
update-next:
|
||||
name: "Update Next Branch"
|
||||
if: ${{ github.repository != 'goauthentik/authentik-internal' }}
|
||||
runs-on: ubuntu-latest
|
||||
environment: internal-production
|
||||
|
21
.github/workflows/release-publish.yml
vendored
21
.github/workflows/release-publish.yml
vendored
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: authentik-on-release
|
||||
name: "Release publish"
|
||||
|
||||
on:
|
||||
release:
|
||||
@ -7,6 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build-server:
|
||||
name: "Build server"
|
||||
uses: ./.github/workflows/_reusable-docker-build.yaml
|
||||
secrets: inherit
|
||||
permissions:
|
||||
@ -21,6 +22,7 @@ jobs:
|
||||
registry_dockerhub: true
|
||||
registry_ghcr: true
|
||||
build-outpost:
|
||||
name: "Build outpost"
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload container images to ghcr.io
|
||||
@ -45,14 +47,14 @@ jobs:
|
||||
uses: docker/setup-qemu-action@v3.6.0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: prepare variables
|
||||
- name: Prepare variables
|
||||
uses: ./.github/actions/docker-push-variables
|
||||
id: ev
|
||||
env:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
with:
|
||||
image-name: ghcr.io/goauthentik/${{ matrix.type }},beryju/authentik-${{ matrix.type }}
|
||||
- name: make empty clients
|
||||
- name: Make empty clients
|
||||
run: |
|
||||
mkdir -p ./gen-ts-api
|
||||
mkdir -p ./gen-go-api
|
||||
@ -85,6 +87,7 @@ jobs:
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
build-outpost-binary:
|
||||
name: "Build outpost binary"
|
||||
timeout-minutes: 120
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
@ -106,14 +109,13 @@ jobs:
|
||||
go-version-file: "go.mod"
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
node-version-file: package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: web/package-lock.json
|
||||
cache-dependency-path: package-lock.json
|
||||
- name: Build web
|
||||
working-directory: web/
|
||||
run: |
|
||||
npm ci
|
||||
npm run build-proxy
|
||||
npm run build-proxy -w @goauthentik/web
|
||||
- name: Build outpost
|
||||
run: |
|
||||
set -x
|
||||
@ -129,6 +131,7 @@ jobs:
|
||||
asset_name: authentik-outpost-${{ matrix.type }}_${{ matrix.goos }}_${{ matrix.goarch }}
|
||||
tag: ${{ github.ref }}
|
||||
upload-aws-cfn-template:
|
||||
name: "Upload AWS CloudFormation template"
|
||||
permissions:
|
||||
# Needed for AWS login
|
||||
id-token: write
|
||||
@ -150,6 +153,7 @@ jobs:
|
||||
aws s3 cp --acl=public-read lifecycle/aws/template.yaml s3://authentik-cloudformation-templates/authentik.ecs.${{ github.ref }}.yaml
|
||||
aws s3 cp --acl=public-read lifecycle/aws/template.yaml s3://authentik-cloudformation-templates/authentik.ecs.latest.yaml
|
||||
test-release:
|
||||
name: "Test release"
|
||||
needs:
|
||||
- build-server
|
||||
- build-outpost
|
||||
@ -166,6 +170,7 @@ jobs:
|
||||
docker compose start postgresql redis
|
||||
docker compose run -u root server test-all
|
||||
sentry-release:
|
||||
name: "Sentry release"
|
||||
needs:
|
||||
- build-server
|
||||
- build-outpost
|
||||
@ -173,7 +178,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: prepare variables
|
||||
- name: Prepare variables
|
||||
uses: ./.github/actions/docker-push-variables
|
||||
id: ev
|
||||
env:
|
||||
|
6
.github/workflows/release-tag.yml
vendored
6
.github/workflows/release-tag.yml
vendored
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: authentik-on-tag
|
||||
name: "authentik on Tag Release"
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -8,7 +8,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Create Release from Tag
|
||||
name: "Create Release from Tag"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -20,7 +20,7 @@ jobs:
|
||||
with:
|
||||
app_id: ${{ secrets.GH_APP_ID }}
|
||||
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||
- name: prepare variables
|
||||
- name: Prepare variables
|
||||
uses: ./.github/actions/docker-push-variables
|
||||
id: ev
|
||||
env:
|
||||
|
4
.github/workflows/repo-mirror.yml
vendored
4
.github/workflows/repo-mirror.yml
vendored
@ -1,13 +1,15 @@
|
||||
name: "authentik-repo-mirror"
|
||||
name: "authentik Repository Mirror"
|
||||
|
||||
on: [push, delete]
|
||||
|
||||
jobs:
|
||||
to_internal:
|
||||
name: "Mirror to internal repository"
|
||||
if: ${{ github.repository != 'goauthentik/authentik-internal' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
name: "Checkout repository"
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- if: ${{ env.MIRROR_KEY != '' }}
|
||||
|
3
.github/workflows/repo-stale.yml
vendored
3
.github/workflows/repo-stale.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: "authentik-repo-stale"
|
||||
name: "authentik Repository Stale Issues"
|
||||
|
||||
on:
|
||||
schedule:
|
||||
@ -11,6 +11,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
name: "Stale Issues"
|
||||
if: ${{ github.repository != 'goauthentik/authentik-internal' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
4
.github/workflows/semgrep.yml
vendored
4
.github/workflows/semgrep.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: authentik-semgrep
|
||||
name: "authentik CI Semgrep"
|
||||
on:
|
||||
workflow_dispatch: {}
|
||||
pull_request: {}
|
||||
@ -13,7 +13,7 @@ on:
|
||||
- cron: '12 15 * * *'
|
||||
jobs:
|
||||
semgrep:
|
||||
name: semgrep/ci
|
||||
name: "semgrep/ci"
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
3
.github/workflows/translation-advice.yml
vendored
3
.github/workflows/translation-advice.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: authentik-translation-advice
|
||||
name: "authentik Translations Advice"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@ -16,6 +16,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
post-comment:
|
||||
name: "Post Comment"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Find Comment
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
name: authentik-translate-extract-compile
|
||||
name: "authentik Extract & Compile Translations"
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # every day at midnight
|
||||
@ -16,6 +16,7 @@ env:
|
||||
|
||||
jobs:
|
||||
compile:
|
||||
name: "Compile Translations"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: generate_token
|
||||
@ -32,15 +33,20 @@ jobs:
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
- name: Generate API
|
||||
- name: Generate TypeScript API
|
||||
run: make gen-client-ts
|
||||
- name: run extract
|
||||
- name: Extract Translations
|
||||
run: |
|
||||
uv run make i18n-extract
|
||||
- name: run compile
|
||||
- name: Build Docs Site
|
||||
run: npm run build-bundled -w @goauthentik/docs
|
||||
- name: Build Web UI
|
||||
run: npm run build -w @goauthentik/web
|
||||
- name: Type check
|
||||
run: npm run typecheck
|
||||
- name: Compile Messages
|
||||
run: |
|
||||
uv run ak compilemessages
|
||||
make web-check-compile
|
||||
- name: Create Pull Request
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
|
3
.github/workflows/translation-rename.yml
vendored
3
.github/workflows/translation-rename.yml
vendored
@ -1,6 +1,6 @@
|
||||
# Rename transifex pull requests to have a correct naming
|
||||
# Also enables auto squash-merge
|
||||
name: authentik-translation-transifex-rename
|
||||
name: "authentik Translations Transifex PR Rename"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@ -12,6 +12,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
rename_pr:
|
||||
name: "Rename PR"
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.pull_request.user.login == 'transifex-integration[bot]'}}
|
||||
steps:
|
||||
|
23
.gitignore
vendored
23
.gitignore
vendored
@ -217,3 +217,26 @@ source_docs/
|
||||
|
||||
### Docker ###
|
||||
docker-compose.override.yml
|
||||
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules/
|
||||
|
||||
tsconfig.tsbuildinfo
|
||||
|
||||
# Wireit's cache
|
||||
.wireit
|
||||
|
||||
custom-elements.json
|
||||
|
||||
|
||||
### Development ###
|
||||
.drafts
|
||||
|
@ -4,12 +4,16 @@
|
||||
**/LICENSE
|
||||
|
||||
authentik/stages/**/*
|
||||
authentik/sources/**/*
|
||||
schemas/**/*
|
||||
blueprints/**/*
|
||||
|
||||
## Build asset directories
|
||||
coverage
|
||||
dist
|
||||
out
|
||||
.docusaurus
|
||||
.wireit
|
||||
website/docs/developer-docs/api/**/*
|
||||
|
||||
## Environment
|
||||
@ -32,14 +36,15 @@ coverage
|
||||
|
||||
# Templates
|
||||
# TODO: Rename affected files to *.template.* or similar.
|
||||
authentik/**/*.html
|
||||
*.html
|
||||
*.mdx
|
||||
*.md
|
||||
|
||||
## Import order matters
|
||||
poly.ts
|
||||
src/locale-codes.ts
|
||||
src/locales/
|
||||
web/src/poly.ts
|
||||
web/src/locale-codes.ts
|
||||
web/src/locales/
|
||||
|
||||
# Storybook
|
||||
storybook-static/
|
||||
|
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"
|
||||
]
|
||||
}
|
||||
|
72
.vscode/settings.json
vendored
72
.vscode/settings.json
vendored
@ -16,7 +16,7 @@
|
||||
],
|
||||
"typescript.preferences.importModuleSpecifier": "non-relative",
|
||||
"typescript.preferences.importModuleSpecifierEnding": "index",
|
||||
"typescript.tsdk": "./web/node_modules/typescript/lib",
|
||||
"typescript.tsdk": "./node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"yaml.schemas": {
|
||||
"./blueprints/schema.json": "blueprints/**/*.yaml"
|
||||
@ -30,7 +30,71 @@
|
||||
}
|
||||
],
|
||||
"go.testFlags": ["-count=1"],
|
||||
"github-actions.workflows.pinned.workflows": [
|
||||
".github/workflows/ci-main.yml"
|
||||
]
|
||||
"github-actions.workflows.pinned.workflows": [".github/workflows/ci-main.yml"],
|
||||
|
||||
"eslint.useFlatConfig": true,
|
||||
|
||||
"explorer.fileNesting.enabled": true,
|
||||
"explorer.fileNesting.patterns": {
|
||||
"*.mjs": "*.d.mts",
|
||||
"*.cjs": "*.d.cts",
|
||||
"package.json": "package-lock.json, yarn.lock, .yarnrc, .yarnrc.yml, .yarn, .nvmrc, .node-version",
|
||||
"tsconfig.json": "tsconfig.*.json, jsconfig.json",
|
||||
"Dockerfile": "*.Dockerfile"
|
||||
},
|
||||
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/*.code-search": true,
|
||||
"**/dist": true,
|
||||
"**/out": true,
|
||||
"**/package-lock.json": true
|
||||
},
|
||||
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[markdown]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[shellscript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[django-html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.removeUnusedImports": "explicit"
|
||||
},
|
||||
// We use Prettier for formatting, but specifying these settings
|
||||
// will ensure that VS Code's IntelliSense doesn't autocomplete unformatted code.
|
||||
"javascript.format.semicolons": "insert",
|
||||
"typescript.format.semicolons": "insert",
|
||||
"javascript.preferences.quoteStyle": "double",
|
||||
"typescript.preferences.quoteStyle": "double",
|
||||
"github.copilot.enable": {
|
||||
"*": true,
|
||||
"plaintext": true,
|
||||
"markdown": true,
|
||||
"scminput": false,
|
||||
"csv": false,
|
||||
"json": true,
|
||||
"yaml": true
|
||||
}
|
||||
}
|
||||
|
40
.vscode/tasks.json
vendored
40
.vscode/tasks.json
vendored
@ -4,12 +4,7 @@
|
||||
{
|
||||
"label": "authentik/core: make",
|
||||
"command": "uv",
|
||||
"args": [
|
||||
"run",
|
||||
"make",
|
||||
"lint-fix",
|
||||
"lint"
|
||||
],
|
||||
"args": ["run", "make", "lint-fix", "lint"],
|
||||
"presentation": {
|
||||
"panel": "new"
|
||||
},
|
||||
@ -18,11 +13,7 @@
|
||||
{
|
||||
"label": "authentik/core: run",
|
||||
"command": "uv",
|
||||
"args": [
|
||||
"run",
|
||||
"ak",
|
||||
"server"
|
||||
],
|
||||
"args": ["run", "ak", "server"],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
@ -32,17 +23,13 @@
|
||||
{
|
||||
"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",
|
||||
@ -52,26 +39,19 @@
|
||||
{
|
||||
"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",
|
||||
@ -81,11 +61,7 @@
|
||||
{
|
||||
"label": "authentik/api: generate",
|
||||
"command": "uv",
|
||||
"args": [
|
||||
"run",
|
||||
"make",
|
||||
"gen"
|
||||
],
|
||||
"args": ["run", "make", "gen"],
|
||||
"group": "build"
|
||||
}
|
||||
]
|
||||
|
65
Dockerfile
65
Dockerfile
@ -1,48 +1,31 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Stage 1: Build website
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:22 AS website-builder
|
||||
# Stage 1 Web UI and Documentation build
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
WORKDIR /work/website
|
||||
|
||||
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
|
||||
|
||||
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:22 AS web-builder
|
||||
|
||||
ARG GIT_BUILD_HASH
|
||||
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
||||
ENV NODE_ENV=production
|
||||
|
||||
WORKDIR /work/web
|
||||
WORKDIR /work
|
||||
|
||||
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 ./package.json
|
||||
COPY ./package-lock.json ./package-lock.json
|
||||
COPY ./packages ./packages
|
||||
COPY ./web ./web
|
||||
COPY ./website ./website
|
||||
|
||||
COPY ./package.json /work
|
||||
COPY ./web /work/web/
|
||||
COPY ./website /work/website/
|
||||
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
|
||||
COPY ./gen-ts-api ./gen-ts-api
|
||||
COPY ./blueprints ./blueprints
|
||||
COPY ./schema.yml ./schema.yml
|
||||
COPY ./SECURITY.md ./SECURITY.md
|
||||
|
||||
RUN npm run build
|
||||
RUN --mount=type=cache,target=/root/.npm npm ci --include=dev
|
||||
|
||||
RUN npm run build-bundled -w @goauthentik/docs
|
||||
RUN npm run build -w @goauthentik/web
|
||||
|
||||
# Stage 2: Build go proxy
|
||||
|
||||
# Stage 3: Build go proxy
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder
|
||||
|
||||
ARG TARGETOS
|
||||
@ -79,7 +62,8 @@ 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 4: MaxMind GeoIP
|
||||
# Stage 3: MaxMind GeoIP
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.1.0 AS geoip
|
||||
|
||||
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN"
|
||||
@ -93,9 +77,10 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
|
||||
mkdir -p /usr/share/GeoIP && \
|
||||
/bin/sh -c "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
|
||||
|
||||
# Stage 5: Download uv
|
||||
# Stage 4: Download uv
|
||||
FROM ghcr.io/astral-sh/uv:0.6.14 AS uv
|
||||
# Stage 6: Base python image
|
||||
|
||||
# Stage 5: Base python image
|
||||
FROM ghcr.io/goauthentik/fips-python:3.12.10-slim-bookworm-fips AS python-base
|
||||
|
||||
ENV VENV_PATH="/ak-root/.venv" \
|
||||
@ -109,7 +94,7 @@ WORKDIR /ak-root/
|
||||
|
||||
COPY --from=uv /uv /uvx /bin/
|
||||
|
||||
# Stage 7: Python dependencies
|
||||
# Stage 6: Python dependencies
|
||||
FROM python-base AS python-deps
|
||||
|
||||
ARG TARGETARCH
|
||||
@ -144,7 +129,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 8: Run
|
||||
# Stage 7: Run
|
||||
FROM python-base AS final-image
|
||||
|
||||
ARG VERSION
|
||||
@ -189,7 +174,7 @@ COPY --from=go-builder /go/authentik /bin/authentik
|
||||
COPY --from=python-deps /ak-root/.venv /ak-root/.venv
|
||||
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=web-builder /work/website/build/ /website/help/
|
||||
COPY --from=geoip /usr/share/GeoIP /geoip
|
||||
|
||||
USER 1000
|
||||
|
107
Makefile
107
Makefile
@ -36,6 +36,13 @@ test: ## Run the server tests and produce a coverage report (locally)
|
||||
uv run coverage html
|
||||
uv run coverage report
|
||||
|
||||
node-check-compile: ## Check and compile the TypeScript source code
|
||||
npm run typecheck
|
||||
|
||||
node-lint-fix: ## Lint and automatically fix errors in the javascript source code
|
||||
lint-codespell
|
||||
npm run lint:fix
|
||||
|
||||
lint-fix: lint-codespell ## Lint and automatically fix errors in the python source code. Reports spelling errors.
|
||||
uv run black $(PY_SOURCES)
|
||||
uv run ruff check --fix $(PY_SOURCES)
|
||||
@ -47,9 +54,6 @@ lint: ## Lint the python and golang sources
|
||||
uv run bandit -c pyproject.toml -r $(PY_SOURCES)
|
||||
golangci-lint run -v
|
||||
|
||||
core-install:
|
||||
uv sync --frozen
|
||||
|
||||
migrate: ## Run the Authentik Django server's migrations
|
||||
uv run python -m lifecycle.migrate
|
||||
|
||||
@ -72,7 +76,9 @@ core-i18n-extract:
|
||||
--ignore website \
|
||||
-l en
|
||||
|
||||
install: web-install website-install core-install ## Install all requires dependencies for `web`, `website` and `core`
|
||||
install: ## Install all requires dependencies for `web`, `website` and `core`
|
||||
npm ci
|
||||
uv sync --frozen
|
||||
|
||||
dev-drop-db:
|
||||
dropdb -U ${pg_user} -h ${pg_host} ${pg_name}
|
||||
@ -94,6 +100,7 @@ gen-build: ## Extract the schema from the database
|
||||
AUTHENTIK_TENANTS__ENABLED=true \
|
||||
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
|
||||
uv run ak make_blueprint_schema > blueprints/schema.json
|
||||
|
||||
AUTHENTIK_DEBUG=true \
|
||||
AUTHENTIK_TENANTS__ENABLED=true \
|
||||
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
|
||||
@ -101,19 +108,24 @@ gen-build: ## Extract the schema from the database
|
||||
|
||||
gen-changelog: ## (Release) generate the changelog based from the commits since the last tag
|
||||
git log --pretty=format:" - %s" $(shell git describe --tags $(shell git rev-list --tags --max-count=1))...$(shell git branch --show-current) | sort > changelog.md
|
||||
|
||||
npx prettier --write changelog.md
|
||||
|
||||
gen-diff: ## (Release) generate the changelog diff between the current schema and the last tag
|
||||
git show $(shell git describe --tags $(shell git rev-list --tags --max-count=1)):schema.yml > old_schema.yml
|
||||
|
||||
docker run \
|
||||
--rm -v ${PWD}:/local \
|
||||
--user ${UID}:${GID} \
|
||||
docker.io/openapitools/openapi-diff:2.1.0-beta.8 \
|
||||
--markdown /local/diff.md \
|
||||
/local/old_schema.yml /local/schema.yml
|
||||
|
||||
rm old_schema.yml
|
||||
|
||||
sed -i 's/{/{/g' diff.md
|
||||
sed -i 's/}/}/g' diff.md
|
||||
|
||||
npx prettier --write diff.md
|
||||
|
||||
gen-clean-ts: ## Remove generated API client for Typescript
|
||||
@ -133,46 +145,57 @@ gen-client-ts: gen-clean-ts ## Build and install the authentik API for Typescri
|
||||
--rm -v ${PWD}:/local \
|
||||
--user ${UID}:${GID} \
|
||||
docker.io/openapitools/openapi-generator-cli:v7.11.0 generate \
|
||||
-i /local/schema.yml \
|
||||
-g typescript-fetch \
|
||||
-o /local/${GEN_API_TS} \
|
||||
-c /local/scripts/api-ts-config.yaml \
|
||||
--input-spec /local/schema.yml \
|
||||
--generator-name typescript-fetch \
|
||||
--output /local/${GEN_API_TS} \
|
||||
--config /local/scripts/api-ts-config.yaml \
|
||||
--additional-properties=npmVersion=${NPM_VERSION} \
|
||||
--git-repo-id authentik \
|
||||
--git-user-id goauthentik
|
||||
mkdir -p web/node_modules/@goauthentik/api
|
||||
cd ./${GEN_API_TS} && npm i
|
||||
\cp -rf ./${GEN_API_TS}/* web/node_modules/@goauthentik/api
|
||||
|
||||
npm install
|
||||
|
||||
gen-client-py: gen-clean-py ## Build and install the authentik API for Python
|
||||
|
||||
docker run \
|
||||
--rm -v ${PWD}:/local \
|
||||
--user ${UID}:${GID} \
|
||||
docker.io/openapitools/openapi-generator-cli:v7.11.0 generate \
|
||||
-i /local/schema.yml \
|
||||
-g python \
|
||||
-o /local/${GEN_API_PY} \
|
||||
-c /local/scripts/api-py-config.yaml \
|
||||
--input-spec /local/schema.yml \
|
||||
--generator-name python \
|
||||
--output /local/${GEN_API_PY} \
|
||||
--config /local/scripts/api-py-config.yaml \
|
||||
--additional-properties=packageVersion=${NPM_VERSION} \
|
||||
--git-repo-id authentik \
|
||||
--git-user-id goauthentik
|
||||
|
||||
pip install ./${GEN_API_PY}
|
||||
|
||||
gen-client-go: gen-clean-go ## Build and install the authentik API for Golang
|
||||
mkdir -p ./${GEN_API_GO} ./${GEN_API_GO}/templates
|
||||
wget https://raw.githubusercontent.com/goauthentik/client-go/main/config.yaml -O ./${GEN_API_GO}/config.yaml
|
||||
wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/README.mustache -O ./${GEN_API_GO}/templates/README.mustache
|
||||
wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/go.mod.mustache -O ./${GEN_API_GO}/templates/go.mod.mustache
|
||||
|
||||
wget https://raw.githubusercontent.com/goauthentik/client-go/main/config.yaml \
|
||||
-O ./${GEN_API_GO}/config.yaml
|
||||
|
||||
wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/README.mustache \
|
||||
-O ./${GEN_API_GO}/templates/README.mustache
|
||||
|
||||
wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/go.mod.mustache \
|
||||
-O ./${GEN_API_GO}/templates/go.mod.mustache
|
||||
|
||||
cp schema.yml ./${GEN_API_GO}/
|
||||
|
||||
docker run \
|
||||
--rm -v ${PWD}/${GEN_API_GO}:/local \
|
||||
--user ${UID}:${GID} \
|
||||
docker.io/openapitools/openapi-generator-cli:v6.5.0 generate \
|
||||
-i /local/schema.yml \
|
||||
-g go \
|
||||
-o /local/ \
|
||||
-c /local/config.yaml
|
||||
--input-spec /local/schema.yml \
|
||||
--generator-name go \
|
||||
--output /local/ \
|
||||
--config /local/config.yaml
|
||||
|
||||
go mod edit -replace goauthentik.io/api/v3=./${GEN_API_GO}
|
||||
|
||||
rm -rf ./${GEN_API_GO}/config.yaml ./${GEN_API_GO}/templates/
|
||||
|
||||
gen-dev-config: ## Generate a local development config file
|
||||
@ -184,56 +207,38 @@ gen: gen-build gen-client-ts
|
||||
## 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
|
||||
|
||||
web-install: ## Install the necessary libraries to build the Authentik UI
|
||||
cd web && npm ci
|
||||
web: web-lint-fix web-lint node-check-compile ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it
|
||||
|
||||
web-test: ## Run tests for the Authentik UI
|
||||
cd web && npm run test
|
||||
npm run test -w @goauthentik/web
|
||||
|
||||
web-watch: ## Build and watch the Authentik UI for changes, updating automatically
|
||||
rm -rf web/dist/
|
||||
mkdir web/dist/
|
||||
touch web/dist/.gitkeep
|
||||
cd web && npm run watch
|
||||
npm run watch -w @goauthentik/web
|
||||
|
||||
web-storybook-watch: ## Build and run the storybook documentation server
|
||||
cd web && npm run storybook
|
||||
npm run storybook -w @goauthentik/web
|
||||
|
||||
web-lint-fix:
|
||||
cd web && npm run prettier
|
||||
npm run prettier -w @goauthentik/web
|
||||
|
||||
web-lint:
|
||||
cd web && npm run lint
|
||||
cd web && npm run lit-analyse
|
||||
|
||||
web-check-compile:
|
||||
cd web && npm run tsc
|
||||
npm run lint -w @goauthentik/web
|
||||
npm run lit-analyse -w @goauthentik/web
|
||||
|
||||
web-i18n-extract:
|
||||
cd web && npm run extract-locales
|
||||
npm run extract-locales -w @goauthentik/web
|
||||
|
||||
#########################
|
||||
## Website
|
||||
#########################
|
||||
|
||||
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
|
||||
cd website && npm run prettier
|
||||
website: node-lint-fix website-build ## Automatically fix formatting issues in the Authentik website/docs source code, lint the code, and compile it
|
||||
|
||||
website-build:
|
||||
cd website && npm run build
|
||||
npm run build -w @goauthentik/docs
|
||||
|
||||
website-watch: ## Build and watch the documentation website, updating automatically
|
||||
cd website && npm run watch
|
||||
npm run watch -w @goauthentik/docs
|
||||
|
||||
#########################
|
||||
## Docker
|
||||
|
@ -2,20 +2,22 @@
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
|
||||
<script>
|
||||
window.authentik = {
|
||||
locale: "{{ LANGUAGE_CODE }}",
|
||||
config: JSON.parse('{{ config_json|escapejs }}'),
|
||||
brand: JSON.parse('{{ brand_json|escapejs }}'),
|
||||
versionFamily: "{{ version_family }}",
|
||||
versionSubdomain: "{{ version_subdomain }}",
|
||||
build: "{{ build }}",
|
||||
api: {
|
||||
base: "{{ base_url }}",
|
||||
relBase: "{{ base_url_rel }}",
|
||||
},
|
||||
};
|
||||
window.authentik = {
|
||||
locale: "{{ LANGUAGE_CODE }}",
|
||||
config: JSON.parse("{{ config_json|escapejs }}" || "{}"),
|
||||
brand: JSON.parse("{{ brand_json|escapejs }}" || "{}"),
|
||||
versionFamily: "{{ version_family }}",
|
||||
versionSubdomain: "{{ version_subdomain }}",
|
||||
build: "{{ build }}",
|
||||
api: {
|
||||
base: "{{ base_url }}",
|
||||
relBase: "{{ base_url_rel }}",
|
||||
},
|
||||
};
|
||||
|
||||
{% if messages %}
|
||||
window.addEventListener("DOMContentLoaded", function () {
|
||||
{% for message in messages %}
|
||||
{% for message in messages %}
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("ak-message", {
|
||||
bubbles: true,
|
||||
@ -26,6 +28,7 @@
|
||||
},
|
||||
}),
|
||||
);
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
});
|
||||
{% endif %}
|
||||
</script>
|
||||
|
@ -2,31 +2,79 @@
|
||||
{% load i18n %}
|
||||
{% load authentik_core %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
{# Darkreader breaks the site regardless of theme as its not compatible with webcomponents, and we default to a dark theme based on preferred colour-scheme #}
|
||||
<meta name="darkreader-lock">
|
||||
<title>{% block title %}{% trans title|default:brand.branding_title %}{% endblock %}</title>
|
||||
<link rel="icon" href="{{ brand.branding_favicon_url }}">
|
||||
<link rel="shortcut icon" href="{{ brand.branding_favicon_url }}">
|
||||
{% block head_before %}
|
||||
{% endblock %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
|
||||
<style>{{ brand.branding_custom_css }}</style>
|
||||
<script src="{% versioned_script 'dist/poly-%v.js' %}" type="module"></script>
|
||||
<script src="{% versioned_script 'dist/standalone/loading/index-%v.js' %}" type="module"></script>
|
||||
{% block head %}
|
||||
{% endblock %}
|
||||
<meta name="sentry-trace" content="{{ sentry_trace }}" />
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
|
||||
{% comment %}
|
||||
Darkreader breaks the site regardless of theme as its not compatible with webcomponents, and we
|
||||
default to a dark theme based on preferred colour-scheme
|
||||
{% endcomment %}
|
||||
|
||||
<meta name="darkreader-lock" />
|
||||
|
||||
<title>{% block title %}{% trans title|default:brand.branding_title %}{% endblock %}</title>
|
||||
|
||||
<link rel="icon" href="{{ brand.branding_favicon_url }}" />
|
||||
<link rel="shortcut icon" href="{{ brand.branding_favicon_url }}" />
|
||||
|
||||
{% block head_before %}
|
||||
{% endblock %}
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}" />
|
||||
|
||||
<style data-test-id="color-scheme">
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
color-scheme: dark light;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style data-test-id="custom-branding-css">
|
||||
{{ brand.branding_custom_css }}
|
||||
</style>
|
||||
|
||||
<script src="{% versioned_script 'dist/poly-%v.js' %}" type="module"></script>
|
||||
<script
|
||||
src="{% versioned_script 'dist/standalone/loading/index-%v.js' %}"
|
||||
type="module"
|
||||
></script>
|
||||
|
||||
{% block head %}
|
||||
{% endblock %}
|
||||
|
||||
<meta name="sentry-trace" content="{{ sentry_trace }}" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{% block body %}{% endblock %}
|
||||
{% block scripts %}{% endblock %}
|
||||
|
||||
<noscript>
|
||||
<style>
|
||||
body {
|
||||
font-family: var(--ak-font-family-base), sans-serif;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>
|
||||
JavaScript is required to use
|
||||
{% trans title|default:brand.branding_title %}
|
||||
</h1>
|
||||
<p>
|
||||
Please enable JavaScript in your browser settings and reload the page. If you are using a
|
||||
browser extension that blocks JavaScript, please disable it for this site.
|
||||
</p>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -4,14 +4,16 @@
|
||||
|
||||
{% block head %}
|
||||
<script src="{% versioned_script 'dist/admin/AdminInterface-%v.js' %}" type="module"></script>
|
||||
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
|
||||
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
|
||||
|
||||
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)" />
|
||||
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)" />
|
||||
{% include "base/header_js.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<ak-message-container></ak-message-container>
|
||||
|
||||
<ak-interface-admin>
|
||||
<ak-loading></ak-loading>
|
||||
<ak-loading></ak-loading>
|
||||
</ak-interface-admin>
|
||||
{% endblock %}
|
||||
|
@ -13,9 +13,14 @@
|
||||
|
||||
{% block card %}
|
||||
<form method="POST" class="pf-c-form">
|
||||
<p>{% trans message %}</p>
|
||||
<a id="ak-back-home" href="{% url 'authentik_core:root-redirect' %}" class="pf-c-button pf-m-primary">
|
||||
{% trans 'Go home' %}
|
||||
</a>
|
||||
<p>{% trans message %}</p>
|
||||
|
||||
<a
|
||||
id="ak-back-home"
|
||||
href="{% url 'authentik_core:root-redirect' %}"
|
||||
class="pf-c-button pf-m-primary"
|
||||
>
|
||||
{% trans 'Go home' %}
|
||||
</a>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
@ -4,14 +4,17 @@
|
||||
|
||||
{% block head %}
|
||||
<script src="{% versioned_script 'dist/user/UserInterface-%v.js' %}" type="module"></script>
|
||||
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: light)">
|
||||
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: dark)">
|
||||
|
||||
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: light)" />
|
||||
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: dark)" />
|
||||
|
||||
{% include "base/header_js.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<ak-message-container></ak-message-container>
|
||||
|
||||
<ak-interface-user>
|
||||
<ak-loading></ak-loading>
|
||||
<ak-loading></ak-loading>
|
||||
</ak-interface-user>
|
||||
{% endblock %}
|
||||
|
@ -5,78 +5,82 @@
|
||||
|
||||
{% block head_before %}
|
||||
<link rel="prefetch" href="{{ request.brand.branding_default_flow_background_url }}" />
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.min.css' %}">
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/theme-dark.css' %}" media="(prefers-color-scheme: dark)">
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.min.css' %}" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="{% static 'dist/theme-dark.css' %}"
|
||||
media="(prefers-color-scheme: dark)"
|
||||
/>
|
||||
{% include "base/header_js.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
:root {
|
||||
<style data-test-id="base-full-root-styles">
|
||||
:root {
|
||||
--ak-flow-background: url("{{ request.brand.branding_default_flow_background_url }}");
|
||||
--pf-c-background-image--BackgroundImage: var(--ak-flow-background);
|
||||
--pf-c-background-image--BackgroundImage-2x: var(--ak-flow-background);
|
||||
--pf-c-background-image--BackgroundImage--sm: var(--ak-flow-background);
|
||||
--pf-c-background-image--BackgroundImage--sm-2x: var(--ak-flow-background);
|
||||
--pf-c-background-image--BackgroundImage--lg: var(--ak-flow-background);
|
||||
}
|
||||
/* Form with user */
|
||||
.form-control-static {
|
||||
}
|
||||
/* Form with user */
|
||||
.form-control-static {
|
||||
margin-top: var(--pf-global--spacer--sm);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.form-control-static .avatar {
|
||||
}
|
||||
.form-control-static .avatar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.form-control-static img {
|
||||
}
|
||||
.form-control-static img {
|
||||
margin-right: var(--pf-global--spacer--xs);
|
||||
}
|
||||
.form-control-static a {
|
||||
}
|
||||
.form-control-static a {
|
||||
padding-top: var(--pf-global--spacer--xs);
|
||||
padding-bottom: var(--pf-global--spacer--xs);
|
||||
line-height: var(--pf-global--spacer--xl);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="pf-c-background-image">
|
||||
</div>
|
||||
<div class="pf-c-background-image"></div>
|
||||
<ak-message-container></ak-message-container>
|
||||
<div class="pf-c-login stacked">
|
||||
<div class="ak-login-container">
|
||||
<main class="pf-c-login__main">
|
||||
<div class="pf-c-login__main-header pf-c-brand ak-brand">
|
||||
<img src="{{ brand.branding_logo_url }}" alt="authentik Logo" />
|
||||
</div>
|
||||
<header class="pf-c-login__main-header">
|
||||
<h1 class="pf-c-title pf-m-3xl">
|
||||
{% block card_title %}
|
||||
{% endblock %}
|
||||
</h1>
|
||||
</header>
|
||||
<div class="pf-c-login__main-body">
|
||||
{% block card %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</main>
|
||||
<footer class="pf-c-login__footer">
|
||||
<ul class="pf-c-list pf-m-inline">
|
||||
{% for link in footer_links %}
|
||||
<li>
|
||||
<a href="{{ link.href }}">{{ link.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li>
|
||||
<span>
|
||||
{% trans 'Powered by authentik' %}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="ak-login-container">
|
||||
<main class="pf-c-login__main">
|
||||
<div class="pf-c-login__main-header pf-c-brand ak-brand">
|
||||
<img src="{{ brand.branding_logo_url }}" alt="authentik Logo" />
|
||||
</div>
|
||||
<header class="pf-c-login__main-header">
|
||||
<h1 class="pf-c-title pf-m-3xl">
|
||||
{% block card_title %}
|
||||
{% endblock %}
|
||||
</h1>
|
||||
</header>
|
||||
<div class="pf-c-login__main-body">
|
||||
{% block card %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</main>
|
||||
<footer class="pf-c-login__footer">
|
||||
<ul class="pf-c-list pf-m-inline">
|
||||
{% for link in footer_links %}
|
||||
<li>
|
||||
<a href="{{ link.href }}">{{ link.name }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li>
|
||||
<span>
|
||||
{% trans 'Powered by authentik' %}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -2,53 +2,52 @@
|
||||
{% load i18n %}
|
||||
{% load authentik_core %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>{% block title %}{% trans title|default:brand.branding_title %}{% endblock %}</title>
|
||||
<link rel="icon" href="{{ brand.branding_favicon_url }}">
|
||||
<link rel="shortcut icon" href="{{ brand.branding_favicon_url }}">
|
||||
{% block head_before %}
|
||||
{% endblock %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/sfe/bootstrap.min.css' %}">
|
||||
<meta name="sentry-trace" content="{{ sentry_trace }}" />
|
||||
{% include "base/header_js.html" %}
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
background-image: url("{{ flow.background_url }}");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.card {
|
||||
padding: 3rem;
|
||||
}
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
<title>{% block title %}{% trans title|default:brand.branding_title %}{% endblock %}</title>
|
||||
<link rel="icon" href="{{ brand.branding_favicon_url }}" />
|
||||
<link rel="shortcut icon" href="{{ brand.branding_favicon_url }}" />
|
||||
{% block head_before %}
|
||||
{% endblock %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/sfe/bootstrap.min.css' %}" />
|
||||
<meta name="sentry-trace" content="{{ sentry_trace }}" />
|
||||
{% include "base/header_js.html" %}
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
background-image: url("{{ flow.background_url }}");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.card {
|
||||
padding: 3rem;
|
||||
}
|
||||
|
||||
.form-signin {
|
||||
max-width: 330px;
|
||||
padding: 1rem;
|
||||
}
|
||||
.form-signin {
|
||||
max-width: 330px;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.form-signin .form-floating:focus-within {
|
||||
z-index: 2;
|
||||
}
|
||||
.brand-icon {
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="d-flex align-items-center py-4 bg-body-tertiary">
|
||||
<div class="card m-auto">
|
||||
<main class="form-signin w-100 m-auto" id="flow-sfe-container">
|
||||
</main>
|
||||
<span class="mt-3 mb-0 text-muted text-center">{% trans 'Powered by authentik' %}</span>
|
||||
</div>
|
||||
<script src="{% static 'dist/sfe/index.js' %}"></script>
|
||||
</body>
|
||||
.form-signin .form-floating:focus-within {
|
||||
z-index: 2;
|
||||
}
|
||||
.brand-icon {
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="d-flex align-items-center py-4 bg-body-tertiary">
|
||||
<div class="card m-auto">
|
||||
<main class="form-signin w-100 m-auto" id="flow-sfe-container"></main>
|
||||
<span class="mt-3 mb-0 text-muted text-center">{% trans 'Powered by authentik' %}</span>
|
||||
</div>
|
||||
<script src="{% static 'dist/sfe/index.js' %}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,34 +1,40 @@
|
||||
{% extends "base/skeleton.html" %}
|
||||
|
||||
{% load static %}
|
||||
{% load authentik_core %}
|
||||
|
||||
{% block head_before %}
|
||||
{{ block.super }}
|
||||
|
||||
<link rel="prefetch" href="{{ flow.background_url }}" />
|
||||
|
||||
{% if flow.compatibility_mode and not inspector %}
|
||||
<script>ShadyDOM = { force: !navigator.webdriver };</script>
|
||||
{% endif %}
|
||||
{% include "base/header_js.html" %}
|
||||
<script>
|
||||
window.authentik.flow = {
|
||||
"layout": "{{ flow.layout }}",
|
||||
};
|
||||
ShadyDOM = { force: !navigator.webdriver };
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{% include "base/header_js.html" %}
|
||||
|
||||
<script>
|
||||
window.authentik.flow = {
|
||||
layout: "{{ flow.layout }}",
|
||||
};
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<script src="{% versioned_script 'dist/flow/FlowInterface-%v.js' %}" type="module"></script>
|
||||
<style>
|
||||
:root {
|
||||
|
||||
<style data-test-id="flow-root-styles">
|
||||
:root {
|
||||
--ak-flow-background: url("{{ flow.background_url }}");
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<ak-message-container></ak-message-container>
|
||||
<ak-flow-executor flowSlug="{{ flow.slug }}">
|
||||
<ak-loading></ak-loading>
|
||||
<ak-loading></ak-loading>
|
||||
</ak-flow-executor>
|
||||
{% endblock %}
|
||||
|
@ -4,10 +4,13 @@
|
||||
|
||||
{% block head %}
|
||||
<script src="{% versioned_script 'dist/rac/index-%v.js' %}" type="module"></script>
|
||||
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
|
||||
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
|
||||
<link rel="icon" href="{{ tenant.branding_favicon_url }}">
|
||||
<link rel="shortcut icon" href="{{ tenant.branding_favicon_url }}">
|
||||
|
||||
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)" />
|
||||
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)" />
|
||||
|
||||
<link rel="icon" href="{{ tenant.branding_favicon_url }}" />
|
||||
<link rel="shortcut icon" href="{{ tenant.branding_favicon_url }}" />
|
||||
|
||||
{% include "base/header_js.html" %}
|
||||
{% endblock %}
|
||||
|
||||
|
10
eslint.config.mjs
Normal file
10
eslint.config.mjs
Normal file
@ -0,0 +1,10 @@
|
||||
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
|
||||
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* ESLint configuration for authentik's monorepo.
|
||||
*/
|
||||
const ESLintConfig = createESLintPackageConfig();
|
||||
|
||||
export default ESLintConfig;
|
@ -1,15 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
|
||||
<title>{{.Title}}</title>
|
||||
<link rel="shortcut icon" type="image/png" href="/outpost.goauthentik.io/static/dist/assets/icons/icon.png">
|
||||
<link rel="stylesheet" type="text/css" href="/outpost.goauthentik.io/static/dist/patternfly.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/outpost.goauthentik.io/static/dist/authentik.css">
|
||||
<link rel="prefetch" href="/outpost.goauthentik.io/static/dist/assets/images/flow_background.jpg" />
|
||||
<style>
|
||||
|
||||
<link
|
||||
rel="shortcut icon"
|
||||
type="image/png"
|
||||
href="/outpost.goauthentik.io/static/dist/assets/icons/icon.png"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="/outpost.goauthentik.io/static/dist/patternfly.min.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="/outpost.goauthentik.io/static/dist/authentik.css"
|
||||
/>
|
||||
|
||||
<link
|
||||
rel="prefetch"
|
||||
href="/outpost.goauthentik.io/static/dist/assets/images/flow_background.jpg"
|
||||
/>
|
||||
|
||||
<style data-test-id="outpost-error-root-styles">
|
||||
.pf-c-background-image::before {
|
||||
--ak-flow-background: url("/outpost.goauthentik.io/static/dist/assets/images/flow_background.jpg");
|
||||
}
|
||||
@ -24,13 +43,15 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="pf-c-background-image">
|
||||
</div>
|
||||
<div class="pf-c-background-image"></div>
|
||||
<div class="pf-c-login stacked">
|
||||
<div class="ak-login-container">
|
||||
<main class="pf-c-login__main">
|
||||
<div class="pf-c-login__main-header pf-c-brand ak-brand">
|
||||
<img src="/outpost.goauthentik.io/static/dist/assets/icons/icon_left_brand.svg" alt="authentik Logo" />
|
||||
<img
|
||||
src="/outpost.goauthentik.io/static/dist/assets/icons/icon_left_brand.svg"
|
||||
alt="authentik Logo"
|
||||
/>
|
||||
</div>
|
||||
<header class="pf-c-login__main-header">
|
||||
<h1 class="pf-c-title pf-m-3xl">
|
||||
@ -47,9 +68,7 @@
|
||||
<footer class="pf-c-login__footer">
|
||||
<ul class="pf-c-list pf-m-inline">
|
||||
<li>
|
||||
<span>
|
||||
Powered by authentik
|
||||
</span>
|
||||
<span> Powered by authentik </span>
|
||||
</li>
|
||||
</ul>
|
||||
</footer>
|
||||
|
@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@goauthentik/lifecycle-aws",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"aws-cfn": "cross-env CI=false cdk synth --version-reporting=false > template.yaml"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"aws-cdk": "^2.1007.0",
|
||||
"cross-env": "^7.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.11"
|
||||
}
|
||||
}
|
||||
|
44519
package-lock.json
generated
44519
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
49
package.json
49
package.json
@ -1,5 +1,50 @@
|
||||
{
|
||||
"name": "@goauthentik/authentik",
|
||||
"name": "@goauthentik/universe",
|
||||
"version": "2025.2.4",
|
||||
"private": true
|
||||
"description": "Monorepo for authentik.",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"lint": "run-s lint:prettier:check lint:eslint:check",
|
||||
"lint:eslint:check": "eslint .",
|
||||
"lint:eslint:fix": "eslint --fix .",
|
||||
"lint:fix": "run-s lint:prettier:fix lint:eslint:fix",
|
||||
"lint:prettier:check": "prettier --cache --check -u .",
|
||||
"lint:prettier:fix": "prettier --cache --write -u .",
|
||||
"typecheck": "NODE_OPTIONS=\"--max-old-space-size=3000\" tsc -b"
|
||||
},
|
||||
"dependencies": {
|
||||
"@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-django-alpine": "^1.3.0",
|
||||
"prettier-plugin-packagejson": "^2.5.10",
|
||||
"typescript": "^5.8.2",
|
||||
"typescript-eslint": "^8.29.0",
|
||||
"zx": "^8.4.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/darwin-arm64": "^0.24.0",
|
||||
"@esbuild/linux-amd64": "^0.18.11",
|
||||
"@esbuild/linux-arm64": "^0.24.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.23.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.23.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.23.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.11"
|
||||
},
|
||||
"workspaces": [
|
||||
"gen-ts-api",
|
||||
"web",
|
||||
"web/packages/*",
|
||||
"website",
|
||||
"packages/*"
|
||||
],
|
||||
"prettier": "@goauthentik/prettier-config"
|
||||
}
|
||||
|
@ -18,9 +18,7 @@
|
||||
}
|
||||
|
||||
.badge--support-community {
|
||||
--ifm-badge-background-color: var(
|
||||
--ifm-color-secondary-contrast-foreground
|
||||
);
|
||||
--ifm-badge-background-color: var(--ifm-color-secondary-contrast-foreground);
|
||||
--ifm-badge-border-color: var(--ifm-color-secondary-dark);
|
||||
--ifm-badge-color: var(--ifm-color-secondary-contrast-background);
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
:root {
|
||||
--ifm-font-family-base:
|
||||
RedHatVF, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell,
|
||||
Noto Sans, sans-serif, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
|
||||
sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
RedHatVF, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans,
|
||||
sans-serif, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
|
||||
--ifm-font-family-monospace:
|
||||
RedHatMonoVF, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||
"Liberation Mono", "Courier New", monospace;
|
||||
RedHatMonoVF, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
|
||||
monospace;
|
||||
|
||||
--ifm-heading-font-family: RedHatDisplayVF, var(--ifm-font-family-base);
|
||||
|
||||
|
@ -7,11 +7,7 @@
|
||||
}
|
||||
|
||||
.homepage_hero__subtitle p {
|
||||
font-size: clamp(
|
||||
1.125rem,
|
||||
0.9946rem + 0.6522vi,
|
||||
1.5rem
|
||||
); /* Adjust font as page scales */
|
||||
font-size: clamp(1.125rem, 0.9946rem + 0.6522vi, 1.5rem); /* Adjust font as page scales */
|
||||
max-width: 28ch; /* Apply a maximum to keep everything in the box */
|
||||
text-wrap: balance; /* Prevent widows, orphans, and runts. Doesn't work in Safari */
|
||||
}
|
||||
|
@ -122,12 +122,8 @@
|
||||
|
||||
@media (min-width: 999px) {
|
||||
border-inline-start: 1px solid var(--ifm-hover-overlay);
|
||||
margin-inline-start: calc(
|
||||
var(--ifm-navbar-item-padding-horizontal) / 2
|
||||
);
|
||||
padding-inline-start: calc(
|
||||
var(--ifm-navbar-item-padding-horizontal) / 2
|
||||
);
|
||||
margin-inline-start: calc(var(--ifm-navbar-item-padding-horizontal) / 2);
|
||||
padding-inline-start: calc(var(--ifm-navbar-item-padding-horizontal) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,19 +147,14 @@
|
||||
hsl(236.84deg 34.55% 10.78%)
|
||||
);
|
||||
--docsearch-key-shadow:
|
||||
inset 0 -2px 0 0 hsl(233.33deg 36% 24.51%),
|
||||
inset 0 0 1px 1px hsl(232.11deg 34.86% 57.25%),
|
||||
inset 0 -2px 0 0 hsl(233.33deg 36% 24.51%), inset 0 0 1px 1px hsl(232.11deg 34.86% 57.25%),
|
||||
0 2px 2px 0 rgba(3, 4, 9, 0.3);
|
||||
--docsearch-key-pressed-shadow:
|
||||
inset 0 -2px 0 0 #282d55,
|
||||
inset 0 0 1px 1px hsl(231.82deg 21.36% 40.39%),
|
||||
inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px hsl(231.82deg 21.36% 40.39%),
|
||||
0 1px 1px 0 hsl(230deg 50% 2.35% / 30.2%);
|
||||
|
||||
padding: var(--ifm-navbar-item-padding-vertical)
|
||||
var(--ifm-navbar-item-padding-horizontal) !important;
|
||||
padding-inline-end: calc(
|
||||
var(--ifm-navbar-item-padding-horizontal) * 1.25
|
||||
) !important;
|
||||
padding: var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal) !important;
|
||||
padding-inline-end: calc(var(--ifm-navbar-item-padding-horizontal) * 1.25) !important;
|
||||
|
||||
.DocSearch-Button-Placeholder {
|
||||
font-family: var(--ifm-heading-font-family);
|
||||
|
@ -4,8 +4,8 @@
|
||||
* @import { Config as DocusaurusConfig } from "@docusaurus/types"
|
||||
* @import { UserThemeConfig } from "./theme.js"
|
||||
*/
|
||||
|
||||
import { deepmerge } from "deepmerge-ts";
|
||||
|
||||
import { createThemeConfig } from "./theme.js";
|
||||
|
||||
//#region Types
|
||||
|
@ -4,7 +4,6 @@
|
||||
* @import { UserThemeConfig as UserThemeConfigCommon } from "@docusaurus/theme-common";
|
||||
* @import { UserThemeConfig as UserThemeConfigAlgolia } from "@docusaurus/theme-search-algolia";
|
||||
*/
|
||||
|
||||
import { deepmerge } from "deepmerge-ts";
|
||||
import { themes as prismThemes } from "prism-react-renderer";
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
/**
|
||||
* @file
|
||||
* Client-side observer for ESBuild events.
|
||||
* @file Client-side observer for ESBuild events.
|
||||
*
|
||||
* @import { Message as ESBuildMessage } from "esbuild";
|
||||
*/
|
||||
import type { Message as ESBuildMessage } from "esbuild";
|
||||
|
||||
const logPrefix = "👷 [ESBuild]";
|
||||
const log = console.debug.bind(console, logPrefix);
|
||||
|
||||
type BuildEventListener<Data = unknown> = (event: MessageEvent<Data>) => void;
|
||||
/**
|
||||
* @template {unknown} [Data=unknown]
|
||||
* @typedef {(event: MessageEvent) => void} BuildEventListener
|
||||
*/
|
||||
|
||||
/**
|
||||
* A client-side watcher for ESBuild.
|
||||
@ -17,13 +20,11 @@ type BuildEventListener<Data = unknown> = (event: MessageEvent<Data>) => void;
|
||||
*
|
||||
* ```ts
|
||||
* if (process.env.NODE_ENV === "development" && process.env.WATCHER_URL) {
|
||||
* const { ESBuildObserver } = await import("@goauthentik/common/client");
|
||||
* const { ESBuildObserver } = await import("@goauthentik/esbuild-plugin-live-reload/client");
|
||||
*
|
||||
* new ESBuildObserver(process.env.WATCHER_URL);
|
||||
* ESBuildObserver.initialize(process.env.WATCHER_URL);
|
||||
* }
|
||||
* ```
|
||||
}
|
||||
|
||||
*/
|
||||
export class ESBuildObserver extends EventSource {
|
||||
/**
|
||||
@ -58,15 +59,19 @@ export class ESBuildObserver extends EventSource {
|
||||
|
||||
/**
|
||||
* The interval for the keep-alive check.
|
||||
* @type {ReturnType<typeof setInterval> | undefined}
|
||||
*/
|
||||
#keepAliveInterval: ReturnType<typeof setInterval> | undefined;
|
||||
#keepAliveInterval;
|
||||
|
||||
#trackActivity = () => {
|
||||
this.lastUpdatedAt = Date.now();
|
||||
this.alive = true;
|
||||
};
|
||||
|
||||
#startListener: BuildEventListener = () => {
|
||||
/**
|
||||
* @type {BuildEventListener}
|
||||
*/
|
||||
#startListener = () => {
|
||||
this.#trackActivity();
|
||||
log("⏰ Build started...");
|
||||
};
|
||||
@ -82,13 +87,18 @@ export class ESBuildObserver extends EventSource {
|
||||
}
|
||||
};
|
||||
|
||||
#errorListener: BuildEventListener<string> = (event) => {
|
||||
/**
|
||||
* @type {BuildEventListener<string>}
|
||||
*/
|
||||
#errorListener = (event) => {
|
||||
this.#trackActivity();
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.group(logPrefix, "⛔️⛔️⛔️ Build error...");
|
||||
|
||||
const esbuildErrorMessages: ESBuildMessage[] = JSON.parse(event.data);
|
||||
/**
|
||||
* @type {ESBuildMessage[]}
|
||||
*/
|
||||
const esbuildErrorMessages = JSON.parse(event.data);
|
||||
|
||||
for (const error of esbuildErrorMessages) {
|
||||
console.warn(error.text);
|
||||
@ -101,11 +111,13 @@ export class ESBuildObserver extends EventSource {
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.groupEnd();
|
||||
};
|
||||
|
||||
#endListener: BuildEventListener = () => {
|
||||
/**
|
||||
* @type {BuildEventListener}
|
||||
*/
|
||||
#endListener = () => {
|
||||
cancelAnimationFrame(this.#reloadFrameID);
|
||||
|
||||
this.#trackActivity();
|
||||
@ -126,12 +138,32 @@ export class ESBuildObserver extends EventSource {
|
||||
});
|
||||
};
|
||||
|
||||
#keepAliveListener: BuildEventListener = () => {
|
||||
/**
|
||||
* @type {BuildEventListener}
|
||||
*/
|
||||
#keepAliveListener = () => {
|
||||
this.#trackActivity();
|
||||
log("🏓 Keep-alive");
|
||||
};
|
||||
|
||||
constructor(url: string | URL) {
|
||||
/**
|
||||
* Initialize the ESBuild observer.
|
||||
* This should be called once in your application.
|
||||
*
|
||||
* @param {string | URL} url
|
||||
* @returns {ESBuildObserver}
|
||||
*/
|
||||
static initialize(url) {
|
||||
const esbuildObserver = new ESBuildObserver(url);
|
||||
|
||||
return esbuildObserver;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string | URL} url
|
||||
*/
|
||||
constructor(url) {
|
||||
super(url);
|
||||
|
||||
this.addEventListener("esbuild:start", this.#startListener);
|
2
packages/esbuild-plugin-live-reload/index.js
Normal file
2
packages/esbuild-plugin-live-reload/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
export * from "./client/index.js";
|
||||
export * from "./plugin/index.js";
|
46
packages/esbuild-plugin-live-reload/package.json
Normal file
46
packages/esbuild-plugin-live-reload/package.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "@goauthentik/esbuild-plugin-live-reload",
|
||||
"version": "1.0.4",
|
||||
"description": "ESBuild plugin to watch for file changes and trigger client-side reloads.",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"import": "./index.js",
|
||||
"types": "./out/index.d.ts"
|
||||
},
|
||||
"./client": {
|
||||
"import": "./client/index.js",
|
||||
"types": "./out/client/index.d.ts"
|
||||
},
|
||||
"./plugin": {
|
||||
"import": "./plugin/index.js",
|
||||
"types": "./out/plugin/index.d.ts"
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.14.1",
|
||||
"esbuild": "^0.25.0",
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"esbuild": "^0.25.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.11"
|
||||
},
|
||||
"types": "./out/index.d.ts",
|
||||
"files": [
|
||||
"./index.js",
|
||||
"client/**/*",
|
||||
"plugin/**/*",
|
||||
"out/**/*"
|
||||
],
|
||||
"prettier": "@goauthentik/prettier-config",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
import * as http from "http";
|
||||
import path from "path";
|
||||
/**
|
||||
* @file Live reload plugin for ESBuild.
|
||||
*/
|
||||
import * as http from "node:http";
|
||||
import * as path from "node:path";
|
||||
|
||||
/**
|
||||
* Serializes a custom event to a text stream.
|
||||
@ -22,7 +25,7 @@ export function serializeCustomEventToStream(event) {
|
||||
* @typedef {Object} BuildObserverOptions
|
||||
*
|
||||
* @property {URL} serverURL
|
||||
* @property {string} logPrefix
|
||||
* @property {string} [logPrefix]
|
||||
* @property {string} relativeRoot
|
||||
*/
|
||||
|
||||
@ -32,8 +35,11 @@ export function serializeCustomEventToStream(event) {
|
||||
* @param {BuildObserverOptions} options
|
||||
* @returns {import('esbuild').Plugin}
|
||||
*/
|
||||
export function buildObserverPlugin({ serverURL, logPrefix, relativeRoot }) {
|
||||
const timerLabel = `[${logPrefix}] Build`;
|
||||
export function liveReloadPlugin({ serverURL, logPrefix = "Build Observer", relativeRoot }) {
|
||||
const timerLabel = `[${logPrefix}] 🏁`;
|
||||
// eslint-disable-next-line no-console
|
||||
const log = console.log.bind(console, `[${logPrefix}]`);
|
||||
|
||||
const endpoint = serverURL.pathname;
|
||||
const dispatcher = new EventTarget();
|
||||
|
||||
@ -43,18 +49,18 @@ export function buildObserverPlugin({ serverURL, logPrefix, relativeRoot }) {
|
||||
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
||||
|
||||
if (req.url !== endpoint) {
|
||||
console.log(`🚫 Invalid request to ${req.url}`);
|
||||
log(`🚫 Invalid request to ${req.url}`);
|
||||
res.writeHead(404);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("🔌 Client connected");
|
||||
log("🔌 Client connected");
|
||||
|
||||
res.writeHead(200, {
|
||||
"Content-Type": "text/event-stream",
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive",
|
||||
Connection: "keep-alive",
|
||||
});
|
||||
|
||||
/**
|
||||
@ -71,7 +77,7 @@ export function buildObserverPlugin({ serverURL, logPrefix, relativeRoot }) {
|
||||
dispatcher.addEventListener("esbuild:end", listener);
|
||||
|
||||
req.on("close", () => {
|
||||
console.log("🔌 Client disconnected");
|
||||
log("🔌 Client disconnected");
|
||||
|
||||
clearInterval(keepAliveInterval);
|
||||
|
10
packages/esbuild-plugin-live-reload/tsconfig.json
Normal file
10
packages/esbuild-plugin-live-reload/tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "@goauthentik/tsconfig",
|
||||
"compilerOptions": {
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||
"resolveJsonModule": true,
|
||||
"baseUrl": ".",
|
||||
"checkJs": true,
|
||||
"emitDeclarationOnly": true
|
||||
}
|
||||
}
|
@ -23,8 +23,9 @@ export const DefaultIgnorePatterns = [
|
||||
"**/out",
|
||||
"**/dist",
|
||||
"**/.wireit",
|
||||
"**/.venv",
|
||||
"website/build/**",
|
||||
"website/.docusaurus/**",
|
||||
"**/.docusaurus/**",
|
||||
"**/node_modules",
|
||||
"**/coverage",
|
||||
"**/storybook-static",
|
||||
|
@ -1,6 +1,8 @@
|
||||
// @ts-check
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
import NodeLintPlugin from "../plugins/node-lint.js";
|
||||
|
||||
const MAX_DEPTH = 4;
|
||||
const MAX_NESTED_CALLBACKS = 4;
|
||||
const MAX_PARAMS = 5;
|
||||
@ -9,22 +11,29 @@ const MAX_PARAMS = 5;
|
||||
* ESLint configuration for JavaScript authentik projects.
|
||||
*/
|
||||
export const javaScriptConfig = tseslint.config({
|
||||
plugins: {
|
||||
"node-lint": NodeLintPlugin,
|
||||
},
|
||||
files: ["**/*.{js,jsx,mjs,cjs}"],
|
||||
rules: {
|
||||
"node-lint/no-unprefixed-imports": "warn",
|
||||
// TODO: Clean up before enabling.
|
||||
"accessor-pairs": "off",
|
||||
"array-callback-return": "error",
|
||||
"block-scoped-var": "error",
|
||||
"consistent-return": ["error", { treatUndefinedAsUnspecified: false }],
|
||||
"consistent-return": "off",
|
||||
// "consistent-return": ["error", { treatUndefinedAsUnspecified: false }],
|
||||
"consistent-this": ["error", "that"],
|
||||
"curly": "off",
|
||||
"dot-notation": [
|
||||
"error",
|
||||
{
|
||||
allowKeywords: true,
|
||||
},
|
||||
],
|
||||
"eqeqeq": "error",
|
||||
"func-names": ["error", "as-needed"],
|
||||
curly: "off",
|
||||
// "dot-notation": [
|
||||
// "error",
|
||||
// {
|
||||
// allowKeywords: true,
|
||||
// },
|
||||
// ],
|
||||
// "eqeqeq": "error",
|
||||
eqeqeq: "off",
|
||||
// "func-names": ["error", "as-needed"],
|
||||
"guard-for-in": "error",
|
||||
"max-depth": ["error", MAX_DEPTH],
|
||||
"max-nested-callbacks": ["error", MAX_NESTED_CALLBACKS],
|
||||
@ -33,13 +42,13 @@ export const javaScriptConfig = tseslint.config({
|
||||
// "new-cap": "error",
|
||||
"no-alert": "error",
|
||||
"no-array-constructor": "error",
|
||||
"no-bitwise": [
|
||||
"error",
|
||||
{
|
||||
allow: ["~"],
|
||||
int32Hint: true,
|
||||
},
|
||||
],
|
||||
// "no-bitwise": [
|
||||
// "error",
|
||||
// {
|
||||
// allow: ["~"],
|
||||
// int32Hint: true,
|
||||
// },
|
||||
// ],
|
||||
"no-caller": "error",
|
||||
"no-case-declarations": "error",
|
||||
"no-class-assign": "error",
|
||||
@ -53,10 +62,10 @@ export const javaScriptConfig = tseslint.config({
|
||||
"no-dupe-args": "error",
|
||||
"no-dupe-keys": "error",
|
||||
"no-duplicate-case": "error",
|
||||
"no-else-return": "error",
|
||||
// "no-else-return": "error",
|
||||
"no-empty": "error",
|
||||
"no-empty-character-class": "error",
|
||||
"no-empty-function": ["error", { allow: ["constructors"] }],
|
||||
// "no-empty-function": ["error", { allow: ["constructors"] }],
|
||||
"no-labels": "error",
|
||||
"no-eq-null": "error",
|
||||
"no-eval": "error",
|
||||
@ -68,7 +77,7 @@ export const javaScriptConfig = tseslint.config({
|
||||
"no-fallthrough": "error",
|
||||
"no-func-assign": "error",
|
||||
"no-implied-eval": "error",
|
||||
"no-implicit-coercion": "error",
|
||||
"no-implicit-coercion": ["error", { boolean: true, allow: ["!!"] }],
|
||||
"no-implicit-globals": "error",
|
||||
"no-inner-declarations": ["error", "functions"],
|
||||
"no-invalid-regexp": "error",
|
||||
@ -76,18 +85,18 @@ export const javaScriptConfig = tseslint.config({
|
||||
"no-iterator": "error",
|
||||
"no-label-var": "error",
|
||||
"no-lone-blocks": "error",
|
||||
"no-lonely-if": "error",
|
||||
// "no-lonely-if": "error",
|
||||
"no-loop-func": "error",
|
||||
"no-multi-str": "error",
|
||||
// TODO: Clean up before enabling.
|
||||
"no-negated-condition": "off",
|
||||
"no-new": "error",
|
||||
"no-new": "off",
|
||||
"no-new-func": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-obj-calls": "error",
|
||||
"no-octal": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-param-reassign": ["error", { props: false }],
|
||||
// "no-param-reassign": ["error", { props: false }],
|
||||
"no-proto": "error",
|
||||
"no-redeclare": "error",
|
||||
"no-regex-spaces": "error",
|
||||
@ -99,39 +108,58 @@ export const javaScriptConfig = tseslint.config({
|
||||
// TODO: Clean up before enabling.
|
||||
// "no-shadow": "error",
|
||||
"no-shadow-restricted-names": "error",
|
||||
"no-sparse-arrays": "error",
|
||||
// TODO: Clean up before enabling.
|
||||
// "no-sparse-arrays": "error",
|
||||
"no-this-before-super": "error",
|
||||
"no-throw-literal": "error",
|
||||
// "no-throw-literal": "error",
|
||||
"no-trailing-spaces": "off", // Handled by Prettier.
|
||||
"no-undef": "off",
|
||||
"no-undef-init": "off",
|
||||
"no-unexpected-multiline": "error",
|
||||
"no-useless-constructor": "error",
|
||||
// "no-useless-constructor": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unneeded-ternary": "error",
|
||||
"no-unreachable": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-unused-labels": "error",
|
||||
"no-use-before-define": "error",
|
||||
// "no-use-before-define": "error",
|
||||
"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",
|
||||
// "prefer-arrow-callback": "error",
|
||||
"prefer-const": "warn",
|
||||
"prefer-rest-params": "error",
|
||||
"prefer-spread": "error",
|
||||
"prefer-template": "error",
|
||||
"radix": "error",
|
||||
"prefer-template": "off",
|
||||
radix: "error",
|
||||
"require-yield": "error",
|
||||
"strict": ["error", "global"],
|
||||
strict: ["error", "global"],
|
||||
"use-isnan": "error",
|
||||
"valid-typeof": "error",
|
||||
"vars-on-top": "error",
|
||||
"yoda": ["error", "never"],
|
||||
yoda: ["error", "never"],
|
||||
|
||||
"no-console": ["error", { allow: ["debug", "warn", "error"] }],
|
||||
"no-console": [
|
||||
"warn",
|
||||
{
|
||||
allow: [
|
||||
//---
|
||||
"debug",
|
||||
"warn",
|
||||
"error",
|
||||
"group",
|
||||
"groupCollapsed",
|
||||
"groupEnd",
|
||||
"table",
|
||||
"trace",
|
||||
"time",
|
||||
"timeEnd",
|
||||
"timeStamp",
|
||||
],
|
||||
},
|
||||
],
|
||||
// SonarJS is not yet compatible with ESLint 9. Commenting these out
|
||||
// until it is.
|
||||
// "sonarjs/cognitive-complexity": ["off", MAX_COGNITIVE_COMPLEXITY],
|
||||
|
2
packages/eslint-config/lib/react-config.js
vendored
2
packages/eslint-config/lib/react-config.js
vendored
@ -13,7 +13,7 @@ export const reactConfig = tseslint.config({
|
||||
},
|
||||
|
||||
plugins: {
|
||||
"react": reactPlugin,
|
||||
react: reactPlugin,
|
||||
"react-hooks": hooksPlugin,
|
||||
},
|
||||
|
||||
|
@ -1,25 +1,42 @@
|
||||
// @ts-check
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
import NodeLintPlugin from "../plugins/node-lint.js";
|
||||
|
||||
/**
|
||||
* ESLint configuration for TypeScript authentik projects.
|
||||
*/
|
||||
export const typescriptConfig = tseslint.config({
|
||||
plugins: {
|
||||
"node-lint": NodeLintPlugin,
|
||||
},
|
||||
|
||||
rules: {
|
||||
"@typescript-eslint/ban-ts-comment": [
|
||||
"error",
|
||||
{
|
||||
"ts-expect-error": "allow-with-description",
|
||||
"ts-ignore": true,
|
||||
"ts-nocheck": "allow-with-description",
|
||||
"ts-check": false,
|
||||
"minimumDescriptionLength": 5,
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
// "@typescript-eslint/ban-ts-comment": [
|
||||
// "error",
|
||||
// {
|
||||
// "ts-expect-error": "allow-with-description",
|
||||
// "ts-ignore": true,
|
||||
// "ts-nocheck": "allow-with-description",
|
||||
// "ts-check": false,
|
||||
// "minimumDescriptionLength": 5,
|
||||
// },
|
||||
// ],
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
"no-unused-private-class-members": "warn",
|
||||
"no-use-before-define": "off",
|
||||
"@typescript-eslint/no-use-before-define": "error",
|
||||
// "@typescript-eslint/no-use-before-define": "error",
|
||||
"no-invalid-this": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/triple-slash-reference": [
|
||||
"warn",
|
||||
{
|
||||
path: "never",
|
||||
types: "always",
|
||||
lib: "always",
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-namespace": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"warn",
|
||||
|
@ -6,26 +6,9 @@
|
||||
"scripts": {
|
||||
"build": "tsc -p ."
|
||||
},
|
||||
"main": "./index.js",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"import": "./index.js",
|
||||
"types": "./out/index.d.ts"
|
||||
},
|
||||
"./react-config": {
|
||||
"import": "./lib/react-config.js",
|
||||
"types": "./out/lib/react-config.d.ts"
|
||||
},
|
||||
"./javascript-config": {
|
||||
"import": "./lib/javascript-config.js",
|
||||
"types": "./out/lib/javascript-config.d.ts"
|
||||
},
|
||||
"./typescript-config": {
|
||||
"import": "./lib/typescript-config.js",
|
||||
"types": "./out/lib/typescript-config.d.ts"
|
||||
}
|
||||
},
|
||||
"exports": "./index.js",
|
||||
"dependencies": {
|
||||
"eslint": "^9.23.0",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
@ -35,8 +18,8 @@
|
||||
"eslint-plugin-wc": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@goauthentik/prettier-config": "^1.0.1",
|
||||
"@goauthentik/tsconfig": "^1.0.1",
|
||||
"@goauthentik/prettier-config": "^1.0.4",
|
||||
"@goauthentik/tsconfig": "^1.0.4",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"typescript": "^5.8.2",
|
||||
"typescript-eslint": "^8.29.0"
|
||||
|
85
packages/eslint-config/plugins/node-lint.js
Normal file
85
packages/eslint-config/plugins/node-lint.js
Normal file
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @file ESLint rule to enforce the use of the `node:` prefix for Node.js built-in modules.
|
||||
*
|
||||
* @import { Rule, ESLint } from "eslint";
|
||||
* @import { RuleTextEditor } from "@eslint/core";
|
||||
*/
|
||||
import { builtinModules } from "node:module";
|
||||
|
||||
const NODE_PROTOCOL_PREFIX = "node:";
|
||||
|
||||
/**
|
||||
* @type {Map<string, string>}
|
||||
*/
|
||||
const NodeModulesIndex = new Map();
|
||||
|
||||
for (const moduleName of builtinModules) {
|
||||
if (moduleName.startsWith("_")) continue;
|
||||
if (moduleName.startsWith(NODE_PROTOCOL_PREFIX)) continue;
|
||||
|
||||
NodeModulesIndex.set(moduleName, `${NODE_PROTOCOL_PREFIX}${moduleName}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Rule.RuleModule}
|
||||
*/
|
||||
const rule = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
fixable: "code",
|
||||
hasSuggestions: true,
|
||||
docs: {
|
||||
description: "Enforce `node:` prefix for Node.js built-in modules.",
|
||||
recommended: true,
|
||||
},
|
||||
},
|
||||
create: (context) => {
|
||||
/**
|
||||
* @type {Rule.RuleListener}
|
||||
*/
|
||||
const ruleListener = {
|
||||
ImportDeclaration({ source }) {
|
||||
if (source.type !== "Literal" || typeof source.value !== "string") {
|
||||
return;
|
||||
}
|
||||
|
||||
const moduleName = source.value;
|
||||
|
||||
const prefixedModuleName = NodeModulesIndex.get(moduleName);
|
||||
|
||||
if (!prefixedModuleName) return;
|
||||
|
||||
/**
|
||||
* @param {RuleTextEditor} editor
|
||||
*/
|
||||
const fix = (editor) =>
|
||||
editor.replaceText(source, JSON.stringify(prefixedModuleName));
|
||||
|
||||
context.report({
|
||||
node: source,
|
||||
message: `Module "${moduleName}" must use the "node:" prefix.`,
|
||||
fix,
|
||||
suggest: [
|
||||
{
|
||||
fix,
|
||||
desc: `Use "${prefixedModuleName}" instead.`,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
return ruleListener;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {ESLint.Plugin}
|
||||
*/
|
||||
const NodeLintPlugin = {
|
||||
rules: {
|
||||
"no-unprefixed-imports": rule,
|
||||
},
|
||||
};
|
||||
|
||||
export default NodeLintPlugin;
|
25
packages/monorepo/build.js
Normal file
25
packages/monorepo/build.js
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @file Utility functions for building and copying files.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Given an object of environment variables, returns a new object with the same keys and values, but
|
||||
* with the values serialized as strings.
|
||||
* @template {string} K
|
||||
*
|
||||
* @param {Record<K, string | number | boolean | object>} input
|
||||
* @returns {Record<`process.env.${K}`, string>}
|
||||
*/
|
||||
export function serializeEnvironmentVars(input) {
|
||||
/**
|
||||
* @type {Record<string, string>}
|
||||
*/
|
||||
const env = {};
|
||||
|
||||
for (const [key, value] of Object.entries(input)) {
|
||||
const namespaceKey = `process.env.${key}`;
|
||||
env[namespaceKey] = JSON.stringify(value || "");
|
||||
}
|
||||
|
||||
return /** @type {Record<string, string>} */ (env);
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
export * from "./paths.js";
|
||||
export * from "./constants.js";
|
||||
export * from "./build.js";
|
||||
export * from "./version.js";
|
||||
export * from "./scripting.js";
|
||||
|
@ -1,19 +1,14 @@
|
||||
{
|
||||
"name": "@goauthentik/monorepo",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.4",
|
||||
"description": "Utilities for the authentik monorepo.",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"import": "./index.js",
|
||||
"types": "./out/index.d.ts"
|
||||
}
|
||||
},
|
||||
"types": "./out/index.d.ts",
|
||||
"exports": "./index.js",
|
||||
"engines": {
|
||||
"node": ">=20.11"
|
||||
}
|
||||
},
|
||||
"types": "./out/index.d.ts"
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { createRequire } from "node:module";
|
||||
import { dirname, join, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const relativeDirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
/**
|
||||
* @typedef {'~authentik'} MonoRepoRoot
|
||||
@ -11,7 +11,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
/**
|
||||
* The root of the authentik monorepo.
|
||||
*/
|
||||
export const MonoRepoRoot = /** @type {MonoRepoRoot} */ (resolve(__dirname, "..", ".."));
|
||||
export const MonoRepoRoot = /** @type {MonoRepoRoot} */ (resolve(relativeDirname, "..", ".."));
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
|
@ -23,7 +23,7 @@ export const AuthentikPrettierConfig = {
|
||||
jsxSingleQuote: false,
|
||||
printWidth: 100,
|
||||
proseWrap: "preserve",
|
||||
quoteProps: "consistent",
|
||||
quoteProps: "as-needed",
|
||||
requirePragma: false,
|
||||
semi: true,
|
||||
singleQuote: false,
|
||||
@ -31,8 +31,23 @@ 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",
|
||||
"prettier-plugin-django-alpine",
|
||||
],
|
||||
importOrder: [
|
||||
// ---
|
||||
// Lit Imports
|
||||
"^(@?)lit(.*)$",
|
||||
// CSS Imports
|
||||
"\\.css$",
|
||||
// API Imports
|
||||
"^@goauthentik/api$",
|
||||
// Relative Imports
|
||||
"^[./]",
|
||||
],
|
||||
importOrderSeparation: true,
|
||||
importOrderSortSpecifiers: true,
|
||||
importOrderParserPlugins: ["typescript", "jsx", "classProperties", "decorators-legacy"],
|
||||
@ -49,6 +64,13 @@ export const AuthentikPrettierConfig = {
|
||||
trailingComma: "none",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: "authentik/**/*.html",
|
||||
options: {
|
||||
tabWidth: 2,
|
||||
parser: "html",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: "package.json",
|
||||
options: {
|
||||
|
@ -6,6 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "tsc -p ."
|
||||
},
|
||||
"main": "./index.js",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
@ -15,17 +16,17 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@goauthentik/tsconfig": "^1.0.1",
|
||||
"@goauthentik/tsconfig": "^1.0.4",
|
||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"prettier-plugin-django-alpine": "^1.3.0",
|
||||
"prettier-plugin-packagejson": "^2.5.10",
|
||||
"typescript": "^5.8.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"prettier-plugin-django-alpine": "^1.3.0",
|
||||
"prettier-plugin-packagejson": "^2.5.10"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -2,19 +2,16 @@
|
||||
"name": "@goauthentik/tsconfig",
|
||||
"version": "1.0.4",
|
||||
"description": "authentik's base TypeScript configuration.",
|
||||
"license": "MIT",
|
||||
"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"
|
||||
}
|
||||
|
@ -6,15 +6,14 @@ FROM --platform=${BUILDPLATFORM} docker.io/library/node:22 AS web-builder
|
||||
ENV NODE_ENV=production
|
||||
WORKDIR /static
|
||||
|
||||
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 ./package.json ./package.json
|
||||
COPY ./package-lock.json ./package-lock.json
|
||||
COPY ./packages ./packages
|
||||
COPY ./web ./web
|
||||
|
||||
RUN --mount=type=cache,target=/root/.npm npm ci --include=dev
|
||||
RUN npm run build-proxy -w @goauthentik/web
|
||||
|
||||
COPY web .
|
||||
RUN npm run build-proxy
|
||||
|
||||
# Stage 2: Build
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS builder
|
||||
@ -65,10 +64,10 @@ RUN apt-get update && \
|
||||
rm -rf /tmp/* /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=builder /go/proxy /
|
||||
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/
|
||||
COPY --from=web-builder /static/web/robots.txt /web/robots.txt
|
||||
COPY --from=web-builder /static/web/security.txt /web/security.txt
|
||||
COPY --from=web-builder /static/web/dist/ /web/dist/
|
||||
COPY --from=web-builder /static/web/authentik/ /web/authentik/
|
||||
|
||||
HEALTHCHECK --interval=5s --retries=20 --start-period=3s CMD [ "/proxy", "healthcheck" ]
|
||||
|
||||
|
27
tsconfig.json
Normal file
27
tsconfig.json
Normal file
@ -0,0 +1,27 @@
|
||||
// TypeScript Project Configuration
|
||||
{
|
||||
"watchOptions": {
|
||||
"excludeDirectories": [
|
||||
"**/.git", // Git
|
||||
"**/.yarn", // Yarn
|
||||
"**/.vscode", // VS Code
|
||||
"**/.vscode-test-web", // VS Code Web Test
|
||||
"**/dist", // Distributed build files
|
||||
"**/out", // Output build files
|
||||
"**/.drafts", // Drafts
|
||||
"**/.github", // GitHub
|
||||
"**/node_modules" // Node modules
|
||||
]
|
||||
},
|
||||
|
||||
// The root project has no sources of its own. By setting `files` to an empty
|
||||
// list, TS won't automatically include all sources below root (the default).
|
||||
"files": [],
|
||||
"references": [
|
||||
// Note that references are in the order we want them to be built.
|
||||
{ "path": "./packages/prettier-config" },
|
||||
{ "path": "./packages/eslint-config" },
|
||||
{ "path": "./packages/esbuild-plugin-live-reload" },
|
||||
{ "path": "./web" }
|
||||
]
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
# don't ever lint node_modules
|
||||
node_modules
|
||||
# don't lint build output (make sure it's set to your correct build folder name)
|
||||
dist
|
||||
# don't lint nyc coverage output
|
||||
coverage
|
||||
# Import order matters
|
||||
poly.ts
|
||||
src/locale-codes.ts
|
||||
src/locales/
|
||||
storybook-static/
|
||||
# Prettier breaks the tsconfig file
|
||||
tsconfig.json
|
||||
.storybook/css-import-maps*
|
||||
package.json
|
||||
packages/**/package.json
|
@ -1,23 +0,0 @@
|
||||
{
|
||||
"arrowParens": "always",
|
||||
"bracketSpacing": true,
|
||||
"embeddedLanguageFormatting": "auto",
|
||||
"htmlWhitespaceSensitivity": "css",
|
||||
"insertPragma": false,
|
||||
"jsxSingleQuote": false,
|
||||
"printWidth": 100,
|
||||
"proseWrap": "preserve",
|
||||
"quoteProps": "consistent",
|
||||
"requirePragma": false,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 4,
|
||||
"trailingComma": "all",
|
||||
"useTabs": false,
|
||||
"vueIndentScriptAndStyle": false,
|
||||
"plugins": ["@trivago/prettier-plugin-sort-imports"],
|
||||
"importOrder": ["^(@?)lit(.*)$", "\\.css$", "^@goauthentik/api$", "^[./]"],
|
||||
"importOrderSeparation": true,
|
||||
"importOrderSortSpecifiers": true,
|
||||
"importOrderParserPlugins": ["typescript", "jsx", "classProperties", "decorators-legacy"]
|
||||
}
|
@ -1,14 +1,15 @@
|
||||
import replace from "@rollup/plugin-replace";
|
||||
import { NodeEnvironment, resolvePackage, serializeEnvironmentVars } from "@goauthentik/monorepo";
|
||||
import { PackageRoot } from "@goauthentik/web/paths";
|
||||
import type { StorybookConfig } from "@storybook/web-components-vite";
|
||||
import { cwd } from "process";
|
||||
import { deepmerge } from "deepmerge-ts";
|
||||
import * as path from "node:path";
|
||||
import modify from "rollup-plugin-modify";
|
||||
import postcssLit from "rollup-plugin-postcss-lit";
|
||||
import tsconfigPaths from "vite-tsconfig-paths";
|
||||
|
||||
export const isProdBuild = process.env.NODE_ENV === "production";
|
||||
export const apiBasePath = process.env.AK_API_BASE_PATH || "";
|
||||
const AK_API_BASE_PATH = process.env.AK_API_BASE_PATH || "";
|
||||
|
||||
const importInlinePatterns = [
|
||||
const inlineImportPatterns = [
|
||||
'import AKGlobal from "(\\.\\./)*common/styles/authentik\\.css',
|
||||
'import AKGlobal from "@goauthentik/common/styles/authentik\\.css',
|
||||
'import PF.+ from "@patternfly/patternfly/\\S+\\.css',
|
||||
@ -17,7 +18,9 @@ const importInlinePatterns = [
|
||||
'import styles from "\\./LibraryPageImpl\\.css',
|
||||
];
|
||||
|
||||
const importInlineRegexp = new RegExp(importInlinePatterns.map((a) => `(${a})`).join("|"));
|
||||
const inlineImportPattern = new RegExp(inlineImportPatterns.map((a) => `(${a})`).join("|"));
|
||||
|
||||
const patternflyPath = resolvePackage("@patternfly/patternfly");
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
|
||||
@ -29,19 +32,19 @@ const config: StorybookConfig = {
|
||||
],
|
||||
staticDirs: [
|
||||
{
|
||||
from: "../node_modules/@patternfly/patternfly/patternfly-base.css",
|
||||
from: path.resolve(patternflyPath, "patternfly-base.css"),
|
||||
to: "@patternfly/patternfly/patternfly-base.css",
|
||||
},
|
||||
{
|
||||
from: "../src/common/styles/authentik.css",
|
||||
from: path.resolve(PackageRoot, "src", "common", "styles", "authentik.css"),
|
||||
to: "@goauthentik/common/styles/authentik.css",
|
||||
},
|
||||
{
|
||||
from: "../src/common/styles/theme-dark.css",
|
||||
from: path.resolve(PackageRoot, "src", "common", "styles", "theme-dark.css"),
|
||||
to: "@goauthentik/common/styles/theme-dark.css",
|
||||
},
|
||||
{
|
||||
from: "../src/common/styles/one-dark.css",
|
||||
from: path.resolve(PackageRoot, "src", "common", "styles", "one-dark.css"),
|
||||
to: "@goauthentik/common/styles/one-dark.css",
|
||||
},
|
||||
],
|
||||
@ -53,28 +56,25 @@ const config: StorybookConfig = {
|
||||
autodocs: "tag",
|
||||
},
|
||||
async viteFinal(config) {
|
||||
return {
|
||||
...config,
|
||||
return deepmerge(config, {
|
||||
define: serializeEnvironmentVars({
|
||||
NODE_ENV: NodeEnvironment,
|
||||
CWD: process.cwd(),
|
||||
AK_API_BASE_PATH: AK_API_BASE_PATH,
|
||||
WATCHER_URL: "",
|
||||
}),
|
||||
|
||||
plugins: [
|
||||
modify({
|
||||
find: importInlineRegexp,
|
||||
find: inlineImportPattern,
|
||||
replace: (match: RegExpMatchArray) => {
|
||||
return `${match}?inline`;
|
||||
},
|
||||
}),
|
||||
replace({
|
||||
"process.env.NODE_ENV": JSON.stringify(
|
||||
isProdBuild ? "production" : "development",
|
||||
),
|
||||
"process.env.CWD": JSON.stringify(cwd()),
|
||||
"process.env.AK_API_BASE_PATH": JSON.stringify(apiBasePath),
|
||||
"preventAssignment": true,
|
||||
}),
|
||||
...config.plugins,
|
||||
postcssLit(),
|
||||
tsconfigPaths(),
|
||||
],
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
<link rel="stylesheet" href="@patternfly/patternfly/patternfly-base.css" />
|
||||
<link rel="stylesheet" href="@goauthentik/common/styles/authentik.css" />
|
||||
|
||||
<style>
|
||||
body {
|
||||
overflow-y: scroll;
|
||||
|
@ -1,90 +0,0 @@
|
||||
import eslint from "@eslint/js";
|
||||
import tsparser from "@typescript-eslint/parser";
|
||||
import litconf from "eslint-plugin-lit";
|
||||
import wcconf from "eslint-plugin-wc";
|
||||
import globals from "globals";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
export default [
|
||||
// You would not believe how much this change has frustrated users: ["if an ignores key is used
|
||||
// without any other keys in the configuration object, then the patterns act as global
|
||||
// ignores"](https://eslint.org/docs/latest/use/configure/ignore)
|
||||
{
|
||||
ignores: [
|
||||
"dist/",
|
||||
// don't lint the cache
|
||||
".wireit/",
|
||||
// let packages have their own configurations
|
||||
"packages/",
|
||||
// don't ever lint node_modules
|
||||
"node_modules/",
|
||||
".storybook/*",
|
||||
// don't lint build output (make sure it's set to your correct build folder name)
|
||||
// don't lint nyc coverage output
|
||||
"coverage/",
|
||||
"src/locale-codes.ts",
|
||||
"storybook-static/",
|
||||
"src/locales/",
|
||||
],
|
||||
},
|
||||
eslint.configs.recommended,
|
||||
wcconf.configs["flat/recommended"],
|
||||
litconf.configs["flat/recommended"],
|
||||
...tseslint.configs.recommended,
|
||||
{
|
||||
languageOptions: {
|
||||
parser: tsparser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
sourceType: "module",
|
||||
},
|
||||
},
|
||||
files: ["src/**"],
|
||||
rules: {
|
||||
"lit/attribute-names": "off",
|
||||
// "lit/attribute-names": "error",
|
||||
"lit/no-private-properties": "error",
|
||||
// "lit/prefer-nothing": "warn",
|
||||
"lit/no-template-bind": "error",
|
||||
"no-unused-vars": "off",
|
||||
"no-console": ["error", { allow: ["debug", "warn", "error"] }],
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
argsIgnorePattern: "^_",
|
||||
varsIgnorePattern: "^_",
|
||||
caughtErrorsIgnorePattern: "^_",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
languageOptions: {
|
||||
parser: tsparser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
sourceType: "module",
|
||||
},
|
||||
globals: {
|
||||
...globals.nodeBuiltin,
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
files: ["scripts/**/*.mjs", "*.ts", "*.mjs"],
|
||||
rules: {
|
||||
"no-unused-vars": "off",
|
||||
// We WANT our scripts to output to the console!
|
||||
"no-console": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
argsIgnorePattern: "^_",
|
||||
varsIgnorePattern: "^_",
|
||||
caughtErrorsIgnorePattern: "^_",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
26423
web/package-lock.json
generated
26423
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
156
web/package.json
156
web/package.json
@ -1,13 +1,39 @@
|
||||
{
|
||||
"name": "@goauthentik/web",
|
||||
"version": "0.0.0",
|
||||
"overrides": {
|
||||
"rapidoc": {
|
||||
"@apitools/openapi-parser@": "0.0.37"
|
||||
},
|
||||
"chromedriver": {
|
||||
"axios": "^1.8.4"
|
||||
}
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "wireit",
|
||||
"build-locales": "wireit",
|
||||
"build-locales:build": "wireit",
|
||||
"build-proxy": "wireit",
|
||||
"build:sfe": "wireit",
|
||||
"esbuild:watch": "node scripts/build-web.mjs --watch",
|
||||
"extract-locales": "wireit",
|
||||
"format": "wireit",
|
||||
"lint": "wireit",
|
||||
"lint:imports": "wireit",
|
||||
"lint:lockfile": "wireit",
|
||||
"lit-analyse": "wireit",
|
||||
"postinstall": "bash scripts/patch-spotlight.sh",
|
||||
"precommit": "wireit",
|
||||
"prettier": "wireit",
|
||||
"prettier-check": "wireit",
|
||||
"pseudolocalize": "wireit",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"storybook:build": "wireit",
|
||||
"test": "wireit",
|
||||
"test:e2e": "wireit",
|
||||
"test:e2e:watch": "wireit",
|
||||
"test:watch": "wireit",
|
||||
"watch": "run-s build-locales esbuild:watch"
|
||||
},
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
"./paths": "./paths.js",
|
||||
"./scripts/*": "./scripts/*.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/lang-css": "^6.3.1",
|
||||
@ -44,6 +70,7 @@
|
||||
"date-fns": "^4.1.0",
|
||||
"deepmerge-ts": "^7.1.5",
|
||||
"dompurify": "^3.2.4",
|
||||
"esbuild-plugin-copy": "^2.1.1",
|
||||
"fuse.js": "^7.0.0",
|
||||
"guacamole-common-js": "^1.5.0",
|
||||
"hastscript": "^9.0.1",
|
||||
@ -62,6 +89,7 @@
|
||||
"remark-gfm": "^4.0.1",
|
||||
"remark-mdx-frontmatter": "^5.0.0",
|
||||
"style-mod": "^4.1.2",
|
||||
"trusted-types": "^2.0.0",
|
||||
"ts-pattern": "^5.4.0",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"webcomponent-qr-code": "^1.2.0",
|
||||
@ -69,12 +97,15 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.11.1",
|
||||
"@goauthentik/esbuild-plugin-live-reload": "^1.0.4",
|
||||
"@goauthentik/monorepo": "^1.0.4",
|
||||
"@goauthentik/prettier-config": "^1.0.4",
|
||||
"@goauthentik/tsconfig": "^1.0.4",
|
||||
"@hcaptcha/types": "^1.0.4",
|
||||
"@lit/localize-tools": "^0.8.0",
|
||||
"@rollup/plugin-replace": "^6.0.1",
|
||||
"@storybook/addon-essentials": "^8.3.4",
|
||||
"@storybook/addon-links": "^8.3.4",
|
||||
"@storybook/api": "^7.6.17",
|
||||
"@storybook/blocks": "^8.3.4",
|
||||
"@storybook/builder-vite": "^8.3.4",
|
||||
"@storybook/manager-api": "^8.3.4",
|
||||
@ -84,13 +115,13 @@
|
||||
"@types/chart.js": "^2.9.41",
|
||||
"@types/codemirror": "^5.60.15",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/eslint__js": "^8.42.3",
|
||||
"@types/grecaptcha": "^3.0.9",
|
||||
"@types/guacamole-common-js": "^1.5.2",
|
||||
"@types/mocha": "^10.0.8",
|
||||
"@types/node": "^22.7.4",
|
||||
"@types/node": "^22.14.1",
|
||||
"@types/react": "^18.3.13",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/trusted-types": "^2.0.7",
|
||||
"@typescript-eslint/eslint-plugin": "^8.8.0",
|
||||
"@typescript-eslint/parser": "^8.8.0",
|
||||
"@wdio/browser-runner": "9.4",
|
||||
@ -105,18 +136,15 @@
|
||||
"eslint-plugin-wc": "^2.1.1",
|
||||
"find-free-ports": "^3.1.1",
|
||||
"github-slugger": "^2.0.0",
|
||||
"glob": "^11.0.0",
|
||||
"globals": "^15.10.0",
|
||||
"knip": "^5.30.6",
|
||||
"lit-analyzer": "^2.0.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier": "^3.5.3",
|
||||
"pseudolocale": "^2.1.0",
|
||||
"rollup-plugin-modify": "^3.0.0",
|
||||
"rollup-plugin-postcss-lit": "^2.1.0",
|
||||
"storybook": "^8.3.4",
|
||||
"storybook-addon-mock": "^5.0.0",
|
||||
"syncpack": "^13.0.0",
|
||||
"turnstile-types": "^1.2.3",
|
||||
"typescript": "^5.6.2",
|
||||
"typescript-eslint": "^8.8.0",
|
||||
@ -124,10 +152,6 @@
|
||||
"vite-tsconfig-paths": "^5.0.1",
|
||||
"wireit": "^0.14.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"@esbuild/darwin-arm64": "^0.24.0",
|
||||
"@esbuild/linux-amd64": "^0.18.11",
|
||||
@ -136,39 +160,6 @@
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.23.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.23.0"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "wireit",
|
||||
"build-locales": "wireit",
|
||||
"build-locales:build": "wireit",
|
||||
"build-proxy": "wireit",
|
||||
"build:sfe": "wireit",
|
||||
"esbuild:watch": "node scripts/build-web.mjs --watch",
|
||||
"extract-locales": "wireit",
|
||||
"format": "wireit",
|
||||
"lint": "wireit",
|
||||
"lint:imports": "wireit",
|
||||
"lint:lockfile": "wireit",
|
||||
"lint:nightmare": "wireit",
|
||||
"lint:package": "wireit",
|
||||
"lint:precommit": "wireit",
|
||||
"lint:types": "wireit",
|
||||
"lit-analyse": "wireit",
|
||||
"postinstall": "bash scripts/patch-spotlight.sh",
|
||||
"precommit": "wireit",
|
||||
"prettier": "wireit",
|
||||
"prettier-check": "wireit",
|
||||
"pseudolocalize": "wireit",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"storybook:build": "wireit",
|
||||
"test": "wireit",
|
||||
"test:e2e": "wireit",
|
||||
"test:e2e:watch": "wireit",
|
||||
"test:watch": "wireit",
|
||||
"tsc": "wireit",
|
||||
"watch": "run-s build-locales esbuild:watch"
|
||||
},
|
||||
"type": "module",
|
||||
"wireit": {
|
||||
"build": {
|
||||
"#comment": [
|
||||
@ -245,10 +236,7 @@
|
||||
"command": "lit-localize extract"
|
||||
},
|
||||
"format": {
|
||||
"command": "prettier --write .",
|
||||
"dependencies": [
|
||||
"lint:package"
|
||||
]
|
||||
"command": "prettier --write ."
|
||||
},
|
||||
"format:packages": {
|
||||
"dependencies": [
|
||||
@ -267,16 +255,6 @@
|
||||
"lint:imports": {
|
||||
"command": "knip --config scripts/knip.config.ts"
|
||||
},
|
||||
"lint:types:tests": {
|
||||
"command": "tsc --noEmit -p ./tests"
|
||||
},
|
||||
"lint:types": {
|
||||
"command": "tsc --noEmit -p .",
|
||||
"dependencies": [
|
||||
"build-locales",
|
||||
"lint:types:tests"
|
||||
]
|
||||
},
|
||||
"lint:lockfile": {
|
||||
"__comment": "The lockfile-lint package does not have an option to ensure resolved hashes are set everywhere",
|
||||
"shell": true,
|
||||
@ -287,27 +265,6 @@
|
||||
"./packages/sfe:lint:lockfile"
|
||||
]
|
||||
},
|
||||
"lint:package": {
|
||||
"command": "syncpack format -i ' '"
|
||||
},
|
||||
"lint:nightmare": {
|
||||
"command": "${NODE_RUNNER} ./scripts/eslint.mjs --nightmare",
|
||||
"env": {
|
||||
"NODE_RUNNER": {
|
||||
"external": true,
|
||||
"default": "node"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint:precommit": {
|
||||
"command": "${NODE_RUNNER} ./scripts/eslint.mjs --precommit",
|
||||
"env": {
|
||||
"NODE_RUNNER": {
|
||||
"external": true,
|
||||
"default": "node"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint:spelling": {
|
||||
"command": "node scripts/check-spelling.mjs"
|
||||
},
|
||||
@ -317,13 +274,10 @@
|
||||
"precommit": {
|
||||
"command": "prettier --write .",
|
||||
"dependencies": [
|
||||
"lint:types",
|
||||
"lint:components",
|
||||
"lint:spelling",
|
||||
"lint:package",
|
||||
"lint:lockfile",
|
||||
"lint:lockfiles",
|
||||
"lint:precommit",
|
||||
"format:packages"
|
||||
]
|
||||
},
|
||||
@ -332,9 +286,6 @@
|
||||
"format"
|
||||
]
|
||||
},
|
||||
"prettier-check": {
|
||||
"command": "prettier --check ."
|
||||
},
|
||||
"pseudolocalize": {
|
||||
"command": "node scripts/pseudolocalize.mjs"
|
||||
},
|
||||
@ -378,15 +329,18 @@
|
||||
"env": {
|
||||
"TS_NODE_PROJECT": "tsconfig.test.json"
|
||||
}
|
||||
},
|
||||
"tsc": {
|
||||
"dependencies": [
|
||||
"lint:types"
|
||||
]
|
||||
}
|
||||
},
|
||||
"workspaces": [
|
||||
".",
|
||||
"./packages/*"
|
||||
]
|
||||
"engines": {
|
||||
"node": ">=22.14.0"
|
||||
},
|
||||
"prettier": "@goauthentik/prettier-config",
|
||||
"overrides": {
|
||||
"rapidoc": {
|
||||
"@apitools/openapi-parser@": "0.0.37"
|
||||
},
|
||||
"chromedriver": {
|
||||
"axios": "^1.8.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
{
|
||||
"arrowParens": "always",
|
||||
"bracketSpacing": true,
|
||||
"embeddedLanguageFormatting": "auto",
|
||||
"htmlWhitespaceSensitivity": "css",
|
||||
"insertPragma": false,
|
||||
"jsxSingleQuote": false,
|
||||
"printWidth": 100,
|
||||
"proseWrap": "preserve",
|
||||
"quoteProps": "consistent",
|
||||
"requirePragma": false,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 4,
|
||||
"trailingComma": "all",
|
||||
"useTabs": false,
|
||||
"vueIndentScriptAndStyle": false,
|
||||
"plugins": ["@trivago/prettier-plugin-sort-imports"],
|
||||
"importOrder": ["^(@?)lit(.*)$", "\\.css$", "^@goauthentik/api$", "^[./]"],
|
||||
"importOrderSeparation": true,
|
||||
"importOrderSortSpecifiers": true,
|
||||
"importOrderParserPlugins": ["typescript", "classProperties", "decorators-legacy"]
|
||||
}
|
@ -1,6 +1,14 @@
|
||||
{
|
||||
"name": "@goauthentik/web-sfe",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "wireit",
|
||||
"lint:lockfile": "wireit",
|
||||
"prettier": "prettier --write ./src ./tsconfig.json ./rollup.config.js ./package.json",
|
||||
"watch": "rollup -w -c rollup.config.js --bundleConfigAsCjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@goauthentik/api": "^2024.6.0-1719577139",
|
||||
"base64-js": "^1.5.1",
|
||||
@ -10,6 +18,7 @@
|
||||
"weakmap-polyfill": "^2.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@goauthentik/prettier-config": "^1.0.4",
|
||||
"@rollup/plugin-commonjs": "^28.0.0",
|
||||
"@rollup/plugin-node-resolve": "^15.3.0",
|
||||
"@rollup/plugin-swc": "^0.4.0",
|
||||
@ -18,12 +27,11 @@
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/jquery": "^3.5.31",
|
||||
"lockfile-lint": "^4.14.0",
|
||||
"prettier": "^3.3.2",
|
||||
"prettier": "^3.5.3",
|
||||
"rollup": "^4.23.0",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"wireit": "^0.14.9"
|
||||
},
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"@swc/core": "^1.7.28",
|
||||
"@swc/core-darwin-arm64": "^1.6.13",
|
||||
@ -37,13 +45,6 @@
|
||||
"@swc/core-win32-ia32-msvc": "^1.6.13",
|
||||
"@swc/core-win32-x64-msvc": "^1.6.13"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "wireit",
|
||||
"lint:lockfile": "wireit",
|
||||
"prettier": "prettier --write ./src ./tsconfig.json ./rollup.config.js ./package.json",
|
||||
"watch": "rollup -w -c rollup.config.js --bundleConfigAsCjs"
|
||||
},
|
||||
"wireit": {
|
||||
"build:sfe": {
|
||||
"command": "rollup -c rollup.config.js --bundleConfigAsCjs",
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { fromByteArray } from "base64-js";
|
||||
// sort-imports-ignore
|
||||
|
||||
import "formdata-polyfill";
|
||||
import $ from "jquery";
|
||||
import "weakmap-polyfill";
|
||||
|
||||
import { fromByteArray } from "base64-js";
|
||||
import $ from "jquery";
|
||||
|
||||
import {
|
||||
type AuthenticatorValidationChallenge,
|
||||
type AutosubmitChallenge,
|
||||
@ -273,7 +276,7 @@ class AuthenticatorValidateStage extends Stage<AuthenticatorValidationChallenge>
|
||||
deviceChallenge?: DeviceChallenge;
|
||||
|
||||
b64enc(buf: Uint8Array): string {
|
||||
return fromByteArray(buf).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
||||
return fromByteArray(buf).replace(/\+/g, "-").replace(/\//g, "_").replace(/[=]/g, "");
|
||||
}
|
||||
|
||||
b64RawEnc(buf: Uint8Array): string {
|
||||
|
78
web/paths.js
Normal file
78
web/paths.js
Normal file
@ -0,0 +1,78 @@
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const relativeDirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
//#region Base paths
|
||||
|
||||
/**
|
||||
* @typedef {'@goauthentik/web'} WebPackageIdentifier
|
||||
*/
|
||||
|
||||
/**
|
||||
* The root of the web package.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
export const DistDirectory = /** @type {`${WebPackageIdentifier}/${DistDirectoryName}`} */ (
|
||||
resolve(relativeDirname, DistDirectoryName)
|
||||
);
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Entry points
|
||||
|
||||
/**
|
||||
* @typedef {{ in: string, out: string }} EntryPointTarget
|
||||
*
|
||||
* ESBuild entrypoint target.
|
||||
* Matches the type defined in the ESBuild context.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Entry points available for building.
|
||||
*
|
||||
* @satisfies {Record<string, EntryPointTarget>}
|
||||
*/
|
||||
export const EntryPoint = /** @type {const} */ ({
|
||||
Admin: {
|
||||
in: resolve(PackageRoot, "src", "admin", "AdminInterface", "index.entrypoint.ts"),
|
||||
out: resolve(DistDirectory, "admin", "AdminInterface"),
|
||||
},
|
||||
User: {
|
||||
in: resolve(PackageRoot, "src", "user", "index.entrypoint.ts"),
|
||||
out: resolve(DistDirectory, "user", "UserInterface"),
|
||||
},
|
||||
Flow: {
|
||||
in: resolve(PackageRoot, "src", "flow", "index.entrypoint.ts"),
|
||||
out: resolve(DistDirectory, "flow", "FlowInterface"),
|
||||
},
|
||||
Standalone: {
|
||||
in: resolve(PackageRoot, "src", "standalone", "api-browser/index.entrypoint.ts"),
|
||||
out: resolve(DistDirectory, "standalone", "api-browser", "index"),
|
||||
},
|
||||
StandaloneLoading: {
|
||||
in: resolve(PackageRoot, "src", "standalone", "loading/index.entrypoint.ts"),
|
||||
out: resolve(DistDirectory, "standalone", "loading", "index"),
|
||||
},
|
||||
RAC: {
|
||||
in: resolve(PackageRoot, "src", "rac", "index.entrypoint.ts"),
|
||||
out: resolve(DistDirectory, "rac", "index"),
|
||||
},
|
||||
Polyfill: {
|
||||
in: resolve(PackageRoot, "src", "polyfill", "index.entrypoint.ts"),
|
||||
out: resolve(DistDirectory, "poly"),
|
||||
},
|
||||
});
|
||||
|
||||
//#endregion
|
@ -1,7 +1,7 @@
|
||||
import { spawnSync } from "child_process";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import process from "process";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import process from "node:process";
|
||||
|
||||
/**
|
||||
* Determines if all the Xliff translation source files are present and if the Typescript source
|
||||
@ -12,6 +12,9 @@ import process from "process";
|
||||
|
||||
const localizeRules = JSON.parse(fs.readFileSync("./lit-localize.json", "utf-8"));
|
||||
|
||||
/**
|
||||
* @param {string} loc
|
||||
*/
|
||||
function generatedFileIsUpToDateWithXliffSource(loc) {
|
||||
const xliff = path.join("./xliff", `${loc}.xlf`);
|
||||
const gened = path.join("./src/locales", `${loc}.ts`);
|
||||
@ -21,16 +24,26 @@ function generatedFileIsUpToDateWithXliffSource(loc) {
|
||||
// than the generated file. The missing XLF file is important enough it
|
||||
// generates a unique error message and halts the build.
|
||||
|
||||
/**
|
||||
* @type {fs.Stats}
|
||||
*/
|
||||
let xlfStat;
|
||||
|
||||
try {
|
||||
var xlfStat = fs.statSync(xliff);
|
||||
xlfStat = fs.statSync(xliff);
|
||||
} catch (_error) {
|
||||
console.error(`lit-localize expected '${loc}.xlf', but XLF file is not present`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {fs.Stats}
|
||||
*/
|
||||
let genedStat;
|
||||
|
||||
// If the generated file doesn't exist, of course it's not up to date.
|
||||
try {
|
||||
var genedStat = fs.statSync(gened);
|
||||
genedStat = fs.statSync(gened);
|
||||
} catch (_error) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1,137 +1,92 @@
|
||||
import { execFileSync } from "child_process";
|
||||
/**
|
||||
* @file ESBuild script for building the authentik web UI.
|
||||
*
|
||||
* @import { BuildOptions } from "esbuild";
|
||||
*/
|
||||
import { liveReloadPlugin } from "@goauthentik/esbuild-plugin-live-reload/plugin";
|
||||
import {
|
||||
MonoRepoRoot,
|
||||
NodeEnvironment,
|
||||
readBuildIdentifier,
|
||||
resolvePackage,
|
||||
serializeEnvironmentVars,
|
||||
} from "@goauthentik/monorepo";
|
||||
import { DistDirectory, DistDirectoryName, EntryPoint, PackageRoot } from "@goauthentik/web/paths";
|
||||
import { deepmerge } from "deepmerge-ts";
|
||||
import esbuild from "esbuild";
|
||||
import copy from "esbuild-plugin-copy";
|
||||
import { polyfillNode } from "esbuild-plugin-polyfill-node";
|
||||
import findFreePorts from "find-free-ports";
|
||||
import { copyFileSync, mkdirSync, readFileSync, statSync } from "fs";
|
||||
import { globSync } from "glob";
|
||||
import * as path from "path";
|
||||
import { cwd } from "process";
|
||||
import process from "process";
|
||||
import { fileURLToPath } from "url";
|
||||
import * as fs from "node:fs/promises";
|
||||
import * as path from "node:path";
|
||||
import process from "node:process";
|
||||
|
||||
import { mdxPlugin } from "./esbuild/build-mdx-plugin.mjs";
|
||||
import { buildObserverPlugin } from "./esbuild/build-observer-plugin.mjs";
|
||||
|
||||
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
||||
let authentikProjectRoot = path.join(__dirname, "..", "..");
|
||||
const logPrefix = "[Build]";
|
||||
|
||||
try {
|
||||
// Use the package.json file in the root folder, as it has the current version information.
|
||||
authentikProjectRoot = execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
||||
encoding: "utf8",
|
||||
}).replace("\n", "");
|
||||
} catch (_error) {
|
||||
// We probably don't have a .git folder, which could happen in container builds.
|
||||
}
|
||||
const definitions = serializeEnvironmentVars({
|
||||
NODE_ENV: NodeEnvironment,
|
||||
CWD: process.cwd(),
|
||||
AK_API_BASE_PATH: process.env.AK_API_BASE_PATH,
|
||||
WATCHER_URL: process.env.WATCHER_URL,
|
||||
});
|
||||
|
||||
const packageJSONPath = path.join(authentikProjectRoot, "./package.json");
|
||||
const rootPackage = JSON.parse(readFileSync(packageJSONPath, "utf8"));
|
||||
|
||||
const NODE_ENV = process.env.NODE_ENV || "development";
|
||||
const AK_API_BASE_PATH = process.env.AK_API_BASE_PATH || "";
|
||||
|
||||
const environmentVars = new Map([
|
||||
["NODE_ENV", NODE_ENV],
|
||||
["CWD", cwd()],
|
||||
["AK_API_BASE_PATH", AK_API_BASE_PATH],
|
||||
]);
|
||||
|
||||
const definitions = Object.fromEntries(
|
||||
Array.from(environmentVars).map(([key, value]) => {
|
||||
return [`process.env.${key}`, JSON.stringify(value)];
|
||||
}),
|
||||
);
|
||||
const patternflyPath = resolvePackage("@patternfly/patternfly");
|
||||
|
||||
/**
|
||||
* All is magic is just to make sure the assets are copied into the right places. This is a very
|
||||
* stripped down version of what the rollup-copy-plugin does, without any of the features we don't
|
||||
* use, and using globSync instead of globby since we already had globSync lying around thanks to
|
||||
* Typescript. If there's a third argument in an array entry, it's used to replace the internal path
|
||||
* before concatenating it all together as the destination target.
|
||||
* @type {Array<[string, string, string?]>}
|
||||
*/
|
||||
const assetsFileMappings = [
|
||||
["node_modules/@patternfly/patternfly/patternfly.min.css", "."],
|
||||
["node_modules/@patternfly/patternfly/assets/**", ".", "node_modules/@patternfly/patternfly/"],
|
||||
["src/common/styles/**", "."],
|
||||
["src/assets/images/**", "./assets/images"],
|
||||
["./icons/*", "./assets/icons"],
|
||||
];
|
||||
|
||||
/**
|
||||
* @param {string} filePath
|
||||
*/
|
||||
const isFile = (filePath) => statSync(filePath).isFile();
|
||||
|
||||
/**
|
||||
* @param {string} src Source file
|
||||
* @param {string} dest Destination folder
|
||||
* @param {string} [strip] Path to strip from the source file
|
||||
*/
|
||||
function nameCopyTarget(src, dest, strip) {
|
||||
const target = path.join(dest, strip ? src.replace(strip, "") : path.parse(src).base);
|
||||
return [src, target];
|
||||
}
|
||||
|
||||
for (const [source, rawdest, strip] of assetsFileMappings) {
|
||||
const matchedPaths = globSync(source);
|
||||
const dest = path.join("dist", rawdest);
|
||||
|
||||
const copyTargets = matchedPaths.map((path) => nameCopyTarget(path, dest, strip));
|
||||
|
||||
for (const [src, dest] of copyTargets) {
|
||||
if (isFile(src)) {
|
||||
mkdirSync(path.dirname(dest), { recursive: true });
|
||||
copyFileSync(src, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {[source: string, destination: string]} EntryPoint
|
||||
*/
|
||||
|
||||
/**
|
||||
* This starts the definitions used for esbuild: Our targets, our arguments, the function for
|
||||
* running a build, and three options for building: watching, building, and building the proxy.
|
||||
* Ordered by largest to smallest interface to build even faster
|
||||
*
|
||||
* @type {EntryPoint[]}
|
||||
*/
|
||||
const entryPoints = [
|
||||
["admin/AdminInterface/AdminInterface.ts", "admin"],
|
||||
["user/UserInterface.ts", "user"],
|
||||
["flow/FlowInterface.ts", "flow"],
|
||||
["standalone/api-browser/index.ts", "standalone/api-browser"],
|
||||
["rac/index.ts", "rac"],
|
||||
["standalone/loading/index.ts", "standalone/loading"],
|
||||
["polyfill/poly.ts", "."],
|
||||
];
|
||||
|
||||
/**
|
||||
* @type {import("esbuild").BuildOptions}
|
||||
* @type {Readonly<BuildOptions>}
|
||||
*/
|
||||
const BASE_ESBUILD_OPTIONS = {
|
||||
entryNames: `[dir]/[name]-${readBuildIdentifier()}`,
|
||||
chunkNames: "[dir]/chunks/[name]-[hash]",
|
||||
assetNames: "assets/[dir]/[name]-[hash]",
|
||||
publicPath: path.join("/static", DistDirectoryName),
|
||||
outdir: DistDirectory,
|
||||
bundle: true,
|
||||
write: true,
|
||||
sourcemap: true,
|
||||
minify: NODE_ENV === "production",
|
||||
minify: NodeEnvironment === "production",
|
||||
legalComments: "external",
|
||||
splitting: true,
|
||||
treeShaking: true,
|
||||
external: ["*.woff", "*.woff2"],
|
||||
tsconfig: "./tsconfig.json",
|
||||
tsconfig: path.resolve(PackageRoot, "tsconfig.build.json"),
|
||||
loader: {
|
||||
".css": "text",
|
||||
},
|
||||
plugins: [
|
||||
copy({
|
||||
assets: [
|
||||
{
|
||||
from: path.join(patternflyPath, "patternfly.min.css"),
|
||||
to: ".",
|
||||
},
|
||||
{
|
||||
from: path.join(patternflyPath, "assets", "**"),
|
||||
to: "./assets",
|
||||
},
|
||||
{
|
||||
from: path.resolve(PackageRoot, "src", "common", "styles", "**"),
|
||||
to: ".",
|
||||
},
|
||||
{
|
||||
from: path.resolve(PackageRoot, "src", "assets", "images", "**"),
|
||||
to: "./assets/images",
|
||||
},
|
||||
{
|
||||
from: path.resolve(PackageRoot, "icons", "*"),
|
||||
to: "./assets/icons",
|
||||
},
|
||||
],
|
||||
}),
|
||||
polyfillNode({
|
||||
polyfills: {
|
||||
path: true,
|
||||
},
|
||||
}),
|
||||
mdxPlugin({
|
||||
root: authentikProjectRoot,
|
||||
root: MonoRepoRoot,
|
||||
}),
|
||||
],
|
||||
define: definitions,
|
||||
@ -147,69 +102,42 @@ const BASE_ESBUILD_OPTIONS = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a version ID for the build.
|
||||
* @returns {string}
|
||||
*/
|
||||
function composeVersionID() {
|
||||
const { version } = rootPackage;
|
||||
const buildHash = process.env.GIT_BUILD_HASH;
|
||||
async function cleanDistDirectory() {
|
||||
const timerLabel = `${logPrefix} ♻️ Cleaning previous builds...`;
|
||||
|
||||
if (buildHash) {
|
||||
return `${version}+${buildHash}`;
|
||||
}
|
||||
console.time(timerLabel);
|
||||
|
||||
return version;
|
||||
await fs.rm(DistDirectory, {
|
||||
recursive: true,
|
||||
force: true,
|
||||
});
|
||||
|
||||
await fs.mkdir(DistDirectory, {
|
||||
recursive: true,
|
||||
});
|
||||
|
||||
console.timeEnd(timerLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a single entry point.
|
||||
* Creates an ESBuild options, extending the base options with the given overrides.
|
||||
*
|
||||
* @param {EntryPoint} buildTarget
|
||||
* @param {Partial<esbuild.BuildOptions>} [overrides]
|
||||
* @throws {Error} on build failure
|
||||
* @param {BuildOptions} overrides
|
||||
* @returns {BuildOptions}
|
||||
*/
|
||||
function createEntryPointOptions([source, dest], overrides = {}) {
|
||||
const outdir = path.join(__dirname, "..", "dist", dest);
|
||||
|
||||
export function createESBuildOptions(overrides) {
|
||||
/**
|
||||
* @type {esbuild.BuildOptions}
|
||||
* @type {BuildOptions}
|
||||
*/
|
||||
const mergedOptions = deepmerge(BASE_ESBUILD_OPTIONS, overrides);
|
||||
|
||||
const entryPointConfig = {
|
||||
entryPoints: [`./src/${source}`],
|
||||
entryNames: `[dir]/[name]-${composeVersionID()}`,
|
||||
publicPath: path.join("/static", "dist", dest),
|
||||
outdir,
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {esbuild.BuildOptions}
|
||||
*/
|
||||
const mergedConfig = deepmerge(BASE_ESBUILD_OPTIONS, entryPointConfig, overrides);
|
||||
|
||||
return mergedConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build all entry points in parallel.
|
||||
*
|
||||
* @param {EntryPoint[]} entryPoints
|
||||
* @returns {Promise<esbuild.BuildResult[]>}
|
||||
*/
|
||||
async function buildParallel(entryPoints) {
|
||||
return Promise.all(
|
||||
entryPoints.map((entryPoint) => {
|
||||
return esbuild.build(createEntryPointOptions(entryPoint));
|
||||
}),
|
||||
);
|
||||
return mergedOptions;
|
||||
}
|
||||
|
||||
function doHelp() {
|
||||
console.log(`Build the authentik UI
|
||||
|
||||
options:
|
||||
-w, --watch: Build all ${entryPoints.length} interfaces
|
||||
-w, --watch: Build all interfaces
|
||||
-p, --proxy: Build only the polyfills and the loading application
|
||||
-h, --help: This help message
|
||||
`);
|
||||
@ -218,36 +146,37 @@ function doHelp() {
|
||||
}
|
||||
|
||||
async function doWatch() {
|
||||
console.log("Watching all entry points...");
|
||||
console.group(`${logPrefix} 🤖 Watching entry points`);
|
||||
|
||||
const wathcherPorts = await findFreePorts(entryPoints.length);
|
||||
const entryPoints = Object.entries(EntryPoint).map(([entrypointID, target]) => {
|
||||
console.log(entrypointID);
|
||||
|
||||
const buildContexts = await Promise.all(
|
||||
entryPoints.map((entryPoint, i) => {
|
||||
const port = wathcherPorts[i];
|
||||
const serverURL = new URL(`http://localhost:${port}/events`);
|
||||
return target;
|
||||
});
|
||||
|
||||
return esbuild.context(
|
||||
createEntryPointOptions(entryPoint, {
|
||||
plugins: [
|
||||
buildObserverPlugin({
|
||||
serverURL,
|
||||
logPrefix: entryPoint[1],
|
||||
relativeRoot: path.join(__dirname, ".."),
|
||||
}),
|
||||
],
|
||||
define: {
|
||||
...definitions,
|
||||
"process.env.WATCHER_URL": JSON.stringify(serverURL.toString()),
|
||||
},
|
||||
}),
|
||||
);
|
||||
console.groupEnd();
|
||||
|
||||
const wathcherPorts = await findFreePorts(1);
|
||||
const port = wathcherPorts[0];
|
||||
const serverURL = new URL(`http://localhost:${port}/events`);
|
||||
|
||||
const buildOptions = createESBuildOptions({
|
||||
entryPoints,
|
||||
plugins: [
|
||||
liveReloadPlugin({
|
||||
serverURL,
|
||||
relativeRoot: PackageRoot,
|
||||
}),
|
||||
],
|
||||
define: serializeEnvironmentVars({
|
||||
WATCHER_URL: serverURL.toString(),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
await Promise.all(buildContexts.map((context) => context.rebuild()));
|
||||
const buildContext = await esbuild.context(buildOptions);
|
||||
|
||||
await Promise.allSettled(buildContexts.map((context) => context.watch()));
|
||||
await buildContext.rebuild();
|
||||
await buildContext.watch();
|
||||
|
||||
return /** @type {Promise<void>} */ (
|
||||
new Promise((resolve) => {
|
||||
@ -259,15 +188,34 @@ async function doWatch() {
|
||||
}
|
||||
|
||||
async function doBuild() {
|
||||
console.log("Building all entry points");
|
||||
console.group(`${logPrefix} 🚀 Building entry points:`);
|
||||
|
||||
return buildParallel(entryPoints);
|
||||
const entryPoints = Object.entries(EntryPoint).map(([entrypointID, target]) => {
|
||||
console.log(entrypointID);
|
||||
|
||||
return target;
|
||||
});
|
||||
|
||||
console.groupEnd();
|
||||
|
||||
const buildOptions = createESBuildOptions({
|
||||
entryPoints,
|
||||
});
|
||||
|
||||
await esbuild.build(buildOptions);
|
||||
|
||||
console.log("Build complete");
|
||||
}
|
||||
|
||||
async function doProxy() {
|
||||
return buildParallel(
|
||||
entryPoints.filter(([_, dest]) => ["standalone/loading", "."].includes(dest)),
|
||||
);
|
||||
const entryPoints = [EntryPoint.StandaloneLoading];
|
||||
|
||||
const buildOptions = createESBuildOptions({
|
||||
entryPoints,
|
||||
});
|
||||
|
||||
await esbuild.build(buildOptions);
|
||||
console.log("Proxy build complete");
|
||||
}
|
||||
|
||||
async function delegateCommand() {
|
||||
@ -289,12 +237,16 @@ async function delegateCommand() {
|
||||
}
|
||||
}
|
||||
|
||||
await delegateCommand()
|
||||
.then(() => {
|
||||
console.log("Build complete");
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
await cleanDistDirectory()
|
||||
// ---
|
||||
.then(() =>
|
||||
delegateCommand()
|
||||
.then(() => {
|
||||
console.log("Build complete");
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}),
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { execSync } from "child_process";
|
||||
import path from "path";
|
||||
import { execSync } from "node:child_process";
|
||||
import path from "node:path";
|
||||
|
||||
const projectRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf8" }).replace(
|
||||
"\n",
|
||||
|
@ -1,56 +0,0 @@
|
||||
import { execFileSync } from "child_process";
|
||||
import { ESLint } from "eslint";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import process from "process";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
function changedFiles() {
|
||||
const gitStatus = execFileSync("git", ["diff", "--name-only", "HEAD"], { encoding: "utf8" });
|
||||
const gitUntracked = execFileSync("git", ["ls-files", "--others", "--exclude-standard"], {
|
||||
encoding: "utf8",
|
||||
});
|
||||
|
||||
const changed = gitStatus
|
||||
.split("\n")
|
||||
.filter((line) => line.trim().substring(0, 4) === "web/")
|
||||
.filter((line) => /\.(m|c)?(t|j)s$/.test(line))
|
||||
.map((line) => line.substring(4))
|
||||
.filter((line) => fs.existsSync(line));
|
||||
|
||||
const untracked = gitUntracked
|
||||
.split("\n")
|
||||
.filter((line) => /\.(m|c)?(t|j)s$/.test(line))
|
||||
.filter((line) => fs.existsSync(line));
|
||||
|
||||
const sourceFiles = [...changed, ...untracked].filter((line) => /^src\//.test(line));
|
||||
const scriptFiles = [...changed, ...untracked].filter(
|
||||
(line) => /^scripts\//.test(line) || !/^src\//.test(line),
|
||||
);
|
||||
|
||||
return [...sourceFiles, ...scriptFiles];
|
||||
}
|
||||
|
||||
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
||||
const projectRoot = path.join(__dirname, "..");
|
||||
process.chdir(projectRoot);
|
||||
|
||||
const hasFlag = (flags) => process.argv.length > 1 && flags.includes(process.argv[2]);
|
||||
|
||||
const [configFile, files] = hasFlag(["-n", "--nightmare"])
|
||||
? [path.join(__dirname, "eslint.nightmare.mjs"), changedFiles()]
|
||||
: hasFlag(["-p", "--precommit"])
|
||||
? [path.join(__dirname, "eslint.precommit.mjs"), changedFiles()]
|
||||
: [path.join(projectRoot, "eslint.config.mjs"), ["."]];
|
||||
|
||||
const eslint = new ESLint({
|
||||
overrideConfigFile: configFile,
|
||||
warnIgnored: false,
|
||||
});
|
||||
|
||||
const results = await eslint.lintFiles(files);
|
||||
const formatter = await eslint.loadFormatter("stylish");
|
||||
const resultText = formatter.format(results);
|
||||
const errors = results.reduce((acc, result) => acc + result.errorCount, 0);
|
||||
console.log(resultText);
|
||||
process.exit(errors > 1 ? 1 : 0);
|
@ -1,217 +0,0 @@
|
||||
import eslint from "@eslint/js";
|
||||
import tsparser from "@typescript-eslint/parser";
|
||||
import litconf from "eslint-plugin-lit";
|
||||
import wcconf from "eslint-plugin-wc";
|
||||
import globals from "globals";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
const MAX_DEPTH = 4;
|
||||
const MAX_NESTED_CALLBACKS = 4;
|
||||
const MAX_PARAMS = 5;
|
||||
|
||||
// Waiting for SonarJS to be compatible
|
||||
// const MAX_COGNITIVE_COMPLEXITY = 9;
|
||||
|
||||
const rules = {
|
||||
"accessor-pairs": "error",
|
||||
"array-callback-return": "error",
|
||||
"block-scoped-var": "error",
|
||||
"consistent-return": "error",
|
||||
"consistent-this": ["error", "that"],
|
||||
"curly": ["error", "all"],
|
||||
"dot-notation": [
|
||||
"error",
|
||||
{
|
||||
allowKeywords: true,
|
||||
},
|
||||
],
|
||||
"eqeqeq": "error",
|
||||
"func-names": "error",
|
||||
"guard-for-in": "error",
|
||||
"max-depth": ["error", MAX_DEPTH],
|
||||
"max-nested-callbacks": ["error", MAX_NESTED_CALLBACKS],
|
||||
"max-params": ["error", MAX_PARAMS],
|
||||
"new-cap": "error",
|
||||
"no-alert": "error",
|
||||
"no-array-constructor": "error",
|
||||
"no-bitwise": "error",
|
||||
"no-caller": "error",
|
||||
"no-case-declarations": "error",
|
||||
"no-class-assign": "error",
|
||||
"no-cond-assign": "error",
|
||||
"no-const-assign": "error",
|
||||
"no-constant-condition": "error",
|
||||
"no-control-regex": "error",
|
||||
"no-debugger": "error",
|
||||
"no-delete-var": "error",
|
||||
"no-div-regex": "error",
|
||||
"no-dupe-args": "error",
|
||||
"no-dupe-keys": "error",
|
||||
"no-duplicate-case": "error",
|
||||
"no-else-return": "error",
|
||||
"no-empty": "error",
|
||||
"no-empty-character-class": "error",
|
||||
"no-empty-function": "error",
|
||||
"no-labels": "error",
|
||||
"no-eq-null": "error",
|
||||
"no-eval": "error",
|
||||
"no-ex-assign": "error",
|
||||
"no-extend-native": "error",
|
||||
"no-extra-bind": "error",
|
||||
"no-extra-boolean-cast": "error",
|
||||
"no-extra-label": "error",
|
||||
"no-fallthrough": "error",
|
||||
"no-func-assign": "error",
|
||||
"no-implied-eval": "error",
|
||||
"no-implicit-coercion": "error",
|
||||
"no-implicit-globals": "error",
|
||||
"no-inner-declarations": ["error", "functions"],
|
||||
"no-invalid-regexp": "error",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-iterator": "error",
|
||||
"no-invalid-this": "error",
|
||||
"no-label-var": "error",
|
||||
"no-lone-blocks": "error",
|
||||
"no-lonely-if": "error",
|
||||
"no-loop-func": "error",
|
||||
"no-magic-numbers": ["error", { ignore: [0, 1, -1] }],
|
||||
"no-multi-str": "error",
|
||||
"no-negated-condition": "error",
|
||||
"no-nested-ternary": "error",
|
||||
"no-new": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-obj-calls": "error",
|
||||
"no-octal": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-param-reassign": "error",
|
||||
"no-proto": "error",
|
||||
"no-redeclare": "error",
|
||||
"no-regex-spaces": "error",
|
||||
"no-restricted-syntax": ["error", "WithStatement"],
|
||||
"no-script-url": "error",
|
||||
"no-self-assign": "error",
|
||||
"no-self-compare": "error",
|
||||
"no-sequences": "error",
|
||||
"no-shadow": "error",
|
||||
"no-shadow-restricted-names": "error",
|
||||
"no-sparse-arrays": "error",
|
||||
"no-this-before-super": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-trailing-spaces": "error",
|
||||
"no-undef": "error",
|
||||
"no-undef-init": "error",
|
||||
"no-unexpected-multiline": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unneeded-ternary": "error",
|
||||
"no-unreachable": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-unused-labels": "error",
|
||||
"no-use-before-define": "error",
|
||||
"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",
|
||||
"prefer-rest-params": "error",
|
||||
"prefer-spread": "error",
|
||||
"prefer-template": "error",
|
||||
"radix": "error",
|
||||
"require-yield": "error",
|
||||
"strict": ["error", "global"],
|
||||
"use-isnan": "error",
|
||||
"valid-typeof": "error",
|
||||
"vars-on-top": "error",
|
||||
"yoda": ["error", "never"],
|
||||
|
||||
"no-unused-vars": "off",
|
||||
"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],
|
||||
// "sonarjs/no-duplicate-string": "off",
|
||||
// "sonarjs/no-nested-template-literals": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
argsIgnorePattern: "^_",
|
||||
varsIgnorePattern: "^_",
|
||||
caughtErrorsIgnorePattern: "^_",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default [
|
||||
// You would not believe how much this change has frustrated users: ["if an ignores key is used
|
||||
// without any other keys in the configuration object, then the patterns act as global
|
||||
// ignores"](https://eslint.org/docs/latest/use/configure/ignore)
|
||||
{
|
||||
ignores: [
|
||||
"dist/",
|
||||
".wireit/",
|
||||
"packages/",
|
||||
// don't ever lint node_modules
|
||||
"node_modules/",
|
||||
".storybook/*",
|
||||
// don't lint build output (make sure it's set to your correct build folder name)
|
||||
// don't lint nyc coverage output
|
||||
"coverage/",
|
||||
"src/locale-codes.ts",
|
||||
"storybook-static/",
|
||||
"src/locales/",
|
||||
"src/**/*.test.ts",
|
||||
],
|
||||
},
|
||||
eslint.configs.recommended,
|
||||
wcconf.configs["flat/recommended"],
|
||||
litconf.configs["flat/recommended"],
|
||||
...tseslint.configs.recommended,
|
||||
// sonar.configs.recommended,
|
||||
{
|
||||
languageOptions: {
|
||||
parser: tsparser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
sourceType: "module",
|
||||
},
|
||||
globals: {
|
||||
...globals.browser,
|
||||
},
|
||||
},
|
||||
files: ["src/**"],
|
||||
rules,
|
||||
},
|
||||
{
|
||||
languageOptions: {
|
||||
parser: tsparser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
sourceType: "module",
|
||||
},
|
||||
globals: {
|
||||
...globals.nodeBuiltin,
|
||||
},
|
||||
},
|
||||
files: ["scripts/*.mjs", "*.ts", "*.mjs"],
|
||||
rules,
|
||||
},
|
||||
{
|
||||
languageOptions: {
|
||||
parser: tsparser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
sourceType: "module",
|
||||
},
|
||||
globals: {
|
||||
...globals.nodeBuiltin,
|
||||
...globals.jest,
|
||||
},
|
||||
},
|
||||
files: ["src/**/*.test.ts"],
|
||||
rules,
|
||||
},
|
||||
];
|
@ -1,87 +0,0 @@
|
||||
import eslint from "@eslint/js";
|
||||
import tsparser from "@typescript-eslint/parser";
|
||||
import litconf from "eslint-plugin-lit";
|
||||
import wcconf from "eslint-plugin-wc";
|
||||
import globals from "globals";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
export default [
|
||||
// You would not believe how much this change has frustrated users: ["if an ignores key is used
|
||||
// without any other keys in the configuration object, then the patterns act as global
|
||||
// ignores"](https://eslint.org/docs/latest/use/configure/ignore)
|
||||
{
|
||||
ignores: [
|
||||
"dist/",
|
||||
".wireit/",
|
||||
"packages/",
|
||||
// don't ever lint node_modules
|
||||
"node_modules/",
|
||||
".storybook/*",
|
||||
// don't lint build output (make sure it's set to your correct build folder name)
|
||||
// don't lint nyc coverage output
|
||||
"coverage/",
|
||||
"src/locale-codes.ts",
|
||||
"storybook-static/",
|
||||
"src/locales/",
|
||||
],
|
||||
},
|
||||
eslint.configs.recommended,
|
||||
wcconf.configs["flat/recommended"],
|
||||
litconf.configs["flat/recommended"],
|
||||
...tseslint.configs.recommended,
|
||||
// sonar.configs.recommended,
|
||||
{
|
||||
languageOptions: {
|
||||
parser: tsparser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
sourceType: "module",
|
||||
},
|
||||
},
|
||||
files: ["src/**"],
|
||||
rules: {
|
||||
"no-unused-vars": "off",
|
||||
"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", 9],
|
||||
// "sonarjs/no-duplicate-string": "off",
|
||||
// "sonarjs/no-nested-template-literals": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
argsIgnorePattern: "^_",
|
||||
varsIgnorePattern: "^_",
|
||||
caughtErrorsIgnorePattern: "^_",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
languageOptions: {
|
||||
parser: tsparser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
sourceType: "module",
|
||||
},
|
||||
globals: {
|
||||
...globals.nodeBuiltin,
|
||||
},
|
||||
},
|
||||
files: ["scripts/*.mjs", "*.ts", "*.mjs"],
|
||||
rules: {
|
||||
"no-unused-vars": "off",
|
||||
"no-console": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
argsIgnorePattern: "^_",
|
||||
varsIgnorePattern: "^_",
|
||||
caughtErrorsIgnorePattern: "^_",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
@ -1,7 +1,7 @@
|
||||
import { type KnipConfig } from "knip";
|
||||
|
||||
const config: KnipConfig = {
|
||||
"entry": [
|
||||
entry: [
|
||||
"./src/admin/AdminInterface/AdminInterface.ts",
|
||||
"./src/user/UserInterface.ts",
|
||||
"./src/flow/FlowInterface.ts",
|
||||
@ -10,18 +10,18 @@ const config: KnipConfig = {
|
||||
"./src/standalone/loading/index.ts",
|
||||
"./src/polyfill/poly.ts",
|
||||
],
|
||||
"project": ["src/**/*.ts", "src/**/*.js", "./scripts/*.mjs", ".storybook/*.ts"],
|
||||
project: ["src/**/*.ts", "src/**/*.js", "./scripts/*.mjs", ".storybook/*.ts"],
|
||||
// "ignore": ["src/**/*.test.ts", "src/**/*.stories.ts"],
|
||||
// Prevent Knip from complaining about web components, which export their classes but also
|
||||
// export their registration, and we don't always use both.
|
||||
"ignoreExportsUsedInFile": true,
|
||||
"typescript": {
|
||||
ignoreExportsUsedInFile: true,
|
||||
typescript: {
|
||||
config: ["tsconfig.json"],
|
||||
},
|
||||
"wireit": {
|
||||
wireit: {
|
||||
config: ["package.json"],
|
||||
},
|
||||
"storybook": {
|
||||
storybook: {
|
||||
config: [".storybook/{main,test-runner}.{js,ts}"],
|
||||
entry: [
|
||||
".storybook/{manager,preview}.{js,jsx,ts,tsx}",
|
||||
@ -29,7 +29,7 @@ const config: KnipConfig = {
|
||||
],
|
||||
project: [".storybook/**/*.{js,jsx,ts,tsx}"],
|
||||
},
|
||||
"eslint": {
|
||||
eslint: {
|
||||
entry: [
|
||||
"eslint.config.mjs",
|
||||
"scripts/eslint.precommit.mjs",
|
||||
|
@ -1,16 +1,18 @@
|
||||
import { readFileSync } from "fs";
|
||||
import path from "path";
|
||||
import { readFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import pseudolocale from "pseudolocale";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
import { makeFormatter } from "@lit/localize-tools/lib/formatters/index.js";
|
||||
import { sortProgramMessages } from "@lit/localize-tools/lib/messages.js";
|
||||
import { TransformLitLocalizer } from "@lit/localize-tools/lib/modes/transform.js";
|
||||
|
||||
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
||||
const relativeDirname = fileURLToPath(new URL(".", import.meta.url));
|
||||
const pseudoLocale = "pseudo-LOCALE";
|
||||
const targetLocales = [pseudoLocale];
|
||||
const baseConfig = JSON.parse(readFileSync(path.join(__dirname, "../lit-localize.json"), "utf-8"));
|
||||
const baseConfig = JSON.parse(
|
||||
readFileSync(path.join(relativeDirname, "../lit-localize.json"), "utf-8"),
|
||||
);
|
||||
|
||||
// Need to make some internal specifications to satisfy the transformer. It doesn't actually matter
|
||||
// which Localizer we use (transformer or runtime), because all of the functionality we care about
|
||||
@ -19,7 +21,7 @@ const baseConfig = JSON.parse(readFileSync(path.join(__dirname, "../lit-localize
|
||||
|
||||
const config = {
|
||||
...baseConfig,
|
||||
baseDir: path.join(__dirname, ".."),
|
||||
baseDir: path.join(relativeDirname, ".."),
|
||||
targetLocales,
|
||||
output: {
|
||||
...baseConfig.output,
|
||||
@ -41,4 +43,8 @@ const translations = messages.map(pseudoMessagify);
|
||||
const sorted = sortProgramMessages([...messages]);
|
||||
const formatter = makeFormatter(config);
|
||||
|
||||
formatter.writeOutput(sorted, new Map([[pseudoLocale, translations]]));
|
||||
formatter.writeOutput(
|
||||
sorted,
|
||||
// @ts-expect-error Needs typing.
|
||||
new Map([[pseudoLocale, translations]]),
|
||||
);
|
||||
|
@ -2,9 +2,9 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { VERSION } from "@goauthentik/common/constants";
|
||||
import { globalAK } from "@goauthentik/common/global";
|
||||
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 { WithBrandConfig } from "@goauthentik/elements/mixins/brand";
|
||||
import { WithLicenseSummary } from "@goauthentik/elements/mixins/license";
|
||||
import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
@ -59,7 +59,7 @@ export class AboutModal extends WithLicenseSummary(WithBrandConfig(ModalButton))
|
||||
|
||||
renderModal() {
|
||||
let product = globalAK().brand.brandingTitle || DefaultBrand.brandingTitle;
|
||||
if (this.licenseSummary.status != LicenseSummaryStatusEnum.Unlicensed) {
|
||||
if (this.licenseSummary?.status !== LicenseSummaryStatusEnum.Unlicensed) {
|
||||
product += ` ${msg("Enterprise")}`;
|
||||
}
|
||||
return html`<div
|
||||
|
@ -4,8 +4,8 @@ import { AKElement } from "@goauthentik/elements/Base";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
WithCapabilitiesConfig,
|
||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||
import { WithVersion } from "@goauthentik/elements/Interface/versionProvider";
|
||||
} from "@goauthentik/elements/mixins/capabilities";
|
||||
import { WithVersion } from "@goauthentik/elements/mixins/version";
|
||||
import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
|
||||
import { getRootStyle } from "@goauthentik/elements/utils/getRootStyle";
|
||||
import { spread } from "@open-wc/lit-helpers";
|
||||
@ -13,6 +13,7 @@ import { spread } from "@open-wc/lit-helpers";
|
||||
import { msg } from "@lit/localize";
|
||||
import { TemplateResult, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { classMap } from "lit/directives/class-map.js";
|
||||
import { map } from "lit/directives/map.js";
|
||||
|
||||
import { UiThemeEnum } from "@goauthentik/api";
|
||||
@ -71,10 +72,12 @@ export class AkAdminSidebar extends WithCapabilitiesConfig(WithVersion(AKElement
|
||||
render() {
|
||||
return html`
|
||||
<ak-sidebar
|
||||
class="pf-c-page__sidebar ${this.open ? "pf-m-expanded" : "pf-m-collapsed"} ${this
|
||||
.activeTheme === UiThemeEnum.Light
|
||||
? "pf-m-light"
|
||||
: ""}"
|
||||
class=${classMap({
|
||||
"pf-c-page__sidebar": true,
|
||||
"pf-m-expanded": this.open,
|
||||
"pf-m-collapsed": !this.open,
|
||||
"pf-m-light": this.colorScheme === UiThemeEnum.Light,
|
||||
})}
|
||||
>
|
||||
${this.renderSidebarItems()}
|
||||
</ak-sidebar>
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
import { configureSentry } from "@goauthentik/common/sentry";
|
||||
import { me } from "@goauthentik/common/users";
|
||||
import { WebsocketClient } from "@goauthentik/common/ws";
|
||||
import { AuthenticatedInterface } from "@goauthentik/elements/Interface";
|
||||
import { AKAuthenticatedInterfaceElement } from "@goauthentik/elements/Interface";
|
||||
import "@goauthentik/elements/ak-locale-context";
|
||||
import "@goauthentik/elements/banner/EnterpriseStatusBanner";
|
||||
import "@goauthentik/elements/banner/VersionBanner";
|
||||
@ -30,12 +30,12 @@ import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";
|
||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
import { SessionUser, UiThemeEnum } from "@goauthentik/api";
|
||||
import { SessionUser } from "@goauthentik/api";
|
||||
|
||||
import "./AdminSidebar";
|
||||
|
||||
@customElement("ak-interface-admin")
|
||||
export class AdminInterface extends AuthenticatedInterface {
|
||||
export class AdminInterface extends AKAuthenticatedInterfaceElement {
|
||||
@property({ type: Boolean })
|
||||
notificationDrawerOpen = getURLParam("notificationDrawerOpen", false);
|
||||
|
||||
@ -123,15 +123,17 @@ export class AdminInterface extends AuthenticatedInterface {
|
||||
super.connectedCallback();
|
||||
|
||||
if (process.env.NODE_ENV === "development" && process.env.WATCHER_URL) {
|
||||
const { ESBuildObserver } = await import("@goauthentik/common/client");
|
||||
const { ESBuildObserver } = await import(
|
||||
"@goauthentik/esbuild-plugin-live-reload/client"
|
||||
);
|
||||
|
||||
new ESBuildObserver(process.env.WATCHER_URL);
|
||||
ESBuildObserver.initialize(process.env.WATCHER_URL);
|
||||
}
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
const sidebarClasses = {
|
||||
"pf-m-light": this.activeTheme === UiThemeEnum.Light,
|
||||
"pf-m-light": this.colorScheme === "light",
|
||||
};
|
||||
|
||||
const drawerOpen = this.notificationDrawerOpen || this.apiDrawerOpen;
|
@ -1,5 +1,5 @@
|
||||
import { AdminInterface } from "./AdminInterface";
|
||||
import "./AdminInterface";
|
||||
import { AdminInterface } from "./index.entrypoint";
|
||||
import "./index.entrypoint";
|
||||
|
||||
export { AdminInterface };
|
||||
export default AdminInterface;
|
||||
|
@ -11,11 +11,11 @@ import "@goauthentik/admin/admin-overview/charts/SyncStatusChart";
|
||||
import { VERSION } from "@goauthentik/common/constants";
|
||||
import { me } from "@goauthentik/common/users";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider.js";
|
||||
import "@goauthentik/elements/PageHeader";
|
||||
import "@goauthentik/elements/cards/AggregatePromiseCard";
|
||||
import "@goauthentik/elements/cards/QuickActionsCard.js";
|
||||
import type { QuickAction } from "@goauthentik/elements/cards/QuickActionsCard.js";
|
||||
import { WithLicenseSummary, isEnterpriseLicense } from "@goauthentik/elements/mixins/license.js";
|
||||
import { paramURL } from "@goauthentik/elements/router/RouterOutlet";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
@ -164,15 +164,16 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
||||
}
|
||||
|
||||
renderCards() {
|
||||
const isEnterprise = this.hasEnterpriseLicense;
|
||||
const enterprise = isEnterpriseLicense(this.licenseSummary);
|
||||
|
||||
const classes = {
|
||||
"card-container": true,
|
||||
"pf-l-grid__item": true,
|
||||
"pf-m-6-col": true,
|
||||
"pf-m-4-col-on-md": !isEnterprise,
|
||||
"pf-m-4-col-on-xl": !isEnterprise,
|
||||
"pf-m-3-col-on-md": isEnterprise,
|
||||
"pf-m-3-col-on-xl": isEnterprise,
|
||||
"pf-m-4-col-on-md": !enterprise,
|
||||
"pf-m-4-col-on-xl": !enterprise,
|
||||
"pf-m-3-col-on-md": enterprise,
|
||||
"pf-m-3-col-on-xl": enterprise,
|
||||
};
|
||||
|
||||
return html`<div class=${classMap(classes)}>
|
||||
@ -184,7 +185,7 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
||||
<div class=${classMap(classes)}>
|
||||
<ak-admin-status-card-workers> </ak-admin-status-card-workers>
|
||||
</div>
|
||||
${isEnterprise
|
||||
${enterprise
|
||||
? html` <div class=${classMap(classes)}>
|
||||
<ak-admin-fips-status-system> </ak-admin-fips-status-system>
|
||||
</div>`
|
||||
|
@ -207,8 +207,8 @@ export class AdminSettingsForm extends Form<SettingsRequest> {
|
||||
.row=${(f?: FooterLink) =>
|
||||
akFooterLinkInput({
|
||||
".footerLink": f,
|
||||
"style": "width: 100%",
|
||||
"name": "footer-link",
|
||||
style: "width: 100%",
|
||||
name: "footer-link",
|
||||
} as unknown as IFooterLinkInput)}
|
||||
>
|
||||
</ak-array-input>
|
||||
|
@ -8,10 +8,6 @@ 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/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
import "@goauthentik/elements/forms/ModalForm";
|
||||
@ -19,6 +15,10 @@ import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
|
||||
import "@goauthentik/elements/forms/ProxyForm";
|
||||
import "@goauthentik/elements/forms/Radio";
|
||||
import "@goauthentik/elements/forms/SearchSelect";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
WithCapabilitiesConfig,
|
||||
} from "@goauthentik/elements/mixins/capabilities.js";
|
||||
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user