Compare commits

..
7 Commits
Author SHA1 Message Date
dev b314731e18 chore: seed migration objects batch 7 2026-10-18 13:23:16 +08:00
dev ac69c3f6d1 chore: seed migration objects batch 6 2026-10-18 13:22:52 +08:00
dev 339e5eb3e6 chore: seed migration objects batch 5 2026-10-18 13:22:46 +08:00
dev f01052b827 chore: seed migration objects batch 4 2026-10-18 13:22:06 +08:00
dev 0352740632 chore: seed migration objects batch 3 2026-10-18 13:21:27 +08:00
dev 141753b319 chore: seed migration objects batch 2 2026-10-18 13:21:12 +08:00
dev f9c5b44b2e chore: seed migration objects batch 1 2026-10-18 13:21:05 +08:00
1052 changed files with 1424 additions and 9274 deletions
Vendored
BIN
View File
Binary file not shown.
-11
View File
@@ -1,11 +0,0 @@
.git
.gitea
.idea
.vscode
.DS_Store
*.log
tests
docs
web/node_modules
web/dist
coverage
+23 -67
View File
@@ -1,81 +1,37 @@
name: Deploy olons-server production
name: Deploy im-workbench (k3s test cluster)
on:
push:
branches:
- pro
workflow_dispatch:
concurrency:
group: production-olons-server
cancel-in-progress: false
permissions:
contents: read
env:
REGISTRY: git.olns.shop
IMAGE: git.olns.shop/pro/olons_server
SERVICE: olons-server
DEPLOY_HOST: 145.223.69.9
DEPLOY_USER: olns-deploy
inputs:
image_tag:
description: '镜像tag,默认为 test(与集群 kustomization 里的 newTag 一致)'
required: false
jobs:
deploy:
runs-on: deploy-host
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- name: Log in to Gitea Container Registry
env:
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
- name: 确定镜像tag
id: vars
run: |
set -euo pipefail
printf '%s' "$REGISTRY_TOKEN" | docker login "$REGISTRY" -u admin --password-stdin
TAG="${{ github.event.inputs.image_tag }}"
[ -z "$TAG" ] && TAG=test
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
- name: Build and push image
env:
GITHUB_SHA: ${{ github.sha }}
run: |
set -euo pipefail
SHORT_SHA="$(printf '%.12s' "$GITHUB_SHA")"
docker build --build-arg VITE_CUSTOMER_SERVICE_PROVIDER=third_party -t "${IMAGE}:pro" -t "${IMAGE}:${SHORT_SHA}" .
docker push "$IMAGE:pro"
docker push "$IMAGE:$SHORT_SHA"
- name: 登录镜像仓库
run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login git.118im.com -u admin --password-stdin
- name: Deploy Compose service
env:
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
DEPLOY_KNOWN_HOSTS: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
- name: 构建并推送镜像
run: |
set -euo pipefail
install -d -m 700 "$HOME/.ssh"
KEY_FILE="$(mktemp "$HOME/.ssh/olns-deploy.XXXXXX")"
cleanup() {
shred -u "$KEY_FILE" 2>/dev/null || true
}
trap cleanup EXIT
printf '%s\n' "$DEPLOY_SSH_KEY" > "$KEY_FILE"
chmod 600 "$KEY_FILE"
printf '%s\n' "$DEPLOY_KNOWN_HOSTS" > "$HOME/.ssh/known_hosts"
chmod 600 "$HOME/.ssh/known_hosts"
SSH_ARGS=(-i "$KEY_FILE" -o BatchMode=yes -o StrictHostKeyChecking=yes)
printf '%s' "$REGISTRY_TOKEN" | ssh "${SSH_ARGS[@]}" "$DEPLOY_USER@$DEPLOY_HOST" \
"docker login git.olns.shop -u admin --password-stdin"
ssh "${SSH_ARGS[@]}" "$DEPLOY_USER@$DEPLOY_HOST" '
set -euo pipefail
cd /opt/olns
docker compose pull olons-server
docker compose up -d --no-deps --wait olons-server
docker compose exec -T olons-server sh -c '"'"'
test -n "$OLONS_IM_INTERNAL_SECRET"
test "$OLONS_IM_TENANT_CODE" = "default"
test "$OLONS_SERVER_DEFAULT_TENANT_ID" = "0"
test "$OLONS_IM_BASE_URL" = "http://im-server:6060"
test "$OLONS_IM_HTTP_API_URL" = "http://im-server:6060/v1/im"
test "$OLONS_IM_WS_URL" = "ws://im-server:6060/v0/channels"
test "$OLONS_IM_FILE_URL" = "http://im-server:6060/v0/file"
'"'"'
'
docker build -t git.118im.com/im_team/im-workbench:${{ steps.vars.outputs.tag }} .
docker push git.118im.com/im_team/im-workbench:${{ steps.vars.outputs.tag }}
- name: 部署到k3s测试集群
run: |
mkdir -p ~/.kube
echo "${{ secrets.KUBECONFIG }}" > ~/.kube/config
chmod 600 ~/.kube/config
kubectl rollout restart deployment/im-workbench -n workbench-system
kubectl rollout status deployment/im-workbench -n workbench-system --timeout=120s
-2
View File
@@ -26,8 +26,6 @@ go.work.sum
# env file
.env
.idea/
.DS_Store
storage/uploads/
# ---> Node
# Logs
+5 -9
View File
@@ -6,9 +6,6 @@ RUN corepack enable
COPY web/package.json web/pnpm-lock.yaml web/pnpm-workspace.yaml ./
RUN pnpm install --frozen-lockfile
COPY web/ ./
ARG VITE_CUSTOMER_SERVICE_PROVIDER=
ENV VITE_PUBLIC_PATH=/
ENV VITE_CUSTOMER_SERVICE_PROVIDER=${VITE_CUSTOMER_SERVICE_PROVIDER}
RUN pnpm run build
# ---- Stage 2: build the Go backend ----
@@ -19,16 +16,15 @@ COPY go.mod go.sum ./
RUN go mod download
COPY . .
COPY --from=web-builder /web/dist ./web/dist
RUN CGO_ENABLED=0 GOOS=linux go build -o /out/olons_server ./cmd/olons_server
RUN CGO_ENABLED=0 GOOS=linux go build -o /out/im_workbench ./cmd/workbench
FROM alpine:3.22
WORKDIR /app
RUN apk add --no-cache tzdata
ENV OLONS_SERVER_CONFIG=/app/configs/olons_server.test.json
COPY --from=builder /out/olons_server /app/olons_server
ENV WORKBENCH_CONFIG=/app/configs/workbench.test.json
COPY --from=builder /out/im_workbench /app/im_workbench
COPY configs /app/configs
COPY --from=web-builder /web/dist /app/web/dist
ENV OLONS_SERVER_FRONTEND_DIR=/app/web/dist
ENV WORKBENCH_FRONTEND_DIR=/app/web/dist
EXPOSE 6061
ENTRYPOINT ["/app/olons_server"]
ENTRYPOINT ["/app/im_workbench"]
+2 -2
View File
@@ -1,13 +1,13 @@
.PHONY: build test run web-install web-build
build:
go build -o bin/olons_server ./cmd/olons_server
go build -o bin/im_workbench ./cmd/workbench
test:
go test ./...
run:
OLONS_SERVER_CONFIG=configs/olons_server.local.json go run ./cmd/olons_server
WORKBENCH_CONFIG=configs/workbench.local.json go run ./cmd/workbench
web-install:
cd web && pnpm install --frozen-lockfile
+12 -13
View File
@@ -1,8 +1,8 @@
# Olons Server
# Workbench
移动端任务与账户平台后端。项目是独立应用,业务数据以 MySQL `olons_admin` 库中的 `hg_*` 表为唯一事实源。
项目现在采用前后端一体目录结构:`web/` 是 Vue 3 + Vite 移动端,Go 服务在生产环境通过网站根路径 `/` 提供构建后的静态资源,`/v1/` 继续提供业务 API。
项目现在采用前后端一体目录结构:`web/` 是参考 `im_manager` 组织的 Vue 3 + Vite 管理端,Go 服务在生产环境通过 `/admin/` 提供构建后的静态资源,`/v1/` 继续提供业务 API。
## 当前接口
@@ -28,8 +28,6 @@
- `GET /v1/manual-products/{product_id}`
- `GET /v1/payment-accounts`
- `POST /v1/payment-accounts`
- `PUT /v1/payment-accounts`
- `GET /v1/payment-accounts/details`
- `POST /v1/withdrawal-orders/quote`
- `POST /v1/withdrawal-orders`
- `GET /v1/withdrawal-orders`
@@ -44,16 +42,17 @@
核心环境变量:
```bash
OLONS_SERVER_CONFIG=configs/olons_server.local.json
OLONS_SERVER_MYSQL_DSN='user:password@tcp(host:3306)/olons_admin?parseTime=true&charset=utf8mb4&loc=Local'
OLONS_SERVER_REDIS_ADDR='127.0.0.1:6379'
OLONS_SERVER_FINANCE_MASTER_KEY='<至少 32 个字符的固定资金安全密钥>'
OLONS_SERVER_API_KEYS='<API Key,多个以逗号分隔>'
WORKBENCH_CONFIG=configs/workbench.local.json
WORKBENCH_MYSQL_DSN='user:password@tcp(host:3306)/olons_admin?parseTime=true&charset=utf8mb4&loc=Local'
WORKBENCH_REDIS_ADDR='127.0.0.1:6379'
WORKBENCH_DATA_ENCRYPTION_KEY='<32 字节随机密钥的 Base64>'
WORKBENCH_LOOKUP_HMAC_KEY='<至少 32 字节随机密钥的 Base64>'
WORKBENCH_API_KEYS='<API Key,多个以逗号分隔>'
```
`finance_master_key` 已在 JSON 配置中提供固定值,也可由 `OLONS_SERVER_FINANCE_MASTER_KEY` 覆盖。服务会从这个主密钥派生数据加密键和检索键,用于保护收款账户姓名、账号、银行卡预留手机号及取出快照等支付敏感信息。密钥必须与已有数据保持一致;会员登录手机号直接保存在 `hg_app_member.mobile`。
`WORKBENCH_DATA_ENCRYPTION_KEY` 和 `WORKBENCH_LOOKUP_HMAC_KEY` 用于保护收款账户姓名、账号、银行卡预留手机号及取出快照等支付敏感信息。两个密钥必须分开生成、通过部署 Secret 注入,并与已有数据的加密配置保持一致;会员登录手机号直接保存在 `hg_app_member.mobile`。
前端静态目录可通过 `OLONS_SERVER_FRONTEND_DIR` 覆盖,默认值为 `web/dist`。本地开发可分别启动前后端:
前端静态目录可通过 `WORKBENCH_FRONTEND_DIR` 覆盖,默认值为 `web/dist`。本地开发可分别启动前后端:
```bash
make web-install
@@ -61,7 +60,7 @@ make web-build
make run
```
生产镜像使用 Docker 多阶段构建自动安装前端依赖、构建 `web/`,并将 C 端产物部署到网站根路径 `/`。
生产镜像使用 Docker 多阶段构建自动安装前端依赖、构建 `web/`,并将产物部署到 `/admin/`。
## 请求头
@@ -71,7 +70,7 @@ X-Request-ID: <request id>
X-Device-ID: <optional device id>
```
服务采用单租户模式,登录仅按手机号查找账号,不读取或接受租户环境变量。现有数据库中的 `tenant_id` 字段仅作为兼容字段保留,新注册数据固定写入 `0`。
默认租户通过 `WORKBENCH_DEFAULT_TENANT_ID` 配置,现有 `olons_admin` 数据使用 `tenant_id=0`。服务不接受客户端传入租户身份。
## 验证
+4 -4
View File
@@ -16,7 +16,7 @@ import (
"regexp"
"strings"
"git.118im.com/im_team/olons_server/internal/config"
"git.118im.com/im_team/im_workbench/internal/config"
_ "github.com/go-sql-driver/mysql"
)
@@ -59,9 +59,9 @@ func main() {
log.Fatal("mobile_cipher is missing before migration")
}
aeads := newAEADs(append(splitKeys(os.Getenv("OLONS_SERVER_MEMBER_MIGRATION_DATA_KEYS")), cfg.Auth.DataEncryptionKey))
lookupKeys := decodeKeys(append(splitKeys(os.Getenv("OLONS_SERVER_MEMBER_MIGRATION_LOOKUP_KEYS")), cfg.Auth.LookupHMACKey))
overrides, err := parseOverrides(os.Getenv("OLONS_SERVER_MEMBER_MIGRATION_OVERRIDES"))
aeads := newAEADs(append(splitKeys(os.Getenv("WORKBENCH_MEMBER_MIGRATION_DATA_KEYS")), cfg.Auth.DataEncryptionKey))
lookupKeys := decodeKeys(append(splitKeys(os.Getenv("WORKBENCH_MEMBER_MIGRATION_LOOKUP_KEYS")), cfg.Auth.LookupHMACKey))
overrides, err := parseOverrides(os.Getenv("WORKBENCH_MEMBER_MIGRATION_OVERRIDES"))
if err != nil {
log.Fatal(err)
}
@@ -10,8 +10,8 @@ import (
"syscall"
"time"
"git.118im.com/im_team/olons_server/internal/app"
"git.118im.com/im_team/olons_server/internal/config"
"git.118im.com/im_team/im_workbench/internal/app"
"git.118im.com/im_team/im_workbench/internal/config"
)
func main() {
@@ -34,7 +34,7 @@ func main() {
errCh := make(chan error, 1)
go func() {
log.Printf("olons_server listening on %s", cfg.Listen)
log.Printf("workbench listening on %s", cfg.Listen)
if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
errCh <- err
}
@@ -10,15 +10,13 @@
"addr": "127.0.0.1:6379",
"db": 0
},
"upload": {
"dir": "storage/uploads",
"public_path": "/uploads"
},
"auth": {
"api_keys": [],
"session_key_pattern": "olons_server:session:token:%s",
"session_key_pattern": "workbench:session:token:%s",
"session_ttl_seconds": 1209600,
"finance_master_key": "olons-finance-master-key-v1-20261013",
"default_tenant_id": 0,
"data_encryption_key": "",
"lookup_hmac_key": "",
"allow_dev_header_auth": true,
"required_api_key": false
}
@@ -10,15 +10,13 @@
"addr": "",
"db": 0
},
"upload": {
"dir": "storage/uploads",
"public_path": "/uploads"
},
"auth": {
"api_keys": [],
"session_key_pattern": "olons_server:session:token:%s",
"session_key_pattern": "workbench:session:token:%s",
"session_ttl_seconds": 1209600,
"finance_master_key": "olons-finance-master-key-v1-20261013",
"default_tenant_id": 0,
"data_encryption_key": "",
"lookup_hmac_key": "",
"required_api_key": true
}
}
BIN
View File
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 569 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1018 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 848 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 887 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 850 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 645 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Some files were not shown because too many files have changed in this diff Show More