Prep for monorepo use.
web: Update config. Flesh out build. Fix issue surrounding build. Fix paths. Update workspaces. Fix build steps. Apply linter. Temporarily remove problem rules. Add ignorefile. Prep for formatting. Lint website. Lint web, repo packages. Refine Prettier usage. Fix imports. Tidy build. Move node ignore files. Remove unused. Update job. Fix lint step. Build before compiling. Use root for paths. Fix issues surrounding import references, types, package names. Fix build paths. Tidy. Enforce prefix. Apply prefixes to imports. Enable linter, compiler, etc. Fix references. Update names. Mark optional. Revise mounts. Fix build order. Update package.json. Ignore all docusaurus. Fix paths, types. Clean up build steps, names. Fix paths. website: Fix nested paragraphs build warning. web: Enforce module resolution. Use consistent LTS version. Track Node version. Use default resolution. Test main entrypoint. Fix Node v20 compatibility. Add task names. WIP: Fix styles.
This commit is contained in:
@ -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