mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-03-30 19:26:37 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4e965434f | ||
|
|
096d214a88 | ||
|
|
afb7fc32e7 | ||
|
|
641bbc9351 | ||
|
|
136c6082f6 | ||
|
|
b9a20d2923 | ||
|
|
74eb2ac0b9 | ||
|
|
51222f5607 | ||
|
|
d6d1a4ced2 | ||
|
|
4b086cebcd | ||
|
|
1f3550c9bd | ||
|
|
912008b048 | ||
|
|
5ad8b03831 | ||
|
|
c1e515a05f | ||
|
|
654593b4b6 | ||
|
|
8999173aa0 | ||
|
|
10b087640f | ||
|
|
d0392d25ed | ||
|
|
2ffc6ba42a | ||
|
|
c114a2edaa | ||
|
|
63db4d5120 |
141
.github/workflows/e2e-tests.yml
vendored
141
.github/workflows/e2e-tests.yml
vendored
@@ -3,15 +3,15 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- 'docs/**'
|
- "docs/**"
|
||||||
- '**.md'
|
- "**.md"
|
||||||
- '.github/**'
|
- ".github/**"
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- 'docs/**'
|
- "docs/**"
|
||||||
- '**.md'
|
- "**.md"
|
||||||
- '.github/**'
|
- ".github/**"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -45,23 +45,29 @@ jobs:
|
|||||||
path: /tmp/docker-image.tar
|
path: /tmp/docker-image.tar
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
|
|
||||||
test-sqlite:
|
test:
|
||||||
if: github.event.pull_request.head.ref != 'i18n_crowdin'
|
if: github.event.pull_request.head.ref != 'i18n_crowdin'
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
actions: write
|
actions: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
db: [sqlite, postgres]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup pnpm
|
||||||
uses: pnpm/action-setup@v4
|
uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 10
|
version: 10
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 22
|
||||||
cache: 'pnpm'
|
cache: "pnpm"
|
||||||
cache-dependency-path: pnpm-lock.yaml
|
cache-dependency-path: pnpm-lock.yaml
|
||||||
|
|
||||||
- name: Cache Playwright Browsers
|
- name: Cache Playwright Browsers
|
||||||
@@ -70,100 +76,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: ~/.cache/ms-playwright
|
path: ~/.cache/ms-playwright
|
||||||
key: ${{ runner.os }}-playwright-${{ hashFiles('pnpm-lock.yaml') }}
|
key: ${{ runner.os }}-playwright-${{ hashFiles('pnpm-lock.yaml') }}
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-playwright-
|
|
||||||
|
|
||||||
- name: Download Docker image artifact
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: docker-image
|
|
||||||
path: /tmp
|
|
||||||
|
|
||||||
- name: Load Docker image
|
|
||||||
run: docker load -i /tmp/docker-image.tar
|
|
||||||
|
|
||||||
- name: Cache LLDAP Docker image
|
|
||||||
uses: actions/cache@v3
|
|
||||||
id: lldap-cache
|
|
||||||
with:
|
|
||||||
path: /tmp/lldap-image.tar
|
|
||||||
key: lldap-stable-${{ runner.os }}
|
|
||||||
|
|
||||||
- name: Pull and save LLDAP image
|
|
||||||
if: steps.lldap-cache.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
docker pull nitnelave/lldap:stable
|
|
||||||
docker save nitnelave/lldap:stable > /tmp/lldap-image.tar
|
|
||||||
|
|
||||||
- name: Load LLDAP image from cache
|
|
||||||
if: steps.lldap-cache.outputs.cache-hit == 'true'
|
|
||||||
run: docker load < /tmp/lldap-image.tar
|
|
||||||
|
|
||||||
- name: Install test dependencies
|
|
||||||
run: pnpm --filter pocket-id-tests install --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
|
||||||
working-directory: ./tests
|
|
||||||
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
|
||||||
run: pnpm dlx playwright install --with-deps chromium
|
|
||||||
|
|
||||||
- name: Run Docker Container with Sqlite DB and LDAP
|
|
||||||
working-directory: ./tests/setup
|
|
||||||
run: |
|
|
||||||
docker compose up -d
|
|
||||||
docker compose logs -f pocket-id &> /tmp/backend.log &
|
|
||||||
|
|
||||||
- name: Run Playwright tests
|
|
||||||
working-directory: tests
|
|
||||||
run: pnpm exec playwright test
|
|
||||||
|
|
||||||
- name: Upload Test Report
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
if: always() && github.event.pull_request.head.ref != 'i18n_crowdin'
|
|
||||||
with:
|
|
||||||
name: playwright-report-sqlite
|
|
||||||
path: tests/.report
|
|
||||||
include-hidden-files: true
|
|
||||||
retention-days: 15
|
|
||||||
|
|
||||||
- name: Upload Backend Test Report
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
if: always() && github.event.pull_request.head.ref != 'i18n_crowdin'
|
|
||||||
with:
|
|
||||||
name: backend-sqlite
|
|
||||||
path: /tmp/backend.log
|
|
||||||
include-hidden-files: true
|
|
||||||
retention-days: 15
|
|
||||||
|
|
||||||
test-postgres:
|
|
||||||
if: github.event.pull_request.head.ref != 'i18n_crowdin'
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: write
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 10
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 22
|
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: pnpm-lock.yaml
|
|
||||||
|
|
||||||
- name: Cache Playwright Browsers
|
|
||||||
uses: actions/cache@v3
|
|
||||||
id: playwright-cache
|
|
||||||
with:
|
|
||||||
path: ~/.cache/ms-playwright
|
|
||||||
key: ${{ runner.os }}-playwright-${{ hashFiles('pnpm-lock.yaml') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-playwright-
|
|
||||||
|
|
||||||
- name: Cache PostgreSQL Docker image
|
- name: Cache PostgreSQL Docker image
|
||||||
|
if: matrix.db == 'postgres'
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
id: postgres-cache
|
id: postgres-cache
|
||||||
with:
|
with:
|
||||||
@@ -171,15 +85,14 @@ jobs:
|
|||||||
key: postgres-17-${{ runner.os }}
|
key: postgres-17-${{ runner.os }}
|
||||||
|
|
||||||
- name: Pull and save PostgreSQL image
|
- name: Pull and save PostgreSQL image
|
||||||
if: steps.postgres-cache.outputs.cache-hit != 'true'
|
if: matrix.db == 'postgres' && steps.postgres-cache.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
docker pull postgres:17
|
docker pull postgres:17
|
||||||
docker save postgres:17 > /tmp/postgres-image.tar
|
docker save postgres:17 > /tmp/postgres-image.tar
|
||||||
|
|
||||||
- name: Load PostgreSQL image from cache
|
- name: Load PostgreSQL image from cache
|
||||||
if: steps.postgres-cache.outputs.cache-hit == 'true'
|
if: matrix.db == 'postgres' && steps.postgres-cache.outputs.cache-hit == 'true'
|
||||||
run: docker load < /tmp/postgres-image.tar
|
run: docker load < /tmp/postgres-image.tar
|
||||||
|
|
||||||
- name: Cache LLDAP Docker image
|
- name: Cache LLDAP Docker image
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
id: lldap-cache
|
id: lldap-cache
|
||||||
@@ -196,7 +109,6 @@ jobs:
|
|||||||
- name: Load LLDAP image from cache
|
- name: Load LLDAP image from cache
|
||||||
if: steps.lldap-cache.outputs.cache-hit == 'true'
|
if: steps.lldap-cache.outputs.cache-hit == 'true'
|
||||||
run: docker load < /tmp/lldap-image.tar
|
run: docker load < /tmp/lldap-image.tar
|
||||||
|
|
||||||
- name: Download Docker image artifact
|
- name: Download Docker image artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -207,14 +119,21 @@ jobs:
|
|||||||
run: docker load -i /tmp/docker-image.tar
|
run: docker load -i /tmp/docker-image.tar
|
||||||
|
|
||||||
- name: Install test dependencies
|
- name: Install test dependencies
|
||||||
run: pnpm --filter pocket-id-tests install
|
run: pnpm --filter pocket-id-tests install --frozen-lockfile
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
working-directory: ./tests
|
working-directory: ./tests
|
||||||
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
||||||
run: pnpm dlx playwright install --with-deps chromium
|
run: pnpm exec playwright install --with-deps chromium
|
||||||
|
- name: Run Docker Container (sqlite) with LDAP
|
||||||
|
if: matrix.db == 'sqlite'
|
||||||
|
working-directory: ./tests/setup
|
||||||
|
run: |
|
||||||
|
docker compose up -d
|
||||||
|
docker compose logs -f pocket-id &> /tmp/backend.log &
|
||||||
|
|
||||||
- name: Run Docker Container with Postgres DB and LDAP
|
- name: Run Docker Container (postgres) with LDAP
|
||||||
|
if: matrix.db == 'postgres'
|
||||||
working-directory: ./tests/setup
|
working-directory: ./tests/setup
|
||||||
run: |
|
run: |
|
||||||
docker compose -f docker-compose-postgres.yml up -d
|
docker compose -f docker-compose-postgres.yml up -d
|
||||||
@@ -228,8 +147,8 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
if: always() && github.event.pull_request.head.ref != 'i18n_crowdin'
|
if: always() && github.event.pull_request.head.ref != 'i18n_crowdin'
|
||||||
with:
|
with:
|
||||||
name: playwright-report-postgres
|
name: playwright-report-${{ matrix.db }}
|
||||||
path: frontend/tests/.report
|
path: tests/.report
|
||||||
include-hidden-files: true
|
include-hidden-files: true
|
||||||
retention-days: 15
|
retention-days: 15
|
||||||
|
|
||||||
@@ -237,7 +156,7 @@ jobs:
|
|||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
if: always() && github.event.pull_request.head.ref != 'i18n_crowdin'
|
if: always() && github.event.pull_request.head.ref != 'i18n_crowdin'
|
||||||
with:
|
with:
|
||||||
name: backend-postgres
|
name: backend-${{ matrix.db }}
|
||||||
path: /tmp/backend.log
|
path: /tmp/backend.log
|
||||||
include-hidden-files: true
|
include-hidden-files: true
|
||||||
retention-days: 15
|
retention-days: 15
|
||||||
|
|||||||
30
CHANGELOG.md
30
CHANGELOG.md
@@ -1,3 +1,33 @@
|
|||||||
|
## [](https://github.com/pocket-id/pocket-id/compare/v1.9.1...v) (2025-08-27)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* redesigned sidebar with administrative dropdown ([#881](https://github.com/pocket-id/pocket-id/issues/881)) ([096d214](https://github.com/pocket-id/pocket-id/commit/096d214a88808848dae726b0ef4c9a9987185836))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* apps showed multiple times if user is in multiple groups ([641bbc9](https://github.com/pocket-id/pocket-id/commit/641bbc935191bad8afbfec90943fc3e9de7a0cb6))
|
||||||
|
## [](https://github.com/pocket-id/pocket-id/compare/v1.9.0...v) (2025-08-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* sqlite migration drops allowed user groups ([d6d1a4c](https://github.com/pocket-id/pocket-id/commit/d6d1a4ced23886f255a9c2048d19ad3599a17f26))
|
||||||
|
|
||||||
|
## [](https://github.com/pocket-id/pocket-id/compare/v1.8.1...v) (2025-08-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* support automatic db migration rollbacks ([#874](https://github.com/pocket-id/pocket-id/issues/874)) ([c114a2e](https://github.com/pocket-id/pocket-id/commit/c114a2edaae4c007c75c34c02e8b0bb011845cae))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* don't force uuid for client id in postgres ([2ffc6ba](https://github.com/pocket-id/pocket-id/commit/2ffc6ba42af4742a13b77543142b66b3e826ab88))
|
||||||
|
* ensure SQLite has a writable temporary directory ([#876](https://github.com/pocket-id/pocket-id/issues/876)) ([1f3550c](https://github.com/pocket-id/pocket-id/commit/1f3550c9bd3aafd3bd2272ef47f3ed8736037d81))
|
||||||
|
* sort order incorrect for apps when using postgres ([d0392d2](https://github.com/pocket-id/pocket-id/commit/d0392d25edcaa5f3c7da2aad70febf63b47763fa))
|
||||||
|
|
||||||
## [](https://github.com/pocket-id/pocket-id/compare/v1.8.0...v) (2025-08-24)
|
## [](https://github.com/pocket-id/pocket-id/compare/v1.8.0...v) (2025-08-24)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ require (
|
|||||||
github.com/go-webauthn/x v0.1.23 // indirect
|
github.com/go-webauthn/x v0.1.23 // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.3 // indirect
|
github.com/golang-jwt/jwt/v5 v5.2.3 // indirect
|
||||||
|
github.com/google/go-github/v39 v39.2.0 // indirect
|
||||||
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/go-tpm v0.9.5 // indirect
|
github.com/google/go-tpm v0.9.5 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
@@ -132,6 +134,7 @@ require (
|
|||||||
golang.org/x/arch v0.20.0 // indirect
|
golang.org/x/arch v0.20.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
|
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
|
||||||
golang.org/x/net v0.43.0 // indirect
|
golang.org/x/net v0.43.0 // indirect
|
||||||
|
golang.org/x/oauth2 v0.27.0 // indirect
|
||||||
golang.org/x/sync v0.16.0 // indirect
|
golang.org/x/sync v0.16.0 // indirect
|
||||||
golang.org/x/sys v0.35.0 // indirect
|
golang.org/x/sys v0.35.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect
|
||||||
|
|||||||
@@ -95,11 +95,19 @@ github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJD
|
|||||||
github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||||
github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs=
|
github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs=
|
||||||
github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY=
|
github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/google/go-github/v39 v39.2.0 h1:rNNM311XtPOz5rDdsJXAp2o8F67X9FnROXTvto3aSnQ=
|
||||||
|
github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE=
|
||||||
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU=
|
github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU=
|
||||||
github.com/google/go-tpm v0.9.5/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
github.com/google/go-tpm v0.9.5/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
@@ -319,6 +327,7 @@ go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
|||||||
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
||||||
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
@@ -339,6 +348,7 @@ golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||||
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
@@ -352,6 +362,9 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
|||||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
|
||||||
|
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -385,6 +398,7 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
|||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
@@ -406,6 +420,8 @@ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxb
|
|||||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4=
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -13,6 +15,7 @@ import (
|
|||||||
"github.com/golang-migrate/migrate/v4/database"
|
"github.com/golang-migrate/migrate/v4/database"
|
||||||
postgresMigrate "github.com/golang-migrate/migrate/v4/database/postgres"
|
postgresMigrate "github.com/golang-migrate/migrate/v4/database/postgres"
|
||||||
sqliteMigrate "github.com/golang-migrate/migrate/v4/database/sqlite3"
|
sqliteMigrate "github.com/golang-migrate/migrate/v4/database/sqlite3"
|
||||||
|
_ "github.com/golang-migrate/migrate/v4/source/github"
|
||||||
"github.com/golang-migrate/migrate/v4/source/iofs"
|
"github.com/golang-migrate/migrate/v4/source/iofs"
|
||||||
slogGorm "github.com/orandin/slog-gorm"
|
slogGorm "github.com/orandin/slog-gorm"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
@@ -20,6 +23,7 @@ import (
|
|||||||
gormLogger "gorm.io/gorm/logger"
|
gormLogger "gorm.io/gorm/logger"
|
||||||
|
|
||||||
"github.com/pocket-id/pocket-id/backend/internal/common"
|
"github.com/pocket-id/pocket-id/backend/internal/common"
|
||||||
|
"github.com/pocket-id/pocket-id/backend/internal/utils"
|
||||||
sqliteutil "github.com/pocket-id/pocket-id/backend/internal/utils/sqlite"
|
sqliteutil "github.com/pocket-id/pocket-id/backend/internal/utils/sqlite"
|
||||||
"github.com/pocket-id/pocket-id/backend/resources"
|
"github.com/pocket-id/pocket-id/backend/resources"
|
||||||
)
|
)
|
||||||
@@ -38,7 +42,9 @@ func NewDatabase() (db *gorm.DB, err error) {
|
|||||||
var driver database.Driver
|
var driver database.Driver
|
||||||
switch common.EnvConfig.DbProvider {
|
switch common.EnvConfig.DbProvider {
|
||||||
case common.DbProviderSqlite:
|
case common.DbProviderSqlite:
|
||||||
driver, err = sqliteMigrate.WithInstance(sqlDb, &sqliteMigrate.Config{})
|
driver, err = sqliteMigrate.WithInstance(sqlDb, &sqliteMigrate.Config{
|
||||||
|
NoTxWrap: true,
|
||||||
|
})
|
||||||
case common.DbProviderPostgres:
|
case common.DbProviderPostgres:
|
||||||
driver, err = postgresMigrate.WithInstance(sqlDb, &postgresMigrate.Config{})
|
driver, err = postgresMigrate.WithInstance(sqlDb, &postgresMigrate.Config{})
|
||||||
default:
|
default:
|
||||||
@@ -58,8 +64,9 @@ func NewDatabase() (db *gorm.DB, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func migrateDatabase(driver database.Driver) error {
|
func migrateDatabase(driver database.Driver) error {
|
||||||
// Use the embedded migrations
|
// Embedded migrations via iofs
|
||||||
source, err := iofs.New(resources.FS, "migrations/"+string(common.EnvConfig.DbProvider))
|
path := "migrations/" + string(common.EnvConfig.DbProvider)
|
||||||
|
source, err := iofs.New(resources.FS, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create embedded migration source: %w", err)
|
return fmt.Errorf("failed to create embedded migration source: %w", err)
|
||||||
}
|
}
|
||||||
@@ -69,14 +76,66 @@ func migrateDatabase(driver database.Driver) error {
|
|||||||
return fmt.Errorf("failed to create migration instance: %w", err)
|
return fmt.Errorf("failed to create migration instance: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.Up()
|
requiredVersion, err := getRequiredMigrationVersion(path)
|
||||||
if err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to apply migrations: %w", err)
|
return fmt.Errorf("failed to get last migration version: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentVersion, _, _ := m.Version()
|
||||||
|
if currentVersion > requiredVersion {
|
||||||
|
slog.Warn("Database version is newer than the application supports, possible downgrade detected", slog.Uint64("db_version", uint64(currentVersion)), slog.Uint64("app_version", uint64(requiredVersion)))
|
||||||
|
if !common.EnvConfig.AllowDowngrade {
|
||||||
|
return fmt.Errorf("database version (%d) is newer than application version (%d), downgrades are not allowed (set ALLOW_DOWNGRADE=true to enable)", currentVersion, requiredVersion)
|
||||||
|
}
|
||||||
|
slog.Info("Fetching migrations from GitHub to handle possible downgrades")
|
||||||
|
return migrateDatabaseFromGitHub(driver, requiredVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.Migrate(requiredVersion); err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
||||||
|
return fmt.Errorf("failed to apply embedded migrations: %w", err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func migrateDatabaseFromGitHub(driver database.Driver, version uint) error {
|
||||||
|
srcURL := "github://pocket-id/pocket-id/backend/resources/migrations/" + string(common.EnvConfig.DbProvider)
|
||||||
|
|
||||||
|
m, err := migrate.NewWithDatabaseInstance(srcURL, "pocket-id", driver)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create GitHub migration instance: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.Migrate(version); err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
||||||
|
return fmt.Errorf("failed to apply GitHub migrations: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getRequiredMigrationVersion reads the embedded migration files and returns the highest version number found.
|
||||||
|
func getRequiredMigrationVersion(path string) (uint, error) {
|
||||||
|
entries, err := resources.FS.ReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("failed to read migration directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxVersion uint
|
||||||
|
for _, entry := range entries {
|
||||||
|
if entry.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name := entry.Name()
|
||||||
|
var version uint
|
||||||
|
n, err := fmt.Sscanf(name, "%d_", &version)
|
||||||
|
if err == nil && n == 1 {
|
||||||
|
if version > maxVersion {
|
||||||
|
maxVersion = version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxVersion, nil
|
||||||
|
}
|
||||||
|
|
||||||
func connectDatabase() (db *gorm.DB, err error) {
|
func connectDatabase() (db *gorm.DB, err error) {
|
||||||
var dialector gorm.Dialector
|
var dialector gorm.Dialector
|
||||||
|
|
||||||
@@ -86,11 +145,20 @@ func connectDatabase() (db *gorm.DB, err error) {
|
|||||||
if common.EnvConfig.DbConnectionString == "" {
|
if common.EnvConfig.DbConnectionString == "" {
|
||||||
return nil, errors.New("missing required env var 'DB_CONNECTION_STRING' for SQLite database")
|
return nil, errors.New("missing required env var 'DB_CONNECTION_STRING' for SQLite database")
|
||||||
}
|
}
|
||||||
|
|
||||||
sqliteutil.RegisterSqliteFunctions()
|
sqliteutil.RegisterSqliteFunctions()
|
||||||
connString, err := parseSqliteConnectionString(common.EnvConfig.DbConnectionString)
|
|
||||||
|
connString, dbPath, err := parseSqliteConnectionString(common.EnvConfig.DbConnectionString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Before we connect, also make sure that there's a temporary folder for SQLite to write its data
|
||||||
|
err = ensureSqliteTempDir(filepath.Dir(dbPath))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
dialector = sqlite.Open(connString)
|
dialector = sqlite.Open(connString)
|
||||||
case common.DbProviderPostgres:
|
case common.DbProviderPostgres:
|
||||||
if common.EnvConfig.DbConnectionString == "" {
|
if common.EnvConfig.DbConnectionString == "" {
|
||||||
@@ -120,7 +188,7 @@ func connectDatabase() (db *gorm.DB, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSqliteConnectionString(connString string) (string, error) {
|
func parseSqliteConnectionString(connString string) (parsedConnString string, dbPath string, err error) {
|
||||||
if !strings.HasPrefix(connString, "file:") {
|
if !strings.HasPrefix(connString, "file:") {
|
||||||
connString = "file:" + connString
|
connString = "file:" + connString
|
||||||
}
|
}
|
||||||
@@ -131,7 +199,7 @@ func parseSqliteConnectionString(connString string) (string, error) {
|
|||||||
// Parse the connection string
|
// Parse the connection string
|
||||||
connStringUrl, err := url.Parse(connString)
|
connStringUrl, err := url.Parse(connString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to parse SQLite connection string: %w", err)
|
return "", "", fmt.Errorf("failed to parse SQLite connection string: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert options for the old SQLite driver to the new one
|
// Convert options for the old SQLite driver to the new one
|
||||||
@@ -140,10 +208,19 @@ func parseSqliteConnectionString(connString string) (string, error) {
|
|||||||
// Add the default and required params
|
// Add the default and required params
|
||||||
err = addSqliteDefaultParameters(connStringUrl, isMemoryDB)
|
err = addSqliteDefaultParameters(connStringUrl, isMemoryDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("invalid SQLite connection string: %w", err)
|
return "", "", fmt.Errorf("invalid SQLite connection string: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return connStringUrl.String(), nil
|
// Get the absolute path to the database
|
||||||
|
// Here, we know for a fact that the ? is present
|
||||||
|
parsedConnString = connStringUrl.String()
|
||||||
|
idx := strings.IndexRune(parsedConnString, '?')
|
||||||
|
dbPath, err = filepath.Abs(parsedConnString[len("file:"):idx])
|
||||||
|
if err != nil {
|
||||||
|
return "", "", fmt.Errorf("failed to determine absolute path to the database: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedConnString, dbPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// The official C implementation of SQLite allows some additional properties in the connection string
|
// The official C implementation of SQLite allows some additional properties in the connection string
|
||||||
@@ -296,6 +373,48 @@ func isSqliteInMemory(connString string) bool {
|
|||||||
return len(qs["mode"]) > 0 && qs["mode"][0] == "memory"
|
return len(qs["mode"]) > 0 && qs["mode"][0] == "memory"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensureSqliteTempDir ensures that SQLite has a directory where it can write temporary files if needed
|
||||||
|
// The default directory may not be writable when using a container with a read-only root file system
|
||||||
|
// See: https://www.sqlite.org/tempfiles.html
|
||||||
|
func ensureSqliteTempDir(dbPath string) error {
|
||||||
|
// Per docs, SQLite tries these folders in order (excluding those that aren't applicable to us):
|
||||||
|
//
|
||||||
|
// - The SQLITE_TMPDIR environment variable
|
||||||
|
// - The TMPDIR environment variable
|
||||||
|
// - /var/tmp
|
||||||
|
// - /usr/tmp
|
||||||
|
// - /tmp
|
||||||
|
//
|
||||||
|
// Source: https://www.sqlite.org/tempfiles.html#temporary_file_storage_locations
|
||||||
|
//
|
||||||
|
// First, let's check if SQLITE_TMPDIR or TMPDIR are set, in which case we trust the user has taken care of the problem already
|
||||||
|
if os.Getenv("SQLITE_TMPDIR") != "" || os.Getenv("TMPDIR") != "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, let's check if /var/tmp, /usr/tmp, or /tmp exist and are writable
|
||||||
|
for _, dir := range []string{"/var/tmp", "/usr/tmp", "/tmp"} {
|
||||||
|
ok, err := utils.IsWritableDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to check if %s is writable: %w", dir, err)
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
// We found a folder that's writable
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're here, there's no temporary directory that's writable (not unusual for containers with a read-only root file system), so we set SQLITE_TMPDIR to the folder where the SQLite database is set
|
||||||
|
err := os.Setenv("SQLITE_TMPDIR", dbPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to set SQLITE_TMPDIR environmental variable: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
slog.Debug("Set SQLITE_TMPDIR to the database directory", "path", dbPath)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getGormLogger() gormLogger.Interface {
|
func getGormLogger() gormLogger.Interface {
|
||||||
loggerOpts := make([]slogGorm.Option, 0, 5)
|
loggerOpts := make([]slogGorm.Option, 0, 5)
|
||||||
loggerOpts = append(loggerOpts,
|
loggerOpts = append(loggerOpts,
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ type EnvConfigSchema struct {
|
|||||||
LogJSON bool `env:"LOG_JSON"`
|
LogJSON bool `env:"LOG_JSON"`
|
||||||
TrustProxy bool `env:"TRUST_PROXY"`
|
TrustProxy bool `env:"TRUST_PROXY"`
|
||||||
AnalyticsDisabled bool `env:"ANALYTICS_DISABLED"`
|
AnalyticsDisabled bool `env:"ANALYTICS_DISABLED"`
|
||||||
|
AllowDowngrade bool `env:"ALLOW_DOWNGRADE"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var EnvConfig = defaultConfig()
|
var EnvConfig = defaultConfig()
|
||||||
@@ -87,6 +88,7 @@ func defaultConfig() EnvConfigSchema {
|
|||||||
TracingEnabled: false,
|
TracingEnabled: false,
|
||||||
TrustProxy: false,
|
TrustProxy: false,
|
||||||
AnalyticsDisabled: false,
|
AnalyticsDisabled: false,
|
||||||
|
AllowDowngrade: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ func (s *TestService) SeedDatabase(baseURL string) error {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Base: model.Base{
|
Base: model.Base{
|
||||||
ID: "b2c3d4e5-f6g7-8901-bcde-f12345678901",
|
ID: "dc3c9c96-714e-48eb-926e-2d7c7858e6cf",
|
||||||
},
|
},
|
||||||
Token: "PARTIAL567890ABC",
|
Token: "PARTIAL567890ABC",
|
||||||
ExpiresAt: datatype.DateTime(time.Now().Add(7 * 24 * time.Hour)),
|
ExpiresAt: datatype.DateTime(time.Now().Add(7 * 24 * time.Hour)),
|
||||||
@@ -352,7 +352,7 @@ func (s *TestService) SeedDatabase(baseURL string) error {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Base: model.Base{
|
Base: model.Base{
|
||||||
ID: "c3d4e5f6-g7h8-9012-cdef-123456789012",
|
ID: "44de1863-ffa5-4db1-9507-4887cd7a1e3f",
|
||||||
},
|
},
|
||||||
Token: "EXPIRED34567890B",
|
Token: "EXPIRED34567890B",
|
||||||
ExpiresAt: datatype.DateTime(time.Now().Add(-24 * time.Hour)), // Expired
|
ExpiresAt: datatype.DateTime(time.Now().Add(-24 * time.Hour)), // Expired
|
||||||
@@ -361,7 +361,7 @@ func (s *TestService) SeedDatabase(baseURL string) error {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Base: model.Base{
|
Base: model.Base{
|
||||||
ID: "d4e5f6g7-h8i9-0123-def0-234567890123",
|
ID: "f1b1678b-7720-4d8b-8f91-1dbff1e2d02b",
|
||||||
},
|
},
|
||||||
Token: "FULLYUSED567890C",
|
Token: "FULLYUSED567890C",
|
||||||
ExpiresAt: datatype.DateTime(time.Now().Add(24 * time.Hour)),
|
ExpiresAt: datatype.DateTime(time.Now().Add(24 * time.Hour)),
|
||||||
|
|||||||
@@ -1379,19 +1379,22 @@ func (s *OidcService) ListAccessibleOidcClients(ctx context.Context, userID stri
|
|||||||
query := tx.
|
query := tx.
|
||||||
WithContext(ctx).
|
WithContext(ctx).
|
||||||
Model(&model.OidcClient{}).
|
Model(&model.OidcClient{}).
|
||||||
Preload("UserAuthorizedOidcClients", "user_id = ?", userID).
|
Preload("UserAuthorizedOidcClients", "user_id = ?", userID)
|
||||||
Distinct()
|
|
||||||
|
|
||||||
// If user has no groups, only return clients with no allowed user groups
|
// If user has no groups, only return clients with no allowed user groups
|
||||||
if len(userGroupIDs) == 0 {
|
if len(userGroupIDs) == 0 {
|
||||||
query = query.
|
query = query.Where(`NOT EXISTS (
|
||||||
Joins("LEFT JOIN oidc_clients_allowed_user_groups ON oidc_clients.id = oidc_clients_allowed_user_groups.oidc_client_id").
|
SELECT 1 FROM oidc_clients_allowed_user_groups
|
||||||
Where("oidc_clients_allowed_user_groups.oidc_client_id IS NULL")
|
WHERE oidc_clients_allowed_user_groups.oidc_client_id = oidc_clients.id)`)
|
||||||
} else {
|
} else {
|
||||||
// Return clients with no allowed user groups OR clients where user is in allowed groups
|
query = query.Where(`
|
||||||
query = query.
|
NOT EXISTS (
|
||||||
Joins("LEFT JOIN oidc_clients_allowed_user_groups ON oidc_clients.id = oidc_clients_allowed_user_groups.oidc_client_id").
|
SELECT 1 FROM oidc_clients_allowed_user_groups
|
||||||
Where("oidc_clients_allowed_user_groups.oidc_client_id IS NULL OR oidc_clients_allowed_user_groups.user_group_id IN (?)", userGroupIDs)
|
WHERE oidc_clients_allowed_user_groups.oidc_client_id = oidc_clients.id
|
||||||
|
) OR EXISTS (
|
||||||
|
SELECT 1 FROM oidc_clients_allowed_user_groups
|
||||||
|
WHERE oidc_clients_allowed_user_groups.oidc_client_id = oidc_clients.id
|
||||||
|
AND oidc_clients_allowed_user_groups.user_group_id IN (?))`, userGroupIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
var clients []model.OidcClient
|
var clients []model.OidcClient
|
||||||
@@ -1401,7 +1404,7 @@ func (s *OidcService) ListAccessibleOidcClients(ctx context.Context, userID stri
|
|||||||
if sortedPaginationRequest.Sort.Column == "lastUsedAt" && utils.IsValidSortDirection(sortedPaginationRequest.Sort.Direction) {
|
if sortedPaginationRequest.Sort.Column == "lastUsedAt" && utils.IsValidSortDirection(sortedPaginationRequest.Sort.Direction) {
|
||||||
query = query.
|
query = query.
|
||||||
Joins("LEFT JOIN user_authorized_oidc_clients ON oidc_clients.id = user_authorized_oidc_clients.client_id AND user_authorized_oidc_clients.user_id = ?", userID).
|
Joins("LEFT JOIN user_authorized_oidc_clients ON oidc_clients.id = user_authorized_oidc_clients.client_id AND user_authorized_oidc_clients.user_id = ?", userID).
|
||||||
Order("user_authorized_oidc_clients.last_used_at " + sortedPaginationRequest.Sort.Direction)
|
Order("user_authorized_oidc_clients.last_used_at " + sortedPaginationRequest.Sort.Direction + " NULLS LAST")
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err = utils.PaginateAndSort(sortedPaginationRequest, query, &clients)
|
response, err = utils.PaginateAndSort(sortedPaginationRequest, query, &clients)
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pocket-id/pocket-id/backend/resources"
|
"github.com/pocket-id/pocket-id/backend/resources"
|
||||||
@@ -136,3 +139,41 @@ func FileExists(path string) (bool, error) {
|
|||||||
}
|
}
|
||||||
return !s.IsDir(), nil
|
return !s.IsDir(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsWritableDir checks if a directory exists and is writable
|
||||||
|
func IsWritableDir(dir string) (bool, error) {
|
||||||
|
// Check if directory exists and it's actually a directory
|
||||||
|
info, err := os.Stat(dir)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false, nil
|
||||||
|
} else if err != nil {
|
||||||
|
return false, fmt.Errorf("failed to stat '%s': %w", dir, err)
|
||||||
|
}
|
||||||
|
if !info.IsDir() {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a random suffix for the test file to avoid conflicts
|
||||||
|
randomBytes := make([]byte, 8)
|
||||||
|
_, err = io.ReadFull(rand.Reader, randomBytes)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("failed to generate random bytes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if directory is writable by trying to create a temporary file
|
||||||
|
testFile := filepath.Join(dir, ".pocketid_test_write_"+hex.EncodeToString(randomBytes))
|
||||||
|
defer os.Remove(testFile)
|
||||||
|
|
||||||
|
file, err := os.Create(testFile)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsPermission(err) || errors.Is(err, syscall.EROFS) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, fmt.Errorf("failed to create test file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = file.Close()
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,7 +55,9 @@ func NewDatabaseForTest(t *testing.T) *gorm.DB {
|
|||||||
// Perform migrations with the embedded migrations
|
// Perform migrations with the embedded migrations
|
||||||
sqlDB, err := db.DB()
|
sqlDB, err := db.DB()
|
||||||
require.NoError(t, err, "Failed to get sql.DB")
|
require.NoError(t, err, "Failed to get sql.DB")
|
||||||
driver, err := sqliteMigrate.WithInstance(sqlDB, &sqliteMigrate.Config{})
|
driver, err := sqliteMigrate.WithInstance(sqlDB, &sqliteMigrate.Config{
|
||||||
|
NoTxWrap: true,
|
||||||
|
})
|
||||||
require.NoError(t, err, "Failed to create migration driver")
|
require.NoError(t, err, "Failed to create migration driver")
|
||||||
source, err := iofs.New(resources.FS, "migrations/sqlite")
|
source, err := iofs.New(resources.FS, "migrations/sqlite")
|
||||||
require.NoError(t, err, "Failed to create embedded migration source")
|
require.NoError(t, err, "Failed to create embedded migration source")
|
||||||
@@ -63,6 +65,8 @@ func NewDatabaseForTest(t *testing.T) *gorm.DB {
|
|||||||
require.NoError(t, err, "Failed to create migration instance")
|
require.NoError(t, err, "Failed to create migration instance")
|
||||||
err = m.Up()
|
err = m.Up()
|
||||||
require.NoError(t, err, "Failed to perform migrations")
|
require.NoError(t, err, "Failed to perform migrations")
|
||||||
|
_, err = sqlDB.Exec("PRAGMA foreign_keys = OFF;")
|
||||||
|
require.NoError(t, err, "Failed to disable foreign keys")
|
||||||
|
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1 +1,7 @@
|
|||||||
-- No-op
|
ALTER TABLE public.audit_logs
|
||||||
|
DROP CONSTRAINT IF EXISTS audit_logs_user_id_fkey,
|
||||||
|
ADD CONSTRAINT audit_logs_user_id_fkey
|
||||||
|
FOREIGN KEY (user_id) REFERENCES public.users (id);
|
||||||
|
|
||||||
|
ALTER TABLE public.oidc_authorization_codes
|
||||||
|
DROP CONSTRAINT IF EXISTS oidc_authorization_codes_client_fk;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
-- No-op because strings can't be converted to UUIDs
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
-- Drop foreign keys that reference oidc_clients(id)
|
||||||
|
ALTER TABLE oidc_authorization_codes
|
||||||
|
DROP CONSTRAINT IF EXISTS oidc_authorization_codes_client_fk;
|
||||||
|
ALTER TABLE user_authorized_oidc_clients
|
||||||
|
DROP CONSTRAINT IF EXISTS user_authorized_oidc_clients_client_id_fkey;
|
||||||
|
ALTER TABLE oidc_refresh_tokens
|
||||||
|
DROP CONSTRAINT IF EXISTS oidc_refresh_tokens_client_id_fkey;
|
||||||
|
ALTER TABLE oidc_device_codes
|
||||||
|
DROP CONSTRAINT IF EXISTS oidc_device_codes_client_id_fkey;
|
||||||
|
ALTER TABLE oidc_clients_allowed_user_groups
|
||||||
|
DROP CONSTRAINT IF EXISTS oidc_clients_allowed_user_groups_oidc_client_id_fkey;
|
||||||
|
|
||||||
|
-- Alter child columns to TEXT
|
||||||
|
ALTER TABLE oidc_authorization_codes
|
||||||
|
ALTER COLUMN client_id TYPE TEXT USING client_id::text;
|
||||||
|
|
||||||
|
ALTER TABLE user_authorized_oidc_clients
|
||||||
|
ALTER
|
||||||
|
COLUMN client_id TYPE TEXT USING client_id::text;
|
||||||
|
|
||||||
|
ALTER TABLE oidc_refresh_tokens
|
||||||
|
ALTER
|
||||||
|
COLUMN client_id TYPE TEXT USING client_id::text;
|
||||||
|
|
||||||
|
ALTER TABLE oidc_device_codes
|
||||||
|
ALTER
|
||||||
|
COLUMN client_id TYPE TEXT USING client_id::text;
|
||||||
|
|
||||||
|
ALTER TABLE oidc_clients_allowed_user_groups
|
||||||
|
ALTER
|
||||||
|
COLUMN oidc_client_id TYPE TEXT USING oidc_client_id::text;
|
||||||
|
|
||||||
|
-- Alter parent primary key column to TEXT
|
||||||
|
ALTER TABLE oidc_clients
|
||||||
|
ALTER
|
||||||
|
COLUMN id TYPE TEXT USING id::text;
|
||||||
|
|
||||||
|
-- Recreate foreign keys with the new type
|
||||||
|
ALTER TABLE oidc_authorization_codes
|
||||||
|
ADD CONSTRAINT oidc_authorization_codes_client_fk
|
||||||
|
FOREIGN KEY (client_id) REFERENCES oidc_clients (id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE user_authorized_oidc_clients
|
||||||
|
ADD CONSTRAINT user_authorized_oidc_clients_client_id_fkey
|
||||||
|
FOREIGN KEY (client_id) REFERENCES oidc_clients (id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE oidc_refresh_tokens
|
||||||
|
ADD CONSTRAINT oidc_refresh_tokens_client_id_fkey
|
||||||
|
FOREIGN KEY (client_id) REFERENCES oidc_clients (id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE oidc_device_codes
|
||||||
|
ADD CONSTRAINT oidc_device_codes_client_id_fkey
|
||||||
|
FOREIGN KEY (client_id) REFERENCES oidc_clients (id) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE oidc_clients_allowed_user_groups
|
||||||
|
ADD CONSTRAINT oidc_clients_allowed_user_groups_oidc_client_id_fkey
|
||||||
|
FOREIGN KEY (oidc_client_id) REFERENCES oidc_clients (id) ON DELETE CASCADE;
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
CREATE TABLE users
|
CREATE TABLE users
|
||||||
(
|
(
|
||||||
id TEXT NOT NULL PRIMARY KEY,
|
id TEXT NOT NULL PRIMARY KEY,
|
||||||
@@ -78,3 +80,5 @@ CREATE TABLE application_configuration_variables
|
|||||||
is_public NUMERIC DEFAULT FALSE NOT NULL,
|
is_public NUMERIC DEFAULT FALSE NOT NULL,
|
||||||
is_internal NUMERIC DEFAULT FALSE NOT NULL
|
is_internal NUMERIC DEFAULT FALSE NOT NULL
|
||||||
);
|
);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE webauthn_credentials ADD COLUMN backup_eligible BOOLEAN NOT NULL DEFAULT FALSE;
|
ALTER TABLE webauthn_credentials ADD COLUMN backup_eligible BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
ALTER TABLE webauthn_credentials ADD COLUMN backup_state BOOLEAN NOT NULL DEFAULT FALSE;
|
ALTER TABLE webauthn_credentials ADD COLUMN backup_state BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE webauthn_credentials DROP COLUMN backup_eligible;
|
ALTER TABLE webauthn_credentials DROP COLUMN backup_eligible;
|
||||||
ALTER TABLE webauthn_credentials DROP COLUMN backup_state;
|
ALTER TABLE webauthn_credentials DROP COLUMN backup_state;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE app_config_variables
|
ALTER TABLE app_config_variables
|
||||||
RENAME TO application_configuration_variables;
|
RENAME TO application_configuration_variables;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE application_configuration_variables
|
ALTER TABLE application_configuration_variables
|
||||||
RENAME TO app_config_variables;
|
RENAME TO app_config_variables;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
create table oidc_clients
|
create table oidc_clients
|
||||||
(
|
(
|
||||||
id TEXT not null primary key,
|
id TEXT not null primary key,
|
||||||
@@ -21,3 +23,5 @@ select id,
|
|||||||
from oidc_clients_dg_tmp;
|
from oidc_clients_dg_tmp;
|
||||||
|
|
||||||
drop table oidc_clients_dg_tmp;
|
drop table oidc_clients_dg_tmp;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
create table oidc_clients_dg_tmp
|
create table oidc_clients_dg_tmp
|
||||||
(
|
(
|
||||||
id TEXT not null primary key,
|
id TEXT not null primary key,
|
||||||
@@ -24,3 +26,5 @@ drop table oidc_clients;
|
|||||||
|
|
||||||
alter table oidc_clients_dg_tmp
|
alter table oidc_clients_dg_tmp
|
||||||
rename to oidc_clients;
|
rename to oidc_clients;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP TABLE audit_logs;
|
DROP TABLE audit_logs;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
CREATE TABLE audit_logs
|
CREATE TABLE audit_logs
|
||||||
(
|
(
|
||||||
id TEXT NOT NULL PRIMARY KEY,
|
id TEXT NOT NULL PRIMARY KEY,
|
||||||
@@ -8,3 +10,5 @@ CREATE TABLE audit_logs
|
|||||||
data BLOB NOT NULL,
|
data BLOB NOT NULL,
|
||||||
user_id TEXT REFERENCES users
|
user_id TEXT REFERENCES users
|
||||||
);
|
);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP TABLE user_groups;
|
DROP TABLE user_groups;
|
||||||
DROP TABLE user_groups_users;
|
DROP TABLE user_groups_users;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
CREATE TABLE user_groups
|
CREATE TABLE user_groups
|
||||||
(
|
(
|
||||||
id TEXT NOT NULL PRIMARY KEY,
|
id TEXT NOT NULL PRIMARY KEY,
|
||||||
@@ -14,3 +16,5 @@ CREATE TABLE user_groups_users
|
|||||||
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
|
FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
|
||||||
FOREIGN KEY (user_group_id) REFERENCES user_groups (id) ON DELETE CASCADE
|
FOREIGN KEY (user_group_id) REFERENCES user_groups (id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE audit_logs DROP COLUMN country;
|
ALTER TABLE audit_logs DROP COLUMN country;
|
||||||
ALTER TABLE audit_logs DROP COLUMN city;
|
ALTER TABLE audit_logs DROP COLUMN city;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE audit_logs ADD COLUMN country TEXT;
|
ALTER TABLE audit_logs ADD COLUMN country TEXT;
|
||||||
ALTER TABLE audit_logs ADD COLUMN city TEXT;
|
ALTER TABLE audit_logs ADD COLUMN city TEXT;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
-- Convert the Unix timestamps back to DATETIME format
|
-- Convert the Unix timestamps back to DATETIME format
|
||||||
|
|
||||||
UPDATE user_groups
|
UPDATE user_groups
|
||||||
@@ -26,3 +28,5 @@ SET created_at = datetime(created_at, 'unixepoch');
|
|||||||
UPDATE webauthn_sessions
|
UPDATE webauthn_sessions
|
||||||
SET created_at = datetime(created_at, 'unixepoch'),
|
SET created_at = datetime(created_at, 'unixepoch'),
|
||||||
expires_at = datetime(expires_at, 'unixepoch');
|
expires_at = datetime(expires_at, 'unixepoch');
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
-- Convert the DATETIME fields to Unix timestamps (in seconds)
|
-- Convert the DATETIME fields to Unix timestamps (in seconds)
|
||||||
UPDATE user_groups
|
UPDATE user_groups
|
||||||
SET created_at = strftime('%s', created_at);
|
SET created_at = strftime('%s', created_at);
|
||||||
@@ -25,3 +27,5 @@ SET created_at = strftime('%s', created_at);
|
|||||||
UPDATE webauthn_sessions
|
UPDATE webauthn_sessions
|
||||||
SET created_at = strftime('%s', created_at),
|
SET created_at = strftime('%s', created_at),
|
||||||
expires_at = strftime('%s', expires_at);
|
expires_at = strftime('%s', expires_at);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE app_config_variables DROP COLUMN default_value;
|
ALTER TABLE app_config_variables DROP COLUMN default_value;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE app_config_variables ADD COLUMN default_value TEXT;
|
ALTER TABLE app_config_variables ADD COLUMN default_value TEXT;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP TABLE custom_claims;
|
DROP TABLE custom_claims;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
CREATE TABLE custom_claims
|
CREATE TABLE custom_claims
|
||||||
(
|
(
|
||||||
id TEXT NOT NULL PRIMARY KEY,
|
id TEXT NOT NULL PRIMARY KEY,
|
||||||
@@ -13,3 +15,5 @@ CREATE TABLE custom_claims
|
|||||||
CONSTRAINT custom_claims_unique UNIQUE (key, user_id, user_group_id),
|
CONSTRAINT custom_claims_unique UNIQUE (key, user_id, user_group_id),
|
||||||
CHECK (user_id IS NOT NULL OR user_group_id IS NOT NULL)
|
CHECK (user_id IS NOT NULL OR user_group_id IS NOT NULL)
|
||||||
);
|
);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_authorization_codes DROP COLUMN code_challenge;
|
ALTER TABLE oidc_authorization_codes DROP COLUMN code_challenge;
|
||||||
ALTER TABLE oidc_authorization_codes DROP COLUMN code_challenge_method_sha256;
|
ALTER TABLE oidc_authorization_codes DROP COLUMN code_challenge_method_sha256;
|
||||||
ALTER TABLE oidc_clients DROP COLUMN is_public;
|
ALTER TABLE oidc_clients DROP COLUMN is_public;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_authorization_codes ADD COLUMN code_challenge TEXT;
|
ALTER TABLE oidc_authorization_codes ADD COLUMN code_challenge TEXT;
|
||||||
ALTER TABLE oidc_authorization_codes ADD COLUMN code_challenge_method_sha256 NUMERIC;
|
ALTER TABLE oidc_authorization_codes ADD COLUMN code_challenge_method_sha256 NUMERIC;
|
||||||
ALTER TABLE oidc_clients ADD COLUMN is_public BOOLEAN DEFAULT FALSE;
|
ALTER TABLE oidc_clients ADD COLUMN is_public BOOLEAN DEFAULT FALSE;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_clients DROP COLUMN pkce_enabled;
|
ALTER TABLE oidc_clients DROP COLUMN pkce_enabled;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_clients ADD COLUMN pkce_enabled BOOLEAN DEFAULT FALSE;
|
ALTER TABLE oidc_clients ADD COLUMN pkce_enabled BOOLEAN DEFAULT FALSE;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE users DROP COLUMN ldap_id;
|
ALTER TABLE users DROP COLUMN ldap_id;
|
||||||
ALTER TABLE user_groups DROP COLUMN ldap_id;
|
ALTER TABLE user_groups DROP COLUMN ldap_id;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE users ADD COLUMN ldap_id TEXT;
|
ALTER TABLE users ADD COLUMN ldap_id TEXT;
|
||||||
ALTER TABLE user_groups ADD COLUMN ldap_id TEXT;
|
ALTER TABLE user_groups ADD COLUMN ldap_id TEXT;
|
||||||
|
|
||||||
CREATE UNIQUE INDEX users_ldap_id ON users (ldap_id);
|
CREATE UNIQUE INDEX users_ldap_id ON users (ldap_id);
|
||||||
CREATE UNIQUE INDEX user_groups_ldap_id ON user_groups (ldap_id);
|
CREATE UNIQUE INDEX user_groups_ldap_id ON user_groups (ldap_id);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
UPDATE app_config_variables SET key = 'emailEnabled' WHERE key = 'emailLoginNotificationEnabled';
|
UPDATE app_config_variables SET key = 'emailEnabled' WHERE key = 'emailLoginNotificationEnabled';
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
UPDATE app_config_variables SET key = 'emailLoginNotificationEnabled' WHERE key = 'emailEnabled';
|
UPDATE app_config_variables SET key = 'emailLoginNotificationEnabled' WHERE key = 'emailEnabled';
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
UPDATE users SET ldap_id = '' WHERE ldap_id IS NULL;
|
UPDATE users SET ldap_id = '' WHERE ldap_id IS NULL;
|
||||||
UPDATE user_groups SET ldap_id = '' WHERE ldap_id IS NULL;
|
UPDATE user_groups SET ldap_id = '' WHERE ldap_id IS NULL;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
UPDATE users SET ldap_id = null WHERE ldap_id = '';
|
UPDATE users SET ldap_id = null WHERE ldap_id = '';
|
||||||
UPDATE user_groups SET ldap_id = null WHERE ldap_id = '';
|
UPDATE user_groups SET ldap_id = null WHERE ldap_id = '';
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP TABLE oidc_clients_allowed_user_groups;
|
DROP TABLE oidc_clients_allowed_user_groups;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
CREATE TABLE oidc_clients_allowed_user_groups
|
CREATE TABLE oidc_clients_allowed_user_groups
|
||||||
(
|
(
|
||||||
user_group_id TEXT NOT NULL,
|
user_group_id TEXT NOT NULL,
|
||||||
@@ -6,3 +8,5 @@ CREATE TABLE oidc_clients_allowed_user_groups
|
|||||||
FOREIGN KEY (oidc_client_id) REFERENCES oidc_clients (id) ON DELETE CASCADE,
|
FOREIGN KEY (oidc_client_id) REFERENCES oidc_clients (id) ON DELETE CASCADE,
|
||||||
FOREIGN KEY (user_group_id) REFERENCES user_groups (id) ON DELETE CASCADE
|
FOREIGN KEY (user_group_id) REFERENCES user_groups (id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
UPDATE user_groups SET ldap_id = '' WHERE ldap_id IS NULL;
|
UPDATE user_groups SET ldap_id = '' WHERE ldap_id IS NULL;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
UPDATE user_groups SET ldap_id = null WHERE ldap_id = '';
|
UPDATE user_groups SET ldap_id = null WHERE ldap_id = '';
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_clients DROP COLUMN logout_callback_urls;
|
ALTER TABLE oidc_clients DROP COLUMN logout_callback_urls;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_clients ADD COLUMN logout_callback_urls BLOB;
|
ALTER TABLE oidc_clients ADD COLUMN logout_callback_urls BLOB;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
UPDATE app_config_variables SET value = 'true' WHERE key = 'smtpTls';
|
UPDATE app_config_variables SET value = 'true' WHERE key = 'smtpTls';
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
UPDATE app_config_variables
|
UPDATE app_config_variables
|
||||||
SET value = CASE
|
SET value = CASE
|
||||||
WHEN value = 'true' AND (SELECT value FROM app_config_variables WHERE key = 'smtpPort' LIMIT 1) = '587' THEN 'starttls'
|
WHEN value = 'true' AND (SELECT value FROM app_config_variables WHERE key = 'smtpPort' LIMIT 1) = '587' THEN 'starttls'
|
||||||
@@ -5,3 +7,5 @@ SET value = CASE
|
|||||||
ELSE 'none'
|
ELSE 'none'
|
||||||
END
|
END
|
||||||
WHERE key = 'smtpTls';
|
WHERE key = 'smtpTls';
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP INDEX IF EXISTS idx_api_keys_key;
|
DROP INDEX IF EXISTS idx_api_keys_key;
|
||||||
DROP TABLE IF EXISTS api_keys;
|
DROP TABLE IF EXISTS api_keys;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
CREATE TABLE api_keys (
|
CREATE TABLE api_keys (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
@@ -10,3 +12,5 @@ CREATE TABLE api_keys (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX idx_api_keys_key ON api_keys(key);
|
CREATE INDEX idx_api_keys_key ON api_keys(key);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE users DROP COLUMN locale;
|
ALTER TABLE users DROP COLUMN locale;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE users ADD COLUMN locale TEXT;
|
ALTER TABLE users ADD COLUMN locale TEXT;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP INDEX IF EXISTS idx_oidc_refresh_tokens_token;
|
DROP INDEX IF EXISTS idx_oidc_refresh_tokens_token;
|
||||||
DROP TABLE IF EXISTS oidc_refresh_tokens;
|
DROP TABLE IF EXISTS oidc_refresh_tokens;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
CREATE TABLE oidc_refresh_tokens (
|
CREATE TABLE oidc_refresh_tokens (
|
||||||
id TEXT NOT NULL PRIMARY KEY,
|
id TEXT NOT NULL PRIMARY KEY,
|
||||||
created_at DATETIME,
|
created_at DATETIME,
|
||||||
@@ -9,3 +11,5 @@ CREATE TABLE oidc_refresh_tokens (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX idx_oidc_refresh_tokens_token ON oidc_refresh_tokens(token);
|
CREATE INDEX idx_oidc_refresh_tokens_token ON oidc_refresh_tokens(token);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP INDEX IF EXISTS idx_audit_logs_event;
|
DROP INDEX IF EXISTS idx_audit_logs_event;
|
||||||
DROP INDEX IF EXISTS idx_audit_logs_user_id;
|
DROP INDEX IF EXISTS idx_audit_logs_user_id;
|
||||||
DROP INDEX IF EXISTS idx_audit_logs_client_name;
|
DROP INDEX IF EXISTS idx_audit_logs_client_name;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
CREATE INDEX idx_audit_logs_event ON audit_logs(event);
|
CREATE INDEX idx_audit_logs_event ON audit_logs(event);
|
||||||
CREATE INDEX idx_audit_logs_user_id ON audit_logs(user_id);
|
CREATE INDEX idx_audit_logs_user_id ON audit_logs(user_id);
|
||||||
CREATE INDEX idx_audit_logs_client_name ON audit_logs((json_extract(data, '$.clientName')));
|
CREATE INDEX idx_audit_logs_client_name ON audit_logs((json_extract(data, '$.clientName')));
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE app_config_variables ADD type VARCHAR(20) NOT NULL,;
|
ALTER TABLE app_config_variables ADD type VARCHAR(20) NOT NULL,;
|
||||||
ALTER TABLE app_config_variables ADD is_public BOOLEAN DEFAULT FALSE NOT NULL,;
|
ALTER TABLE app_config_variables ADD is_public BOOLEAN DEFAULT FALSE NOT NULL,;
|
||||||
ALTER TABLE app_config_variables ADD is_internal BOOLEAN DEFAULT FALSE NOT NULL,;
|
ALTER TABLE app_config_variables ADD is_internal BOOLEAN DEFAULT FALSE NOT NULL,;
|
||||||
ALTER TABLE app_config_variables ADD default_value TEXT;
|
ALTER TABLE app_config_variables ADD default_value TEXT;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE app_config_variables DROP type;
|
ALTER TABLE app_config_variables DROP type;
|
||||||
ALTER TABLE app_config_variables DROP is_public;
|
ALTER TABLE app_config_variables DROP is_public;
|
||||||
ALTER TABLE app_config_variables DROP is_internal;
|
ALTER TABLE app_config_variables DROP is_internal;
|
||||||
ALTER TABLE app_config_variables DROP default_value;
|
ALTER TABLE app_config_variables DROP default_value;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP INDEX idx_users_disabled;
|
DROP INDEX idx_users_disabled;
|
||||||
|
|
||||||
ALTER TABLE users
|
ALTER TABLE users
|
||||||
DROP COLUMN disabled;
|
DROP COLUMN disabled;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE users
|
ALTER TABLE users
|
||||||
ADD COLUMN disabled NUMERIC DEFAULT FALSE NOT NULL;
|
ADD COLUMN disabled NUMERIC DEFAULT FALSE NOT NULL;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE api_keys
|
ALTER TABLE api_keys
|
||||||
DROP COLUMN expiration_email_sent;
|
DROP COLUMN expiration_email_sent;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE api_keys
|
ALTER TABLE api_keys
|
||||||
ADD COLUMN expiration_email_sent BOOLEAN NOT NULL DEFAULT 0;
|
ADD COLUMN expiration_email_sent BOOLEAN NOT NULL DEFAULT 0;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP TABLE oidc_device_codes;
|
DROP TABLE oidc_device_codes;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
CREATE TABLE oidc_device_codes
|
CREATE TABLE oidc_device_codes
|
||||||
(
|
(
|
||||||
id TEXT NOT NULL PRIMARY KEY,
|
id TEXT NOT NULL PRIMARY KEY,
|
||||||
@@ -10,3 +12,5 @@ CREATE TABLE oidc_device_codes
|
|||||||
user_id TEXT REFERENCES users ON DELETE CASCADE,
|
user_id TEXT REFERENCES users ON DELETE CASCADE,
|
||||||
client_id TEXT NOT NULL REFERENCES oidc_clients ON DELETE CASCADE
|
client_id TEXT NOT NULL REFERENCES oidc_clients ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
-- No rollback is needed for this migration.
|
-- No-op
|
||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DELETE FROM app_config_variables WHERE value = '';
|
DELETE FROM app_config_variables WHERE value = '';
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_clients DROP COLUMN credentials;
|
ALTER TABLE oidc_clients DROP COLUMN credentials;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_clients ADD COLUMN credentials TEXT NULL;
|
ALTER TABLE oidc_clients ADD COLUMN credentials TEXT NULL;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP INDEX idx_audit_logs_country;
|
DROP INDEX idx_audit_logs_country;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
CREATE INDEX idx_audit_logs_country ON audit_logs(country);
|
CREATE INDEX idx_audit_logs_country ON audit_logs(country);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP INDEX IF EXISTS idx_signup_tokens_expires_at;
|
DROP INDEX IF EXISTS idx_signup_tokens_expires_at;
|
||||||
DROP INDEX IF EXISTS idx_signup_tokens_token;
|
DROP INDEX IF EXISTS idx_signup_tokens_token;
|
||||||
DROP TABLE IF EXISTS signup_tokens;
|
DROP TABLE IF EXISTS signup_tokens;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
CREATE TABLE signup_tokens (
|
CREATE TABLE signup_tokens (
|
||||||
id TEXT NOT NULL PRIMARY KEY,
|
id TEXT NOT NULL PRIMARY KEY,
|
||||||
created_at DATETIME NOT NULL,
|
created_at DATETIME NOT NULL,
|
||||||
@@ -9,3 +11,5 @@ CREATE TABLE signup_tokens (
|
|||||||
|
|
||||||
CREATE INDEX idx_signup_tokens_token ON signup_tokens(token);
|
CREATE INDEX idx_signup_tokens_token ON signup_tokens(token);
|
||||||
CREATE INDEX idx_signup_tokens_expires_at ON signup_tokens(expires_at);
|
CREATE INDEX idx_signup_tokens_expires_at ON signup_tokens(expires_at);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
-- Re-create the table with non-nullable ip_address
|
-- Re-create the table with non-nullable ip_address
|
||||||
-- We then move the data and rename the table
|
-- We then move the data and rename the table
|
||||||
CREATE TABLE audit_logs_new
|
CREATE TABLE audit_logs_new
|
||||||
@@ -28,3 +30,6 @@ CREATE INDEX idx_audit_logs_user_id ON audit_logs(user_id);
|
|||||||
CREATE INDEX idx_audit_logs_user_agent ON audit_logs(user_agent);
|
CREATE INDEX idx_audit_logs_user_agent ON audit_logs(user_agent);
|
||||||
CREATE INDEX idx_audit_logs_client_name ON audit_logs((json_extract(data, '$.clientName')));
|
CREATE INDEX idx_audit_logs_client_name ON audit_logs((json_extract(data, '$.clientName')));
|
||||||
CREATE INDEX idx_audit_logs_country ON audit_logs(country);
|
CREATE INDEX idx_audit_logs_country ON audit_logs(country);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
-- Re-create the table with nullable ip_address
|
-- Re-create the table with nullable ip_address
|
||||||
-- We then move the data and rename the table
|
-- We then move the data and rename the table
|
||||||
CREATE TABLE audit_logs_new
|
CREATE TABLE audit_logs_new
|
||||||
@@ -28,3 +30,6 @@ CREATE INDEX idx_audit_logs_user_id ON audit_logs(user_id);
|
|||||||
CREATE INDEX idx_audit_logs_user_agent ON audit_logs(user_agent);
|
CREATE INDEX idx_audit_logs_user_agent ON audit_logs(user_agent);
|
||||||
CREATE INDEX idx_audit_logs_client_name ON audit_logs((json_extract(data, '$.clientName')));
|
CREATE INDEX idx_audit_logs_client_name ON audit_logs((json_extract(data, '$.clientName')));
|
||||||
CREATE INDEX idx_audit_logs_country ON audit_logs(country);
|
CREATE INDEX idx_audit_logs_country ON audit_logs(country);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1 +1,6 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
DROP TABLE kv;
|
DROP TABLE kv;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
-- The "kv" tables contains miscellaneous key-value pairs
|
-- The "kv" tables contains miscellaneous key-value pairs
|
||||||
CREATE TABLE kv
|
CREATE TABLE kv
|
||||||
(
|
(
|
||||||
"key" TEXT NOT NULL PRIMARY KEY,
|
"key" TEXT NOT NULL PRIMARY KEY,
|
||||||
"value" TEXT NOT NULL
|
"value" TEXT NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
-- Normalize (form NFC) all existing values in the database
|
-- Normalize (form NFC) all existing values in the database
|
||||||
UPDATE api_keys SET
|
UPDATE api_keys SET
|
||||||
name = normalize(name, 'nfc'),
|
name = normalize(name, 'nfc'),
|
||||||
@@ -23,3 +25,6 @@ UPDATE users SET
|
|||||||
UPDATE user_groups SET
|
UPDATE user_groups SET
|
||||||
friendly_name = normalize(friendly_name, 'nfc'),
|
friendly_name = normalize(friendly_name, 'nfc'),
|
||||||
"name" = normalize("name", 'nfc');
|
"name" = normalize("name", 'nfc');
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_clients DROP COLUMN launch_url;
|
ALTER TABLE oidc_clients DROP COLUMN launch_url;
|
||||||
|
|
||||||
ALTER TABLE user_authorized_oidc_clients DROP COLUMN created_at;
|
ALTER TABLE user_authorized_oidc_clients DROP COLUMN created_at;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_clients ADD COLUMN launch_url TEXT;
|
ALTER TABLE oidc_clients ADD COLUMN launch_url TEXT;
|
||||||
|
|
||||||
CREATE TABLE user_authorized_oidc_clients_new
|
CREATE TABLE user_authorized_oidc_clients_new
|
||||||
@@ -14,3 +16,6 @@ SELECT scope, user_id, client_id, unixepoch() FROM user_authorized_oidc_clients;
|
|||||||
|
|
||||||
DROP TABLE user_authorized_oidc_clients;
|
DROP TABLE user_authorized_oidc_clients;
|
||||||
ALTER TABLE user_authorized_oidc_clients_new RENAME TO user_authorized_oidc_clients;
|
ALTER TABLE user_authorized_oidc_clients_new RENAME TO user_authorized_oidc_clients;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_clients DROP COLUMN requires_reauthentication;
|
ALTER TABLE oidc_clients DROP COLUMN requires_reauthentication;
|
||||||
DROP INDEX IF EXISTS idx_reauthentication_tokens_token;
|
DROP INDEX IF EXISTS idx_reauthentication_tokens_token;
|
||||||
DROP TABLE IF EXISTS reauthentication_tokens;
|
DROP TABLE IF EXISTS reauthentication_tokens;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
ALTER TABLE oidc_clients ADD COLUMN requires_reauthentication BOOLEAN NOT NULL DEFAULT FALSE;
|
ALTER TABLE oidc_clients ADD COLUMN requires_reauthentication BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
|
|
||||||
CREATE TABLE reauthentication_tokens (
|
CREATE TABLE reauthentication_tokens (
|
||||||
@@ -9,3 +11,5 @@ CREATE TABLE reauthentication_tokens (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX idx_reauthentication_tokens_token ON reauthentication_tokens(token);
|
CREATE INDEX idx_reauthentication_tokens_token ON reauthentication_tokens(token);
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
PRAGMA foreign_keys=OFF;
|
PRAGMA foreign_keys=OFF;
|
||||||
|
BEGIN;
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
---------------------------
|
---------------------------
|
||||||
-- Delete all orphaned rows
|
-- Delete all orphaned rows
|
||||||
---------------------------
|
---------------------------
|
||||||
@@ -175,3 +177,5 @@ ALTER TABLE webauthn_credentials_new RENAME TO webauthn_credentials;
|
|||||||
|
|
||||||
PRAGMA foreign_keys=ON;
|
PRAGMA foreign_keys=ON;
|
||||||
PRAGMA foreign_key_check;
|
PRAGMA foreign_key_check;
|
||||||
|
COMMIT;
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
"image_should_be_in_format": "The image should be in PNG or JPEG format.",
|
"image_should_be_in_format": "The image should be in PNG or JPEG format.",
|
||||||
"items_per_page": "Items per page",
|
"items_per_page": "Items per page",
|
||||||
"no_items_found": "No items found",
|
"no_items_found": "No items found",
|
||||||
|
"select_items": "Select items...",
|
||||||
"search": "Search...",
|
"search": "Search...",
|
||||||
"expand_card": "Expand card",
|
"expand_card": "Expand card",
|
||||||
"copied": "Copied",
|
"copied": "Copied",
|
||||||
@@ -440,5 +441,7 @@
|
|||||||
"last_signed_in_ago": "Last signed in {time} ago",
|
"last_signed_in_ago": "Last signed in {time} ago",
|
||||||
"invalid_client_id": "Client ID can only contain letters, numbers, underscores, and hyphens",
|
"invalid_client_id": "Client ID can only contain letters, numbers, underscores, and hyphens",
|
||||||
"custom_client_id_description": "Set a custom client ID if this is required by your application. Otherwise, leave it blank to generate a random one.",
|
"custom_client_id_description": "Set a custom client ID if this is required by your application. Otherwise, leave it blank to generate a random one.",
|
||||||
"generated": "Generated"
|
"generated": "Generated",
|
||||||
|
"administration": "Administration"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -276,8 +276,8 @@
|
|||||||
"public_clients_description": "공개 클라이언트는 클라이언트 시크릿이 없습니다. 이들은 시크릿을 안전하게 보관할 수 없는 모바일, 웹, 네이티브 애플리케이션을 위해 설계되었습니다.",
|
"public_clients_description": "공개 클라이언트는 클라이언트 시크릿이 없습니다. 이들은 시크릿을 안전하게 보관할 수 없는 모바일, 웹, 네이티브 애플리케이션을 위해 설계되었습니다.",
|
||||||
"pkce": "PKCE",
|
"pkce": "PKCE",
|
||||||
"public_key_code_exchange_is_a_security_feature_to_prevent_csrf_and_authorization_code_interception_attacks": "공개 키 코드 교환은 CSRF 및 승인 코드 가로채기 공격을 방지하기 위한 보안 기능입니다.",
|
"public_key_code_exchange_is_a_security_feature_to_prevent_csrf_and_authorization_code_interception_attacks": "공개 키 코드 교환은 CSRF 및 승인 코드 가로채기 공격을 방지하기 위한 보안 기능입니다.",
|
||||||
"requires_reauthentication": "재인증이 필요합니다.",
|
"requires_reauthentication": "재인증 요구",
|
||||||
"requires_users_to_authenticate_again_on_each_authorization": "사용자가 이미 로그인한 상태에서도 각 권한 부여 시마다 다시 인증을 요구합니다.",
|
"requires_users_to_authenticate_again_on_each_authorization": "사용자가 이미 로그인한 상태에서도 승인할 때마다 다시 인증을 요구합니다.",
|
||||||
"name_logo": "{name} 로고",
|
"name_logo": "{name} 로고",
|
||||||
"change_logo": "로고 변경",
|
"change_logo": "로고 변경",
|
||||||
"upload_logo": "로고 업로드",
|
"upload_logo": "로고 업로드",
|
||||||
@@ -439,6 +439,6 @@
|
|||||||
"revoke_access_successful": "{clientName}의 접근이 성공적으로 취소되었습니다.",
|
"revoke_access_successful": "{clientName}의 접근이 성공적으로 취소되었습니다.",
|
||||||
"last_signed_in_ago": "{time} 전에 로그인함",
|
"last_signed_in_ago": "{time} 전에 로그인함",
|
||||||
"invalid_client_id": "고객 ID에는 영문자, 숫자, 밑줄, 하이픈만 포함될 수 있습니다.",
|
"invalid_client_id": "고객 ID에는 영문자, 숫자, 밑줄, 하이픈만 포함될 수 있습니다.",
|
||||||
"custom_client_id_description": "응용 프로그램에서 이 정보가 필요한 경우 사용자 정의 클라이언트 ID를 설정하세요. 그렇지 않은 경우 빈 상태로 두면 무작위로 생성됩니다.",
|
"custom_client_id_description": "애플리케이션에서 사용자 정의 클라이언트 ID가 요구되는 경우 설정하세요. 그렇지 않으면 빈 상태로 두어서 무작위로 생성할 수 있습니다.",
|
||||||
"generated": "생성됨"
|
"generated": "생성됨"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pocket-id-frontend",
|
"name": "pocket-id-frontend",
|
||||||
"version": "1.8.1",
|
"version": "1.10.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"jose": "^5.10.0",
|
"jose": "^5.10.0",
|
||||||
"qrcode": "^1.5.4",
|
"qrcode": "^1.5.4",
|
||||||
|
"runed": "^0.31.1",
|
||||||
"sveltekit-superforms": "^2.27.1",
|
"sveltekit-superforms": "^2.27.1",
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
"zod": "^4.0.9"
|
"zod": "^4.0.9"
|
||||||
@@ -32,7 +33,7 @@
|
|||||||
"@internationalized/date": "^3.8.2",
|
"@internationalized/date": "^3.8.2",
|
||||||
"@lucide/svelte": "^0.525.0",
|
"@lucide/svelte": "^0.525.0",
|
||||||
"@sveltejs/adapter-static": "^3.0.8",
|
"@sveltejs/adapter-static": "^3.0.8",
|
||||||
"@sveltejs/kit": "^2.26.0",
|
"@sveltejs/kit": "^2.36.3",
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.1.0",
|
"@sveltejs/vite-plugin-svelte": "^6.1.0",
|
||||||
"@types/eslint": "^9.6.1",
|
"@types/eslint": "^9.6.1",
|
||||||
"@types/node": "^22.16.5",
|
"@types/node": "^22.16.5",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { Badge } from '$lib/components/ui/badge';
|
import { Badge } from '$lib/components/ui/badge';
|
||||||
import * as Table from '$lib/components/ui/table';
|
import * as Table from '$lib/components/ui/table';
|
||||||
import { m } from '$lib/paraglide/messages';
|
import { m } from '$lib/paraglide/messages';
|
||||||
|
import {translateAuditLogEvent} from "$lib/utils/audit-log-translator";
|
||||||
import AuditLogService from '$lib/services/audit-log-service';
|
import AuditLogService from '$lib/services/audit-log-service';
|
||||||
import type { AuditLog } from '$lib/types/audit-log.type';
|
import type { AuditLog } from '$lib/types/audit-log.type';
|
||||||
import type { Paginated, SearchPaginationSortRequest } from '$lib/types/pagination.type';
|
import type { Paginated, SearchPaginationSortRequest } from '$lib/types/pagination.type';
|
||||||
@@ -18,14 +19,6 @@
|
|||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
const auditLogService = new AuditLogService();
|
const auditLogService = new AuditLogService();
|
||||||
|
|
||||||
function toFriendlyEventString(event: string) {
|
|
||||||
const words = event.split('_');
|
|
||||||
const capitalizedWords = words.map((word) => {
|
|
||||||
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
||||||
});
|
|
||||||
return capitalizedWords.join(' ');
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<AdvancedTable
|
<AdvancedTable
|
||||||
@@ -58,7 +51,7 @@
|
|||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
{/if}
|
{/if}
|
||||||
<Table.Cell>
|
<Table.Cell>
|
||||||
<Badge class="rounded-full" variant="outline">{toFriendlyEventString(item.event)}</Badge>
|
<Badge class="rounded-full" variant="outline">{translateAuditLogEvent(item.event)}</Badge>
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
<Table.Cell
|
<Table.Cell
|
||||||
>{item.city && item.country ? `${item.city}, ${item.country}` : m.unknown()}</Table.Cell
|
>{item.city && item.country ? `${item.city}, ${item.country}` : m.unknown()}</Table.Cell
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import * as Command from '$lib/components/ui/command';
|
import * as Command from '$lib/components/ui/command';
|
||||||
import * as Popover from '$lib/components/ui/popover';
|
import * as Popover from '$lib/components/ui/popover';
|
||||||
import { cn } from '$lib/utils/style';
|
import { cn } from '$lib/utils/style';
|
||||||
|
import { m } from '$lib/paraglide/messages';
|
||||||
import { LoaderCircle, LucideCheck, LucideChevronDown } from '@lucide/svelte';
|
import { LoaderCircle, LucideCheck, LucideChevronDown } from '@lucide/svelte';
|
||||||
import type { FormEventHandler } from 'svelte/elements';
|
import type { FormEventHandler } from 'svelte/elements';
|
||||||
|
|
||||||
@@ -18,9 +19,6 @@
|
|||||||
onSelect,
|
onSelect,
|
||||||
oninput,
|
oninput,
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
placeholder = 'Select items...',
|
|
||||||
searchText = 'Search...',
|
|
||||||
noItemsText = 'No items found.',
|
|
||||||
disableInternalSearch = false,
|
disableInternalSearch = false,
|
||||||
id
|
id
|
||||||
}: {
|
}: {
|
||||||
@@ -29,9 +27,6 @@
|
|||||||
onSelect?: (value: string[]) => void;
|
onSelect?: (value: string[]) => void;
|
||||||
oninput?: FormEventHandler<HTMLInputElement>;
|
oninput?: FormEventHandler<HTMLInputElement>;
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
placeholder?: string;
|
|
||||||
searchText?: string;
|
|
||||||
noItemsText?: string;
|
|
||||||
disableInternalSearch?: boolean;
|
disableInternalSearch?: boolean;
|
||||||
id?: string;
|
id?: string;
|
||||||
} = $props();
|
} = $props();
|
||||||
@@ -93,7 +88,7 @@
|
|||||||
<Badge variant="secondary">{label}</Badge>
|
<Badge variant="secondary">{label}</Badge>
|
||||||
{/each}
|
{/each}
|
||||||
{:else}
|
{:else}
|
||||||
<span class="text-muted-foreground font-normal">{placeholder}</span>
|
<span class="text-muted-foreground font-normal">{m.select_items()}</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<LucideChevronDown class="ml-2 size-4 shrink-0 opacity-50" />
|
<LucideChevronDown class="ml-2 size-4 shrink-0 opacity-50" />
|
||||||
@@ -103,7 +98,7 @@
|
|||||||
<Popover.Content class="p-0" sameWidth>
|
<Popover.Content class="p-0" sameWidth>
|
||||||
<Command.Root shouldFilter={false}>
|
<Command.Root shouldFilter={false}>
|
||||||
<Command.Input
|
<Command.Input
|
||||||
placeholder={searchText}
|
placeholder={m.search()}
|
||||||
value={searchValue}
|
value={searchValue}
|
||||||
oninput={(e) => {
|
oninput={(e) => {
|
||||||
filterItems(e.currentTarget.value);
|
filterItems(e.currentTarget.value);
|
||||||
@@ -116,7 +111,7 @@
|
|||||||
<LoaderCircle class="size-4 animate-spin" />
|
<LoaderCircle class="size-4 animate-spin" />
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
{noItemsText}
|
{m.no_items_found()}
|
||||||
{/if}
|
{/if}
|
||||||
</Command.Empty>
|
</Command.Empty>
|
||||||
<Command.Group class="max-h-60 overflow-y-auto">
|
<Command.Group class="max-h-60 overflow-y-auto">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import WebAuthnService from '$lib/services/webauthn-service';
|
import WebAuthnService from '$lib/services/webauthn-service';
|
||||||
import userStore from '$lib/stores/user-store';
|
import userStore from '$lib/stores/user-store';
|
||||||
import { cachedProfilePicture } from '$lib/utils/cached-image-util';
|
import { cachedProfilePicture } from '$lib/utils/cached-image-util';
|
||||||
import { LayoutDashboard, LucideLogOut, LucideUser } from '@lucide/svelte';
|
import { LucideLogOut, LucideUser } from '@lucide/svelte';
|
||||||
|
|
||||||
const webauthnService = new WebAuthnService();
|
const webauthnService = new WebAuthnService();
|
||||||
|
|
||||||
@@ -34,9 +34,6 @@
|
|||||||
</DropdownMenu.Label>
|
</DropdownMenu.Label>
|
||||||
<DropdownMenu.Separator />
|
<DropdownMenu.Separator />
|
||||||
<DropdownMenu.Group>
|
<DropdownMenu.Group>
|
||||||
<DropdownMenu.Item onclick={() => goto('/settings/apps')}
|
|
||||||
><LayoutDashboard class="mr-2 size-4" /> {m.my_apps()}</DropdownMenu.Item
|
|
||||||
>
|
|
||||||
<DropdownMenu.Item onclick={() => goto('/settings/account')}
|
<DropdownMenu.Item onclick={() => goto('/settings/account')}
|
||||||
><LucideUser class="mr-2 size-4" /> {m.my_account()}</DropdownMenu.Item
|
><LucideUser class="mr-2 size-4" /> {m.my_account()}</DropdownMenu.Item
|
||||||
>
|
>
|
||||||
|
|||||||
157
frontend/src/lib/components/sidebar.svelte
Normal file
157
frontend/src/lib/components/sidebar.svelte
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { page } from '$app/state';
|
||||||
|
import { m } from '$lib/paraglide/messages';
|
||||||
|
import appConfigStore from '$lib/stores/application-configuration-store';
|
||||||
|
import { cn } from '$lib/utils/style';
|
||||||
|
import { LucideChevronDown, LucideExternalLink } from '@lucide/svelte';
|
||||||
|
import { PersistedState } from 'runed';
|
||||||
|
import { slide } from 'svelte/transition';
|
||||||
|
|
||||||
|
type NavItem = {
|
||||||
|
href?: string;
|
||||||
|
label: string;
|
||||||
|
children?: NavItem[];
|
||||||
|
};
|
||||||
|
|
||||||
|
let {
|
||||||
|
items = [] as NavItem[],
|
||||||
|
storageKey = 'sidebar-open:settings',
|
||||||
|
isAdmin = false,
|
||||||
|
isUpToDate = undefined
|
||||||
|
} = $props();
|
||||||
|
|
||||||
|
const openState = new PersistedState<Record<string, boolean>>(storageKey, {});
|
||||||
|
|
||||||
|
function groupId(item: NavItem, idx: number) {
|
||||||
|
return `${item.label}-${idx}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isActive(href?: string) {
|
||||||
|
if (!href) return false;
|
||||||
|
return page.url.pathname.startsWith(href);
|
||||||
|
}
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
const state = openState.current;
|
||||||
|
items.forEach((item, idx) => {
|
||||||
|
if (!item.children?.length) return;
|
||||||
|
const id = groupId(item, idx);
|
||||||
|
if (state[id] === undefined) {
|
||||||
|
state[id] = item.children.some((c) => isActive(c.href));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function isOpen(id: string) {
|
||||||
|
return !!openState.current[id];
|
||||||
|
}
|
||||||
|
function toggle(id: string) {
|
||||||
|
openState.current[id] = !openState.current[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
const activeClasses =
|
||||||
|
'text-primary bg-card rounded-md px-3 py-1.5 font-medium shadow-sm transition-all';
|
||||||
|
const inactiveClasses =
|
||||||
|
'hover:text-foreground hover:bg-muted/70 rounded-md px-3 py-1.5 transition-all hover:-translate-y-[2px] hover:shadow-sm';
|
||||||
|
|
||||||
|
const ROW_STAGGER = 50;
|
||||||
|
|
||||||
|
// Derive the offset (row index) for each top-level item,
|
||||||
|
// counting expanded children of previous items.
|
||||||
|
const layout = $derived(() => {
|
||||||
|
const offsets: number[] = [];
|
||||||
|
let total = 0;
|
||||||
|
items.forEach((it, idx) => {
|
||||||
|
offsets[idx] = total; // row index for this top-level item
|
||||||
|
total += 1; // this item itself
|
||||||
|
const id = groupId(it, idx);
|
||||||
|
if (it.children?.length && openState.current[id]) {
|
||||||
|
total += it.children.length; // rows for visible children
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return { offsets, total };
|
||||||
|
});
|
||||||
|
|
||||||
|
const delayTop = (i: number) => `${layout().offsets[i] * ROW_STAGGER}ms`;
|
||||||
|
const delayChild = (i: number, j: number) => `${(layout().offsets[i] + 1 + j) * ROW_STAGGER}ms`;
|
||||||
|
const delayUpdateLink = () => `${layout().total * ROW_STAGGER}ms`;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<nav class="text-muted-foreground grid gap-2 text-sm">
|
||||||
|
{#each items as item, i}
|
||||||
|
{#if item.children?.length}
|
||||||
|
{@const id = groupId(item, i)}
|
||||||
|
<div class="group">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class={cn(
|
||||||
|
'hover:bg-muted/70 hover:text-foreground flex w-full items-center justify-between rounded-md px-3 py-1.5 text-left transition-all',
|
||||||
|
!$appConfigStore.disableAnimations && 'animate-fade-in'
|
||||||
|
)}
|
||||||
|
style={`animation-delay: ${delayTop(i)};`}
|
||||||
|
aria-expanded={isOpen(id)}
|
||||||
|
aria-controls={`submenu-${id}`}
|
||||||
|
onclick={() => toggle(id)}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
|
||||||
|
<LucideChevronDown
|
||||||
|
class={cn('size-4 transition-transform', isOpen(id) ? 'rotate-180' : '')}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{#if isOpen(id)}
|
||||||
|
<ul
|
||||||
|
id={`submenu-${id}`}
|
||||||
|
class="border-border/50 ml-2 border-l pl-2"
|
||||||
|
transition:slide|local={{ duration: 120 }}
|
||||||
|
>
|
||||||
|
{#each item.children as child, j}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href={child.href}
|
||||||
|
class={cn(
|
||||||
|
isActive(child.href) ? activeClasses : inactiveClasses,
|
||||||
|
'my-1 block',
|
||||||
|
!$appConfigStore.disableAnimations && 'animate-fade-in'
|
||||||
|
)}
|
||||||
|
style={`animation-delay: ${delayChild(i, j)};`}
|
||||||
|
>
|
||||||
|
{child.label}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<a
|
||||||
|
href={item.href}
|
||||||
|
class={cn(
|
||||||
|
isActive(item.href) ? activeClasses : inactiveClasses,
|
||||||
|
!$appConfigStore.disableAnimations && 'animate-fade-in'
|
||||||
|
)}
|
||||||
|
style={`animation-delay: ${delayTop(i)};`}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
{#if isAdmin && isUpToDate === false}
|
||||||
|
<a
|
||||||
|
href="https://github.com/pocket-id/pocket-id/releases/latest"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class={cn(
|
||||||
|
inactiveClasses,
|
||||||
|
'flex items-center gap-2 text-orange-500 hover:text-orange-500/90',
|
||||||
|
!$appConfigStore.disableAnimations && 'animate-fade-in'
|
||||||
|
)}
|
||||||
|
style={`animation-delay: ${delayUpdateLink()};`}
|
||||||
|
>
|
||||||
|
{m.update_pocket_id()}
|
||||||
|
<LucideExternalLink class="my-auto inline-block size-3" />
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
</nav>
|
||||||
29
frontend/src/lib/utils/audit-log-translator.ts
Normal file
29
frontend/src/lib/utils/audit-log-translator.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { m } from '$lib/paraglide/messages';
|
||||||
|
|
||||||
|
export const eventTypes: Record<string, string> = {
|
||||||
|
SIGN_IN: m.sign_in(),
|
||||||
|
TOKEN_SIGN_IN: m.token_sign_in(),
|
||||||
|
CLIENT_AUTHORIZATION: m.client_authorization(),
|
||||||
|
NEW_CLIENT_AUTHORIZATION: m.new_client_authorization(),
|
||||||
|
ACCOUNT_CREATED: m.account_created()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates an audit log event type using paraglide messages.
|
||||||
|
* Falls back to a formatted string if no specific translation is found.
|
||||||
|
* @param event The event type string from the backend (e.g., "CLIENT_AUTHORIZATION").
|
||||||
|
* @returns The translated string.
|
||||||
|
*/
|
||||||
|
export function translateAuditLogEvent(event: string): string {
|
||||||
|
if (event in eventTypes) {
|
||||||
|
return eventTypes[event];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no specific translation is found, provide a readable fallback.
|
||||||
|
// This converts "SOME_EVENT" to "Some Event".
|
||||||
|
const words = event.split('_');
|
||||||
|
const capitalizedWords = words.map((word) => {
|
||||||
|
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
||||||
|
});
|
||||||
|
return capitalizedWords.join(' ');
|
||||||
|
}
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/state';
|
|
||||||
import FadeWrapper from '$lib/components/fade-wrapper.svelte';
|
import FadeWrapper from '$lib/components/fade-wrapper.svelte';
|
||||||
import { m } from '$lib/paraglide/messages';
|
import { m } from '$lib/paraglide/messages';
|
||||||
import appConfigStore from '$lib/stores/application-configuration-store';
|
|
||||||
import userStore from '$lib/stores/user-store';
|
import userStore from '$lib/stores/user-store';
|
||||||
import { cn } from '$lib/utils/style';
|
import Sidebar from '$lib/components/sidebar.svelte';
|
||||||
import { LucideExternalLink, LucideSettings } from '@lucide/svelte';
|
import { LucideSettings } from '@lucide/svelte';
|
||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
import { fade, fly } from 'svelte/transition';
|
import { fade, fly } from 'svelte/transition';
|
||||||
import type { LayoutData } from './$types';
|
import type { LayoutData } from './$types';
|
||||||
@@ -20,14 +18,19 @@
|
|||||||
|
|
||||||
const { versionInformation, user } = data;
|
const { versionInformation, user } = data;
|
||||||
|
|
||||||
const links = [
|
type NavItem = {
|
||||||
|
href?: string;
|
||||||
|
label: string;
|
||||||
|
children?: NavItem[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const items: NavItem[] = [
|
||||||
{ href: '/settings/account', label: m.my_account() },
|
{ href: '/settings/account', label: m.my_account() },
|
||||||
|
{ href: '/settings/apps', label: m.my_apps() },
|
||||||
{ href: '/settings/audit-log', label: m.audit_log() }
|
{ href: '/settings/audit-log', label: m.audit_log() }
|
||||||
];
|
];
|
||||||
|
|
||||||
const nonAdminLinks = [{ href: '/settings/apps', label: m.my_apps() }];
|
const adminChildren: NavItem[] = [
|
||||||
|
|
||||||
const adminLinks = [
|
|
||||||
{ href: '/settings/admin/users', label: m.users() },
|
{ href: '/settings/admin/users', label: m.users() },
|
||||||
{ href: '/settings/admin/user-groups', label: m.user_groups() },
|
{ href: '/settings/admin/user-groups', label: m.user_groups() },
|
||||||
{ href: '/settings/admin/oidc-clients', label: m.oidc_clients() },
|
{ href: '/settings/admin/oidc-clients', label: m.oidc_clients() },
|
||||||
@@ -36,9 +39,7 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (user?.isAdmin || $userStore?.isAdmin) {
|
if (user?.isAdmin || $userStore?.isAdmin) {
|
||||||
links.push(...adminLinks);
|
items.push({ label: m.administration(), children: adminChildren });
|
||||||
} else {
|
|
||||||
links.push(...nonAdminLinks);
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -58,35 +59,16 @@
|
|||||||
{m.settings()}
|
{m.settings()}
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<nav class="text-muted-foreground grid gap-2 text-sm">
|
|
||||||
{#each links as { href, label }, i}
|
<Sidebar
|
||||||
<a
|
{items}
|
||||||
{href}
|
storageKey="sidebar-open:settings"
|
||||||
class={cn(
|
isAdmin={$userStore?.isAdmin || user?.isAdmin}
|
||||||
!$appConfigStore.disableAnimations && 'animate-fade-in',
|
isUpToDate={versionInformation?.isUpToDate}
|
||||||
page.url.pathname.startsWith(href)
|
/>
|
||||||
? 'text-primary bg-card rounded-md px-3 py-1.5 font-medium shadow-sm transition-all'
|
|
||||||
: 'hover:text-foreground hover:bg-muted/70 rounded-md px-3 py-1.5 transition-all hover:-translate-y-[2px] hover:shadow-sm'
|
|
||||||
)}
|
|
||||||
style={`animation-delay: ${150 + i * 50}ms;`}
|
|
||||||
>
|
|
||||||
{label}
|
|
||||||
</a>
|
|
||||||
{/each}
|
|
||||||
{#if $userStore?.isAdmin && versionInformation.isUpToDate === false}
|
|
||||||
<a
|
|
||||||
href="https://github.com/pocket-id/pocket-id/releases/latest"
|
|
||||||
target="_blank"
|
|
||||||
class="animate-fade-in hover:text-foreground hover:bg-muted/70 mt-1 flex items-center gap-2 rounded-md px-3 py-1.5 text-orange-500 transition-all hover:-translate-y-[2px] hover:shadow-sm"
|
|
||||||
style={`animation-delay: ${150 + links.length * 75}ms;`}
|
|
||||||
>
|
|
||||||
{m.update_pocket_id()}
|
|
||||||
<LucideExternalLink class="my-auto inline-block size-3" />
|
|
||||||
</a>
|
|
||||||
{/if}
|
|
||||||
</nav>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex w-full flex-col gap-4 overflow-hidden">
|
<div class="flex w-full flex-col gap-4 overflow-hidden">
|
||||||
<FadeWrapper>
|
<FadeWrapper>
|
||||||
{@render children()}
|
{@render children()}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
let signupTokens = $state(data.signupTokens);
|
let signupTokens = $state(data.signupTokens);
|
||||||
let signupTokensRequestOptions = $state(data.signupTokensRequestOptions);
|
let signupTokensRequestOptions = $state(data.signupTokensRequestOptions);
|
||||||
|
|
||||||
let selectedCreateOptions = $state('Add User');
|
let selectedCreateOptions = $state(m.add_user());
|
||||||
let expandAddUser = $state(false);
|
let expandAddUser = $state(false);
|
||||||
let signupTokenModalOpen = $state(false);
|
let signupTokenModalOpen = $state(false);
|
||||||
let signupTokenListModalOpen = $state(false);
|
let signupTokenListModalOpen = $state(false);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import AuditLogService from '$lib/services/audit-log-service';
|
import AuditLogService from '$lib/services/audit-log-service';
|
||||||
import type { AuditLogFilter } from '$lib/types/audit-log.type';
|
import type { AuditLogFilter } from '$lib/types/audit-log.type';
|
||||||
import AuditLogSwitcher from '../audit-log-switcher.svelte';
|
import AuditLogSwitcher from '../audit-log-switcher.svelte';
|
||||||
|
import {eventTypes as eventTranslations} from "$lib/utils/audit-log-translator";
|
||||||
|
|
||||||
let { data } = $props();
|
let { data } = $props();
|
||||||
|
|
||||||
@@ -27,13 +28,7 @@
|
|||||||
internal: 'Internal Networks'
|
internal: 'Internal Networks'
|
||||||
});
|
});
|
||||||
|
|
||||||
const eventTypes = $state({
|
const eventTypes = $state(eventTranslations);
|
||||||
SIGN_IN: m.sign_in(),
|
|
||||||
TOKEN_SIGN_IN: m.token_sign_in(),
|
|
||||||
CLIENT_AUTHORIZATION: m.client_authorization(),
|
|
||||||
NEW_CLIENT_AUTHORIZATION: m.new_client_authorization(),
|
|
||||||
ACCOUNT_CREATED: m.account_created()
|
|
||||||
});
|
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
auditLogService.listAllLogs(requestOptions, filters).then((response) => (auditLogs = response));
|
auditLogService.listAllLogs(requestOptions, filters).then((response) => (auditLogs = response));
|
||||||
|
|||||||
62
pnpm-lock.yaml
generated
62
pnpm-lock.yaml
generated
@@ -4,6 +4,9 @@ settings:
|
|||||||
autoInstallPeers: true
|
autoInstallPeers: true
|
||||||
excludeLinksFromLockfile: false
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
devalue: ^5.3.2
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
.: {}
|
.: {}
|
||||||
@@ -31,9 +34,12 @@ importers:
|
|||||||
qrcode:
|
qrcode:
|
||||||
specifier: ^1.5.4
|
specifier: ^1.5.4
|
||||||
version: 1.5.4
|
version: 1.5.4
|
||||||
|
runed:
|
||||||
|
specifier: ^0.31.1
|
||||||
|
version: 0.31.1(svelte@5.36.17)
|
||||||
sveltekit-superforms:
|
sveltekit-superforms:
|
||||||
specifier: ^2.27.1
|
specifier: ^2.27.1
|
||||||
version: 2.27.1(@sveltejs/kit@2.26.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(@types/json-schema@7.0.15)(esbuild@0.25.8)(svelte@5.36.17)(typescript@5.8.3)
|
version: 2.27.1(@sveltejs/kit@2.36.3(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(@types/json-schema@7.0.15)(esbuild@0.25.8)(svelte@5.36.17)(typescript@5.8.3)
|
||||||
tailwind-merge:
|
tailwind-merge:
|
||||||
specifier: ^3.3.1
|
specifier: ^3.3.1
|
||||||
version: 3.3.1
|
version: 3.3.1
|
||||||
@@ -58,10 +64,10 @@ importers:
|
|||||||
version: 0.525.0(svelte@5.36.17)
|
version: 0.525.0(svelte@5.36.17)
|
||||||
'@sveltejs/adapter-static':
|
'@sveltejs/adapter-static':
|
||||||
specifier: ^3.0.8
|
specifier: ^3.0.8
|
||||||
version: 3.0.8(@sveltejs/kit@2.26.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))
|
version: 3.0.8(@sveltejs/kit@2.36.3(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))
|
||||||
'@sveltejs/kit':
|
'@sveltejs/kit':
|
||||||
specifier: ^2.26.0
|
specifier: ^2.36.3
|
||||||
version: 2.26.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))
|
version: 2.36.3(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))
|
||||||
'@sveltejs/vite-plugin-svelte':
|
'@sveltejs/vite-plugin-svelte':
|
||||||
specifier: ^6.1.0
|
specifier: ^6.1.0
|
||||||
version: 6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))
|
version: 6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))
|
||||||
@@ -88,7 +94,7 @@ importers:
|
|||||||
version: 3.11.0(eslint@9.32.0(jiti@2.5.1))(svelte@5.36.17)
|
version: 3.11.0(eslint@9.32.0(jiti@2.5.1))(svelte@5.36.17)
|
||||||
formsnap:
|
formsnap:
|
||||||
specifier: ^2.0.1
|
specifier: ^2.0.1
|
||||||
version: 2.0.1(svelte@5.36.17)(sveltekit-superforms@2.27.1(@sveltejs/kit@2.26.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(@types/json-schema@7.0.15)(esbuild@0.25.8)(svelte@5.36.17)(typescript@5.8.3))
|
version: 2.0.1(svelte@5.36.17)(sveltekit-superforms@2.27.1(@sveltejs/kit@2.36.3(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(@types/json-schema@7.0.15)(esbuild@0.25.8)(svelte@5.36.17)(typescript@5.8.3))
|
||||||
globals:
|
globals:
|
||||||
specifier: ^16.3.0
|
specifier: ^16.3.0
|
||||||
version: 16.3.0
|
version: 16.3.0
|
||||||
@@ -615,14 +621,18 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@sveltejs/kit': ^2.0.0
|
'@sveltejs/kit': ^2.0.0
|
||||||
|
|
||||||
'@sveltejs/kit@2.26.1':
|
'@sveltejs/kit@2.36.3':
|
||||||
resolution: {integrity: sha512-FwDhHAoXYUGnYndrrEzEYcKdYWpSoRKq4kli29oMe83hLri4/DOGQk3xUgwjDo0LKpSmj5M/Sj29/Ug3wO0Cbg==}
|
resolution: {integrity: sha512-MVzwZz1GFznEQbL3f0i2v9AIc3lZH01izQj6XfIrthmZAwOzyXJCgXbLRss8vk//HfYsE4w6Tz+ukbf3rScPNQ==}
|
||||||
engines: {node: '>=18.13'}
|
engines: {node: '>=18.13'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
'@opentelemetry/api': ^1.0.0
|
||||||
'@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0
|
'@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0
|
||||||
svelte: ^4.0.0 || ^5.0.0-next.0
|
svelte: ^4.0.0 || ^5.0.0-next.0
|
||||||
vite: ^5.0.3 || ^6.0.0 || ^7.0.0-beta.0
|
vite: ^5.0.3 || ^6.0.0 || ^7.0.0-beta.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@opentelemetry/api':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@sveltejs/vite-plugin-svelte-inspector@5.0.0':
|
'@sveltejs/vite-plugin-svelte-inspector@5.0.0':
|
||||||
resolution: {integrity: sha512-iwQ8Z4ET6ZFSt/gC+tVfcsSBHwsqc6RumSaiLUkAurW3BCpJam65cmHw0oOlDMTO0u+PZi9hilBRYN+LZNHTUQ==}
|
resolution: {integrity: sha512-iwQ8Z4ET6ZFSt/gC+tVfcsSBHwsqc6RumSaiLUkAurW3BCpJam65cmHw0oOlDMTO0u+PZi9hilBRYN+LZNHTUQ==}
|
||||||
@@ -1025,8 +1035,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
|
resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
devalue@5.1.1:
|
devalue@5.3.2:
|
||||||
resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==}
|
resolution: {integrity: sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw==}
|
||||||
|
|
||||||
dijkstrajs@1.0.3:
|
dijkstrajs@1.0.3:
|
||||||
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
|
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
|
||||||
@@ -1800,6 +1810,11 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
svelte: ^5.7.0
|
svelte: ^5.7.0
|
||||||
|
|
||||||
|
runed@0.31.1:
|
||||||
|
resolution: {integrity: sha512-v3czcTnO+EJjiPvD4dwIqfTdHLZ8oH0zJheKqAHh9QMViY7Qb29UlAMRpX7ZtHh7AFqV60KmfxaJ9QMy+L1igQ==}
|
||||||
|
peerDependencies:
|
||||||
|
svelte: ^5.7.0
|
||||||
|
|
||||||
sade@1.8.1:
|
sade@1.8.1:
|
||||||
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
|
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -2512,25 +2527,25 @@ snapshots:
|
|||||||
|
|
||||||
'@sqlite.org/sqlite-wasm@3.48.0-build4': {}
|
'@sqlite.org/sqlite-wasm@3.48.0-build4': {}
|
||||||
|
|
||||||
'@standard-schema/spec@1.0.0':
|
'@standard-schema/spec@1.0.0': {}
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@sveltejs/acorn-typescript@1.0.5(acorn@8.15.0)':
|
'@sveltejs/acorn-typescript@1.0.5(acorn@8.15.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.15.0
|
acorn: 8.15.0
|
||||||
|
|
||||||
'@sveltejs/adapter-static@3.0.8(@sveltejs/kit@2.26.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))':
|
'@sveltejs/adapter-static@3.0.8(@sveltejs/kit@2.36.3(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sveltejs/kit': 2.26.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))
|
'@sveltejs/kit': 2.36.3(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))
|
||||||
|
|
||||||
'@sveltejs/kit@2.26.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))':
|
'@sveltejs/kit@2.36.3(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@standard-schema/spec': 1.0.0
|
||||||
'@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0)
|
'@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0)
|
||||||
'@sveltejs/vite-plugin-svelte': 6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))
|
'@sveltejs/vite-plugin-svelte': 6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))
|
||||||
'@types/cookie': 0.6.0
|
'@types/cookie': 0.6.0
|
||||||
acorn: 8.15.0
|
acorn: 8.15.0
|
||||||
cookie: 0.6.0
|
cookie: 0.6.0
|
||||||
devalue: 5.1.1
|
devalue: 5.3.2
|
||||||
esm-env: 1.2.2
|
esm-env: 1.2.2
|
||||||
kleur: 4.1.5
|
kleur: 4.1.5
|
||||||
magic-string: 0.30.17
|
magic-string: 0.30.17
|
||||||
@@ -2949,7 +2964,7 @@ snapshots:
|
|||||||
|
|
||||||
detect-libc@2.0.4: {}
|
detect-libc@2.0.4: {}
|
||||||
|
|
||||||
devalue@5.1.1: {}
|
devalue@5.3.2: {}
|
||||||
|
|
||||||
dijkstrajs@1.0.3: {}
|
dijkstrajs@1.0.3: {}
|
||||||
|
|
||||||
@@ -3193,11 +3208,11 @@ snapshots:
|
|||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
|
|
||||||
formsnap@2.0.1(svelte@5.36.17)(sveltekit-superforms@2.27.1(@sveltejs/kit@2.26.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(@types/json-schema@7.0.15)(esbuild@0.25.8)(svelte@5.36.17)(typescript@5.8.3)):
|
formsnap@2.0.1(svelte@5.36.17)(sveltekit-superforms@2.27.1(@sveltejs/kit@2.36.3(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(@types/json-schema@7.0.15)(esbuild@0.25.8)(svelte@5.36.17)(typescript@5.8.3)):
|
||||||
dependencies:
|
dependencies:
|
||||||
svelte: 5.36.17
|
svelte: 5.36.17
|
||||||
svelte-toolbelt: 0.5.0(svelte@5.36.17)
|
svelte-toolbelt: 0.5.0(svelte@5.36.17)
|
||||||
sveltekit-superforms: 2.27.1(@sveltejs/kit@2.26.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(@types/json-schema@7.0.15)(esbuild@0.25.8)(svelte@5.36.17)(typescript@5.8.3)
|
sveltekit-superforms: 2.27.1(@sveltejs/kit@2.36.3(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(@types/json-schema@7.0.15)(esbuild@0.25.8)(svelte@5.36.17)(typescript@5.8.3)
|
||||||
|
|
||||||
fsevents@2.3.2:
|
fsevents@2.3.2:
|
||||||
optional: true
|
optional: true
|
||||||
@@ -3630,6 +3645,11 @@ snapshots:
|
|||||||
esm-env: 1.2.2
|
esm-env: 1.2.2
|
||||||
svelte: 5.36.17
|
svelte: 5.36.17
|
||||||
|
|
||||||
|
runed@0.31.1(svelte@5.36.17):
|
||||||
|
dependencies:
|
||||||
|
esm-env: 1.2.2
|
||||||
|
svelte: 5.36.17
|
||||||
|
|
||||||
sade@1.8.1:
|
sade@1.8.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
mri: 1.2.0
|
mri: 1.2.0
|
||||||
@@ -3756,10 +3776,10 @@ snapshots:
|
|||||||
magic-string: 0.30.17
|
magic-string: 0.30.17
|
||||||
zimmerframe: 1.1.2
|
zimmerframe: 1.1.2
|
||||||
|
|
||||||
sveltekit-superforms@2.27.1(@sveltejs/kit@2.26.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(@types/json-schema@7.0.15)(esbuild@0.25.8)(svelte@5.36.17)(typescript@5.8.3):
|
sveltekit-superforms@2.27.1(@sveltejs/kit@2.36.3(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(@types/json-schema@7.0.15)(esbuild@0.25.8)(svelte@5.36.17)(typescript@5.8.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sveltejs/kit': 2.26.1(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))
|
'@sveltejs/kit': 2.36.3(@sveltejs/vite-plugin-svelte@6.1.0(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1)))(svelte@5.36.17)(vite@7.0.6(@types/node@22.16.5)(jiti@2.5.1)(lightningcss@1.30.1))
|
||||||
devalue: 5.1.1
|
devalue: 5.3.2
|
||||||
memoize-weak: 1.0.2
|
memoize-weak: 1.0.2
|
||||||
svelte: 5.36.17
|
svelte: 5.36.17
|
||||||
ts-deepmerge: 7.0.3
|
ts-deepmerge: 7.0.3
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
packages:
|
packages:
|
||||||
- 'frontend'
|
- 'frontend'
|
||||||
- 'tests'
|
- 'tests'
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
'devalue': '^5.3.2'
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export const oidcClients = {
|
|||||||
id: '7c21a609-96b5-4011-9900-272b8d31a9d1',
|
id: '7c21a609-96b5-4011-9900-272b8d31a9d1',
|
||||||
name: 'Tailscale',
|
name: 'Tailscale',
|
||||||
callbackUrl: 'http://tailscale/auth/callback',
|
callbackUrl: 'http://tailscale/auth/callback',
|
||||||
secret: 'n4VfQeXlTzA6yKpWbR9uJcMdSx2qH0Lo',
|
secret: 'n4VfQeXlTzA6yKpWbR9uJcMdSx2qH0Lo'
|
||||||
},
|
},
|
||||||
federated: {
|
federated: {
|
||||||
id: 'c48232ff-ff65-45ed-ae96-7afa8a9b443b',
|
id: 'c48232ff-ff65-45ed-ae96-7afa8a9b443b',
|
||||||
@@ -116,7 +116,7 @@ export const signupTokens = {
|
|||||||
createdAt: new Date().toISOString()
|
createdAt: new Date().toISOString()
|
||||||
},
|
},
|
||||||
partiallyUsed: {
|
partiallyUsed: {
|
||||||
id: 'b2c3d4e5-f6g7-8901-bcde-f12345678901',
|
id: 'dc3c9c96-714e-48eb-926e-2d7c7858e6cf',
|
||||||
token: 'PARTIAL567890ABC',
|
token: 'PARTIAL567890ABC',
|
||||||
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
||||||
usageLimit: 5,
|
usageLimit: 5,
|
||||||
@@ -124,7 +124,7 @@ export const signupTokens = {
|
|||||||
createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString()
|
createdAt: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000).toISOString()
|
||||||
},
|
},
|
||||||
expired: {
|
expired: {
|
||||||
id: 'c3d4e5f6-g7h8-9012-cdef-123456789012',
|
id: '44de1863-ffa5-4db1-9507-4887cd7a1e3f',
|
||||||
token: 'EXPIRED34567890B',
|
token: 'EXPIRED34567890B',
|
||||||
expiresAt: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),
|
expiresAt: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),
|
||||||
usageLimit: 3,
|
usageLimit: 3,
|
||||||
@@ -132,7 +132,7 @@ export const signupTokens = {
|
|||||||
createdAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString()
|
createdAt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000).toISOString()
|
||||||
},
|
},
|
||||||
fullyUsed: {
|
fullyUsed: {
|
||||||
id: 'd4e5f6g7-h8i9-0123-def0-234567890123',
|
id: 'f1b1678b-7720-4d8b-8f91-1dbff1e2d02b',
|
||||||
token: 'FULLYUSED567890C',
|
token: 'FULLYUSED567890C',
|
||||||
expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
||||||
usageLimit: 1,
|
usageLimit: 1,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user