Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
de10ecb
feat(ldap): add enterprise ldap auth, sync, and admin settings
big-dimple Feb 13, 2026
44f2882
feat: improve LDAP onboarding UX and enterprise ops guide
big-dimple Feb 14, 2026
adf1fe7
docs: add LDAP handover checklist for WSL continuation
big-dimple Feb 14, 2026
195a222
docs: consolidate IT handoff into enterprise LDAP README
big-dimple Feb 14, 2026
47c0a38
docs: restore WSL validation handover for LDAP rollout
big-dimple Feb 14, 2026
ca6a35c
fix: handle ldap conn close errors
Feb 14, 2026
85cb2ba
docs: remove internal AI handover docs for upstream PR
Feb 24, 2026
52d7d52
chore: fix LDAP auth service logging and update API contract tests af…
Feb 25, 2026
3cb006f
feat(ldap): add test connection and sync now buttons with backend han…
Feb 25, 2026
a458c96
chore: restore huawei cloud mirrors for apk and npm
Feb 25, 2026
b2d668b
feat(deploy): add production upgrade script with backup
Feb 25, 2026
d6f5b67
fix(deploy): use correct postgres user in upgrade script
Feb 25, 2026
658d89a
fix(test): update setting handler constructor signature in contract t…
Feb 25, 2026
3dcdca8
docs: add enterprise deployment and ops guide
Feb 25, 2026
70ed2c9
chore(ldap): refine elastic sync workflow, tests, and documentation
Mar 1, 2026
262e11d
chore(ldap): resolve merge conflicts and integrate upstream changes
Mar 4, 2026
2b3c2a0
fix(ldap): harden sync workflow and clean release branch artifacts
Mar 4, 2026
3d15719
feat(skill): auto-backfill support branch after release sync
Mar 4, 2026
ce1ee0a
fix(deploy): harden docker healthcheck, permissions, and ldap ops run…
Mar 4, 2026
f0205d0
feat(skill): add deploy sanity gate for ldap sync workflow
Mar 4, 2026
4a7f6af
Merge LDAP patch (feature/ldap-support) into release
Mar 4, 2026
929a6c4
fix(build): add missing wire generator module checksums
Mar 4, 2026
85aef7e
chore(skill): make overlay apply idempotent
Mar 4, 2026
7588170
fix(deploy): harden ldap upgrade script with mandatory backup and res…
Mar 4, 2026
897b25d
Merge LDAP patch (feature/ldap-support) into release
Mar 6, 2026
f3878dd
fix(ldap): stabilize sync workflow and release versioning
Mar 6, 2026
0f4f413
Merge LDAP patch (feature/ldap-support) into release
Mar 9, 2026
790058c
fix(skill): define overlay script dir
Mar 9, 2026
02708c0
fix(version): derive build version beyond tags
Mar 9, 2026
6790259
fix(skill): fetch upstream tags for version sync
Mar 9, 2026
ed04843
Merge LDAP patch (feature/ldap-support) into release
Mar 10, 2026
d4fce99
chore(ldap): sync upstream 0.1.95
Mar 10, 2026
b7c7aea
Merge LDAP patch (feature/ldap-support) into release
Mar 16, 2026
20730a1
chore(ldap): regenerate build artifacts
Mar 16, 2026
efeff96
chore(skill): auto-resolve known LDAP merge conflicts
Mar 16, 2026
459ab5c
fix(deploy): handle force-pushed release branch on upgrade
Mar 16, 2026
4b3c91d
feat(ldap): sync upstream release and repair flows
Mar 29, 2026
465e9a7
chore(skill): gate frontend vitest in ldap sync
Mar 29, 2026
3187232
fix(deploy): raise frontend build heap limit
Mar 29, 2026
f0e29a5
Merge LDAP patch (feature/ldap-support) into release
Apr 1, 2026
d7c7f76
chore(ldap): regenerate sync artifacts
Apr 1, 2026
8a9ca11
chore(skill): harden ldap sync workflow
Apr 1, 2026
a4cb534
fix(gemini): disable platform-side rate limiting
Mar 10, 2026
003d71f
chore(main): publish ldap workflow on main
Apr 1, 2026
40ba6ee
fix(deploy): upgrade from remote snapshot when worktree is dirty
Apr 1, 2026
2355c84
fix(deploy): force-fetch rewritten remote branches
Apr 1, 2026
40e1404
fix(deploy): unify ldap upgrades and disable in-app updater
Apr 1, 2026
8a82f7d
fix(docs): keep ldap ops single-entry
Apr 1, 2026
2d14356
docs(deploy): clarify web updater behavior
Apr 1, 2026
3c49985
Merge LDAP patch (feature/ldap-support) into release
Apr 9, 2026
090038a
chore(ldap): regenerate sync artifacts
Apr 9, 2026
bc41f78
chore(skill): optimize sub2api-sync-ldap structure
Apr 9, 2026
91a85bf
Merge LDAP patch (feature/ldap-support) into release
Apr 15, 2026
091fc51
fix(frontend): harden usage fallback refresh
Apr 15, 2026
53b002f
chore(skill): publish ldap sync by default
Apr 15, 2026
89b98d5
chore(skill): add conflict resume helper
Apr 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ temp/
.cache/
.dev/
.serena/
.pnpm-store/
backups/

# ===================
# 构建产物
Expand Down Expand Up @@ -135,3 +137,9 @@ frontend/coverage/
aicodex
output/

# keep codex LDAP sync skill scripts in repo
!skills/
!skills/sub2api-sync-ldap/
!skills/sub2api-sync-ldap/SKILL.md
!skills/sub2api-sync-ldap/scripts/
!skills/sub2api-sync-ldap/scripts/*.sh
18 changes: 13 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ FROM ${NODE_IMAGE} AS frontend-builder

WORKDIR /app/frontend

# Set NPM mirror
RUN npm config set registry https://repo.huaweicloud.com/repository/npm/

# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate

Expand All @@ -29,7 +32,7 @@ RUN pnpm install --frozen-lockfile

# Copy frontend source and build
COPY frontend/ ./
RUN pnpm run build
RUN NODE_OPTIONS=--max-old-space-size=2048 pnpm run build

# -----------------------------------------------------------------------------
# Stage 2: Backend Builder
Expand All @@ -40,12 +43,15 @@ FROM ${GOLANG_IMAGE} AS backend-builder
ARG VERSION=
ARG COMMIT=docker
ARG DATE
ARG GOPROXY
ARG GOSUMDB
ARG GOPROXY=https://goproxy.cn,direct
ARG GOSUMDB=sum.golang.google.cn

ENV GOPROXY=${GOPROXY}
ENV GOSUMDB=${GOSUMDB}

# Set APK mirror
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.huaweicloud.com/g' /etc/apk/repositories

# Install build dependencies
RUN apk add --no-cache git ca-certificates tzdata

Expand All @@ -66,8 +72,7 @@ COPY --from=frontend-builder /app/backend/internal/web/dist ./internal/web/dist
RUN VERSION_VALUE="${VERSION}" && \
if [ -z "${VERSION_VALUE}" ]; then VERSION_VALUE="$(tr -d '\r\n' < ./cmd/server/VERSION)"; fi && \
DATE_VALUE="${DATE:-$(date -u +%Y-%m-%dT%H:%M:%SZ)}" && \
CGO_ENABLED=0 GOOS=linux go build \
-tags embed \
CGO_ENABLED=0 GOOS=linux go build -tags "embed ldap" \
-ldflags="-s -w -X main.Version=${VERSION_VALUE} -X main.Commit=${COMMIT} -X main.Date=${DATE_VALUE} -X main.BuildType=release" \
-trimpath \
-o /app/sub2api \
Expand All @@ -83,6 +88,9 @@ FROM ${POSTGRES_IMAGE} AS pg-client
# -----------------------------------------------------------------------------
FROM ${ALPINE_IMAGE}

# Set APK mirror
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.huaweicloud.com/g' /etc/apk/repositories

# Labels
LABEL maintainer="Wei-Shaw <github.com/Wei-Shaw>"
LABEL description="Sub2API - AI API Gateway Platform"
Expand Down
202 changes: 202 additions & 0 deletions LDAP_REVIEW_CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# LDAP Review Context (2026-03-01)

## Inputs Read
- `deploy/README_LDAP_ENTERPRISE.md`
- `DEV_GUIDE.md`
- `backend/internal/service/auth_service.go`
- `backend/internal/service/auth_service_ldap.go`
- `backend/internal/service/wire.go`
- `backend/cmd/server/wire.go`
- `backend/cmd/server/wire_gen.go`
- `backend/internal/repository/user_repo.go`
- `backend/internal/handler/admin/setting_handler.go`
- `backend/internal/server/routes/admin.go`
- `backend/internal/server/api_contract_test.go`
- `frontend/src/views/admin/SettingsView.vue`
- `frontend/src/api/admin/settings.ts`
- `frontend/src/stores/app.ts`
- `frontend/src/stores/adminSettings.ts`
- `/root/.codex/skills/sub2api-sync-ldap/scripts/sync.sh`

## Current Repo Signals
- `go test ./internal/server/routes -run TestNonExistent` fails.
- Failure: `backend/internal/server/routes/admin.go:402:2 syntax error: non-declaration statement outside function body`.
- Worktree already has uncommitted edits in generated/wire files (before this review).

## Dimension 1: Backend Architectural Decoupling

### High-risk Coupling Points
1. `AuthService` uses runtime type assertion for LDAP capability:
- `if ldapRepo, ok := userRepo.(LDAPUserRepository); ok { ... }`
- This is fragile when repository composition changes; LDAP capability can silently disappear.
2. LDAP mode branching is embedded in core auth methods:
- `Register`, `SendVerifyCode`, `Login`, `LoginOrRegisterOAuth`, `LoginOrRegisterOAuthWithTokenPair`.
3. LDAP sync worker lifecycle is coupled to `NewAuthService` and package globals (`sync.Once`, `sync.Mutex`).
4. Admin setting handler depends on concrete `*service.AuthService` instead of interface, reducing plugin replaceability.

### Suggested Target Design
- Introduce `ExternalAuthProvider` interface and route LDAP through it:
- `Login(ctx, identifier, password)`
- `OnSettingsChanged(ctx)` (optional)
- `TestConnection(ctx)`
- `SyncNow(ctx)`
- Keep official `AuthService` as orchestration owner with one extension point:
- `AuthService.externalAuth ExternalAuthProvider`
- Move LDAP runtime logic into dedicated provider object:
- `LDAPProvider` holds LDAP-specific repos/settings/parser/sync scheduler.
- Replace package-level `sync.Once` with provider-level lifecycle (`Start`, `Stop`), allowing test isolation.

### Wire Conflict Reduction Plan
- Split provider sets:
- `service.ProviderSetCore` (upstream-compatible)
- `service.ProviderSetLDAP` (fork extension)
- In `cmd/server/wire.go`, select provider set with build tags:
- `wire_core.go` (`//go:build !ldap`)
- `wire_ldap.go` (`//go:build ldap`)
- Do **not** treat `wire_gen.go` as conflict source of truth; always regenerate from tagged wire injectors.

## Dimension 2: Skill Resilience (`sync.sh`)

## Observed Gaps in Current Script
- No dirty-worktree guard before rebase.
- No rebase conflict preflight hooks.
- Runs `go generate ./ent` but lacks post-generation sanity checks.
- No wire health check (`go generate ./cmd/server` + provider diagnostics).
- No automatic handling for known duplicate declarations in generated files.

### Suggested Hardening Snippet (drop-in shell logic)
```bash
# Known duplicate declarations cleanup in generated schema.go
clean_known_schema_dups() {
local f="backend/ent/migrate/schema.go"
[ -f "$f" ] || return 0

for sym in IdempotencyRecordsColumns IdempotencyRecordsTable; do
local cnt
cnt=$(rg -n "^[[:space:]]*${sym}[[:space:]]*=" "$f" | wc -l | tr -d ' ')
if [ "${cnt}" -le 1 ]; then
continue
fi

echo "[fix] remove duplicate declaration: ${sym}"
awk -v sym="$sym" '
function brace_delta(s, i, c, d) {
d=0
for (i=1;i<=length(s);i++) {
c=substr(s,i,1)
if (c=="{") d++
else if (c=="}") d--
}
return d
}
{
if (!skip && $0 ~ "^[[:space:]]*" sym "[[:space:]]*=") {
if (seen) {
skip=1
depth=brace_delta($0)
next
}
seen=1
}
if (skip) {
depth += brace_delta($0)
if (depth <= 0) {
skip=0
}
next
}
print
}
' "$f" >"${f}.tmp" && mv "${f}.tmp" "$f"
done
}
```

### Wire Strategy Recommendation
- Pre-rebase backup `wire_gen.go` is optional and low value (generated artifact).
- Better strategy:
1. Rebase complete.
2. `go generate ./ent`.
3. `go generate ./cmd/server`.
4. If failure includes `no provider found`, parse type and locate provider set gaps (`service/wire.go`, `repository/wire.go`, `handler/wire.go`).
5. Regenerate `wire_gen.go` after fix.

### Health Self-check Pseudocode
```text
health_check():
run go generate ./ent
if fail: print "Ent generation failed" + stderr summary + fix tips

run go generate ./cmd/server
if fail:
if stderr contains "no provider found":
extract missing type
print:
- check constructor exists
- check constructor is in ProviderSet (service/repository/handler)
- check wire inject file includes correct ProviderSet
else:
print generic wire failure tips
return fail

run go test -tags=unit ./...
if fail: print first failing package and suggestion

return ok
```

## Dimension 3: Frontend Isolation & Pluginization

### Observed Coupling
- LDAP UI block is hardcoded inside `SettingsView.vue` template and script payload construction.
- LDAP parsing/serialization is mixed with unrelated settings fields in one giant `saveSettings()` payload builder.
- No dedicated LDAP store; current stores only include global app/admin ops settings.

### Suggested Frontend Refactor
1. Extract `LDAPSettingsPanel.vue` (pure LDAP form + test/sync actions).
2. Add `useLdapSettingsStore` for:
- form state
- text<->array/json normalization
- `testConnection()` / `syncNow()` actions
3. Mount via plugin slot registry in settings page:
- `SettingsExtensionHost` reads extension list and mounts panels.
- LDAP contributes one extension with stable key (e.g. `ldap.settings.panel`).
4. Keep parent page generic:
- parent only loads full settings and dispatches subsection save handlers.

### Minimal plugin anchor pattern
- Keep one stable anchor id in settings page (`<SettingsExtensionHost area="auth" />`).
- LDAP panel is discovered by extension registry instead of static block.

## Dimension 4: Regression Testing & API Contract

### Current Coverage State
- `api_contract_test.go` only validates LDAP fields in `GET /admin/settings` response schema.
- No contract tests for:
- LDAP login flow
- LDAP JIT user creation
- AuthSource persistence
- group mapping enforcement
- periodic sync disable behavior

### Recommended LDAP Contract Test Matrix
1. `POST /auth/login` with LDAP enabled + valid LDAP user:
- expect success
- user `auth_source=ldap`
- role/balance/concurrency follow mapping
2. Existing local admin + LDAP enabled:
- local admin password login still works
3. User removed from allowed LDAP groups:
- sync run disables user and revokes sessions
4. Upstream model drift simulation:
- missing/renamed user fields should not panic; fail with stable error code
5. Group mapping precedence:
- multiple groups -> highest priority mapping wins

## Immediate Action Items
1. Fix compile blocker in `backend/internal/server/routes/admin.go` first.
2. Add `ExternalAuthProvider` seam and migrate LDAP logic behind it.
3. Split wire injector files by build tags (`ldap` / `!ldap`).
4. Harden `sync.sh` with duplicate cleanup + wire health checks.
5. Extract LDAP settings panel + dedicated store + extension host.
6. Add LDAP contract tests and at least one sync lifecycle test.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ build-frontend:

# 编译 datamanagementd(宿主机数据管理进程)
build-datamanagementd:
@cd datamanagement && go build -o datamanagementd ./cmd/datamanagementd
@cd datamanagement && go build -tags="embed ldap" -o datamanagementd ./cmd/datamanagementd

# 运行测试(后端 + 前端)
test: test-backend test-frontend
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ Nginx drops headers containing underscores by default (e.g. `session_id`), which

One-click installation script that downloads pre-built binaries from GitHub Releases.

> Note: this fork's public LDAP edition is published on `main` for Docker/source deployment. The binary installer below still targets official upstream releases and does not include this fork's LDAP customization.

#### Prerequisites

- Linux server (amd64 or arm64)
Expand Down Expand Up @@ -214,7 +216,7 @@ Use the automated deployment script for easy setup:
mkdir -p sub2api-deploy && cd sub2api-deploy

# Download and run deployment preparation script
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash
curl -sSL https://raw.githubusercontent.com/big-dimple/sub2api/main/deploy/docker-deploy.sh | bash

# Start services
docker compose up -d
Expand All @@ -236,7 +238,7 @@ If you prefer manual setup:

```bash
# 1. Clone the repository
git clone https://github.com/Wei-Shaw/sub2api.git
git clone https://github.com/big-dimple/sub2api.git
cd sub2api/deploy

# 2. Copy environment configuration
Expand Down Expand Up @@ -375,7 +377,7 @@ Build and run from source code for development or customization.

```bash
# 1. Clone the repository
git clone https://github.com/Wei-Shaw/sub2api.git
git clone https://github.com/big-dimple/sub2api.git
cd sub2api

# 2. Install pnpm (if not already installed)
Expand Down
8 changes: 5 additions & 3 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ Nginx 默认会丢弃名称中含下划线的请求头(如 `session_id`),

一键安装脚本,自动从 GitHub Releases 下载预编译的二进制文件。

> 说明:本 fork 的公开 LDAP 版以 `main` 分支的 Docker/源码部署为准。下方二进制安装脚本仍然指向官方 upstream release,不包含本 fork 的 LDAP 定制。

#### 前置条件

- Linux 服务器(amd64 或 arm64)
Expand Down Expand Up @@ -213,7 +215,7 @@ curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install
mkdir -p sub2api-deploy && cd sub2api-deploy

# 下载并运行部署准备脚本
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash
curl -sSL https://raw.githubusercontent.com/big-dimple/sub2api/main/deploy/docker-deploy.sh | bash

# 启动服务
docker compose up -d
Expand All @@ -235,7 +237,7 @@ docker compose logs -f sub2api

```bash
# 1. 克隆仓库
git clone https://github.com/Wei-Shaw/sub2api.git
git clone https://github.com/big-dimple/sub2api.git
cd sub2api/deploy

# 2. 复制环境配置文件
Expand Down Expand Up @@ -386,7 +388,7 @@ rm -rf data/ postgres_data/ redis_data/

```bash
# 1. 克隆仓库
git clone https://github.com/Wei-Shaw/sub2api.git
git clone https://github.com/big-dimple/sub2api.git
cd sub2api

# 2. 安装 pnpm(如果还没有安装)
Expand Down
8 changes: 5 additions & 3 deletions README_JA.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ Nginx はデフォルトでアンダースコアを含むヘッダー(例: `se

GitHub Releases からビルド済みバイナリをダウンロードするワンクリックインストールスクリプトです。

> 注意: この fork の公開 LDAP 版は `main` ブランチの Docker / ソース配布を正とします。下記のバイナリインストーラは引き続き公式 upstream release を参照し、この fork の LDAP カスタマイズは含みません。

#### 前提条件

- Linux サーバー(amd64 または arm64)
Expand Down Expand Up @@ -213,7 +215,7 @@ PostgreSQL と Redis のコンテナを含む Docker Compose でデプロイし
mkdir -p sub2api-deploy && cd sub2api-deploy

# デプロイ準備スクリプトをダウンロードして実行
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash
curl -sSL https://raw.githubusercontent.com/big-dimple/sub2api/main/deploy/docker-deploy.sh | bash

# サービスを起動
docker compose up -d
Expand All @@ -235,7 +237,7 @@ docker compose logs -f sub2api

```bash
# 1. リポジトリをクローン
git clone https://github.com/Wei-Shaw/sub2api.git
git clone https://github.com/big-dimple/sub2api.git
cd sub2api/deploy

# 2. 環境設定ファイルをコピー
Expand Down Expand Up @@ -374,7 +376,7 @@ rm -rf data/ postgres_data/ redis_data/

```bash
# 1. リポジトリをクローン
git clone https://github.com/Wei-Shaw/sub2api.git
git clone https://github.com/big-dimple/sub2api.git
cd sub2api

# 2. pnpm をインストール(未インストールの場合)
Expand Down
Loading