init: 1.0.0
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": ["@commitlint/config-conventional"]
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
name: Build matrix binaries and push to external repo
|
||||
run-name: Build ${{ github.ref_name }} of ${{ github.repository }}
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*' # match semver only, e.g. v1.2.3
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
prepare_release:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Extract Go version (from go.mod)
|
||||
id: extract_go_version
|
||||
run: | # Read Go version from go.mod and save it to the VER_GO environment variable.
|
||||
VER_GO=$(grep -m 1 go go.mod | cut -d\ -f2)
|
||||
echo "VER_GO=$VER_GO" >> $GITHUB_ENV
|
||||
|
||||
- name: Extract PPanel(api) version (from pkg/constant/types.go)
|
||||
id: extract_api_version
|
||||
run: | # Read API version from pkg/constant/types.go and save it to the VER_API environment variable.
|
||||
VER_API=$(grep -oP '(?<=const Version = \")[0-9]+\.[0-9]+\.[0-9]+' pkg/constant/version.go)
|
||||
echo "VER_API=$VER_API" >> $GITHUB_ENV
|
||||
|
||||
- name: Create release in destination repo
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REL_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref_name }}
|
||||
release_name: PPanel Server ${{ github.ref_name }}
|
||||
body: |
|
||||
PPanel Server ${{ github.ref_name }}
|
||||
PPanel API v${{ env.VER_API }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
owner: ${{ vars.REL_OWNER }}
|
||||
repo: ${{ vars.REL_REPO }}
|
||||
commitish: master
|
||||
|
||||
build_matrix:
|
||||
needs: prepare_release
|
||||
strategy:
|
||||
matrix:
|
||||
goos: [linux, windows, darwin]
|
||||
goarch: [amd64, arm64]
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build binaries and push to external repo
|
||||
id: build_and_push
|
||||
uses: wangyoucao577/go-release-action@v1
|
||||
with:
|
||||
github_token: ${{ secrets.REL_TOKEN }}
|
||||
goos: ${{ matrix.goos }}
|
||||
goarch: ${{ matrix.goarch }}
|
||||
goversion: ${{ env.VER_GO }}
|
||||
binary_name: ppanel-server
|
||||
pre_command: export CGO_ENABLED=0
|
||||
ldflags: -s -w
|
||||
release_repo: ${{ vars.REL_OWNER }}/${{ vars.REL_REPO }}
|
||||
extra_files: LICENSE etc
|
||||
md5sum: false
|
||||
@@ -0,0 +1,50 @@
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["develop"]
|
||||
pull_request:
|
||||
branches: ["develop"]
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Get short Git commit ID
|
||||
id: vars
|
||||
run: echo "COMMIT_ID=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||
|
||||
|
||||
- name: Build Docker image
|
||||
run: docker build -t ${{ secrets.DOCKER_USERNAME }}/ppanel-server-dev:${{ env.COMMIT_ID }} .
|
||||
|
||||
- name: Push Docker image
|
||||
run: docker push ${{ secrets.DOCKER_USERNAME }}/ppanel-server-dev:${{ env.COMMIT_ID }}
|
||||
|
||||
- name: Deploy to server
|
||||
uses: appleboy/ssh-action@v0.1.6
|
||||
with:
|
||||
host: ${{ secrets.SSH_HOST }}
|
||||
username: ${{ secrets.SSH_USER }}
|
||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
script: |
|
||||
if [ $(docker ps -q -f name=ppanel-server-dev) ]; then
|
||||
echo "Stopping and removing existing ppanel-server container..."
|
||||
docker stop ppanel-server-dev
|
||||
docker rm ppanel-server-dev
|
||||
else
|
||||
echo "No existing ppanel-server-dev container running."
|
||||
fi
|
||||
|
||||
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
|
||||
docker run -d --restart=always --log-driver=journald --name ppanel-server-dev -p 8080:8080 -v /www/wwwroot/api/etc:/app/etc --restart=always -d ${{ secrets.DOCKER_USERNAME }}/ppanel-server-dev:${{ env.COMMIT_ID }}
|
||||
@@ -0,0 +1,124 @@
|
||||
name: Build and Publish Docker Image
|
||||
|
||||
on:
|
||||
# release:
|
||||
# types: [published]
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build-docker:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
IMAGE_NAME: ppanel-server
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Extract version from pkg/constant/types.go
|
||||
id: version
|
||||
run: |
|
||||
# 提取版本号 0.1.3
|
||||
VERSION=$(grep -oP '(?<=const Version = ")[0-9]+\.[0-9]+\.[0-9]+' pkg/constant/version.go)
|
||||
echo "VERSION=$VERSION"
|
||||
|
||||
# 提取构建号 01300
|
||||
BUILD_NUMBER=$(grep -oP 'const Version = "[0-9]+\.[0-9]+\.[0-9]+\(\K[0-9]+' pkg/constant/version.go)
|
||||
echo "BUILD_NUMBER=$BUILD_NUMBER"
|
||||
|
||||
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
||||
echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV
|
||||
|
||||
- name: Get short SHA
|
||||
id: sha
|
||||
run: echo "GIT_SHA=${GITHUB_SHA::8}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build and push Docker image for main release
|
||||
if: "!contains(github.ref_name, 'beta')"
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:latest
|
||||
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}-${{ env.BUILD_NUMBER }}
|
||||
|
||||
- name: Build and push Docker image for beta release
|
||||
if: contains(github.ref_name, 'beta')
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:beta
|
||||
${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}-${{ env.BUILD_NUMBER }}-beta
|
||||
|
||||
|
||||
|
||||
release-notes:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.23
|
||||
|
||||
- name: Install GoReleaser
|
||||
run: |
|
||||
go install github.com/goreleaser/goreleaser@latest
|
||||
|
||||
- name: Run GoReleaser
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
run: |
|
||||
goreleaser check
|
||||
goreleaser release --clean
|
||||
releases-matrix:
|
||||
name: Release ppanel-server binary
|
||||
runs-on: ubuntu-latest
|
||||
needs: release-notes # wait for release-notes job to finish
|
||||
strategy:
|
||||
matrix:
|
||||
# build and publish in parallel: linux/386, linux/amd64, linux/arm64,
|
||||
# windows/386, windows/amd64, windows/arm64, darwin/amd64, darwin/arm64
|
||||
goos: [ linux, windows, darwin ]
|
||||
goarch: [ '386', amd64, arm64 ]
|
||||
exclude:
|
||||
- goarch: '386'
|
||||
goos: darwin
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: wangyoucao577/go-release-action@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
goos: ${{ matrix.goos }}
|
||||
goarch: ${{ matrix.goarch }}
|
||||
asset_name: "ppanel-server-${{ matrix.goos }}-${{ matrix.goarch }}"
|
||||
goversion: "https://dl.google.com/go/go1.23.3.linux-amd64.tar.gz"
|
||||
project_path: "."
|
||||
binary_name: "ppanel-server"
|
||||
extra_files: LICENSE etc
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
name: Go CI/CD with goctl and Swagger
|
||||
|
||||
on:
|
||||
# release:
|
||||
# types: [published]
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install goctl
|
||||
run: |
|
||||
curl -L https://github.com/zeromicro/go-zero/releases/download/tools%2Fgoctl%2Fv1.7.2/goctl-v1.7.2-linux-amd64.tar.gz -o goctl-v1.7.2-linux-amd64.tar.gz
|
||||
tar -xvzf goctl-v1.7.2-linux-amd64.tar.gz
|
||||
chmod +x goctl
|
||||
sudo mv goctl /usr/local/bin/goctl
|
||||
goctl --version
|
||||
|
||||
- name: Install goctl-swagger
|
||||
run: |
|
||||
curl -L https://github.com/tensionc/goctl-swagger/releases/download/v1.0.1/goctl-swagger-v1.0.1-linux-amd64.tar.gz -o goctl-swagger.tar.gz
|
||||
tar -xvzf goctl-swagger.tar.gz
|
||||
chmod +x goctl-swagger
|
||||
sudo mv goctl-swagger /usr/local/bin/
|
||||
|
||||
- name: Generate Swagger file
|
||||
run: |
|
||||
mkdir -p swagger
|
||||
goctl api plugin -plugin goctl-swagger='swagger -filename common.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_common.api -dir ./swagger
|
||||
goctl api plugin -plugin goctl-swagger='swagger -filename user.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_user.api -dir ./swagger
|
||||
goctl api plugin -plugin goctl-swagger='swagger -filename app.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_app.api -dir ./swagger
|
||||
goctl api plugin -plugin goctl-swagger='swagger -filename admin.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_admin.api -dir ./swagger
|
||||
goctl api plugin -plugin goctl-swagger='swagger -filename ppanel.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ppanel.api -dir ./swagger
|
||||
goctl api plugin -plugin goctl-swagger='swagger -filename node.json -pack Response -response "[{\"name\":\"code\",\"type\":\"integer\",\"description\":\"状态码\"},{\"name\":\"msg\",\"type\":\"string\",\"description\":\"消息\"},{\"name\":\"data\",\"type\":\"object\",\"description\":\"数据\",\"is_data\":true}]";' -api ./apis/swagger_node.api -dir ./swagger
|
||||
|
||||
|
||||
- name: Verify Swagger file
|
||||
run: |
|
||||
test -f ./swagger/common.json
|
||||
test -f ./swagger/user.json
|
||||
test -f ./swagger/app.json
|
||||
test -f ./swagger/admin.json
|
||||
|
||||
- name: Checkout target repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: perfect-panel/ppanel-docs
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: ppanel-docs
|
||||
persist-credentials: true
|
||||
|
||||
- name: Verify or create public/swagger directory
|
||||
run: |
|
||||
mkdir -p ./ppanel-docs/public/swagger
|
||||
|
||||
- name: Copy Swagger files
|
||||
run: |
|
||||
cp -rf swagger/* ppanel-docs/public/swagger
|
||||
cd ppanel-docs
|
||||
|
||||
- name: Check for file changes
|
||||
run: |
|
||||
cd ppanel-docs
|
||||
git add .
|
||||
git status
|
||||
if [ "$(git status --porcelain)" ]; then
|
||||
echo "Changes detected in the doc repository."
|
||||
git config user.name "GitHub Actions"
|
||||
git config user.email "actions@ppanel.dev"
|
||||
git commit -m "Update Swagger files"
|
||||
git push
|
||||
else
|
||||
echo "No changes detected."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
.idea/
|
||||
.vscode/
|
||||
*-dev.yaml
|
||||
*.local.yaml
|
||||
/test/
|
||||
*.log
|
||||
.DS_Store
|
||||
*_test_config.go
|
||||
*.log*
|
||||
/build/
|
||||
etc/ppanel.yaml
|
||||
*.p8
|
||||
*.crt
|
||||
*.key
|
||||
node_modules
|
||||
package-lock.json
|
||||
package.json
|
||||
@@ -0,0 +1,66 @@
|
||||
project_name: ppanel
|
||||
version: 1
|
||||
release:
|
||||
prerelease: auto
|
||||
builds:
|
||||
- # If true, skip the build.
|
||||
# Useful for library projects.
|
||||
# Default is false
|
||||
skip: true
|
||||
|
||||
changelog:
|
||||
# Set it to true if you wish to skip the changelog generation.
|
||||
# This may result in an empty release notes on GitHub/GitLab/Gitea.
|
||||
disable: false
|
||||
|
||||
# Changelog generation implementation to use.
|
||||
#
|
||||
# Valid options are:
|
||||
# - `git`: uses `git log`;
|
||||
# - `github`: uses the compare GitHub API, appending the author login to the changelog.
|
||||
# - `gitlab`: uses the compare GitLab API, appending the author name and email to the changelog.
|
||||
# - `github-native`: uses the GitHub release notes generation API, disables the groups feature.
|
||||
#
|
||||
# Defaults to `git`.
|
||||
use: github
|
||||
|
||||
# Sorts the changelog by the commit's messages.
|
||||
# Could either be asc, desc or empty
|
||||
# Default is empty
|
||||
sort: asc
|
||||
|
||||
# Format to use for commit formatting.
|
||||
# Only available when use is one of `github`, `gitea`, or `gitlab`.
|
||||
#
|
||||
# Default: '{{ .SHA }}: {{ .Message }} ({{ with .AuthorUsername }}@{{ . }}{{ else }}{{ .AuthorName }} <{{ .AuthorEmail }}>{{ end }})'.
|
||||
# Extra template fields: `SHA`, `Message`, `AuthorName`, `AuthorEmail`, and
|
||||
# `AuthorUsername`.
|
||||
format: "{{ .Message }}"
|
||||
|
||||
# Group commits messages by given regex and title.
|
||||
# Order value defines the order of the groups.
|
||||
# Proving no regex means all commits will be grouped under the default group.
|
||||
# Groups are disabled when using github-native, as it already groups things by itself.
|
||||
#
|
||||
# Default is no groups.
|
||||
groups:
|
||||
- title: "✨ Features"
|
||||
regexp: "^.*feat[(\\w)]*:+.*$"
|
||||
order: 0
|
||||
- title: "🐛 Bug Fixes"
|
||||
regexp: "^.*fix[(\\w)]*:+.*$"
|
||||
order: 1
|
||||
- title: "🎫 Chores"
|
||||
regexp: "^.*chore[(\\w)]*:+.*$"
|
||||
order: 2
|
||||
- title: "🔨 Refactor"
|
||||
regexp: "^.*refactor[(\\w)]*:+.*$"
|
||||
order: 3
|
||||
- title: "🔧 Build"
|
||||
regexp: "^.*?(ci)(\\(.+\\))??!?:.+$"
|
||||
order: 4
|
||||
- title: "📝 Documentation"
|
||||
regexp: "^.*?docs?(\\(.+\\))??!?:.+$"
|
||||
order: 5
|
||||
- title: "✨ Others"
|
||||
order: 999
|
||||
@@ -0,0 +1,12 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="go build github.com/perfect-panel/ppanel-server" type="GoApplicationRunConfiguration" factoryName="Go Application" nameIsGenerated="true">
|
||||
<module name="server" />
|
||||
<working_directory value="$PROJECT_DIR$" />
|
||||
<parameters value="run --config etc/ppanel-dev.yaml" />
|
||||
<kind value="PACKAGE" />
|
||||
<package value="github.com/perfect-panel/ppanel-server" />
|
||||
<directory value="$PROJECT_DIR$" />
|
||||
<filePath value="$PROJECT_DIR$/ppanel.go" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -0,0 +1,40 @@
|
||||
# Pull Request Submission Guidelines
|
||||
|
||||
To ensure the quality of the codebase and maintainability of the project, please follow these guidelines before submitting a Pull Request (PR):
|
||||
|
||||
## 1. PR Title and Description
|
||||
|
||||
- **Clear Title**: Concisely describe the main content of the PR, for example:
|
||||
- Fix: Correct error messages in user login
|
||||
- Feature: Add order export functionality
|
||||
|
||||
- **Detailed Description**: Include the following details in the description:
|
||||
- Purpose and background of this PR.
|
||||
- Detailed explanation of the changes.
|
||||
- For bug fixes, describe the steps to reproduce the issue.
|
||||
- For new features, explain how to use them.
|
||||
- Link related issues (if any) using keywords like `Closes #123`.
|
||||
|
||||
## 2. Code Checks Before Submission
|
||||
|
||||
- **Code Style**: Ensure the code adheres to the project's coding standards (e.g., ESLint, Prettier, or GoLint).
|
||||
- **Functional Testing**: Fully test new features or bug fixes to ensure no missing functionality or regressions.
|
||||
- **Unit Tests**: Write unit tests for added or modified functionality and ensure all tests pass.
|
||||
- **Documentation Updates**: Update documentation if the PR includes new features or API changes.
|
||||
|
||||
## 3. Branch Strategy
|
||||
|
||||
- **Correct Branch**:
|
||||
- Develop new features based on `feature/*` branches.
|
||||
- Fix bugs based on `fix/*` branches.
|
||||
- Ensure the target branch of the PR aligns with the project's branching strategy.
|
||||
|
||||
- **Sync with Base Branch**: Before submitting the PR, ensure your branch is up-to-date with the target branch (e.g., `main` or `develop`).
|
||||
|
||||
## 4. Review Process
|
||||
|
||||
- **Small Commits**: Avoid submitting excessive changes in a single PR; break it into smaller logical units.
|
||||
|
||||
---
|
||||
|
||||
Thank you for your contribution!
|
||||
@@ -0,0 +1,44 @@
|
||||
# Pull Request 提交须知
|
||||
|
||||
为了确保代码库的质量和项目的可维护性,在提交 Pull Request(PR)之前,请务必遵循以下准则:
|
||||
|
||||
## 1. PR 标题和描述
|
||||
|
||||
- **标题清晰**:简明扼要地描述 PR 的主要内容,例如:
|
||||
- Fix: 修复用户登录时的错误提示
|
||||
- Feature: 添加订单导出功能
|
||||
|
||||
- **描述详细**:在描述中包括以下内容:
|
||||
- 此 PR 的目的和背景。
|
||||
- 变更的详细说明。
|
||||
- 如果涉及 Bug 修复,需描述问题重现的步骤。
|
||||
- 如果涉及新功能,需描述其使用方式。
|
||||
- 关联的 Issue(如有),使用关键字关闭 Issue,例如:`Closes #123`。
|
||||
|
||||
## 2. 提交代码前的检查
|
||||
|
||||
- **代码风格**:确保代码符合项目的代码规范。
|
||||
- **功能测试**:对新功能或 Bug 修复进行全面测试,确保没有功能缺失或回归问题。
|
||||
- **单元测试**:为新增或修改的功能编写单元测试,并确保所有测试通过(工具类即`pkg/*`下面的必须带有单元测试)。
|
||||
- **文档更新**:如果 PR 涉及新功能或接口更改,确保文档同步更新。
|
||||
|
||||
## 3. 分支策略
|
||||
|
||||
- **正确的分支**:
|
||||
- 新功能应基于 `feature/*` 分支进行开发。
|
||||
- Bug 修复应基于 `fix/*` 分支。
|
||||
- 确保 PR 的目标分支与项目的分支策略一致。
|
||||
|
||||
- **同步主干代码**:在提交 PR 之前,请确保分支已经与目标分支(develop)同步。
|
||||
|
||||
## 4. 审查流程
|
||||
|
||||
- **小型提交**:避免一次性提交过多的更改,将 PR 拆分为更小的逻辑单元。
|
||||
|
||||
---
|
||||
|
||||
感谢您的贡献!
|
||||
|
||||
|
||||
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
# Use a smaller base image for the build stage
|
||||
FROM golang:alpine AS builder
|
||||
|
||||
LABEL stage=gobuilder
|
||||
|
||||
ARG TARGETARCH
|
||||
ENV CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH}
|
||||
|
||||
# Combine apk commands into one to reduce layer size
|
||||
RUN apk update --no-cache && apk add --no-cache tzdata ca-certificates
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Copy go.mod and go.sum first to take advantage of Docker caching
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
# Copy the rest of the application code
|
||||
COPY . .
|
||||
|
||||
# Build the binary with optimization flags to reduce binary size
|
||||
RUN go build -ldflags="-s -w" -o /app/ppanel ppanel.go
|
||||
|
||||
# Final minimal image
|
||||
FROM scratch
|
||||
|
||||
# Copy CA certificates and timezone data
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
|
||||
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
# Set working directory and copy binary
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /app/ppanel /app/ppanel
|
||||
COPY --from=builder /etc /app/etc
|
||||
|
||||
# Expose the port (optional)
|
||||
EXPOSE 8080
|
||||
|
||||
# Specify entry point
|
||||
ENTRYPOINT ["/app/ppanel"]
|
||||
CMD ["run", "--config", "etc/ppanel.yaml"]
|
||||
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
@@ -0,0 +1,79 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Ads API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
type (
|
||||
CreateAdsRequest {
|
||||
Title string `json:"title"`
|
||||
Type string `json:"type"`
|
||||
Content string `json:"content"`
|
||||
Description string `json:"description"`
|
||||
TargetURL string `json:"target_url"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
EndTime int64 `json:"end_time"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
UpdateAdsRequest {
|
||||
Id int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Type string `json:"type"`
|
||||
Content string `json:"content"`
|
||||
Description string `json:"description"`
|
||||
TargetURL string `json:"target_url"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
EndTime int64 `json:"end_time"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
DeleteAdsRequest {
|
||||
Id int64 `json:"id"`
|
||||
}
|
||||
GetAdsListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Status *int `form:"status,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
GetAdsListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Ads `json:"list"`
|
||||
}
|
||||
GetAdsDetailRequest {
|
||||
Id int64 `form:"id"`
|
||||
}
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/ads
|
||||
group: admin/ads
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Create Ads"
|
||||
@handler CreateAds
|
||||
post / (CreateAdsRequest)
|
||||
|
||||
@doc "Update Ads"
|
||||
@handler UpdateAds
|
||||
put / (UpdateAdsRequest)
|
||||
|
||||
@doc "Delete Ads"
|
||||
@handler DeleteAds
|
||||
delete / (DeleteAdsRequest)
|
||||
|
||||
@doc "Get Ads List"
|
||||
@handler GetAdsList
|
||||
get /list (GetAdsListRequest) returns (GetAdsListResponse)
|
||||
|
||||
@doc "Get Ads Detail"
|
||||
@handler GetAdsDetail
|
||||
get /detail (GetAdsDetailRequest) returns (Ads)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Announcement API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
CreateAnnouncementRequest {
|
||||
Title string `json:"title" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
}
|
||||
UpdateAnnouncementRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Show *bool `json:"show"`
|
||||
Pinned *bool `json:"pinned"`
|
||||
Popup *bool `json:"popup"`
|
||||
}
|
||||
UpdateAnnouncementEnableRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Enable *bool `json:"enable" validate:"required"`
|
||||
}
|
||||
DeleteAnnouncementRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
GetAnnouncementListRequest {
|
||||
Page int64 `form:"page"`
|
||||
Size int64 `form:"size"`
|
||||
Show *bool `form:"show,omitempty"`
|
||||
Pinned *bool `form:"pinned,omitempty"`
|
||||
Popup *bool `form:"popup,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
GetAnnouncementListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Announcement `json:"list"`
|
||||
}
|
||||
GetAnnouncementRequest {
|
||||
Id int64 `form:"id" validate:"required"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/announcement
|
||||
group: admin/announcement
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Create announcement"
|
||||
@handler CreateAnnouncement
|
||||
post / (CreateAnnouncementRequest)
|
||||
|
||||
@doc "Update announcement"
|
||||
@handler UpdateAnnouncement
|
||||
put / (UpdateAnnouncementRequest)
|
||||
|
||||
@doc "Get announcement list"
|
||||
@handler GetAnnouncementList
|
||||
get /list (GetAnnouncementListRequest) returns (GetAnnouncementListResponse)
|
||||
|
||||
@doc "Delete announcement"
|
||||
@handler DeleteAnnouncement
|
||||
delete / (DeleteAnnouncementRequest)
|
||||
|
||||
@doc "Get announcement"
|
||||
@handler GetAnnouncement
|
||||
get /detail (GetAnnouncementRequest) returns (Announcement)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Auth Method Management"
|
||||
desc: "System auth method management"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.1.2"
|
||||
)
|
||||
|
||||
import (
|
||||
"../types.api"
|
||||
)
|
||||
|
||||
type (
|
||||
UpdateAuthMethodConfigRequest {
|
||||
Id int64 `json:"id"`
|
||||
Method string `json:"method"`
|
||||
Config interface{} `json:"config"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
GetAuthMethodConfigRequest {
|
||||
Method string `form:"method"`
|
||||
}
|
||||
GetAuthMethodListResponse {
|
||||
List []AuthMethodConfig `json:"list"`
|
||||
}
|
||||
|
||||
|
||||
TestSmsSendRequest {
|
||||
AreaCode string `json:"area_code" validate:"required"`
|
||||
Telephone string `json:"telephone" validate:"required"`
|
||||
}
|
||||
// Test email smtp request
|
||||
TestEmailSendRequest {
|
||||
Email string `json:"email" validate:"required"`
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/auth-method
|
||||
group: admin/authMethod
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get auth method list"
|
||||
@handler GetAuthMethodList
|
||||
get /list returns (GetAuthMethodListResponse)
|
||||
|
||||
@doc "Get auth method config"
|
||||
@handler GetAuthMethodConfig
|
||||
get /config (GetAuthMethodConfigRequest) returns (AuthMethodConfig)
|
||||
|
||||
@doc "Update auth method config"
|
||||
@handler UpdateAuthMethodConfig
|
||||
put /config (UpdateAuthMethodConfigRequest) returns (AuthMethodConfig)
|
||||
|
||||
|
||||
@doc "Test sms send"
|
||||
@handler TestSmsSend
|
||||
post /test_sms_send (TestSmsSendRequest)
|
||||
|
||||
@doc "Test email send"
|
||||
@handler TestEmailSend
|
||||
post /test_email_send (TestEmailSendRequest)
|
||||
|
||||
@doc "Get sms support platform"
|
||||
@handler GetSmsPlatform
|
||||
get /sms_platform returns (PlatformResponse)
|
||||
|
||||
@doc "Get email support platform"
|
||||
@handler GetEmailPlatform
|
||||
get /email_platform returns (PlatformResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Console API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
type (
|
||||
ServerTrafficData {
|
||||
ServerId int64 `json:"server_id"`
|
||||
Name string `json:"name"`
|
||||
Upload int64 `json:"upload"`
|
||||
Download int64 `json:"download"`
|
||||
}
|
||||
UserTrafficData {
|
||||
SID int64 `json:"sid"`
|
||||
Upload int64 `json:"upload"`
|
||||
Download int64 `json:"download"`
|
||||
}
|
||||
ServerTotalDataResponse {
|
||||
OnlineUserIPs int64 `json:"online_user_ips"`
|
||||
OnlineServers int64 `json:"online_servers"`
|
||||
OfflineServers int64 `json:"offline_servers"`
|
||||
TodayUpload int64 `json:"today_upload"`
|
||||
TodayDownload int64 `json:"today_download"`
|
||||
MonthlyUpload int64 `json:"monthly_upload"`
|
||||
MonthlyDownload int64 `json:"monthly_download"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
ServerTrafficRankingToday []ServerTrafficData `json:"server_traffic_ranking_today"`
|
||||
ServerTrafficRankingYesterday []ServerTrafficData `json:"server_traffic_ranking_yesterday"`
|
||||
UserTrafficRankingToday []UserTrafficData `json:"user_traffic_ranking_today"`
|
||||
UserTrafficRankingYesterday []UserTrafficData `json:"user_traffic_ranking_yesterday"`
|
||||
}
|
||||
UserStatistics {
|
||||
Date string `json:"date,omitempty"`
|
||||
Register int64 `json:"register"`
|
||||
NewOrderUsers int64 `json:"new_order_users"`
|
||||
RenewalOrderUsers int64 `json:"renewal_order_users"`
|
||||
List []UserStatistics `json:"list,omitempty"`
|
||||
}
|
||||
OrdersStatistics {
|
||||
Date string `json:"date,omitempty"`
|
||||
AmountTotal int64 `json:"amount_total"`
|
||||
NewOrderAmount int64 `json:"new_order_amount"`
|
||||
RenewalOrderAmount int64 `json:"renewal_order_amount"`
|
||||
List []OrdersStatistics `json:"list,omitempty"`
|
||||
}
|
||||
RevenueStatisticsResponse {
|
||||
Today OrdersStatistics `json:"today"`
|
||||
Monthly OrdersStatistics `json:"monthly"`
|
||||
All OrdersStatistics `json:"all"`
|
||||
}
|
||||
UserStatisticsResponse {
|
||||
Today UserStatistics `json:"today"`
|
||||
Monthly UserStatistics `json:"monthly"`
|
||||
All UserStatistics `json:"all"`
|
||||
}
|
||||
TicketWaitRelpyResponse {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/console
|
||||
group: admin/console
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Query server total data"
|
||||
@handler QueryServerTotalData
|
||||
get /server returns (ServerTotalDataResponse)
|
||||
|
||||
@doc "Query revenue statistics"
|
||||
@handler QueryRevenueStatistics
|
||||
get /revenue returns (RevenueStatisticsResponse)
|
||||
|
||||
@doc "Query user statistics"
|
||||
@handler QueryUserStatistics
|
||||
get /user returns (UserStatisticsResponse)
|
||||
|
||||
@doc "Query ticket wait reply"
|
||||
@handler QueryTicketWaitReply
|
||||
get /ticket returns (TicketWaitRelpyResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "coupon API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
CreateCouponRequest {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Code string `json:"code,omitempty"`
|
||||
Count int64 `json:"count,omitempty"`
|
||||
Type uint8 `json:"type" validate:"required"`
|
||||
Discount int64 `json:"discount" validate:"required"`
|
||||
StartTime int64 `json:"start_time" validate:"required"`
|
||||
ExpireTime int64 `json:"expire_time" validate:"required"`
|
||||
UserLimit int64 `json:"user_limit,omitempty"`
|
||||
Subscribe []int64 `json:"subscribe,omitempty"`
|
||||
UsedCount int64 `json:"used_count,omitempty"`
|
||||
Enable *bool `json:"enable,omitempty"`
|
||||
}
|
||||
UpdateCouponRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Code string `json:"code,omitempty"`
|
||||
Count int64 `json:"count,omitempty"`
|
||||
Type uint8 `json:"type" validate:"required"`
|
||||
Discount int64 `json:"discount" validate:"required"`
|
||||
StartTime int64 `json:"start_time" validate:"required"`
|
||||
ExpireTime int64 `json:"expire_time" validate:"required"`
|
||||
UserLimit int64 `json:"user_limit,omitempty"`
|
||||
Subscribe []int64 `json:"subscribe,omitempty"`
|
||||
UsedCount int64 `json:"used_count,omitempty"`
|
||||
Enable *bool `json:"enable,omitempty"`
|
||||
}
|
||||
DeleteCouponRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
BatchDeleteCouponRequest {
|
||||
Ids []int64 `json:"ids" validate:"required"`
|
||||
}
|
||||
GetCouponListRequest {
|
||||
Page int64 `form:"page" validate:"required"`
|
||||
Size int64 `form:"size" validate:"required"`
|
||||
Subscribe int64 `form:"subscribe,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
GetCouponListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Coupon `json:"list"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/coupon
|
||||
group: admin/coupon
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Create coupon"
|
||||
@handler CreateCoupon
|
||||
post / (CreateCouponRequest)
|
||||
|
||||
@doc "Update coupon"
|
||||
@handler UpdateCoupon
|
||||
put / (UpdateCouponRequest)
|
||||
|
||||
@doc "Delete coupon"
|
||||
@handler DeleteCoupon
|
||||
delete / (DeleteCouponRequest)
|
||||
|
||||
@doc "Batch delete coupon"
|
||||
@handler BatchDeleteCoupon
|
||||
delete /batch (BatchDeleteCouponRequest)
|
||||
|
||||
@doc "Get coupon list"
|
||||
@handler GetCouponList
|
||||
get /list (GetCouponListRequest) returns (GetCouponListResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "Device API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
)
|
||||
@@ -0,0 +1,78 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Document API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
CreateDocumentRequest {
|
||||
Title string `json:"title" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
Tags []string `json:"tags,omitempty" `
|
||||
Show *bool `json:"show"`
|
||||
}
|
||||
UpdateDocumentRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Title string `json:"title" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
Tags []string `json:"tags,omitempty" `
|
||||
Show *bool `json:"show"`
|
||||
}
|
||||
DeleteDocumentRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
BatchDeleteDocumentRequest {
|
||||
Ids []int64 `json:"ids" validate:"required"`
|
||||
}
|
||||
GetDocumentListRequest {
|
||||
Page int64 `form:"page" validate:"required"`
|
||||
Size int64 `form:"size" validate:"required"`
|
||||
Tag string `form:"tag,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
GetDocumentListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Document `json:"list"`
|
||||
}
|
||||
GetDocumentDetailRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/document
|
||||
group: admin/document
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Create document"
|
||||
@handler CreateDocument
|
||||
post / (CreateDocumentRequest)
|
||||
|
||||
@doc "Update document"
|
||||
@handler UpdateDocument
|
||||
put / (UpdateDocumentRequest)
|
||||
|
||||
@doc "Delete document"
|
||||
@handler DeleteDocument
|
||||
delete / (DeleteDocumentRequest)
|
||||
|
||||
@doc "Batch delete document"
|
||||
@handler BatchDeleteDocument
|
||||
delete /batch (BatchDeleteDocumentRequest)
|
||||
|
||||
@doc "Get document list"
|
||||
@handler GetDocumentList
|
||||
get /list (GetDocumentListRequest) returns (GetDocumentListResponse)
|
||||
|
||||
@doc "Get document detail"
|
||||
@handler GetDocumentDetail
|
||||
get /detail (GetDocumentDetailRequest) returns (Document)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Log API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
GetMessageLogListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Type string `form:"type"`
|
||||
Platform string `form:"platform,omitempty"`
|
||||
To string `form:"to,omitempty"`
|
||||
Subject string `form:"subject,omitempty"`
|
||||
Content string `form:"content,omitempty"`
|
||||
Status int `form:"status,omitempty"`
|
||||
}
|
||||
GetMessageLogListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []MessageLog `json:"list"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/log
|
||||
group: admin/log
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get message log list"
|
||||
@handler GetMessageLogList
|
||||
get /message/list (GetMessageLogListRequest) returns (GetMessageLogListResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "order API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
CreateOrderRequest {
|
||||
UserId int64 `json:"user_id" validate:"required"`
|
||||
Type uint8 `json:"type" validate:"required"`
|
||||
Quantity int64 `json:"quantity,omitempty"`
|
||||
Price int64 `json:"price" validate:"required"`
|
||||
Amount int64 `json:"amount" validate:"required"`
|
||||
Discount int64 `json:"discount,omitempty"`
|
||||
Coupon string `json:"coupon,omitempty"`
|
||||
CouponDiscount int64 `json:"coupon_discount,omitempty"`
|
||||
Commission int64 `json:"commission"`
|
||||
FeeAmount int64 `json:"fee_amount" validate:"required"`
|
||||
PaymentId int64 `json:"payment_id" validate:"required"`
|
||||
TradeNo string `json:"trade_no,omitempty"`
|
||||
Status uint8 `json:"status,omitempty"`
|
||||
SubscribeId int64 `json:"subscribe_id,omitempty"`
|
||||
}
|
||||
UpdateOrderStatusRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Status uint8 `json:"status" validate:"required"`
|
||||
PaymentId int64 `json:"payment_id,omitempty"`
|
||||
TradeNo string `json:"trade_no,omitempty"`
|
||||
}
|
||||
GetOrderListRequest {
|
||||
Page int64 `form:"page" validate:"required"`
|
||||
Size int64 `form:"size" validate:"required"`
|
||||
UserId int64 `form:"user_id,omitempty"`
|
||||
Status uint8 `form:"status,omitempty"`
|
||||
SubscribeId int64 `form:"subscribe_id,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
GetOrderListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Order `json:"list"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/order
|
||||
group: admin/order
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Create order"
|
||||
@handler CreateOrder
|
||||
post / (CreateOrderRequest)
|
||||
|
||||
@doc "Get order list"
|
||||
@handler GetOrderList
|
||||
get /list (GetOrderListRequest) returns (GetOrderListResponse)
|
||||
|
||||
@doc "Update order status"
|
||||
@handler UpdateOrderStatus
|
||||
put /status (UpdateOrderStatusRequest)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "payment API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
CreatePaymentMethodRequest {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Platform string `json:"platform" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
Config interface{} `json:"config" validate:"required"`
|
||||
FeeMode uint `json:"fee_mode"`
|
||||
FeePercent int64 `json:"fee_percent,omitempty"`
|
||||
FeeAmount int64 `json:"fee_amount,omitempty"`
|
||||
Enable *bool `json:"enable" validate:"required"`
|
||||
}
|
||||
UpdatePaymentMethodRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Platform string `json:"platform" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
Config interface{} `json:"config" validate:"required"`
|
||||
FeeMode uint `json:"fee_mode"`
|
||||
FeePercent int64 `json:"fee_percent,omitempty"`
|
||||
FeeAmount int64 `json:"fee_amount,omitempty"`
|
||||
Enable *bool `json:"enable" validate:"required"`
|
||||
}
|
||||
DeletePaymentMethodRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
GetPaymentMethodListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Platform string `form:"platform,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
Enable *bool `form:"enable,omitempty"`
|
||||
}
|
||||
GetPaymentMethodListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []PaymentMethodDetail `json:"list"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/payment
|
||||
group: admin/payment
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Create Payment Method"
|
||||
@handler CreatePaymentMethod
|
||||
post / (CreatePaymentMethodRequest) returns (PaymentConfig)
|
||||
|
||||
@doc "Update Payment Method"
|
||||
@handler UpdatePaymentMethod
|
||||
put / (UpdatePaymentMethodRequest) returns (PaymentConfig)
|
||||
|
||||
@doc "Delete Payment Method"
|
||||
@handler DeletePaymentMethod
|
||||
delete / (DeletePaymentMethodRequest)
|
||||
|
||||
@doc "Get Payment Method List"
|
||||
@handler GetPaymentMethodList
|
||||
get /list (GetPaymentMethodListRequest) returns (GetPaymentMethodListResponse)
|
||||
|
||||
@doc "Get supported payment platform"
|
||||
@handler GetPaymentPlatform
|
||||
get /platform returns (PlatformResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Node API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
GetNodeServerListRequest {
|
||||
Page int `form:"page" validate:"required"`
|
||||
Size int `form:"size" validate:"required"`
|
||||
Tag string `form:"tag,omitempty"`
|
||||
GroupId int64 `form:"group_id,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
GetNodeServerListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Server `json:"list"`
|
||||
}
|
||||
UpdateNodeRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Tags []string `json:"tags"`
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
ServerAddr string `json:"server_addr" validate:"required"`
|
||||
RelayMode string `json:"relay_mode"`
|
||||
RelayNode []NodeRelay `json:"relay_node"`
|
||||
SpeedLimit int `json:"speed_limit"`
|
||||
TrafficRatio float32 `json:"traffic_ratio"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
Protocol string `json:"protocol" validate:"required"`
|
||||
Config interface{} `json:"config" validate:"required"`
|
||||
Enable *bool `json:"enable"`
|
||||
Sort int64 `json:"sort"`
|
||||
}
|
||||
CreateNodeRequest {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Tags []string `json:"tags"`
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
ServerAddr string `json:"server_addr" validate:"required"`
|
||||
RelayMode string `json:"relay_mode"`
|
||||
RelayNode []NodeRelay `json:"relay_node"`
|
||||
SpeedLimit int `json:"speed_limit"`
|
||||
TrafficRatio float32 `json:"traffic_ratio"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
Protocol string `json:"protocol" validate:"required"`
|
||||
Config interface{} `json:"config" validate:"required"`
|
||||
Enable *bool `json:"enable"`
|
||||
Sort int64 `json:"sort"`
|
||||
}
|
||||
DeleteNodeRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
GetNodeGroupListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []ServerGroup `json:"list"`
|
||||
}
|
||||
CreateNodeGroupRequest {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
UpdateNodeGroupRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
DeleteNodeGroupRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
BatchDeleteNodeRequest {
|
||||
Ids []int64 `json:"ids" validate:"required"`
|
||||
}
|
||||
BatchDeleteNodeGroupRequest {
|
||||
Ids []int64 `json:"ids" validate:"required"`
|
||||
}
|
||||
GetNodeDetailRequest {
|
||||
Id int64 `form:"id" validate:"required"`
|
||||
}
|
||||
NodeSortRequest {
|
||||
Sort []SortItem `json:"sort"`
|
||||
}
|
||||
CreateRuleGroupRequest {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Icon string `json:"icon"`
|
||||
Tags []string `json:"tags"`
|
||||
Rules string `json:"rules"`
|
||||
Enable bool `json:"enable"`
|
||||
}
|
||||
UpdateRuleGroupRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Icon string `json:"icon"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Tags []string `json:"tags"`
|
||||
Rules string `json:"rules"`
|
||||
Enable bool `json:"enable"`
|
||||
}
|
||||
DeleteRuleGroupRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
GetRuleGroupResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []ServerRuleGroup `json:"list"`
|
||||
}
|
||||
GetNodeTagListResponse {
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/server
|
||||
group: admin/server
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get node tag list"
|
||||
@handler GetNodeTagList
|
||||
get /tag/list returns (GetNodeTagListResponse)
|
||||
|
||||
@doc "Get node list"
|
||||
@handler GetNodeList
|
||||
get /list (GetNodeServerListRequest) returns (GetNodeServerListResponse)
|
||||
|
||||
@doc "Get node detail"
|
||||
@handler GetNodeDetail
|
||||
get /detail (GetNodeDetailRequest) returns (Server)
|
||||
|
||||
@doc "Update node"
|
||||
@handler UpdateNode
|
||||
put / (UpdateNodeRequest)
|
||||
|
||||
@doc "Create node"
|
||||
@handler CreateNode
|
||||
post / (CreateNodeRequest)
|
||||
|
||||
@doc "Delete node"
|
||||
@handler DeleteNode
|
||||
delete / (DeleteNodeRequest)
|
||||
|
||||
@doc "Batch delete node"
|
||||
@handler BatchDeleteNode
|
||||
delete /batch (BatchDeleteNodeRequest)
|
||||
|
||||
@doc "Get node group list"
|
||||
@handler GetNodeGroupList
|
||||
get /group/list returns (GetNodeGroupListResponse)
|
||||
|
||||
@doc "Create node group"
|
||||
@handler CreateNodeGroup
|
||||
post /group (CreateNodeGroupRequest)
|
||||
|
||||
@doc "Update node group"
|
||||
@handler UpdateNodeGroup
|
||||
put /group (UpdateNodeGroupRequest)
|
||||
|
||||
@doc "Delete node group"
|
||||
@handler DeleteNodeGroup
|
||||
delete /group (DeleteNodeGroupRequest)
|
||||
|
||||
@doc "Batch delete node group"
|
||||
@handler BatchDeleteNodeGroup
|
||||
delete /group/batch (BatchDeleteNodeGroupRequest)
|
||||
|
||||
@doc "Node sort "
|
||||
@handler NodeSort
|
||||
post /sort (NodeSortRequest)
|
||||
|
||||
@doc "Create rule group"
|
||||
@handler CreateRuleGroup
|
||||
post /rule_group (CreateRuleGroupRequest)
|
||||
|
||||
@doc "Update rule group"
|
||||
@handler UpdateRuleGroup
|
||||
put /rule_group (UpdateRuleGroupRequest)
|
||||
|
||||
@doc "Delete rule group"
|
||||
@handler DeleteRuleGroup
|
||||
delete /rule_group (DeleteRuleGroupRequest)
|
||||
|
||||
@doc "Get rule group list"
|
||||
@handler GetRuleGroupList
|
||||
get /rule_group_list returns (GetRuleGroupResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Subscribe API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
GetSubscribeDetailsRequest {
|
||||
Id int64 `form:"id" validate:"required"`
|
||||
}
|
||||
CreateSubscribeGroupRequest {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
UpdateSubscribeGroupRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
GetSubscribeGroupListResponse {
|
||||
List []SubscribeGroup `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
DeleteSubscribeGroupRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
BatchDeleteSubscribeGroupRequest {
|
||||
Ids []int64 `json:"ids" validate:"required"`
|
||||
}
|
||||
CreateSubscribeRequest {
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
UnitPrice int64 `json:"unit_price"`
|
||||
UnitTime string `json:"unit_time"`
|
||||
Discount []SubscribeDiscount `json:"discount"`
|
||||
Replacement int64 `json:"replacement"`
|
||||
Inventory int64 `json:"inventory"`
|
||||
Traffic int64 `json:"traffic"`
|
||||
SpeedLimit int64 `json:"speed_limit"`
|
||||
DeviceLimit int64 `json:"device_limit"`
|
||||
Quota int64 `json:"quota"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
ServerGroup []int64 `json:"server_group"`
|
||||
Server []int64 `json:"server"`
|
||||
Show *bool `json:"show"`
|
||||
Sell *bool `json:"sell"`
|
||||
DeductionRatio int64 `json:"deduction_ratio"`
|
||||
AllowDeduction *bool `json:"allow_deduction"`
|
||||
ResetCycle int64 `json:"reset_cycle"`
|
||||
RenewalReset *bool `json:"renewal_reset"`
|
||||
}
|
||||
UpdateSubscribeRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
UnitPrice int64 `json:"unit_price"`
|
||||
UnitTime string `json:"unit_time"`
|
||||
Discount []SubscribeDiscount `json:"discount"`
|
||||
Replacement int64 `json:"replacement"`
|
||||
Inventory int64 `json:"inventory"`
|
||||
Traffic int64 `json:"traffic"`
|
||||
SpeedLimit int64 `json:"speed_limit"`
|
||||
DeviceLimit int64 `json:"device_limit"`
|
||||
Quota int64 `json:"quota"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
ServerGroup []int64 `json:"server_group"`
|
||||
Server []int64 `json:"server"`
|
||||
Show *bool `json:"show"`
|
||||
Sell *bool `json:"sell"`
|
||||
Sort int64 `json:"sort"`
|
||||
DeductionRatio int64 `json:"deduction_ratio"`
|
||||
AllowDeduction *bool `json:"allow_deduction"`
|
||||
ResetCycle int64 `json:"reset_cycle"`
|
||||
RenewalReset *bool `json:"renewal_reset"`
|
||||
}
|
||||
SubscribeSortRequest {
|
||||
Sort []SortItem `json:"sort"`
|
||||
}
|
||||
GetSubscribeListRequest {
|
||||
Page int64 `form:"page" validate:"required"`
|
||||
Size int64 `form:"size" validate:"required"`
|
||||
GroupId int64 `form:"group_id,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
|
||||
SubscribeItem {
|
||||
Subscribe
|
||||
|
||||
Sold int64 `json:"sold"`
|
||||
}
|
||||
|
||||
GetSubscribeListResponse {
|
||||
List []SubscribeItem `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
DeleteSubscribeRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
BatchDeleteSubscribeRequest {
|
||||
Ids []int64 `json:"ids" validate:"required"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/subscribe
|
||||
group: admin/subscribe
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Create subscribe group"
|
||||
@handler CreateSubscribeGroup
|
||||
post /group (CreateSubscribeGroupRequest)
|
||||
|
||||
@doc "Update subscribe group"
|
||||
@handler UpdateSubscribeGroup
|
||||
put /group (UpdateSubscribeGroupRequest)
|
||||
|
||||
@doc "Get subscribe group list"
|
||||
@handler GetSubscribeGroupList
|
||||
get /group/list returns (GetSubscribeGroupListResponse)
|
||||
|
||||
@doc "Delete subscribe group"
|
||||
@handler DeleteSubscribeGroup
|
||||
delete /group (DeleteSubscribeGroupRequest)
|
||||
|
||||
@doc "Batch delete subscribe group"
|
||||
@handler BatchDeleteSubscribeGroup
|
||||
delete /group/batch (BatchDeleteSubscribeGroupRequest)
|
||||
|
||||
@doc "Create subscribe"
|
||||
@handler CreateSubscribe
|
||||
post / (CreateSubscribeRequest)
|
||||
|
||||
@doc "Update subscribe"
|
||||
@handler UpdateSubscribe
|
||||
put / (UpdateSubscribeRequest)
|
||||
|
||||
@doc "Get subscribe list"
|
||||
@handler GetSubscribeList
|
||||
get /list (GetSubscribeListRequest) returns (GetSubscribeListResponse)
|
||||
|
||||
@doc "Delete subscribe"
|
||||
@handler DeleteSubscribe
|
||||
delete / (DeleteSubscribeRequest)
|
||||
|
||||
@doc "Batch delete subscribe"
|
||||
@handler BatchDeleteSubscribe
|
||||
delete /batch (BatchDeleteSubscribeRequest)
|
||||
|
||||
@doc "Get subscribe details"
|
||||
@handler GetSubscribeDetails
|
||||
get /details (GetSubscribeDetailsRequest) returns (Subscribe)
|
||||
|
||||
@doc "Subscribe sort"
|
||||
@handler SubscribeSort
|
||||
post /sort (SubscribeSortRequest)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "System API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
// Update application request
|
||||
UpdateApplicationRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Icon string `json:"icon"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
SubscribeType string `json:"subscribe_type"`
|
||||
Platform ApplicationPlatform `json:"platform"`
|
||||
}
|
||||
// Create application request
|
||||
CreateApplicationRequest {
|
||||
Icon string `json:"icon"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
SubscribeType string `json:"subscribe_type"`
|
||||
Platform ApplicationPlatform `json:"platform"`
|
||||
}
|
||||
// Update application request
|
||||
UpdateApplicationVersionRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Url string `json:"url"`
|
||||
Version string `json:"version" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Platform string `json:"platform" validate:"required,oneof=windows mac linux android ios harmony"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
ApplicationId int64 `json:"application_id" validate:"required"`
|
||||
}
|
||||
// Create application request
|
||||
CreateApplicationVersionRequest {
|
||||
Url string `json:"url"`
|
||||
Version string `json:"version" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Platform string `json:"platform" validate:"required,oneof=windows mac linux android ios harmony"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
ApplicationId int64 `json:"application_id" validate:"required"`
|
||||
}
|
||||
// Delete application request
|
||||
DeleteApplicationRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
// Delete application request
|
||||
DeleteApplicationVersionRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
}
|
||||
GetNodeMultiplierResponse {
|
||||
Periods []TimePeriod `json:"periods"`
|
||||
}
|
||||
// SetNodeMultiplierRequest
|
||||
SetNodeMultiplierRequest {
|
||||
Periods []TimePeriod `json:"periods"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/system
|
||||
group: admin/system
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get site config"
|
||||
@handler GetSiteConfig
|
||||
get /site_config returns (SiteConfig)
|
||||
|
||||
@doc "Update site config"
|
||||
@handler UpdateSiteConfig
|
||||
put /site_config (SiteConfig)
|
||||
|
||||
@doc "Get subscribe config"
|
||||
@handler GetSubscribeConfig
|
||||
get /subscribe_config returns (SubscribeConfig)
|
||||
|
||||
@doc "Update subscribe config"
|
||||
@handler UpdateSubscribeConfig
|
||||
put /subscribe_config (SubscribeConfig)
|
||||
|
||||
@doc "Get subscribe type"
|
||||
@handler GetSubscribeType
|
||||
get /subscribe_type returns (SubscribeType)
|
||||
|
||||
@doc "update application config"
|
||||
@handler UpdateApplicationConfig
|
||||
put /application_config (ApplicationConfig)
|
||||
|
||||
@doc "get application config"
|
||||
@handler GetApplicationConfig
|
||||
get /application_config returns (ApplicationConfig)
|
||||
|
||||
@doc "Get application"
|
||||
@handler GetApplication
|
||||
get /application returns (ApplicationResponse)
|
||||
|
||||
@doc "Update application"
|
||||
@handler UpdateApplication
|
||||
put /application (UpdateApplicationRequest)
|
||||
|
||||
@doc "Create application"
|
||||
@handler CreateApplication
|
||||
post /application (CreateApplicationRequest)
|
||||
|
||||
@doc "Delete application"
|
||||
@handler DeleteApplication
|
||||
delete /application (DeleteApplicationRequest)
|
||||
|
||||
@doc "Update application version"
|
||||
@handler UpdateApplicationVersion
|
||||
put /application_version (UpdateApplicationVersionRequest)
|
||||
|
||||
@doc "Create application version"
|
||||
@handler CreateApplicationVersion
|
||||
post /application_version (CreateApplicationVersionRequest)
|
||||
|
||||
@doc "Delete application"
|
||||
@handler DeleteApplicationVersion
|
||||
delete /application_version (DeleteApplicationVersionRequest)
|
||||
|
||||
@doc "Get register config"
|
||||
@handler GetRegisterConfig
|
||||
get /register_config returns (RegisterConfig)
|
||||
|
||||
@doc "Update register config"
|
||||
@handler UpdateRegisterConfig
|
||||
put /register_config (RegisterConfig)
|
||||
|
||||
@doc "Get verify config"
|
||||
@handler GetVerifyConfig
|
||||
get /verify_config returns (VerifyConfig)
|
||||
|
||||
@doc "Update verify config"
|
||||
@handler UpdateVerifyConfig
|
||||
put /verify_config (VerifyConfig)
|
||||
|
||||
@doc "Get node config"
|
||||
@handler GetNodeConfig
|
||||
get /node_config returns (NodeConfig)
|
||||
|
||||
@doc "Update node config"
|
||||
@handler UpdateNodeConfig
|
||||
put /node_config (NodeConfig)
|
||||
|
||||
@doc "Get invite config"
|
||||
@handler GetInviteConfig
|
||||
get /invite_config returns (InviteConfig)
|
||||
|
||||
@doc "Update invite config"
|
||||
@handler UpdateInviteConfig
|
||||
put /invite_config (InviteConfig)
|
||||
|
||||
@doc "Get Team of Service Config"
|
||||
@handler GetTosConfig
|
||||
get /tos_config returns (TosConfig)
|
||||
|
||||
@doc "Update Team of Service Config"
|
||||
@handler UpdateTosConfig
|
||||
put /tos_config (TosConfig)
|
||||
|
||||
@doc "get Privacy Policy Config"
|
||||
@handler GetPrivacyPolicyConfig
|
||||
get /privacy returns (PrivacyPolicyConfig)
|
||||
|
||||
@doc "Update Privacy Policy Config"
|
||||
@handler UpdatePrivacyPolicyConfig
|
||||
put /privacy (PrivacyPolicyConfig)
|
||||
|
||||
@doc "Get Currency Config"
|
||||
@handler GetCurrencyConfig
|
||||
get /currency_config returns (CurrencyConfig)
|
||||
|
||||
@doc "Update Currency Config"
|
||||
@handler UpdateCurrencyConfig
|
||||
put /currency_config (CurrencyConfig)
|
||||
|
||||
@doc "setting telegram bot"
|
||||
@handler SettingTelegramBot
|
||||
post /setting_telegram_bot
|
||||
|
||||
@doc "Get Node Multiplier"
|
||||
@handler GetNodeMultiplier
|
||||
get /get_node_multiplier returns (GetNodeMultiplierResponse)
|
||||
|
||||
@doc "Set Node Multiplier"
|
||||
@handler SetNodeMultiplier
|
||||
post /set_node_multiplier (SetNodeMultiplierRequest)
|
||||
|
||||
@doc "Get Verify Code Config"
|
||||
@handler GetVerifyCodeConfig
|
||||
get /verify_code_config returns (VerifyCodeConfig)
|
||||
|
||||
@doc "Update Verify Code Config"
|
||||
@handler UpdateVerifyCodeConfig
|
||||
put /verify_code_config (VerifyCodeConfig)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Ticket API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
UpdateTicketStatusRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Status *uint8 `json:"status" validate:"required"`
|
||||
}
|
||||
GetTicketListRequest {
|
||||
Page int64 `form:"page"`
|
||||
Size int64 `form:"size"`
|
||||
UserId int64 `form:"user_id,omitempty"`
|
||||
Status *uint8 `form:"status,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
GetTicketListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Ticket `json:"list"`
|
||||
}
|
||||
GetTicketRequest {
|
||||
Id int64 `form:"id" validate:"required"`
|
||||
}
|
||||
CreateTicketFollowRequest {
|
||||
TicketId int64 `json:"ticket_id" validate:"required"`
|
||||
From string `json:"from" validate:"required"`
|
||||
Type uint8 `json:"type" validate:"required"`
|
||||
Content string `json:"content" validate:"required"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/ticket
|
||||
group: admin/ticket
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get ticket list"
|
||||
@handler GetTicketList
|
||||
get /list (GetTicketListRequest) returns (GetTicketListResponse)
|
||||
|
||||
@doc "Get ticket detail"
|
||||
@handler GetTicket
|
||||
get /detail (GetTicketRequest) returns (Ticket)
|
||||
|
||||
@doc "Update ticket status"
|
||||
@handler UpdateTicketStatus
|
||||
put / (UpdateTicketStatusRequest)
|
||||
|
||||
@doc "Create ticket follow"
|
||||
@handler CreateTicketFollow
|
||||
post /follow (CreateTicketFollowRequest)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "Tools Api"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
LogResponse {
|
||||
List interface{} `json:"list"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/tool
|
||||
group: admin/tool
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
|
||||
service ppanel {
|
||||
@doc "Get System Log"
|
||||
@handler GetSystemLog
|
||||
get /log returns (LogResponse)
|
||||
|
||||
@doc "Restart System"
|
||||
@handler RestartSystem
|
||||
get /restart
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "User API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import (
|
||||
"../types.api"
|
||||
)
|
||||
|
||||
type (
|
||||
// GetUserListRequest
|
||||
GetUserListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Search string `form:"search,omitempty"`
|
||||
UserId *int64 `form:"user_id,omitempty"`
|
||||
SubscribeId *int64 `form:"subscribe_id,omitempty"`
|
||||
UserSubscribeId *int64 `form:"user_subscribe_id,omitempty"`
|
||||
}
|
||||
// GetUserListResponse
|
||||
GetUserListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []User `json:"list"`
|
||||
}
|
||||
// GetUserDetail
|
||||
GetDetailRequest {
|
||||
Id int64 `form:"id" validate:"required"`
|
||||
}
|
||||
UpdateUserBasiceInfoRequest {
|
||||
UserId int64 `json:"user_id" validate:"required"`
|
||||
Password string `json:"password"`
|
||||
Avatar string `json:"avatar"`
|
||||
Balance int64 `json:"balance"`
|
||||
Commission int64 `json:"commission"`
|
||||
GiftAmount int64 `json:"gift_amount"`
|
||||
Telegram int64 `json:"telegram"`
|
||||
ReferCode string `json:"refer_code"`
|
||||
RefererId int64 `json:"referer_id"`
|
||||
Enable bool `json:"enable"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
}
|
||||
UpdateUserNotifySettingRequest {
|
||||
UserId int64 `json:"user_id" validate:"required"`
|
||||
EnableBalanceNotify bool `json:"enable_balance_notify"`
|
||||
EnableLoginNotify bool `json:"enable_login_notify"`
|
||||
EnableSubscribeNotify bool `json:"enable_subscribe_notify"`
|
||||
EnableTradeNotify bool `json:"enable_trade_notify"`
|
||||
}
|
||||
CreateUserRequest {
|
||||
Email string `json:"email"`
|
||||
Telephone string `json:"telephone"`
|
||||
TelephoneAreaCode string `json:"telephone_area_code"`
|
||||
Password string `json:"password"`
|
||||
ProductId int64 `json:"product_id"`
|
||||
Duration int64 `json:"duration"`
|
||||
RefererUser string `json:"referer_user"`
|
||||
ReferCode string `json:"refer_code"`
|
||||
Balance int64 `json:"balance"`
|
||||
Commission int64 `json:"commission"`
|
||||
GiftAmount int64 `json:"gift_amount"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
}
|
||||
UserSubscribeDetail {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
User User `json:"user"`
|
||||
OrderId int64 `json:"order_id"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Subscribe Subscribe `json:"subscribe"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
ExpireTime int64 `json:"expire_time"`
|
||||
ResetTime int64 `json:"reset_time"`
|
||||
Traffic int64 `json:"traffic"`
|
||||
Download int64 `json:"download"`
|
||||
Upload int64 `json:"upload"`
|
||||
Token string `json:"token"`
|
||||
Status uint8 `json:"status"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
BatchDeleteUserRequest {
|
||||
Ids []int64 `json:"ids" validate:"required"`
|
||||
}
|
||||
DeleteUserDeivceRequest {
|
||||
Id int64 `json:"id"`
|
||||
}
|
||||
KickOfflineRequest {
|
||||
Id int64 `json:"id"`
|
||||
}
|
||||
CreateUserAuthMethodRequest {
|
||||
UserId int64 `json:"user_id"`
|
||||
AuthType string `json:"auth_type"`
|
||||
AuthIdentifier string `json:"auth_identifier"`
|
||||
}
|
||||
DeleteUserAuthMethodRequest {
|
||||
UserId int64 `json:"user_id"`
|
||||
AuthType string `json:"auth_type"`
|
||||
}
|
||||
UpdateUserAuthMethodRequest {
|
||||
UserId int64 `json:"user_id"`
|
||||
AuthType string `json:"auth_type"`
|
||||
AuthIdentifier string `json:"auth_identifier"`
|
||||
}
|
||||
GetUserAuthMethodRequest {
|
||||
UserId int64 `json:"user_id"`
|
||||
}
|
||||
GetUserAuthMethodResponse {
|
||||
AuthMethods []UserAuthMethod `json:"auth_methods"`
|
||||
}
|
||||
GetUserSubscribeListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
UserId int64 `form:"user_id"`
|
||||
}
|
||||
GetUserSubscribeListResponse {
|
||||
List []UserSubscribe `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
GetUserSubscribeLogsRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
UserId int64 `form:"user_id"`
|
||||
SubscribeId int64 `form:"subscribe_id,omitempty"`
|
||||
}
|
||||
GetUserSubscribeLogsResponse {
|
||||
List []UserSubscribeLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
GetUserSubscribeDevicesRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
UserId int64 `form:"user_id"`
|
||||
SubscribeId int64 `form:"subscribe_id"`
|
||||
}
|
||||
GetUserSubscribeDevicesResponse {
|
||||
List []UserDevice `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
CreateUserSubscribeRequest {
|
||||
UserId int64 `json:"user_id"`
|
||||
ExpiredAt int64 `json:"expired_at"`
|
||||
Traffic int64 `json:"traffic"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
}
|
||||
UpdateUserSubscribeRequest {
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Traffic int64 `json:"traffic"`
|
||||
ExpiredAt int64 `json:"expired_at"`
|
||||
Upload int64 `json:"upload"`
|
||||
Download int64 `json:"download"`
|
||||
}
|
||||
GetUserLoginLogsRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
UserId int64 `form:"user_id"`
|
||||
}
|
||||
GetUserLoginLogsResponse {
|
||||
List []UserLoginLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
DeleteUserSubscribeRequest {
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
}
|
||||
GetUserSubscribeByIdRequest {
|
||||
Id int64 `form:"id" validate:"required"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/admin/user
|
||||
group: admin/user
|
||||
jwt: JwtAuth
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get user list"
|
||||
@handler GetUserList
|
||||
get /list (GetUserListRequest) returns (GetUserListResponse)
|
||||
|
||||
@doc "Get user detail"
|
||||
@handler GetUserDetail
|
||||
get /detail (GetDetailRequest) returns (User)
|
||||
|
||||
@doc "Update user basic info"
|
||||
@handler UpdateUserBasicInfo
|
||||
put /basic (UpdateUserBasiceInfoRequest)
|
||||
|
||||
@doc "Update user notify setting"
|
||||
@handler UpdateUserNotifySetting
|
||||
put /notify (UpdateUserNotifySettingRequest)
|
||||
|
||||
@doc "Delete user"
|
||||
@handler DeleteUser
|
||||
delete / (GetDetailRequest)
|
||||
|
||||
@doc "Current user"
|
||||
@handler CurrentUser
|
||||
get /current returns (User)
|
||||
|
||||
@doc "Batch delete user"
|
||||
@handler BatchDeleteUser
|
||||
delete /batch (BatchDeleteUserRequest)
|
||||
|
||||
@doc "Create user"
|
||||
@handler CreateUser
|
||||
post / (CreateUserRequest)
|
||||
|
||||
@doc "User device"
|
||||
@handler UpdateUserDevice
|
||||
put /device (UserDevice)
|
||||
|
||||
@doc "Delete user device"
|
||||
@handler DeleteUserDevice
|
||||
delete /device (DeleteUserDeivceRequest)
|
||||
|
||||
@doc "kick offline user device"
|
||||
@handler KickOfflineByUserDevice
|
||||
put /device/kick_offline (KickOfflineRequest)
|
||||
|
||||
@doc "Create user auth method"
|
||||
@handler CreateUserAuthMethod
|
||||
post /auth_method (CreateUserAuthMethodRequest)
|
||||
|
||||
@doc "Delete user auth method"
|
||||
@handler DeleteUserAuthMethod
|
||||
delete /auth_method (DeleteUserAuthMethodRequest)
|
||||
|
||||
@doc "Update user auth method"
|
||||
@handler UpdateUserAuthMethod
|
||||
put /auth_method (UpdateUserAuthMethodRequest)
|
||||
|
||||
@doc "Get user auth method"
|
||||
@handler GetUserAuthMethod
|
||||
get /auth_method (GetUserAuthMethodRequest) returns (GetUserAuthMethodResponse)
|
||||
|
||||
@doc "Get user subcribe"
|
||||
@handler GetUserSubscribe
|
||||
get /subscribe (GetUserSubscribeListRequest) returns (GetUserSubscribeListResponse)
|
||||
|
||||
@doc "Get user subcribe by id"
|
||||
@handler GetUserSubscribeById
|
||||
get /subscribe/detail (GetUserSubscribeByIdRequest) returns (UserSubscribeDetail)
|
||||
|
||||
@doc "Get user subcribe logs"
|
||||
@handler GetUserSubscribeLogs
|
||||
get /subscribe/logs (GetUserSubscribeLogsRequest) returns (GetUserSubscribeLogsResponse)
|
||||
|
||||
@doc "Get user subcribe traffic logs"
|
||||
@handler GetUserSubscribeTrafficLogs
|
||||
get /subscribe/traffic_logs (GetUserSubscribeTrafficLogsRequest) returns (GetUserSubscribeTrafficLogsResponse)
|
||||
|
||||
@doc "Get user subcribe devices"
|
||||
@handler GetUserSubscribeDevices
|
||||
get /subscribe/device (GetUserSubscribeDevicesRequest) returns (GetUserSubscribeDevicesResponse)
|
||||
|
||||
@doc "Create user subcribe"
|
||||
@handler CreateUserSubscribe
|
||||
post /subscribe (CreateUserSubscribeRequest)
|
||||
|
||||
@doc "Update user subcribe"
|
||||
@handler UpdateUserSubscribe
|
||||
put /subscribe (UpdateUserSubscribeRequest)
|
||||
|
||||
@doc "Delete user subcribe"
|
||||
@handler DeleteUserSubscribe
|
||||
delete /subscribe (DeleteUserSubscribeRequest)
|
||||
|
||||
@doc "Get user login logs"
|
||||
@handler GetUserLoginLogs
|
||||
get /login/logs (GetUserLoginLogsRequest) returns (GetUserLoginLogsResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Announcement API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
|
||||
@server (
|
||||
prefix: v1/app/announcement
|
||||
group: app/announcement
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Query announcement"
|
||||
@handler QueryAnnouncement
|
||||
get /list (QueryAnnouncementRequest) returns (QueryAnnouncementResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "App Auth Api"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import (
|
||||
"../types.api"
|
||||
)
|
||||
|
||||
type (
|
||||
AppAuthCheckRequest {
|
||||
Method string `json:"method" validate:"required" validate:"required,oneof=device email mobile"`
|
||||
Account string `json:"account"`
|
||||
Identifier string `json:"identifier" validate:"required"`
|
||||
UserAgent string `json:"user_agent" validate:"required,oneof=windows mac linux android ios harmony"`
|
||||
AreaCode string `json:"area_code"`
|
||||
}
|
||||
AppAuthCheckResponse {
|
||||
Status bool
|
||||
}
|
||||
AppAuthRequest {
|
||||
Method string `json:"method" validate:"required" validate:"required,oneof=device email mobile"`
|
||||
Account string `json:"account"`
|
||||
Password string `json:"password"`
|
||||
Identifier string `json:"identifier" validate:"required"`
|
||||
UserAgent string `json:"user_agent" validate:"required,oneof=windows mac linux android ios harmony"`
|
||||
Code string `json:"code"`
|
||||
Invite string `json:"invite"`
|
||||
AreaCode string `json:"area_code"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
AppAuthRespone {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
AppSendCodeRequest {
|
||||
Method string `json:"method" validate:"required" validate:"required,oneof=email mobile"`
|
||||
Account string `json:"account"`
|
||||
AreaCode string `json:"area_code"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
AppSendCodeRespone {
|
||||
Status bool `json:"status"`
|
||||
Code string `json:"code,omitempty"`
|
||||
}
|
||||
AppConfigRequest {
|
||||
UserAgent string `json:"user_agent" validate:"required,oneof=windows mac linux android ios harmony"`
|
||||
}
|
||||
AppConfigResponse {
|
||||
EncryptionKey string `json:"encryption_key"`
|
||||
EncryptionMethod string `json:"encryption_method"`
|
||||
Domains []string `json:"domains"`
|
||||
StartupPicture string `json:"startup_picture"`
|
||||
StartupPictureSkipTime int64 `json:"startup_picture_skip_time"`
|
||||
Application AppInfo `json:"applications"`
|
||||
OfficialEmail string `json:"official_email"`
|
||||
OfficialWebsite string `json:"official_website"`
|
||||
OfficialTelegram string `json:"official_telegram"`
|
||||
OfficialTelephone string `json:"official_telephone"`
|
||||
InvitationLink string `json:"invitation_link"`
|
||||
KrWebsiteId string `json:"kr_website_id"`
|
||||
}
|
||||
AppInfo {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Url string `json:"url"`
|
||||
Version string `json:"version"`
|
||||
VersionDescription string `json:"version_description"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
}
|
||||
)
|
||||
|
||||
@server(
|
||||
prefix: v1/app/auth
|
||||
group: app/auth
|
||||
middleware: AppMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Check Account"
|
||||
@handler Check
|
||||
post /check (AppAuthCheckRequest) returns (AppAuthCheckResponse)
|
||||
|
||||
@doc "Login"
|
||||
@handler Login
|
||||
post /login (AppAuthRequest) returns (AppAuthRespone)
|
||||
|
||||
@doc "Register"
|
||||
@handler Register
|
||||
post /register (AppAuthRequest) returns (AppAuthRespone)
|
||||
|
||||
@doc "Reset Password"
|
||||
@handler ResetPassword
|
||||
post /reset_password (AppAuthRequest) returns (AppAuthRespone)
|
||||
|
||||
@doc "GetAppConfig"
|
||||
@handler GetAppConfig
|
||||
post /config (AppConfigRequest) returns (AppConfigResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "Document API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
@server (
|
||||
prefix: v1/app/document
|
||||
group: app/document
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
|
||||
service ppanel {
|
||||
@doc "Get document list"
|
||||
@handler QueryDocumentList
|
||||
get /list returns (QueryDocumentListResponse)
|
||||
|
||||
@doc "Get document detail"
|
||||
@handler QueryDocumentDetail
|
||||
get /detail (QueryDocumentDetailRequest) returns (Document)
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
syntax = "v1"
|
||||
|
||||
|
||||
info(
|
||||
title: "App Node Api"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type(
|
||||
|
||||
|
||||
AppRuleGroupListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []ServerRuleGroup `json:"list"`
|
||||
}
|
||||
|
||||
AppUserSubscbribeNodeRequest {
|
||||
Id int64 `form:"id" validate:"required"`
|
||||
}
|
||||
|
||||
AppUserSubscbribeNodeResponse{
|
||||
List []AppUserSubscbribeNode `json:"list"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/app/node
|
||||
group: app/node
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
|
||||
service ppanel {
|
||||
|
||||
|
||||
|
||||
@doc "Get Node list"
|
||||
@handler GetNodeList
|
||||
get /list (AppUserSubscbribeNodeRequest) returns(AppUserSubscbribeNodeResponse)
|
||||
|
||||
@doc "Get rule group list"
|
||||
@handler GetRuleGroupList
|
||||
get /rule_group_list returns (AppRuleGroupListResponse)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Order API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import (
|
||||
"../types.api"
|
||||
)
|
||||
|
||||
|
||||
@server (
|
||||
prefix: v1/app/order
|
||||
group: app/order
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Pre create order"
|
||||
@handler PreCreateOrder
|
||||
post /pre (PurchaseOrderRequest) returns (PreOrderResponse)
|
||||
|
||||
@doc "purchase Subscription"
|
||||
@handler Purchase
|
||||
post /purchase (PurchaseOrderRequest) returns (PurchaseOrderResponse)
|
||||
|
||||
@doc "Renewal Subscription"
|
||||
@handler Renewal
|
||||
post /renewal (RenewalOrderRequest) returns (RenewalOrderResponse)
|
||||
|
||||
@doc "Reset traffic"
|
||||
@handler ResetTraffic
|
||||
post /reset (ResetTrafficOrderRequest) returns (ResetTrafficOrderResponse)
|
||||
|
||||
@doc "Recharge"
|
||||
@handler Recharge
|
||||
post /recharge (RechargeOrderRequest) returns (RechargeOrderResponse)
|
||||
|
||||
@doc "Checkout order"
|
||||
@handler CheckoutOrder
|
||||
post /checkout (CheckoutOrderRequest) returns (CheckoutOrderResponse)
|
||||
|
||||
@doc "Close order"
|
||||
@handler CloseOrder
|
||||
post /close (CloseOrderRequest)
|
||||
|
||||
@doc "Get order"
|
||||
@handler QueryOrderDetail
|
||||
get /detail (QueryOrderDetailRequest) returns (OrderDetail)
|
||||
|
||||
@doc "Get order list"
|
||||
@handler QueryOrderList
|
||||
get /list (QueryOrderListRequest) returns (QueryOrderListResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "payment API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
@server (
|
||||
prefix: v1/app/payment
|
||||
group: app/payment
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get available payment methods"
|
||||
@handler GetAvailablePaymentMethods
|
||||
get /methods returns (GetAvailablePaymentMethodsResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "Subscribe API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
|
||||
type (
|
||||
QueryUserSubscribeResp {
|
||||
Data []UserSubscribeData `json:"data"`
|
||||
}
|
||||
|
||||
UserSubscribeData {
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
}
|
||||
|
||||
|
||||
UserSubscribeResetPeriodRequest {
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
}
|
||||
|
||||
UserSubscribeResetPeriodResponse {
|
||||
Status bool `json:"status"`
|
||||
}
|
||||
|
||||
AppUserSubscribeRequest {
|
||||
ContainsNodes *bool `form:"contains_nodes"`
|
||||
}
|
||||
|
||||
AppUserSubscbribeResponse {
|
||||
List []AppUserSubcbribe `json:"list"`
|
||||
}
|
||||
)
|
||||
|
||||
@server(
|
||||
prefix: v1/app/subscribe
|
||||
group: app/subscribe
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
|
||||
|
||||
service ppanel {
|
||||
@doc "Get subscribe list"
|
||||
@handler QuerySubscribeList
|
||||
get /list returns (QuerySubscribeListResponse)
|
||||
|
||||
@doc "Get subscribe group list"
|
||||
@handler QuerySubscribeGroupList
|
||||
get /group/list returns (QuerySubscribeGroupListResponse)
|
||||
|
||||
@doc "Get application config"
|
||||
@handler QueryApplicationConfig
|
||||
get /application/config returns (ApplicationResponse)
|
||||
|
||||
@doc "Get Already subscribed to package"
|
||||
@handler QueryUserAlreadySubscribe
|
||||
get /user/already_subscribe returns (QueryUserSubscribeResp)
|
||||
|
||||
|
||||
@doc "Get Available subscriptions for users"
|
||||
@handler QueryUserAvailableUserSubscribe
|
||||
get /user/available_subscribe (AppUserSubscribeRequest) returns (AppUserSubscbribeResponse)
|
||||
|
||||
@doc "Reset user subscription period"
|
||||
@handler ResetUserSubscribePeriod
|
||||
post /reset/period (UserSubscribeResetPeriodRequest) returns (UserSubscribeResetPeriodResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "App User Api"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import (
|
||||
"../types.api"
|
||||
)
|
||||
|
||||
type (
|
||||
UserInfoResponse {
|
||||
Id int64 `json:"id"`
|
||||
Balance int64 `json:"balance"`
|
||||
Email string `json:"email"`
|
||||
RefererId int64 `json:"referer_id"`
|
||||
ReferCode string `json:"refer_code"`
|
||||
Avatar string `json:"avatar"`
|
||||
AreaCode string `json:"area_code"`
|
||||
Telephone string `json:"telephone"`
|
||||
Devices []UserDevice `json:"devices"`
|
||||
AuthMethods []UserAuthMethod `json:"auth_methods"`
|
||||
}
|
||||
UpdatePasswordRequeset {
|
||||
Password string `json:"password"`
|
||||
NewPassword string `json:"new_password"`
|
||||
}
|
||||
DeleteAccountRequest {
|
||||
Method string `json:"method" validate:"required" validate:"required,oneof=email telephone device"`
|
||||
Code string `json:"code"`
|
||||
}
|
||||
|
||||
GetUserOnlineTimeStatisticsResponse{
|
||||
WeeklyStats []WeeklyStat`json:"weekly_stats"`
|
||||
ConnectionRecords ConnectionRecords`json:"connection_records"`
|
||||
}
|
||||
|
||||
WeeklyStat{
|
||||
Day int `json:"day"`
|
||||
DayName string `json:"day_name"`
|
||||
Hours float64 `json:"hours"`
|
||||
}
|
||||
ConnectionRecords{
|
||||
CurrentContinuousDays int64 `json:"current_continuous_days"`
|
||||
HistoryContinuousDays int64 `json:"history_continuous_days"`
|
||||
LongestSingleConnection int64 `json:"longest_single_connection"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/app/user
|
||||
group: app/user
|
||||
middleware: AppMiddleware,AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "query user info"
|
||||
@handler QueryUserInfo
|
||||
get /info returns (UserInfoResponse)
|
||||
|
||||
@doc "Update Password "
|
||||
@handler UpdatePassword
|
||||
put /password (UpdatePasswordRequeset)
|
||||
|
||||
@doc "Delete Account"
|
||||
@handler DeleteAccount
|
||||
delete /account (DeleteAccountRequest)
|
||||
|
||||
@doc "Get user subcribe traffic logs"
|
||||
@handler GetUserSubscribeTrafficLogs
|
||||
get /subscribe/traffic_logs (GetUserSubscribeTrafficLogsRequest) returns (GetUserSubscribeTrafficLogsResponse)
|
||||
|
||||
@doc "Get user online time total"
|
||||
@handler GetUserOnlineTimeStatistics
|
||||
get /online_time/statistics returns (GetUserOnlineTimeStatisticsResponse)
|
||||
|
||||
@doc "Query User Affiliate List"
|
||||
@handler QueryUserAffiliateList
|
||||
get /affiliate/list (QueryUserAffiliateListRequest) returns (QueryUserAffiliateListResponse)
|
||||
|
||||
@doc "Query User Affiliate Count"
|
||||
@handler QueryUserAffiliate
|
||||
get /affiliate/count returns (QueryUserAffiliateCountResponse)
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "App Heartbeat Api"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
|
||||
@server(
|
||||
prefix: v1/app/ws
|
||||
group: app/ws
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
|
||||
|
||||
service ppanel {
|
||||
@doc "App heartbeat"
|
||||
@handler AppWs
|
||||
get /:userid/:identifier
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "User auth API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
type (
|
||||
// User login request
|
||||
UserLoginRequest {
|
||||
Email string `json:"email" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
UserAgent string `header:"User-Agent"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
// Check user is exist request
|
||||
CheckUserRequest {
|
||||
Email string `form:"email" validate:"required"`
|
||||
}
|
||||
// User login response
|
||||
CheckUserResponse {
|
||||
exist bool `json:"exist"`
|
||||
}
|
||||
// User login response
|
||||
UserRegisterRequest {
|
||||
Email string `json:"email" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Invite string `json:"invite,optional"`
|
||||
Code string `json:"code,optional"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
UserAgent string `header:"User-Agent"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
// User login response
|
||||
ResetPasswordRequest {
|
||||
Email string `json:"email" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Code string `json:"code,optional"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
UserAgent string `header:"User-Agent"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
LoginResponse {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
OAthLoginRequest {
|
||||
Method string `json:"method" validate:"required"` // google, facebook, apple, telegram, github etc.
|
||||
Redirect string `json:"redirect"`
|
||||
}
|
||||
OAuthLoginResponse {
|
||||
Redirect string `json:"redirect"`
|
||||
}
|
||||
|
||||
OAuthLoginGetTokenRequest {
|
||||
Method string `json:"method" validate:"required"` // google, facebook, apple, telegram, github etc.
|
||||
Callback interface{} `json:"callback" validate:"required"`
|
||||
}
|
||||
|
||||
// login request
|
||||
TelephoneLoginRequest {
|
||||
Telephone string `json:"telephone" validate:"required"`
|
||||
TelephoneCode string `json:"telephone_code"`
|
||||
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
|
||||
Password string `json:"password"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
// Check user is exist request
|
||||
TelephoneCheckUserRequest {
|
||||
Telephone string `form:"telephone" validate:"required"`
|
||||
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
|
||||
}
|
||||
// User login response
|
||||
TelephoneCheckUserResponse {
|
||||
exist bool `json:"exist"`
|
||||
}
|
||||
// User login response
|
||||
TelephoneRegisterRequest {
|
||||
Telephone string `json:"telephone" validate:"required"`
|
||||
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Invite string `json:"invite,optional"`
|
||||
Code string `json:"code,optional"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
// User login response
|
||||
TelephoneResetPasswordRequest {
|
||||
Telephone string `json:"telephone" validate:"required"`
|
||||
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Code string `json:"code,optional"`
|
||||
IP string `header:"X-Original-Forwarded-For"`
|
||||
CfToken string `json:"cf_token,optional"`
|
||||
}
|
||||
AppleLoginCallbackRequest {
|
||||
Code string `form:"code"`
|
||||
IDToken string `form:"id_token"`
|
||||
State string `form:"state"`
|
||||
}
|
||||
GoogleLoginCallbackRequest {
|
||||
Code string `form:"code"`
|
||||
State string `form:"state"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/auth
|
||||
group: auth
|
||||
)
|
||||
service ppanel {
|
||||
@doc "User login"
|
||||
@handler UserLogin
|
||||
post /login (UserLoginRequest) returns (LoginResponse)
|
||||
|
||||
@doc "Check user is exist"
|
||||
@handler CheckUser
|
||||
get /check (CheckUserRequest) returns (CheckUserResponse)
|
||||
|
||||
@doc "User register"
|
||||
@handler UserRegister
|
||||
post /register (UserRegisterRequest) returns (LoginResponse)
|
||||
|
||||
@doc "Reset password"
|
||||
@handler ResetPassword
|
||||
post /reset (ResetPasswordRequest) returns (LoginResponse)
|
||||
|
||||
@doc "User Telephone login"
|
||||
@handler TelephoneLogin
|
||||
post /login/telephone (TelephoneLoginRequest) returns (LoginResponse)
|
||||
|
||||
@doc "Check user telephone is exist"
|
||||
@handler CheckUserTelephone
|
||||
get /check/telephone (TelephoneCheckUserRequest) returns (TelephoneCheckUserResponse)
|
||||
|
||||
@doc "User Telephone register"
|
||||
@handler TelephoneUserRegister
|
||||
post /register/telephone (TelephoneRegisterRequest) returns (LoginResponse)
|
||||
|
||||
@doc "Reset password"
|
||||
@handler TelephoneResetPassword
|
||||
post /reset/telephone (TelephoneResetPasswordRequest) returns (LoginResponse)
|
||||
}
|
||||
|
||||
@server (
|
||||
prefix: v1/auth/oauth
|
||||
group: auth/oauth
|
||||
)
|
||||
service ppanel {
|
||||
@doc "OAuth login"
|
||||
@handler OAuthLogin
|
||||
post /login (OAthLoginRequest) returns (OAuthLoginResponse)
|
||||
|
||||
@doc "OAuth login get token"
|
||||
@handler OAuthLoginGetToken
|
||||
post /login/token (OAuthLoginGetTokenRequest) returns (LoginResponse)
|
||||
|
||||
@doc "Apple Login Callback"
|
||||
@handler AppleLoginCallback
|
||||
post /callback/apple (AppleLoginCallbackRequest)
|
||||
}
|
||||
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Common API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "./types.api"
|
||||
|
||||
type (
|
||||
VeifyConfig {
|
||||
TurnstileSiteKey string `json:"turnstile_site_key"`
|
||||
EnableLoginVerify bool `json:"enable_login_verify"`
|
||||
EnableRegisterVerify bool `json:"enable_register_verify"`
|
||||
EnableResetPasswordVerify bool `json:"enable_reset_password_verify"`
|
||||
}
|
||||
GetGlobalConfigResponse {
|
||||
Site SiteConfig `json:"site"`
|
||||
Verify VeifyConfig `json:"verify"`
|
||||
Auth AuthConfig `json:"auth"`
|
||||
Invite InviteConfig `json:"invite"`
|
||||
Currency Currency `json:"currency"`
|
||||
Subscribe SubscribeConfig `json:"subscribe"`
|
||||
VerifyCode PubilcVerifyCodeConfig `json:"verify_code"`
|
||||
OAuthMethods []string `json:"oauth_methods"`
|
||||
WebAd bool `json:"web_ad"`
|
||||
}
|
||||
Currency {
|
||||
CurrencyUnit string `json:"currency_unit"`
|
||||
CurrencySymbol string `json:"currency_symbol"`
|
||||
}
|
||||
GetTosResponse {
|
||||
TosContent string `json:"tos_content"`
|
||||
}
|
||||
GetAppcationResponse {
|
||||
Config ApplicationConfig `json:"config"`
|
||||
Applications []ApplicationResponseInfo `json:"applications"`
|
||||
}
|
||||
// GetCodeRequest Get code request
|
||||
SendCodeRequest {
|
||||
Email string `json:"email" validate:"required"`
|
||||
Type uint8 `json:"type" validate:"required"`
|
||||
}
|
||||
SendSmsCodeRequest {
|
||||
Type uint8 `json:"type" validate:"required"`
|
||||
Telephone string `json:"telephone" validate:"required"`
|
||||
TelephoneAreaCode string `json:"telephone_area_code" validate:"required"`
|
||||
}
|
||||
// GetCodeResponse Get code response
|
||||
SendCodeResponse {
|
||||
Code string `json:"code,omitempty"`
|
||||
Status bool `json:"status"`
|
||||
}
|
||||
// GetStatResponse Get stat response
|
||||
GetStatResponse {
|
||||
User int64 `json:"user"`
|
||||
Node int64 `json:"node"`
|
||||
Country int64 `json:"country"`
|
||||
Protocol []string `json:"protocol"`
|
||||
}
|
||||
// Get ads
|
||||
GetAdsRequest {
|
||||
Device string `form:"device"`
|
||||
Position string `form:"position"`
|
||||
}
|
||||
GetAdsResponse {
|
||||
List []Ads `json:"list"`
|
||||
}
|
||||
CheckVerificationCodeRequest {
|
||||
Method string `json:"method" validate:"required,oneof=email mobile"`
|
||||
Account string `json:"account" validate:"required"`
|
||||
Code string `json:"code" validate:"required"`
|
||||
Type uint8 `json:"type" validate:"required"`
|
||||
}
|
||||
|
||||
CheckVerificationCodeRespone{
|
||||
Status bool `json:"status"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/common
|
||||
group: common
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get global config"
|
||||
@handler GetGlobalConfig
|
||||
get /site/config returns (GetGlobalConfigResponse)
|
||||
|
||||
@doc "Get Tos Content"
|
||||
@handler GetApplication
|
||||
get /application returns (GetAppcationResponse)
|
||||
|
||||
@doc "Get Tos Content"
|
||||
@handler GetTos
|
||||
get /site/tos returns (GetTosResponse)
|
||||
|
||||
@doc "Get Privacy Policy"
|
||||
@handler GetPrivacyPolicy
|
||||
get /site/privacy returns (PrivacyPolicyConfig)
|
||||
|
||||
@doc "Get stat"
|
||||
@handler GetStat
|
||||
get /site/stat returns (GetStatResponse)
|
||||
|
||||
@doc "Get verification code"
|
||||
@handler SendEmailCode
|
||||
post /send_code (SendCodeRequest) returns (SendCodeResponse)
|
||||
|
||||
@doc "Get sms verification code"
|
||||
@handler SendSmsCode
|
||||
post /send_sms_code (SendSmsCodeRequest) returns (SendCodeResponse)
|
||||
|
||||
@doc "Get Ads"
|
||||
@handler GetAds
|
||||
get /ads (GetAdsRequest) returns (GetAdsResponse)
|
||||
|
||||
@doc "Check verification code"
|
||||
@handler CheckVerificationCode
|
||||
post /check_verification_code (CheckVerificationCodeRequest) returns (CheckVerificationCodeRespone)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Node API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
ShadowsocksProtocol {
|
||||
Port int `json:"port"`
|
||||
Method string `json:"method"`
|
||||
}
|
||||
VmessProtocol {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
EnableTLS *bool `json:"enable_tls"`
|
||||
TLSConfig string `json:"tls_config"`
|
||||
Network string `json:"network"`
|
||||
Transport string `json:"transport"`
|
||||
}
|
||||
VlessProtocol {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Network string `json:"network"`
|
||||
Transport string `json:"transport"`
|
||||
Security string `json:"security"`
|
||||
SecurityConfig string `json:"security_config"`
|
||||
XTLS string `json:"xtls"`
|
||||
}
|
||||
TrojanProtocol {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
EnableTLS *bool `json:"enable_tls"`
|
||||
TLSConfig string `json:"tls_config"`
|
||||
Network string `json:"network"`
|
||||
Transport string `json:"transport"`
|
||||
}
|
||||
GetServerConfigRequest {
|
||||
ServerCommon
|
||||
}
|
||||
GetServerConfigResponse {
|
||||
Basic ServerBasic `json:"basic"`
|
||||
Protocol string `json:"protocol"`
|
||||
Config interface{} `json:"config"`
|
||||
}
|
||||
ServerBasic {
|
||||
PushInterval int64 `json:"push_interval"`
|
||||
PullInterval int64 `json:"pull_interval"`
|
||||
}
|
||||
ServerCommon {
|
||||
Protocol string `form:"protocol"`
|
||||
ServerId int64 `form:"server_id"`
|
||||
SecretKey string `form:"secret_key"`
|
||||
}
|
||||
ServerUser {
|
||||
Id int64 `json:"id"`
|
||||
UUID string `json:"uuid"`
|
||||
SpeedLimit int64 `json:"speed_limit"`
|
||||
DeviceLimit int64 `json:"device_limit"`
|
||||
}
|
||||
GetServerUserListRequest {
|
||||
ServerCommon
|
||||
}
|
||||
GetServerUserListResponse {
|
||||
Users []ServerUser `json:"users"`
|
||||
}
|
||||
UserTraffic {
|
||||
SID int64 `json:"uid"`
|
||||
Upload int64 `json:"upload"`
|
||||
Download int64 `json:"download"`
|
||||
}
|
||||
ServerPushUserTrafficRequest {
|
||||
ServerCommon
|
||||
Traffic []UserTraffic `json:"traffic"`
|
||||
}
|
||||
|
||||
ServerPushStatusRequest {
|
||||
ServerCommon
|
||||
Cpu float64 `json:"cpu"`
|
||||
Mem float64 `json:"mem"`
|
||||
Disk float64 `json:"disk"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
OnlineUsersRequest {
|
||||
ServerCommon
|
||||
Users []OnlineUser `json:"users"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/server
|
||||
group: server
|
||||
middleware: ServerMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get user list"
|
||||
@handler GetServerUserList
|
||||
get /user (GetServerUserListRequest) returns (GetServerUserListResponse)
|
||||
|
||||
@doc "Push user Traffic"
|
||||
@handler ServerPushUserTraffic
|
||||
post /push (ServerPushUserTrafficRequest)
|
||||
|
||||
@doc "Push server status"
|
||||
@handler ServerPushStatus
|
||||
post /status (ServerPushStatusRequest)
|
||||
|
||||
@doc "Get server config"
|
||||
@handler GetServerConfig
|
||||
get /config (GetServerConfigRequest) returns (GetServerConfigResponse)
|
||||
|
||||
@doc "Push online users"
|
||||
@handler PushOnlineUsers
|
||||
post /online (OnlineUsersRequest)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Announcement API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
|
||||
@server (
|
||||
prefix: v1/public/announcement
|
||||
group: public/announcement
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Query announcement"
|
||||
@handler QueryAnnouncement
|
||||
get /list (QueryAnnouncementRequest) returns (QueryAnnouncementResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "Document API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
|
||||
@server (
|
||||
prefix: v1/public/document
|
||||
group: public/document
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
|
||||
service ppanel {
|
||||
@doc "Get document list"
|
||||
@handler QueryDocumentList
|
||||
get /list returns (QueryDocumentListResponse)
|
||||
|
||||
@doc "Get document detail"
|
||||
@handler QueryDocumentDetail
|
||||
get /detail (QueryDocumentDetailRequest) returns (Document)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Order API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
@server (
|
||||
prefix: v1/public/order
|
||||
group: public/order
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Pre create order"
|
||||
@handler PreCreateOrder
|
||||
post /pre (PurchaseOrderRequest) returns (PreOrderResponse)
|
||||
|
||||
@doc "purchase Subscription"
|
||||
@handler Purchase
|
||||
post /purchase (PurchaseOrderRequest) returns (PurchaseOrderResponse)
|
||||
|
||||
@doc "Renewal Subscription"
|
||||
@handler Renewal
|
||||
post /renewal (RenewalOrderRequest) returns (RenewalOrderResponse)
|
||||
|
||||
@doc "Reset traffic"
|
||||
@handler ResetTraffic
|
||||
post /reset (ResetTrafficOrderRequest) returns (ResetTrafficOrderResponse)
|
||||
|
||||
@doc "Recharge"
|
||||
@handler Recharge
|
||||
post /recharge (RechargeOrderRequest) returns (RechargeOrderResponse)
|
||||
|
||||
@doc "Close order"
|
||||
@handler CloseOrder
|
||||
post /close (CloseOrderRequest)
|
||||
|
||||
@doc "Get order"
|
||||
@handler QueryOrderDetail
|
||||
get /detail (QueryOrderDetailRequest) returns (OrderDetail)
|
||||
|
||||
@doc "Get order list"
|
||||
@handler QueryOrderList
|
||||
get /list (QueryOrderListRequest) returns (QueryOrderListResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "payment API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
|
||||
@server (
|
||||
prefix: v1/public/payment
|
||||
group: public/payment
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get available payment methods"
|
||||
@handler GetAvailablePaymentMethods
|
||||
get /methods returns (GetAvailablePaymentMethodsResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Portal API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
PortalPurchaseRequest {
|
||||
AuthType string `json:"auth_type"`
|
||||
Identifier string `json:"identifier"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Payment int64 `json:"payment"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
Coupon string `json:"coupon,omitempty"`
|
||||
InviteCode string `json:"invite_code,omitempty"`
|
||||
TurnstileToken string `json:"turnstile_token,omitempty"`
|
||||
}
|
||||
PortalPurchaseResponse {
|
||||
OrderNo string `json:"order_no"`
|
||||
}
|
||||
GetSubscriptionResponse {
|
||||
List []Subscribe `json:"list"`
|
||||
}
|
||||
PrePurchaseOrderRequest {
|
||||
Payment int64 `json:"payment,omitempty"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
Coupon string `json:"coupon,omitempty"`
|
||||
}
|
||||
PrePurchaseOrderResponse {
|
||||
Price int64 `json:"price"`
|
||||
Amount int64 `json:"amount"`
|
||||
Discount int64 `json:"discount"`
|
||||
Coupon string `json:"coupon"`
|
||||
CouponDiscount int64 `json:"coupon_discount"`
|
||||
FeeAmount int64 `json:"fee_amount"`
|
||||
}
|
||||
QueryPurchaseOrderRequest {
|
||||
AuthType string `form:"auth_type"`
|
||||
Identifier string `form:"identifier"`
|
||||
OrderNo string `form:"order_no"`
|
||||
}
|
||||
QueryPurchaseOrderResponse {
|
||||
OrderNo string `json:"order_no"`
|
||||
Subscribe Subscribe `json:"subscribe"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
Price int64 `json:"price"`
|
||||
Amount int64 `json:"amount"`
|
||||
Discount int64 `json:"discount"`
|
||||
Coupon string `json:"coupon"`
|
||||
CouponDiscount int64 `json:"coupon_discount"`
|
||||
FeeAmount int64 `json:"fee_amount"`
|
||||
Payment PaymentMethod `json:"payment"`
|
||||
Status uint8 `json:"status"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
Token string `json:"token,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/public/portal
|
||||
group: public/portal
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get available payment methods"
|
||||
@handler GetAvailablePaymentMethods
|
||||
get /payment-method returns (GetAvailablePaymentMethodsResponse)
|
||||
|
||||
@doc "Get Subscription"
|
||||
@handler GetSubscription
|
||||
get /subscribe returns (GetSubscriptionResponse)
|
||||
|
||||
@doc "Pre Purchase Order"
|
||||
@handler PrePurchaseOrder
|
||||
post /pre (PrePurchaseOrderRequest) returns (PrePurchaseOrderResponse)
|
||||
|
||||
@doc "Purchase subscription"
|
||||
@handler Purchase
|
||||
post /purchase (PortalPurchaseRequest) returns (PortalPurchaseResponse)
|
||||
|
||||
@doc "Query Purchase Order"
|
||||
@handler QueryPurchaseOrder
|
||||
get /order/status (QueryPurchaseOrderRequest) returns (QueryPurchaseOrderResponse)
|
||||
|
||||
@doc "Purchase Checkout"
|
||||
@handler PurchaseCheckout
|
||||
post /order/checkout (CheckoutOrderRequest) returns (CheckoutOrderResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Subscribe API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
@server (
|
||||
prefix: v1/public/subscribe
|
||||
group: public/subscribe
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get subscribe list"
|
||||
@handler QuerySubscribeList
|
||||
get /list returns (QuerySubscribeListResponse)
|
||||
|
||||
@doc "Get subscribe group list"
|
||||
@handler QuerySubscribeGroupList
|
||||
get /group/list returns (QuerySubscribeGroupListResponse)
|
||||
|
||||
@doc "Get application config"
|
||||
@handler QueryApplicationConfig
|
||||
get /application/config returns (ApplicationResponse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Ticket API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
|
||||
GetUserTicketListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Ticket `json:"list"`
|
||||
}
|
||||
CreateUserTicketRequest {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
GetUserTicketListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Status *uint8 `form:"status,omitempty"`
|
||||
Search string `form:"search,omitempty"`
|
||||
}
|
||||
GetUserTicketDetailRequest {
|
||||
Id int64 `form:"id" validate:"required"`
|
||||
}
|
||||
UpdateUserTicketStatusRequest {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Status *uint8 `json:"status" validate:"required"`
|
||||
}
|
||||
CreateUserTicketFollowRequest {
|
||||
TicketId int64 `json:"ticket_id"`
|
||||
From string `json:"from"`
|
||||
Type uint8 `json:"type"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/public/ticket
|
||||
group: public/ticket
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Get ticket list"
|
||||
@handler GetUserTicketList
|
||||
get /list (GetUserTicketListRequest) returns (GetUserTicketListResponse)
|
||||
|
||||
@doc "Get ticket detail"
|
||||
@handler GetUserTicketDetails
|
||||
get /detail (GetUserTicketDetailRequest) returns (Ticket)
|
||||
|
||||
@doc "Update ticket status"
|
||||
@handler UpdateUserTicketStatus
|
||||
put / (UpdateUserTicketStatusRequest)
|
||||
|
||||
@doc "Create ticket follow"
|
||||
@handler CreateUserTicketFollow
|
||||
post /follow (CreateUserTicketFollowRequest)
|
||||
|
||||
@doc "Create ticket"
|
||||
@handler CreateUserTicket
|
||||
post / (CreateUserTicketRequest)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "User API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "../types.api"
|
||||
|
||||
type (
|
||||
UpdateUserNotifyRequest {
|
||||
EnableBalanceNotify *bool `json:"enable_balance_notify"`
|
||||
EnableLoginNotify *bool `json:"enable_login_notify"`
|
||||
EnableSubscribeNotify *bool `json:"enable_subscribe_notify"`
|
||||
EnableTradeNotify *bool `json:"enable_trade_notify"`
|
||||
}
|
||||
UpdateUserPasswordRequest {
|
||||
Password string `json:"password" validate:"required"`
|
||||
}
|
||||
QueryUserSubscribeListResponse {
|
||||
List []UserSubscribe `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
QueryUserBalanceLogListResponse {
|
||||
List []UserBalanceLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
CommissionLog {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
OrderNo string `json:"order_no"`
|
||||
Amount int64 `json:"amount"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
QueryUserCommissionLogListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
}
|
||||
QueryUserCommissionLogListResponse {
|
||||
List []CommissionLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
BindTelegramResponse {
|
||||
Url string `json:"url"`
|
||||
ExpiredAt int64 `json:"expired_at"`
|
||||
}
|
||||
PreUnsubscribeRequest {
|
||||
Id int64 `json:"id"`
|
||||
}
|
||||
PreUnsubscribeResponse {
|
||||
DeductionAmount int64 `json:"deduction_amount"`
|
||||
}
|
||||
UnsubscribeRequest {
|
||||
Id int64 `json:"id"`
|
||||
}
|
||||
BindOAuthRequest {
|
||||
Method string `json:"method"`
|
||||
Redirect string `json:"redirect"`
|
||||
}
|
||||
BindOAuthResponse {
|
||||
Redirect string `json:"redirect"`
|
||||
}
|
||||
BindOAuthCallbackRequest {
|
||||
Method string `json:"method"`
|
||||
Callback interface{} `json:"callback"`
|
||||
}
|
||||
GetOAuthMethodsResponse {
|
||||
Methods []UserAuthMethod `json:"methods"`
|
||||
}
|
||||
UnbindOAuthRequest {
|
||||
Method string `json:"method"`
|
||||
}
|
||||
ResetUserSubscribeTokenRequest {
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
}
|
||||
|
||||
GetLoginLogRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
}
|
||||
|
||||
GetLoginLogResponse {
|
||||
List []UserLoginLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
GetSubscribeLogRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
}
|
||||
|
||||
GetSubscribeLogResponse {
|
||||
List []UserSubscribeLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
UpdateBindMobileRequest{
|
||||
AreaCode string `json:"area_code" validate:"required"`
|
||||
Mobile string `json:"mobile" validate:"required"`
|
||||
Code string `json:"code" validate:"required"`
|
||||
}
|
||||
|
||||
UpdateBindEmailRequest{
|
||||
Email string `json:"email" validate:"required"`
|
||||
}
|
||||
|
||||
VerifyEmailRequest {
|
||||
Email string `json:"email" validate:"required"`
|
||||
Code string `json:"code" validate:"required"`
|
||||
}
|
||||
)
|
||||
|
||||
@server (
|
||||
prefix: v1/public/user
|
||||
group: public/user
|
||||
middleware: AuthMiddleware
|
||||
)
|
||||
service ppanel {
|
||||
@doc "Query User Info"
|
||||
@handler QueryUserInfo
|
||||
get /info returns (User)
|
||||
|
||||
@doc "Update User Notify"
|
||||
@handler UpdateUserNotify
|
||||
put /notify (UpdateUserNotifyRequest)
|
||||
|
||||
@doc "Update User Password"
|
||||
@handler UpdateUserPassword
|
||||
put /password (UpdateUserPasswordRequest)
|
||||
|
||||
@doc "Query User Subscribe"
|
||||
@handler QueryUserSubscribe
|
||||
get /subscribe returns (QueryUserSubscribeListResponse)
|
||||
|
||||
@doc "Pre Unsubscribe"
|
||||
@handler PreUnsubscribe
|
||||
post /unsubscribe/pre (PreUnsubscribeRequest) returns (PreUnsubscribeResponse)
|
||||
|
||||
@doc "Unsubscribe"
|
||||
@handler Unsubscribe
|
||||
post /unsubscribe (UnsubscribeRequest)
|
||||
|
||||
@doc "Query User Balance Log"
|
||||
@handler QueryUserBalanceLog
|
||||
get /balance_log returns (QueryUserBalanceLogListResponse)
|
||||
|
||||
@doc "Query User Affiliate Count"
|
||||
@handler QueryUserAffiliate
|
||||
get /affiliate/count returns (QueryUserAffiliateCountResponse)
|
||||
|
||||
@doc "Query User Affiliate List"
|
||||
@handler QueryUserAffiliateList
|
||||
get /affiliate/list (QueryUserAffiliateListRequest) returns (QueryUserAffiliateListResponse)
|
||||
|
||||
@doc "Bind Telegram"
|
||||
@handler BindTelegram
|
||||
get /bind_telegram returns (BindTelegramResponse)
|
||||
|
||||
@doc "Unbind Telegram"
|
||||
@handler UnbindTelegram
|
||||
post /unbind_telegram
|
||||
|
||||
@doc "Query User Commission Log"
|
||||
@handler QueryUserCommissionLog
|
||||
get /commission_log (QueryUserCommissionLogListRequest) returns (QueryUserCommissionLogListResponse)
|
||||
|
||||
@doc "Bind OAuth"
|
||||
@handler BindOAuth
|
||||
post /bind_oauth (BindOAuthRequest) returns (BindOAuthResponse)
|
||||
|
||||
@doc "Bind OAuth Callback"
|
||||
@handler BindOAuthCallback
|
||||
post /bind_oauth/callback (BindOAuthCallbackRequest)
|
||||
|
||||
@doc "Get OAuth Methods"
|
||||
@handler GetOAuthMethods
|
||||
get /oauth_methods returns (GetOAuthMethodsResponse)
|
||||
|
||||
@doc "Unbind OAuth"
|
||||
@handler UnbindOAuth
|
||||
post /unbind_oauth (UnbindOAuthRequest)
|
||||
|
||||
@doc "Reset User Subscribe Token"
|
||||
@handler ResetUserSubscribeToken
|
||||
put /subscribe_token (ResetUserSubscribeTokenRequest)
|
||||
|
||||
@doc "Get Login Log"
|
||||
@handler GetLoginLog
|
||||
get /login_log (GetLoginLogRequest) returns (GetLoginLogResponse)
|
||||
|
||||
@doc "Get Subscribe Log"
|
||||
@handler GetSubscribeLog
|
||||
get /subscribe_log (GetSubscribeLogRequest) returns (GetSubscribeLogResponse)
|
||||
|
||||
@doc "Verify Email"
|
||||
@handler VerifyEmail
|
||||
post /verify_email (VerifyEmailRequest)
|
||||
|
||||
@doc "Update Bind Mobile"
|
||||
@handler UpdateBindMobile
|
||||
put /bind_mobile (UpdateBindMobileRequest)
|
||||
|
||||
@doc "Update Bind Email"
|
||||
@handler UpdateBindEmail
|
||||
put /bind_email (UpdateBindEmailRequest)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "admin API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
import (
|
||||
"./admin/system.api"
|
||||
"./admin/user.api"
|
||||
"./admin/server.api"
|
||||
"./admin/subscribe.api"
|
||||
"./admin/payment.api"
|
||||
"./admin/coupon.api"
|
||||
"./admin/order.api"
|
||||
"./admin/ticket.api"
|
||||
"./admin/announcement.api"
|
||||
"./admin/document.api"
|
||||
"./admin/tool.api"
|
||||
"./admin/console.api"
|
||||
"./admin/auth.api"
|
||||
"./admin/log.api"
|
||||
"./admin/ads.api"
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "App API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import (
|
||||
"./app/auth.api"
|
||||
"./app/user.api"
|
||||
"./app/node.api"
|
||||
"./app/ws.api"
|
||||
"./app/order.api"
|
||||
"./app/announcement.api"
|
||||
"./app/payment.api"
|
||||
"./app/document.api"
|
||||
"./app/subscribe.api"
|
||||
)
|
||||
@@ -0,0 +1,14 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "common API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import (
|
||||
"./common.api"
|
||||
"./auth/auth.api"
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "Node API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
import "./node/node.api"
|
||||
@@ -0,0 +1,19 @@
|
||||
syntax = "v1"
|
||||
|
||||
info(
|
||||
title: "User API"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
import (
|
||||
"./public/user.api"
|
||||
"./public/subscribe.api"
|
||||
"./public/order.api"
|
||||
"./public/announcement.api"
|
||||
"./public/ticket.api"
|
||||
"./public/payment.api"
|
||||
"./public/document.api"
|
||||
"./public/portal.api"
|
||||
)
|
||||
+750
@@ -0,0 +1,750 @@
|
||||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Interface Model"
|
||||
desc: "API for ppanel"
|
||||
author: "Tension"
|
||||
email: "tension@ppanel.com"
|
||||
version: "0.0.1"
|
||||
)
|
||||
|
||||
type (
|
||||
User {
|
||||
Id int64 `json:"id"`
|
||||
Avatar string `json:"avatar"`
|
||||
Balance int64 `json:"balance"`
|
||||
Commission int64 `json:"commission"`
|
||||
GiftAmount int64 `json:"gift_amount"`
|
||||
Telegram int64 `json:"telegram"`
|
||||
ReferCode string `json:"refer_code"`
|
||||
RefererId int64 `json:"referer_id"`
|
||||
Enable bool `json:"enable"`
|
||||
IsAdmin bool `json:"is_admin,omitempty"`
|
||||
EnableBalanceNotify bool `json:"enable_balance_notify"`
|
||||
EnableLoginNotify bool `json:"enable_login_notify"`
|
||||
EnableSubscribeNotify bool `json:"enable_subscribe_notify"`
|
||||
EnableTradeNotify bool `json:"enable_trade_notify"`
|
||||
AuthMethods []UserAuthMethod `json:"auth_methods"`
|
||||
UserDevices []UserDevice `json:"user_devices"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
DeletedAt int64 `json:"deleted_at,omitempty"`
|
||||
IsDel bool `json:"is_del,omitempty"`
|
||||
}
|
||||
Follow {
|
||||
Id int64 `json:"id"`
|
||||
TicketId int64 `json:"ticket_id"`
|
||||
From string `json:"from"`
|
||||
Type uint8 `json:"type"`
|
||||
Content string `json:"content"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
Ticket {
|
||||
Id int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
UserId int64 `json:"user_id"`
|
||||
Follows []Follow `json:"follow,omitempty"`
|
||||
Status uint8 `json:"status"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
SiteConfig {
|
||||
Host string `json:"host"`
|
||||
SiteName string `json:"site_name"`
|
||||
SiteDesc string `json:"site_desc"`
|
||||
SiteLogo string `json:"site_logo"`
|
||||
Keywords string `json:"keywords"`
|
||||
CustomHTML string `json:"custom_html"`
|
||||
CustomData string `json:"custom_data"`
|
||||
}
|
||||
SubscribeConfig {
|
||||
SingleModel bool `json:"single_model"`
|
||||
SubscribePath string `json:"subscribe_path"`
|
||||
SubscribeDomain string `json:"subscribe_domain"`
|
||||
PanDomain bool `json:"pan_domain"`
|
||||
}
|
||||
VerifyCodeConfig {
|
||||
VerifyCodeExpireTime int64 `json:"verify_code_expire_time"`
|
||||
VerifyCodeLimit int64 `json:"verify_code_limit"`
|
||||
VerifyCodeInterval int64 `json:"verify_code_interval"`
|
||||
}
|
||||
PubilcVerifyCodeConfig {
|
||||
VerifyCodeInterval int64 `json:"verify_code_interval"`
|
||||
}
|
||||
SubscribeType {
|
||||
SubscribeTypes []string `json:"subscribe_types"`
|
||||
}
|
||||
Application {
|
||||
Id int64 `json:"id"`
|
||||
Icon string `json:"icon"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
SubscribeType string `json:"subscribe_type"`
|
||||
}
|
||||
ApplicationVersion {
|
||||
Id int64 `json:"id"`
|
||||
Url string `json:"url"`
|
||||
Version string `json:"version" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
}
|
||||
ApplicationResponse {
|
||||
Applications []ApplicationResponseInfo `json:"applications"`
|
||||
}
|
||||
ApplicationResponseInfo {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Icon string `json:"icon"`
|
||||
Description string `json:"description"`
|
||||
SubscribeType string `json:"subscribe_type"`
|
||||
Platform ApplicationPlatform `json:"platform"`
|
||||
}
|
||||
ApplicationPlatform {
|
||||
IOS []*ApplicationVersion `json:"ios,omitempty"`
|
||||
MacOS []*ApplicationVersion `json:"macos,omitempty"`
|
||||
Linux []*ApplicationVersion `json:"linux,omitempty"`
|
||||
Android []*ApplicationVersion `json:"android,omitempty"`
|
||||
Windows []*ApplicationVersion `json:"windows,omitempty"`
|
||||
Harmony []*ApplicationVersion `json:"harmony,omitempty"`
|
||||
}
|
||||
AuthConfig {
|
||||
Mobile MobileAuthenticateConfig `json:"mobile"`
|
||||
Email EmailAuthticateConfig `json:"email"`
|
||||
Register PubilcRegisterConfig `json:"register"`
|
||||
}
|
||||
PubilcRegisterConfig {
|
||||
StopRegister bool `json:"stop_register"`
|
||||
EnableIpRegisterLimit bool `json:"enable_ip_register_limit"`
|
||||
IpRegisterLimit int64 `json:"ip_register_limit"`
|
||||
IpRegisterLimitDuration int64 `json:"ip_register_limit_duration"`
|
||||
}
|
||||
MobileAuthenticateConfig {
|
||||
Enable bool `json:"enable"`
|
||||
EnableWhitelist bool `json:"enable_whitelist"`
|
||||
Whitelist []string `json:"whitelist"`
|
||||
}
|
||||
EmailAuthticateConfig {
|
||||
Enable bool `json:"enable"`
|
||||
EnableVerify bool `json:"enable_verify"`
|
||||
EnableDomainSuffix bool `json:"enable_domain_suffix"`
|
||||
DomainSuffixList string `json:"domain_suffix_list"`
|
||||
}
|
||||
RegisterConfig {
|
||||
StopRegister bool `json:"stop_register"`
|
||||
EnableTrial bool `json:"enable_trial"`
|
||||
TrialSubscribe int64 `json:"trial_subscribe"`
|
||||
TrialTime int64 `json:"trial_time"`
|
||||
TrialTimeUnit string `json:"trial_time_unit"`
|
||||
EnableIpRegisterLimit bool `json:"enable_ip_register_limit"`
|
||||
IpRegisterLimit int64 `json:"ip_register_limit"`
|
||||
IpRegisterLimitDuration int64 `json:"ip_register_limit_duration"`
|
||||
}
|
||||
VerifyConfig {
|
||||
TurnstileSiteKey string `json:"turnstile_site_key"`
|
||||
TurnstileSecret string `json:"turnstile_secret"`
|
||||
EnableLoginVerify bool `json:"enable_login_verify"`
|
||||
EnableRegisterVerify bool `json:"enable_register_verify"`
|
||||
EnableResetPasswordVerify bool `json:"enable_reset_password_verify"`
|
||||
}
|
||||
NodeConfig {
|
||||
NodeSecret string `json:"node_secret"`
|
||||
NodePullInterval int64 `json:"node_pull_interval"`
|
||||
NodePushInterval int64 `json:"node_push_interval"`
|
||||
}
|
||||
InviteConfig {
|
||||
ForcedInvite bool `json:"forced_invite"`
|
||||
ReferralPercentage int64 `json:"referral_percentage"`
|
||||
OnlyFirstPurchase bool `json:"only_first_purchase"`
|
||||
}
|
||||
TelegramConfig {
|
||||
TelegramBotToken string `json:"telegram_bot_token"`
|
||||
TelegramGroupUrl string `json:"telegram_group_url"`
|
||||
TelegramNotify bool `json:"telegram_notify"`
|
||||
TelegramWebHookDomain string `json:"telegram_web_hook_domain"`
|
||||
}
|
||||
TosConfig {
|
||||
TosContent string `json:"tos_content"`
|
||||
}
|
||||
PrivacyPolicyConfig {
|
||||
PrivacyPolicy string `json:"privacy_policy"`
|
||||
}
|
||||
CurrencyConfig {
|
||||
AccessKey string `json:"access_key"`
|
||||
CurrencyUnit string `json:"currency_unit"`
|
||||
CurrencySymbol string `json:"currency_symbol"`
|
||||
}
|
||||
SubscribeDiscount {
|
||||
Quantity int64 `json:"quantity"`
|
||||
Discount int64 `json:"discount"`
|
||||
}
|
||||
Subscribe {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
UnitPrice int64 `json:"unit_price"`
|
||||
UnitTime string `json:"unit_time"`
|
||||
Discount []SubscribeDiscount `json:"discount"`
|
||||
Replacement int64 `json:"replacement"`
|
||||
Inventory int64 `json:"inventory"`
|
||||
Traffic int64 `json:"traffic"`
|
||||
SpeedLimit int64 `json:"speed_limit"`
|
||||
DeviceLimit int64 `json:"device_limit"`
|
||||
Quota int64 `json:"quota"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
ServerGroup []int64 `json:"server_group"`
|
||||
Server []int64 `json:"server"`
|
||||
Show bool `json:"show"`
|
||||
Sell bool `json:"sell"`
|
||||
Sort int64 `json:"sort"`
|
||||
DeductionRatio int64 `json:"deduction_ratio"`
|
||||
AllowDeduction bool `json:"allow_deduction"`
|
||||
ResetCycle int64 `json:"reset_cycle"`
|
||||
RenewalReset bool `json:"renewal_reset"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
SubscribeGroup {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
Shadowsocks {
|
||||
Method string `json:"method" validate:"required"`
|
||||
Port int `json:"port" validate:"required"`
|
||||
ServerKey string `json:"server_key"`
|
||||
}
|
||||
Vmess {
|
||||
Port int `json:"port" validate:"required"`
|
||||
Transport string `json:"transport" validate:"required"`
|
||||
TransportConfig TransportConfig `json:"transport_config"`
|
||||
Security string `json:"security" validate:"required"`
|
||||
SecurityConfig SecurityConfig `json:"security_config"`
|
||||
}
|
||||
Vless {
|
||||
Port int `json:"port" validate:"required"`
|
||||
Flow string `json:"flow" validate:"required"`
|
||||
Transport string `json:"transport" validate:"required"`
|
||||
TransportConfig TransportConfig `json:"transport_config"`
|
||||
Security string `json:"security" validate:"required"`
|
||||
SecurityConfig SecurityConfig `json:"security_config"`
|
||||
}
|
||||
Trojan {
|
||||
Port int `json:"port" validate:"required"`
|
||||
Transport string `json:"transport" validate:"required"`
|
||||
TransportConfig TransportConfig `json:"transport_config"`
|
||||
Security string `json:"security" validate:"required"`
|
||||
SecurityConfig SecurityConfig `json:"security_config"`
|
||||
}
|
||||
Hysteria2 {
|
||||
Port int `json:"port" validate:"required"`
|
||||
HopPorts string `json:"hop_ports" validate:"required"`
|
||||
HopInterval int `json:"hop_interval" validate:"required"`
|
||||
ObfsPassword string `json:"obfs_password" validate:"required"`
|
||||
SecurityConfig SecurityConfig `json:"security_config"`
|
||||
}
|
||||
Tuic {
|
||||
Port int `json:"port" validate:"required"`
|
||||
SecurityConfig SecurityConfig `json:"security_config"`
|
||||
}
|
||||
SecurityConfig {
|
||||
SNI string `json:"sni"`
|
||||
AllowInsecure *bool `json:"allow_insecure"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
RealityServerAddr string `json:"reality_server_addr"`
|
||||
RealityServerPort int `json:"reality_server_port"`
|
||||
RealityPrivateKey string `json:"reality_private_key"`
|
||||
RealityPublicKey string `json:"reality_public_key"`
|
||||
RealityShortId string `json:"reality_short_id"`
|
||||
}
|
||||
TransportConfig {
|
||||
Path string `json:"path"`
|
||||
Host string `json:"host"`
|
||||
ServiceName string `json:"service_name"`
|
||||
}
|
||||
Server {
|
||||
Id int64 `json:"id"`
|
||||
Tags []string `json:"tags"`
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
Name string `json:"name"`
|
||||
ServerAddr string `json:"server_addr"`
|
||||
RelayMode string `json:"relay_mode"`
|
||||
RelayNode []NodeRelay `json:"relay_node"`
|
||||
SpeedLimit int `json:"speed_limit"`
|
||||
TrafficRatio float32 `json:"traffic_ratio"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
Protocol string `json:"protocol"`
|
||||
Config interface{} `json:"config"`
|
||||
Enable *bool `json:"enable"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
Status *NodeStatus `json:"status"`
|
||||
Sort int64 `json:"sort"`
|
||||
}
|
||||
OnlineUser {
|
||||
SID int64 `json:"uid"`
|
||||
IP string `json:"ip"`
|
||||
}
|
||||
NodeStatus {
|
||||
Online interface{} `json:"online"`
|
||||
Cpu float64 `json:"cpu"`
|
||||
Mem float64 `json:"mem"`
|
||||
Disk float64 `json:"disk"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
ServerGroup {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
PaymentMethod {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Platform string `json:"platform"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon"`
|
||||
FeeMode uint `json:"fee_mode"`
|
||||
FeePercent int64 `json:"fee_percent"`
|
||||
FeeAmount int64 `json:"fee_amount"`
|
||||
}
|
||||
PaymentConfig {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Platform string `json:"platform" validate:"required"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
Config interface{} `json:"config" validate:"required"`
|
||||
FeeMode uint `json:"fee_mode"`
|
||||
FeePercent int64 `json:"fee_percent,omitempty"`
|
||||
FeeAmount int64 `json:"fee_amount,omitempty"`
|
||||
Enable *bool `json:"enable" validate:"required"`
|
||||
}
|
||||
PaymentMethodDetail {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Platform string `json:"platform"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon"`
|
||||
Domain string `json:"domain"`
|
||||
Config interface{} `json:"config"`
|
||||
FeeMode uint `json:"fee_mode"`
|
||||
FeePercent int64 `json:"fee_percent"`
|
||||
FeeAmount int64 `json:"fee_amount"`
|
||||
Enable bool `json:"enable"`
|
||||
NotifyURL string `json:"notify_url"`
|
||||
}
|
||||
Order {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
OrderNo string `json:"order_no"`
|
||||
Type uint8 `json:"type"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
Price int64 `json:"price"`
|
||||
Amount int64 `json:"amount"`
|
||||
GiftAmount int64 `json:"gift_amount"`
|
||||
Discount int64 `json:"discount"`
|
||||
Coupon string `json:"coupon"`
|
||||
CouponDiscount int64 `json:"coupon_discount"`
|
||||
Commission int64 `json:"commission,omitempty"`
|
||||
Payment PaymentMethod `json:"payment"`
|
||||
FeeAmount int64 `json:"fee_amount"`
|
||||
TradeNo string `json:"trade_no"`
|
||||
Status uint8 `json:"status"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
OrderDetail {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
OrderNo string `json:"order_no"`
|
||||
Type uint8 `json:"type"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
Price int64 `json:"price"`
|
||||
Amount int64 `json:"amount"`
|
||||
GiftAmount int64 `json:"gift_amount"`
|
||||
Discount int64 `json:"discount"`
|
||||
Coupon string `json:"coupon"`
|
||||
CouponDiscount int64 `json:"coupon_discount"`
|
||||
Commission int64 `json:"commission,omitempty"`
|
||||
Payment PaymentMethod `json:"payment"`
|
||||
Method string `json:"method"`
|
||||
FeeAmount int64 `json:"fee_amount"`
|
||||
TradeNo string `json:"trade_no"`
|
||||
Status uint8 `json:"status"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Subscribe Subscribe `json:"subscribe"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
Document {
|
||||
Id int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Tags []string `json:"tags"`
|
||||
Show bool `json:"show"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
Coupon {
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Code string `json:"code"`
|
||||
Count int64 `json:"count"`
|
||||
Type uint8 `json:"type"`
|
||||
Discount int64 `json:"discount"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
ExpireTime int64 `json:"expire_time"`
|
||||
UserLimit int64 `json:"user_limit"`
|
||||
Subscribe []int64 `json:"subscribe"`
|
||||
UsedCount int64 `json:"used_count"`
|
||||
Enable bool `json:"enable"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
Announcement {
|
||||
Id int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Show *bool `json:"show"`
|
||||
Pinned *bool `json:"pinned"`
|
||||
Popup *bool `json:"popup"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
UserSubscribe {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
OrderId int64 `json:"order_id"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Subscribe Subscribe `json:"subscribe"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
ExpireTime int64 `json:"expire_time"`
|
||||
FinishedAt int64 `json:"finished_at"`
|
||||
ResetTime int64 `json:"reset_time"`
|
||||
Traffic int64 `json:"traffic"`
|
||||
Download int64 `json:"download"`
|
||||
Upload int64 `json:"upload"`
|
||||
Token string `json:"token"`
|
||||
Status uint8 `json:"status"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
UserBalanceLog {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
Amount int64 `json:"amount"`
|
||||
Type uint8 `json:"type"`
|
||||
OrderId int64 `json:"order_id"`
|
||||
Balance int64 `json:"balance"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
UserAffiliate {
|
||||
Avatar string `json:"avatar"`
|
||||
Identifier string `json:"identifier"`
|
||||
RegisteredAt int64 `json:"registered_at"`
|
||||
Enable bool `json:"enable"`
|
||||
}
|
||||
SortItem {
|
||||
Id int64 `json:"id" validate:"required"`
|
||||
Sort int64 `json:"sort" validate:"required"`
|
||||
}
|
||||
TimePeriod {
|
||||
StartTime string `json:"start_time"`
|
||||
EndTime string `json:"end_time"`
|
||||
Multiplier float32 `json:"multiplier"`
|
||||
}
|
||||
NodeRelay {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Prefix string `json:"prefix"`
|
||||
}
|
||||
ApplicationConfig {
|
||||
AppId int64 `json:"app_id"`
|
||||
EncryptionKey string `json:"encryption_key"`
|
||||
EncryptionMethod string `json:"encryption_method"`
|
||||
Domains []string `json:"domains" validate:"required"`
|
||||
StartupPicture string `json:"startup_picture"`
|
||||
StartupPictureSkipTime int64 `json:"startup_picture_skip_time"`
|
||||
}
|
||||
UserDevice {
|
||||
Id int64 `json:"id"`
|
||||
Ip string `json:"ip"`
|
||||
Identifier string `json:"identifier"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
Online bool `json:"online"`
|
||||
Enabled bool `json:"enabled"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
UserAuthMethod {
|
||||
AuthType string `json:"auth_type"`
|
||||
AuthIdentifier string `json:"auth_identifier"`
|
||||
Verified bool `json:"verified"`
|
||||
}
|
||||
AuthMethodConfig {
|
||||
Id int64 `json:"id"`
|
||||
Method string `json:"method"`
|
||||
Config interface{} `json:"config"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
TrafficLog {
|
||||
Id int64 `json:"id"`
|
||||
ServerId int64 `json:"server_id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Download int64 `json:"download"`
|
||||
Upload int64 `json:"upload"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
ServerRuleGroup {
|
||||
Id int64 `json:"id"`
|
||||
Icon string `json:"icon"`
|
||||
Name string `json:"name" validate:"required"`
|
||||
Tags []string `json:"tags"`
|
||||
Rules string `json:"rules"`
|
||||
Enable bool `json:"enable"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
UserSubscribeLog {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
UserSubscribeId int64 `json:"user_subscribe_id"`
|
||||
Token string `json:"token"`
|
||||
IP string `json:"ip"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
UserLoginLog {
|
||||
Id int64 `json:"id"`
|
||||
UserId int64 `json:"user_id"`
|
||||
LoginIP string `json:"login_ip"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
Success bool `json:"success"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
MessageLog {
|
||||
Id int64 `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Platform string `json:"platform"`
|
||||
To string `json:"to"`
|
||||
Subject string `json:"subject"`
|
||||
Content string `json:"content"`
|
||||
Status int `json:"status"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
Ads {
|
||||
Id int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Type string `json:"type"`
|
||||
Content string `json:"content"`
|
||||
Description string `json:"description"`
|
||||
TargetURL string `json:"target_url"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
EndTime int64 `json:"end_time"`
|
||||
Status int `json:"status"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
UpdatedAt int64 `json:"updated_at"`
|
||||
}
|
||||
//public order
|
||||
PurchaseOrderRequest {
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Quantity int64 `json:"quantity" validate:"required,gt=0"`
|
||||
Payment int64 `json:"payment,omitempty"`
|
||||
Coupon string `json:"coupon,omitempty"`
|
||||
}
|
||||
PreOrderResponse {
|
||||
Price int64 `json:"price"`
|
||||
Amount int64 `json:"amount"`
|
||||
Discount int64 `json:"discount"`
|
||||
GiftAmount int64 `json:"gift_amount"`
|
||||
Coupon string `json:"coupon"`
|
||||
CouponDiscount int64 `json:"coupon_discount"`
|
||||
FeeAmount int64 `json:"fee_amount"`
|
||||
}
|
||||
PurchaseOrderResponse {
|
||||
OrderNo string `json:"order_no"`
|
||||
}
|
||||
RenewalOrderRequest {
|
||||
UserSubscribeID int64 `json:"user_subscribe_id"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
Payment int64 `json:"payment"`
|
||||
Coupon string `json:"coupon,omitempty"`
|
||||
}
|
||||
RenewalOrderResponse {
|
||||
OrderNo string `json:"order_no"`
|
||||
}
|
||||
ResetTrafficOrderRequest {
|
||||
UserSubscribeID int64 `json:"user_subscribe_id"`
|
||||
Payment int64 `json:"payment"`
|
||||
}
|
||||
ResetTrafficOrderResponse {
|
||||
OrderNo string `json:"order_no"`
|
||||
}
|
||||
RechargeOrderRequest {
|
||||
Amount int64 `json:"amount"`
|
||||
Payment int64 `json:"payment"`
|
||||
}
|
||||
RechargeOrderResponse {
|
||||
OrderNo string `json:"order_no"`
|
||||
}
|
||||
PreRenewalOrderResponse {
|
||||
OrderNo string `json:"orderNo"`
|
||||
}
|
||||
CloseOrderRequest {
|
||||
OrderNo string `json:"orderNo" validate:"required"`
|
||||
}
|
||||
QueryOrderDetailRequest {
|
||||
OrderNo string `form:"order_no" validate:"required"`
|
||||
}
|
||||
StripePayment {
|
||||
Method string `json:"method"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
PublishableKey string `json:"publishable_key"`
|
||||
}
|
||||
QueryOrderListRequest {
|
||||
Page int `form:"page" validate:"required"`
|
||||
Size int `form:"size" validate:"required"`
|
||||
}
|
||||
QueryOrderListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []OrderDetail `json:"list"`
|
||||
}
|
||||
//public document
|
||||
QueryDocumentListResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Document `json:"list"`
|
||||
}
|
||||
QueryDocumentDetailRequest {
|
||||
Id int64 `form:"id" validate:"required"`
|
||||
}
|
||||
// public payment
|
||||
GetAvailablePaymentMethodsResponse {
|
||||
List []PaymentMethod `json:"list"`
|
||||
}
|
||||
// public announcement
|
||||
QueryAnnouncementRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
Pinned *bool `form:"pinned"`
|
||||
Popup *bool `form:"popup"`
|
||||
}
|
||||
QueryAnnouncementResponse {
|
||||
Total int64 `json:"total"`
|
||||
List []Announcement `json:"announcements"`
|
||||
}
|
||||
//subscribe
|
||||
QuerySubscribeListResponse {
|
||||
List []Subscribe `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
QuerySubscribeGroupListResponse {
|
||||
List []SubscribeGroup `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
GetUserSubscribeTrafficLogsRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
UserId int64 `form:"user_id"`
|
||||
SubscribeId int64 `form:"subscribe_id"`
|
||||
StartTime int64 `form:"start_time"`
|
||||
EndTime int64 `form:"end_time"`
|
||||
}
|
||||
GetUserSubscribeTrafficLogsResponse {
|
||||
List []TrafficLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
QueryUserAffiliateListResponse {
|
||||
List []UserAffiliate `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
PlatformResponse {
|
||||
List []PlatformInfo `json:"list"`
|
||||
}
|
||||
PlatformInfo {
|
||||
Platform string `json:"platform"`
|
||||
PlatformUrl string `json:"platform_url"`
|
||||
PlatformFieldDescription map[string]string `json:"platform_field_description"`
|
||||
}
|
||||
AlipayNotifyResponse {
|
||||
ReturnCode string `json:"return_code"`
|
||||
}
|
||||
EPayNotifyRequest {
|
||||
Pid int64 `json:"pid" form:"pid"`
|
||||
TradeNo string `json:"trade_no" form:"trade_no"`
|
||||
OutTradeNo string `json:"out_trade_no" form:"out_trade_no"`
|
||||
Type string `json:"type" form:"type"`
|
||||
Name string `json:"name" form:"name"`
|
||||
Money string `json:"money" form:"money"`
|
||||
TradeStatus string `json:"trade_status" form:"trade_status"`
|
||||
Param string `json:"param" form:"param"`
|
||||
Sign string `json:"sign" form:"sign"`
|
||||
SignType string `json:"sign_type" form:"sign_type"`
|
||||
}
|
||||
QueryUserAffiliateListRequest {
|
||||
Page int `form:"page"`
|
||||
Size int `form:"size"`
|
||||
}
|
||||
CheckoutOrderRequest {
|
||||
OrderNo string `json:"orderNo"`
|
||||
ReturnUrl string `json:"returnUrl,omitempty"`
|
||||
}
|
||||
CheckoutOrderResponse {
|
||||
Type string `json:"type"`
|
||||
CheckoutUrl string `json:"checkout_url,omitempty"`
|
||||
Stripe *StripePayment `json:"stripe,omitempty"`
|
||||
}
|
||||
SiteCustomDataContacts {
|
||||
Email string `json:"email"`
|
||||
Telephone string `json:"telephone"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
QueryUserAffiliateCountResponse {
|
||||
Registers int64 `json:"registers"`
|
||||
TotalCommission int64 `json:"total_commission"`
|
||||
}
|
||||
|
||||
AppUserSubcbribe{
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Upload int64 `json:"upload"`
|
||||
Traffic int64 `json:"traffic"`
|
||||
Download int64 `json:"download"`
|
||||
DeviceLimit int64 `json:"device_limit"`
|
||||
StartTime string `json:"start_time"`
|
||||
ExpireTime string `json:"expire_time"`
|
||||
List []AppUserSubscbribeNode `json:"list"`
|
||||
}
|
||||
|
||||
AppUserSubscbribeNode{
|
||||
Id int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Uuid string `json:"uuid"`
|
||||
Protocol string `json:"protocol"`
|
||||
RelayMode string `json:"relay_mode"`
|
||||
RelayNode string `json:"relay_node"`
|
||||
ServerAddr string `json:"server_addr"`
|
||||
SpeedLimit int `json:"speed_limit"`
|
||||
Tags []string `json:"tags"`
|
||||
Traffic int64 `json:"traffic"`
|
||||
TrafficRatio float64 `json:"traffic_ratio"`
|
||||
Upload int64 `json:"upload"`
|
||||
Config string `json:"config"`
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
Latitude string `json:"latitude"`
|
||||
Longitude string `json:"longitude"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
Download int64 `json:"download"`
|
||||
}
|
||||
)
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(startCmd)
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
}
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "PPanel",
|
||||
Short: "PPanel is a modern multi-user agent panel.",
|
||||
Long: `[ PPanel is a pure, professional, and perfect open-source proxy panel tool, designed to be your ideal choice for learning and practical use.]
|
||||
[ Simple and easy to operate.]`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("args:", args)
|
||||
},
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/constant"
|
||||
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/initialize"
|
||||
"github.com/perfect-panel/ppanel-server/internal"
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/conf"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/orm"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/service"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
"github.com/perfect-panel/ppanel-server/queue"
|
||||
"github.com/perfect-panel/ppanel-server/scheduler"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func init() {
|
||||
startCmd.Flags().StringVar(&startConfigPath, "config", "etc/ppanel.yaml", "ppanel.yaml directory to read from")
|
||||
}
|
||||
|
||||
var (
|
||||
startConfigPath string
|
||||
)
|
||||
|
||||
var startCmd = &cobra.Command{
|
||||
Use: "run",
|
||||
Short: "start PPanel",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("[PPanel version] v" + fmt.Sprintf("%s(%s)", constant.Version, constant.BuildNumber))
|
||||
run()
|
||||
},
|
||||
}
|
||||
|
||||
func run() {
|
||||
services := getServers()
|
||||
defer services.Stop()
|
||||
go services.Start()
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||
<-quit
|
||||
}
|
||||
func getServers() *service.Group {
|
||||
var c config.Config
|
||||
|
||||
// check config file is exist
|
||||
if _, err := os.Stat(startConfigPath); os.IsNotExist(err) {
|
||||
// check directory is existed
|
||||
if _, err := os.Stat("etc"); os.IsNotExist(err) {
|
||||
logger.Errorf("Directory %s does not exist. Creating it...\n", "etc")
|
||||
if err = os.MkdirAll("etc", os.ModePerm); err != nil {
|
||||
log.Fatalf("Please create the directory %s and place the configuration file %s in it.\n", "etc", startConfigPath)
|
||||
}
|
||||
}
|
||||
// create new config file
|
||||
if _, err := os.Create(startConfigPath); err != nil {
|
||||
logger.Errorf("Please create the configuration file %s in the directory %s.\n", startConfigPath, "etc")
|
||||
panic(fmt.Sprintf("Please create the configuration file %s in the directory %s.\n", startConfigPath, "etc"))
|
||||
}
|
||||
}
|
||||
// check config file is empty, if empty, start init web server
|
||||
if initConfig(&c) {
|
||||
status, server := initialize.Config(startConfigPath)
|
||||
<-status
|
||||
if err := server.Shutdown(context.TODO()); err != nil {
|
||||
log.Printf("Init Server Shutdown: %s\n", err.Error())
|
||||
}
|
||||
}
|
||||
conf.MustLoad(startConfigPath, &c)
|
||||
if !c.Debug {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
// init logger
|
||||
if err := logger.SetUp(c.Logger); err != nil {
|
||||
logger.Errorf("Logger setup failed: %v", err.Error())
|
||||
}
|
||||
|
||||
// init service context
|
||||
ctx := svc.NewServiceContext(c)
|
||||
services := service.NewServiceGroup()
|
||||
services.Add(internal.NewService(ctx))
|
||||
services.Add(queue.NewService(ctx))
|
||||
services.Add(scheduler.NewService(ctx))
|
||||
return services
|
||||
}
|
||||
|
||||
func initConfig(c *config.Config) bool {
|
||||
// load config
|
||||
conf.MustLoad(startConfigPath, c)
|
||||
// check custom config
|
||||
if startConfigPath != "etc/ppanel.yaml" && c.MySQL.Addr == "" {
|
||||
return true
|
||||
}
|
||||
// check access secret
|
||||
if c.JwtAuth.AccessSecret == "" && startConfigPath == "etc/ppanel.yaml" {
|
||||
c.JwtAuth.AccessSecret = uuid.New().String()
|
||||
// Get environment variables
|
||||
dsn := os.Getenv("PPANEL_DB")
|
||||
if dsn == "" {
|
||||
return true
|
||||
}
|
||||
cfg := orm.ParseDSN(dsn)
|
||||
if cfg == nil {
|
||||
return true
|
||||
} else {
|
||||
c.MySQL = *cfg
|
||||
}
|
||||
|
||||
// Get environment variables
|
||||
uri := os.Getenv("PPANEL_REDIS")
|
||||
if uri == "" {
|
||||
return true
|
||||
}
|
||||
addr, pass, db, err := tool.ParseRedisURI(uri)
|
||||
if err != nil {
|
||||
return true
|
||||
} else {
|
||||
c.Redis.Host = addr
|
||||
c.Redis.Pass = pass
|
||||
c.Redis.DB = db
|
||||
}
|
||||
// save yaml file
|
||||
newConfig := config.File{
|
||||
Host: c.Host,
|
||||
Port: c.Port,
|
||||
Debug: c.Debug,
|
||||
JwtAuth: c.JwtAuth,
|
||||
Logger: c.Logger,
|
||||
MySQL: c.MySQL,
|
||||
Redis: c.Redis,
|
||||
}
|
||||
fileData, err := yaml.Marshal(newConfig)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
// write to file
|
||||
if err := os.WriteFile(startConfigPath, fileData, 0644); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "PPanel version",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("[PPanel version] " + config.Version)
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
# PPanel 配置指南
|
||||
|
||||
本文件为 PPanel 应用程序的配置文件提供全面指南。配置文件采用 YAML 格式,定义了服务器、日志、数据库、Redis 和管理员访问的相关设置。
|
||||
|
||||
## 1. 配置文件概述
|
||||
|
||||
- **默认路径**:`./etc/ppanel.yaml`
|
||||
- **自定义路径**:通过启动参数 `--config` 指定配置文件路径。
|
||||
- **格式**:YAML 格式,支持注释,文件名需以 `.yaml` 结尾。
|
||||
|
||||
## 2. 配置文件结构
|
||||
|
||||
以下是配置文件示例,包含默认值和说明:
|
||||
|
||||
```yaml
|
||||
# PPanel 配置文件
|
||||
Host: "0.0.0.0" # 服务监听地址
|
||||
Port: 8080 # 服务监听端口
|
||||
Debug: false # 是否开启调试模式(禁用后台日志)
|
||||
JwtAuth: # JWT 认证配置
|
||||
AccessSecret: "" # 访问令牌密钥(为空时随机生成)
|
||||
AccessExpire: 604800 # 访问令牌过期时间(秒)
|
||||
Logger: # 日志配置
|
||||
ServiceName: "" # 日志服务标识名称
|
||||
Mode: "console" # 日志输出模式(console、file、volume)
|
||||
Encoding: "json" # 日志格式(json、plain)
|
||||
TimeFormat: "2006-01-02T15:04:05.000Z07:00" # 自定义时间格式
|
||||
Path: "logs" # 日志文件目录
|
||||
Level: "info" # 日志级别(info、error、severe)
|
||||
Compress: false # 是否压缩日志文件
|
||||
KeepDays: 7 # 日志保留天数
|
||||
StackCooldownMillis: 100 # 堆栈日志冷却时间(毫秒)
|
||||
MaxBackups: 3 # 最大日志备份数
|
||||
MaxSize: 50 # 最大日志文件大小(MB)
|
||||
Rotation: "daily" # 日志轮转策略(daily、size)
|
||||
MySQL: # MySQL 数据库配置
|
||||
Addr: "" # MySQL 地址(必填)
|
||||
Username: "" # MySQL 用户名(必填)
|
||||
Password: "" # MySQL 密码(必填)
|
||||
Dbname: "" # MySQL 数据库名(必填)
|
||||
Config: "charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai" # MySQL 连接参数
|
||||
MaxIdleConns: 10 # 最大空闲连接数
|
||||
MaxOpenConns: 100 # 最大打开连接数
|
||||
LogMode: "info" # 日志级别(debug、error、warn、info)
|
||||
LogZap: true # 是否使用 Zap 记录 SQL 日志
|
||||
SlowThreshold: 1000 # 慢查询阈值(毫秒)
|
||||
Redis: # Redis 配置
|
||||
Host: "localhost:6379" # Redis 地址
|
||||
Pass: "" # Redis 密码
|
||||
DB: 0 # Redis 数据库索引
|
||||
Administer: # 管理员登录配置
|
||||
Email: "admin@ppanel.dev" # 管理员登录邮箱
|
||||
Password: "password" # 管理员登录密码
|
||||
```
|
||||
|
||||
## 3. 配置项说明
|
||||
|
||||
### 3.1 服务器设置
|
||||
|
||||
- **`Host`**:服务监听的地址。
|
||||
- 默认:`0.0.0.0`(监听所有网络接口)。
|
||||
- **`Port`**:服务监听的端口。
|
||||
- 默认:`8080`。
|
||||
- **`Debug`**:是否开启调试模式,开启后禁用后台日志功能。
|
||||
- 默认:`false`。
|
||||
|
||||
### 3.2 JWT 认证 (`JwtAuth`)
|
||||
|
||||
- **`AccessSecret`**:访问令牌的密钥。
|
||||
- 默认:为空时随机生成。
|
||||
- **`AccessExpire`**:令牌过期时间(秒)。
|
||||
- 默认:`604800`(7天)。
|
||||
|
||||
### 3.3 日志配置 (`Logger`)
|
||||
|
||||
- **`ServiceName`**:日志的服务标识名称,在 `volume` 模式下用作日志文件名。
|
||||
- 默认:`""`。
|
||||
- **`Mode`**:日志输出方式。
|
||||
- 选项:`console`(标准输出/错误输出)、`file`(写入指定目录)、`volume`(Docker 卷)。
|
||||
- 默认:`console`。
|
||||
- **`Encoding`**:日志格式。
|
||||
- 选项:`json`(结构化 JSON)、`plain`(纯文本,带颜色)。
|
||||
- 默认:`json`。
|
||||
- **`TimeFormat`**:日志时间格式。
|
||||
- 默认:`2006-01-02T15:04:05.000Z07:00`。
|
||||
- **`Path`**:日志文件存储目录。
|
||||
- 默认:`logs`。
|
||||
- **`Level`**:日志过滤级别。
|
||||
- 选项:`info`(记录所有日志)、`error`(仅错误和严重日志)、`severe`(仅严重日志)。
|
||||
- 默认:`info`。
|
||||
- **`Compress`**:是否压缩日志文件(仅在 `file` 模式下生效)。
|
||||
- 默认:`false`。
|
||||
- **`KeepDays`**:日志文件保留天数。
|
||||
- 默认:`7`。
|
||||
- **`StackCooldownMillis`**:堆栈日志冷却时间(毫秒),防止日志过多。
|
||||
- 默认:`100`。
|
||||
- **`MaxBackups`**:最大日志备份数量(仅在 `size` 轮转时生效)。
|
||||
- 默认:`3`。
|
||||
- **`MaxSize`**:日志文件最大大小(MB,仅在 `size` 轮转时生效)。
|
||||
- 默认:`50`。
|
||||
- **`Rotation`**:日志轮转策略。
|
||||
- 选项:`daily`(按天轮转)、`size`(按大小轮转)。
|
||||
- 默认:`daily`。
|
||||
|
||||
### 3.4 MySQL 数据库 (`MySQL`)
|
||||
|
||||
- **`Addr`**:MySQL 服务器地址。
|
||||
- 必填。
|
||||
- **`Username`**:MySQL 用户名。
|
||||
- 必填。
|
||||
- **`Password`**:MySQL 密码。
|
||||
- 必填。
|
||||
- **`Dbname`**:MySQL 数据库名。
|
||||
- 必填。
|
||||
- **`Config`**:MySQL 连接参数。
|
||||
- 默认:`charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai`。
|
||||
- **`MaxIdleConns`**:最大空闲连接数。
|
||||
- 默认:`10`。
|
||||
- **`MaxOpenConns`**:最大打开连接数。
|
||||
- 默认:`100`。
|
||||
- **`LogMode`**:SQL 日志级别。
|
||||
- 选项:`debug`、`error`、`warn`、`info`。
|
||||
- 默认:`info`。
|
||||
- **`LogZap`**:是否使用 Zap 记录 SQL 日志。
|
||||
- 默认:`true`。
|
||||
- **`SlowThreshold`**:慢查询阈值(毫秒)。
|
||||
- 默认:`1000`。
|
||||
|
||||
### 3.5 Redis 配置 (`Redis`)
|
||||
|
||||
- **`Host`**:Redis 服务器地址。
|
||||
- 默认:`localhost:6379`。
|
||||
- **`Pass`**:Redis 密码。
|
||||
- 默认:`""`(无密码)。
|
||||
- **`DB`**:Redis 数据库索引。
|
||||
- 默认:`0`。
|
||||
|
||||
### 3.6 管理员登录 (`Administer`)
|
||||
|
||||
- **`Email`**:管理员登录邮箱。
|
||||
- 默认:`admin@ppanel.dev`。
|
||||
- **`Password`**:管理员登录密码。
|
||||
- 默认:`password`。
|
||||
|
||||
## 4. 环境变量
|
||||
|
||||
以下环境变量可用于覆盖配置文件中的设置:
|
||||
|
||||
| 环境变量 | 配置项 | 示例值 |
|
||||
|----------------|----------|----------------------------------------------|
|
||||
| `PPANEL_DB` | MySQL 配置 | `root:password@tcp(localhost:3306)/vpnboard` |
|
||||
| `PPANEL_REDIS` | Redis 配置 | `redis://localhost:6379` |
|
||||
|
||||
## 5. 最佳实践
|
||||
|
||||
- **安全性**:生产环境中避免使用默认的 `Administer` 凭据,更新 `Email` 和 `Password` 为安全值。
|
||||
- **日志**:生产环境中建议使用 `file` 或 `volume` 模式持久化日志,将 `Level` 设置为 `error` 或 `severe` 以减少日志量。
|
||||
- **数据库**:确保 `MySQL` 和 `Redis` 凭据安全,避免在版本控制中暴露。
|
||||
- **JWT**:为 `JwtAuth` 的 `AccessSecret` 设置强密钥以增强安全性。
|
||||
|
||||
如需进一步帮助,请参考 PPanel 官方文档或联系支持团队。
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
# PPanel Configuration Guide
|
||||
|
||||
This document provides a comprehensive guide to the configuration file for the PPanel application. The configuration
|
||||
file is in YAML format and defines settings for the server, logging, database, Redis, and admin access.
|
||||
|
||||
## 1. Configuration File Overview
|
||||
|
||||
- **Default Path**: `./etc/ppanel.yaml`
|
||||
- **Custom Path**: Specify a custom path using the `--config` startup parameter.
|
||||
- **Format**: YAML, supports comments, and must be named with a `.yaml` extension.
|
||||
|
||||
## 2. Configuration File Structure
|
||||
|
||||
Below is an example of the configuration file with default values and explanations:
|
||||
|
||||
```yaml
|
||||
# PPanel Configuration
|
||||
Host: "0.0.0.0" # Server listening address
|
||||
Port: 8080 # Server listening port
|
||||
Debug: false # Enable debug mode (disables background logging)
|
||||
JwtAuth: # JWT authentication settings
|
||||
AccessSecret: "" # Access token secret (randomly generated if empty)
|
||||
AccessExpire: 604800 # Access token expiration (seconds)
|
||||
Logger: # Logging configuration
|
||||
ServiceName: "" # Service name for log identification
|
||||
Mode: "console" # Log output mode (console, file, volume)
|
||||
Encoding: "json" # Log format (json, plain)
|
||||
TimeFormat: "2006-01-02T15:04:05.000Z07:00" # Custom time format
|
||||
Path: "logs" # Log file directory
|
||||
Level: "info" # Log level (info, error, severe)
|
||||
Compress: false # Enable log compression
|
||||
KeepDays: 7 # Log retention period (days)
|
||||
StackCooldownMillis: 100 # Stack trace cooldown (milliseconds)
|
||||
MaxBackups: 3 # Maximum number of log backups
|
||||
MaxSize: 50 # Maximum log file size (MB)
|
||||
Rotation: "daily" # Log rotation strategy (daily, size)
|
||||
MySQL: # MySQL database configuration
|
||||
Addr: "" # MySQL address (required)
|
||||
Username: "" # MySQL username (required)
|
||||
Password: "" # MySQL password (required)
|
||||
Dbname: "" # MySQL database name (required)
|
||||
Config: "charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai" # MySQL connection parameters
|
||||
MaxIdleConns: 10 # Maximum idle connections
|
||||
MaxOpenConns: 100 # Maximum open connections
|
||||
LogMode: "info" # Log level (debug, error, warn, info)
|
||||
LogZap: true # Enable Zap logging for SQL
|
||||
SlowThreshold: 1000 # Slow query threshold (milliseconds)
|
||||
Redis: # Redis configuration
|
||||
Host: "localhost:6379" # Redis address
|
||||
Pass: "" # Redis password
|
||||
DB: 0 # Redis database index
|
||||
Administer: # Admin login configuration
|
||||
Email: "admin@ppanel.dev" # Admin login email
|
||||
Password: "password" # Admin login password
|
||||
```
|
||||
|
||||
## 3. Configuration Details
|
||||
|
||||
### 3.1 Server Settings
|
||||
|
||||
- **`Host`**: Address the server listens on.
|
||||
- Default: `0.0.0.0` (all network interfaces).
|
||||
- **`Port`**: Port the server listens on.
|
||||
- Default: `8080`.
|
||||
- **`Debug`**: Enables debug mode, disabling background logging.
|
||||
- Default: `false`.
|
||||
|
||||
### 3.2 JWT Authentication (`JwtAuth`)
|
||||
|
||||
- **`AccessSecret`**: Secret key for access tokens.
|
||||
- Default: Randomly generated if not specified.
|
||||
- **`AccessExpire`**: Token expiration time in seconds.
|
||||
- Default: `604800` (7 days).
|
||||
|
||||
### 3.3 Logging (`Logger`)
|
||||
|
||||
- **`ServiceName`**: Identifier for logs, used as the log filename in `volume` mode.
|
||||
- Default: `""`.
|
||||
- **`Mode`**: Log output destination.
|
||||
- Options: `console` (stdout/stderr), `file` (to a directory), `volume` (Docker volume).
|
||||
- Default: `console`.
|
||||
- **`Encoding`**: Log format.
|
||||
- Options: `json` (structured JSON), `plain` (plain text with colors).
|
||||
- Default: `json`.
|
||||
- **`TimeFormat`**: Custom time format for logs.
|
||||
- Default: `2006-01-02T15:04:05.000Z07:00`.
|
||||
- **`Path`**: Directory for log files.
|
||||
- Default: `logs`.
|
||||
- **`Level`**: Log filtering level.
|
||||
- Options: `info` (all logs), `error` (error and severe), `severe` (severe only).
|
||||
- Default: `info`.
|
||||
- **`Compress`**: Enable compression for log files (only in `file` mode).
|
||||
- Default: `false`.
|
||||
- **`KeepDays`**: Retention period for log files (in days).
|
||||
- Default: `7`.
|
||||
- **`StackCooldownMillis`**: Cooldown for stack trace logging to prevent log flooding.
|
||||
- Default: `100`.
|
||||
- **`MaxBackups`**: Maximum number of log backups (for `size` rotation).
|
||||
- Default: `3`.
|
||||
- **`MaxSize`**: Maximum log file size in MB (for `size` rotation).
|
||||
- Default: `50`.
|
||||
- **`Rotation`**: Log rotation strategy.
|
||||
- Options: `daily` (rotate daily), `size` (rotate by size).
|
||||
- Default: `daily`.
|
||||
|
||||
### 3.4 MySQL Database (`MySQL`)
|
||||
|
||||
- **`Addr`**: MySQL server address.
|
||||
- Required.
|
||||
- **`Username`**: MySQL username.
|
||||
- Required.
|
||||
- **`Password`**: MySQL password.
|
||||
- Required.
|
||||
- **`Dbname`**: MySQL database name.
|
||||
- Required.
|
||||
- **`Config`**: MySQL connection parameters.
|
||||
- Default: `charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai`.
|
||||
- **`MaxIdleConns`**: Maximum idle connections.
|
||||
- Default: `10`.
|
||||
- **`MaxOpenConns`**: Maximum open connections.
|
||||
- Default: `100`.
|
||||
- **`LogMode`**: SQL logging level.
|
||||
- Options: `debug`, `error`, `warn`, `info`.
|
||||
- Default: `info`.
|
||||
- **`LogZap`**: Enable Zap logging for SQL queries.
|
||||
- Default: `true`.
|
||||
- **`SlowThreshold`**: Threshold for slow query logging (in milliseconds).
|
||||
- Default: `1000`.
|
||||
|
||||
### 3.5 Redis (`Redis`)
|
||||
|
||||
- **`Host`**: Redis server address.
|
||||
- Default: `localhost:6379`.
|
||||
- **`Pass`**: Redis password.
|
||||
- Default: `""` (no password).
|
||||
- **`DB`**: Redis database index.
|
||||
- Default: `0`.
|
||||
|
||||
### 3.6 Admin Login (`Administer`)
|
||||
|
||||
- **`Email`**: Admin login email.
|
||||
- Default: `admin@ppanel.dev`.
|
||||
- **`Password`**: Admin login password.
|
||||
- Default: `password`.
|
||||
|
||||
## 4. Environment Variables
|
||||
|
||||
The following environment variables can be used to override configuration settings:
|
||||
|
||||
| Environment Variable | Configuration Section | Example Value |
|
||||
|----------------------|-----------------------|----------------------------------------------|
|
||||
| `PPANEL_DB` | MySQL | `root:password@tcp(localhost:3306)/vpnboard` |
|
||||
| `PPANEL_REDIS` | Redis | `redis://localhost:6379` |
|
||||
|
||||
## 5. Best Practices
|
||||
|
||||
- **Security**: Avoid using default `Administer` credentials in production. Update `Email` and `Password` to secure
|
||||
values.
|
||||
- **Logging**: Use `file` or `volume` mode for production to persist logs. Adjust `Level` to `error` or `severe` to
|
||||
reduce log volume.
|
||||
- **Database**: Ensure `MySQL` and `Redis` credentials are secure and not exposed in version control.
|
||||
- **JWT**: Specify a strong `AccessSecret` for `JwtAuth` to enhance security.
|
||||
|
||||
For further assistance, refer to the official PPanel documentation or contact support.
|
||||
@@ -0,0 +1,133 @@
|
||||
### 安装说明
|
||||
#### 前置系统要求
|
||||
- Mysql 5.7+ (推荐使用8.0)
|
||||
- Redis 6.0+ (推荐使用7.0)
|
||||
|
||||
#### 二进制安装
|
||||
1.确定系统架构,并下载对应的二进制文件
|
||||
|
||||
下载地址:`https://github.com/perfect-panel/ppanel/releases`
|
||||
|
||||
示例说明:系统:Linux amd64,用户:root,当前目录:/root
|
||||
|
||||
- 下载二进制文件
|
||||
|
||||
```shell
|
||||
$ wget https://github.com/perfect-panel/ppanel/releases/download/v0.1.0/ppanel-server-linux-amd64.tar.gz
|
||||
```
|
||||
|
||||
- 解压二进制文件
|
||||
|
||||
```shell
|
||||
$ tar -zxvf ppanel-server-linux-amd64.tar.gz
|
||||
```
|
||||
|
||||
- 进入解压后的目录
|
||||
|
||||
```shell
|
||||
$ cd ppanel-server-linux-amd64
|
||||
```
|
||||
|
||||
- 赋予二进制文件执行权限
|
||||
|
||||
```shell
|
||||
$ chmod +x ppanel-server
|
||||
```
|
||||
|
||||
- 创建 systemd 服务文件
|
||||
|
||||
```shell
|
||||
$ cat > /etc/systemd/system/ppanel.service <<EOF
|
||||
[Unit]
|
||||
Description=PPANEL Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/root/ppanel-server-linux-amd64/ppanel-server
|
||||
Restart=always
|
||||
User=root
|
||||
WorkingDirectory=/root/ppanel-server-linux-amd64
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
```
|
||||
|
||||
- 重新加载 systemd 服务
|
||||
|
||||
```shell
|
||||
$ systemctl daemon-reload
|
||||
```
|
||||
- 启动服务
|
||||
|
||||
```shell
|
||||
$ systemctl start ppanel
|
||||
```
|
||||
##### 其他说明
|
||||
1. 安装路径:二进制文件将解压到 /root/ppanel-server-linux-amd64 目录下
|
||||
2. systemd 服务:
|
||||
- 服务名称:ppanel
|
||||
- 服务配置文件:/etc/systemd/system/ppanel.service
|
||||
- 服务启动命令:systemctl start ppanel
|
||||
- 服务停止命令:systemctl stop ppanel
|
||||
- 服务重启命令:systemctl restart ppanel
|
||||
- 服务状态命令:systemctl status ppanel
|
||||
- 服务开机自启:systemctl enable ppanel
|
||||
3. 设置开机自启可通过以下命令开机自启
|
||||
```shell
|
||||
$ systemctl enable ppanel
|
||||
```
|
||||
4. 服务日志:服务日志默认输出到 /root/ppanel-server-linux-amd64/ppanel.log 文件中
|
||||
5. 可通过 `journalctl -u ppanel -f` 查看服务日志
|
||||
6. 当配置文件为空或者不存在的情况下,服务会使用默认配置启动,配置文件路径为:`./etc/ppanel.yaml`,
|
||||
请通过`http://服务器地址:8080/init` 初始化系统配置
|
||||
|
||||
#### NGINX 反向代理配置
|
||||
|
||||
以下是反向代理配置示例,将 `ppanel` 服务代理到 `api.ppanel.dev` 域名下
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name ppanel.dev;
|
||||
|
||||
location / {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header REMOTE-HOST $remote_addr;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
add_header X-Cache $upstream_cache_status;
|
||||
|
||||
#Set Nginx Cache
|
||||
|
||||
set $static_filezbsQiET1 0;
|
||||
if ( $uri ~* "\.(gif|png|jpg|css|js|woff|woff2)$" )
|
||||
{
|
||||
set $static_filezbsQiET1 1;
|
||||
expires 1m;
|
||||
}
|
||||
if ( $static_filezbsQiET1 = 0 )
|
||||
{
|
||||
add_header Cache-Control no-cache;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
如果使用cloudflare代理服务,需要获取到用户真实访问IP。请在Nginx配置文件中Http段落中加入:
|
||||
|
||||
- 需要依赖:**ngx_http_realip_module**模块, 使用nginx -V命令查看nginx是否已经编译该模块,没有的话需要自己编译。
|
||||
|
||||
|
||||
```nginx
|
||||
# cloudflare Start
|
||||
set_real_ip_from 0.0.0.0/0;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
# cloudflare END
|
||||
```
|
||||
|
||||
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
### Installation Instructions
|
||||
|
||||
#### Prerequisites
|
||||
- MySQL 5.7+ (recommended: 8.0)
|
||||
- Redis 6.0+ (recommended: 7.0)
|
||||
|
||||
#### Binary Installation
|
||||
|
||||
1. Determine your system architecture and download the corresponding binary file.
|
||||
|
||||
Download URL: `https://github.com/perfect-panel/ppanel/releases`
|
||||
|
||||
Example setup: OS: Linux amd64, User: root, Current directory: `/root`
|
||||
|
||||
- Download the binary file:
|
||||
|
||||
```shell
|
||||
$ wget https://github.com/perfect-panel/ppanel/releases/download/v0.1.0/ppanel-server-linux-amd64.tar.gz
|
||||
```
|
||||
|
||||
- Extract the binary file:
|
||||
|
||||
```shell
|
||||
$ tar -zxvf ppanel-server-linux-amd64.tar.gz
|
||||
```
|
||||
|
||||
- Navigate to the extracted directory:
|
||||
|
||||
```shell
|
||||
$ cd ppanel-server-linux-amd64
|
||||
```
|
||||
|
||||
- Grant execution permissions to the binary:
|
||||
|
||||
```shell
|
||||
$ chmod +x ppanel
|
||||
```
|
||||
|
||||
- Create a systemd service file:
|
||||
|
||||
```shell
|
||||
$ cat > /etc/systemd/system/ppanel.service <<EOF
|
||||
[Unit]
|
||||
Description=PPANEL Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/root/ppanel-server-linux-amd64/ppanel
|
||||
Restart=always
|
||||
User=root
|
||||
WorkingDirectory=/root/ppanel-server-linux-amd64
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
```
|
||||
|
||||
- Reload the systemd service configuration:
|
||||
|
||||
```shell
|
||||
$ systemctl daemon-reload
|
||||
```
|
||||
- Start the service:
|
||||
|
||||
```shell
|
||||
$ systemctl start ppanel
|
||||
```
|
||||
|
||||
#### Additional Notes
|
||||
|
||||
1. Installation Path: The binary files will be extracted to /root/ppanel-server-linux-amd64.
|
||||
|
||||
2. systemd Service:
|
||||
- Service Name: ppanel
|
||||
|
||||
- Service Configuration File: /etc/systemd/system/ppanel.service
|
||||
|
||||
- Service Commands:
|
||||
|
||||
- Start: systemctl start ppanel
|
||||
|
||||
- Stop: systemctl stop ppanel
|
||||
|
||||
- Restart: systemctl restart ppanel
|
||||
|
||||
- Status: systemctl status ppanel
|
||||
|
||||
- Enable on Boot: systemctl enable ppanel
|
||||
|
||||
3. Enable Auto-start: Use the following command to enable the service on boot:
|
||||
```shell
|
||||
$ systemctl enable ppanel
|
||||
```
|
||||
4. Service Logs: By default, logs are output to `/root/ppanel-server-linux-amd64/ppanel.log`.
|
||||
|
||||
5. You can view service logs using: `journalctl -u ppanel -f`
|
||||
6. If the configuration file is missing or empty, the service will start with default settings. The configuration file path is `./etc/ppanel.yaml`. Access `http://<server_address>:8080/init` to **initialize the system configuration**.
|
||||
|
||||
#### NGINX Reverse Proxy Configuration
|
||||
|
||||
Below is an example configuration to proxy the ppanel service to the domain api.ppanel.dev:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name ppanel.dev;
|
||||
|
||||
location / {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header REMOTE-HOST $remote_addr;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
add_header X-Cache $upstream_cache_status;
|
||||
|
||||
# Set Nginx Cache
|
||||
set $static_file_cache 0;
|
||||
if ($uri ~* "\.(gif|png|jpg|css|js|woff|woff2)$") {
|
||||
set $static_file_cache 1;
|
||||
expires 1m;
|
||||
}
|
||||
if ($static_file_cache = 0) {
|
||||
add_header Cache-Control no-cache;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If using Cloudflare as a proxy service, you need to retrieve the user's real IP address. Add the following to the http section of the NGINX configuration file:
|
||||
|
||||
- Dependency: `ngx_http_realip_module`. Check if your NGINX build includes this module by running `nginx -V`. If not, you will need to recompile NGINX with this module.
|
||||
|
||||
```nginx
|
||||
# Cloudflare Start
|
||||
set_real_ip_from 0.0.0.0/0;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
# Cloudflare End
|
||||
```
|
||||
@@ -0,0 +1,13 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
ppanel:
|
||||
container_name: ppanel-server
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- ./etc/ppanel.yaml:/app/etc/ppanel.yaml
|
||||
restart: always
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -0,0 +1,139 @@
|
||||
module github.com/perfect-panel/ppanel-server
|
||||
|
||||
go 1.23.3
|
||||
|
||||
require (
|
||||
github.com/GUAIK-ORG/go-snowflake v0.0.0-20200116064823-220c4260e85f
|
||||
github.com/alibabacloud-go/darabonba-openapi v0.1.18
|
||||
github.com/alibabacloud-go/dysmsapi-20170525/v2 v2.0.18
|
||||
github.com/alibabacloud-go/tea v1.2.2
|
||||
github.com/alicebob/miniredis/v2 v2.34.0
|
||||
github.com/anaskhan96/go-password-encoder v0.0.0-20201010210601-c765b799fd72
|
||||
github.com/andybalholm/brotli v1.1.1
|
||||
github.com/forgoer/openssl v1.6.0
|
||||
github.com/gin-contrib/sessions v1.0.1
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-playground/locales v0.14.1
|
||||
github.com/go-playground/universal-translator v0.18.1
|
||||
github.com/go-playground/validator/v10 v10.24.0
|
||||
github.com/go-resty/resty/v2 v2.15.3
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
||||
github.com/gofrs/uuid/v5 v5.3.0
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/hibiken/asynq v0.24.1
|
||||
github.com/jinzhu/copier v0.4.0
|
||||
github.com/klauspost/compress v1.17.7
|
||||
github.com/nyaruka/phonenumbers v1.5.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/redis/go-redis/v9 v9.6.1
|
||||
github.com/smartwalle/alipay/v3 v3.2.23
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/stripe/stripe-go/v81 v81.1.0
|
||||
github.com/twilio/twilio-go v1.23.11
|
||||
go.opentelemetry.io/otel v1.29.0
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0
|
||||
go.opentelemetry.io/otel/exporters/zipkin v1.24.0
|
||||
go.opentelemetry.io/otel/sdk v1.29.0
|
||||
go.opentelemetry.io/otel/trace v1.29.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/crypto v0.32.0
|
||||
golang.org/x/oauth2 v0.25.0
|
||||
golang.org/x/time v0.6.0
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/driver/mysql v1.5.7
|
||||
gorm.io/gorm v1.25.12
|
||||
gorm.io/plugin/soft_delete v1.2.1
|
||||
k8s.io/apimachinery v0.31.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/fatih/color v1.18.0
|
||||
github.com/goccy/go-json v0.10.4
|
||||
github.com/golang-migrate/migrate/v4 v4.18.2
|
||||
github.com/spaolacci/murmur3 v1.1.0
|
||||
google.golang.org/grpc v1.64.1
|
||||
google.golang.org/protobuf v1.36.3
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
|
||||
github.com/alibabacloud-go/debug v1.0.1 // indirect
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
|
||||
github.com/alibabacloud-go/openapi-util v0.1.1 // indirect
|
||||
github.com/alibabacloud-go/tea-utils v1.4.5 // indirect
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
|
||||
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect
|
||||
github.com/aliyun/credentials-go v1.3.10 // indirect
|
||||
github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect
|
||||
github.com/bytedance/sonic v1.12.7 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.3 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.5.6 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gin-contrib/sse v1.0.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/golang/glog v1.2.0 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/gomodule/redigo v2.0.0+incompatible // indirect
|
||||
github.com/gorilla/context v1.1.2 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
github.com/gorilla/sessions v1.2.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/openzipkin/zipkin-go v0.4.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/smartwalle/ncrypto v1.0.4 // indirect
|
||||
github.com/smartwalle/ngx v1.0.9 // indirect
|
||||
github.com/smartwalle/nsign v1.0.9 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/yuin/gopher-lua v1.1.1 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.29.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/arch v0.13.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d // indirect
|
||||
golang.org/x/net v0.34.0 // indirect
|
||||
golang.org/x/sys v0.29.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
)
|
||||
@@ -0,0 +1,544 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/GUAIK-ORG/go-snowflake v0.0.0-20200116064823-220c4260e85f h1:RDkg3pyE1qGbBpRWmvSN9RNZC5nUrOaEPiEpEb8y2f0=
|
||||
github.com/GUAIK-ORG/go-snowflake v0.0.0-20200116064823-220c4260e85f/go.mod h1:zA7AF9RTfpluCfz0omI4t5KCMaWHUMicsZoMccnaT44=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g=
|
||||
github.com/alibabacloud-go/darabonba-openapi v0.1.18 h1:3eUVmAr7WCJp7fgIvmCd9ZUyuwtJYbtUqJIed5eXCmk=
|
||||
github.com/alibabacloud-go/darabonba-openapi v0.1.18/go.mod h1:PB4HffMhJVmAgNKNq3wYbTUlFvPgxJpTzd1F5pTuUsc=
|
||||
github.com/alibabacloud-go/darabonba-string v1.0.0/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA=
|
||||
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY=
|
||||
github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
|
||||
github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg=
|
||||
github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
|
||||
github.com/alibabacloud-go/dysmsapi-20170525/v2 v2.0.18 h1:hfZA4cgIl6frNdsRmAyj8sn9J1bihQpYbzIVv2T/+Cs=
|
||||
github.com/alibabacloud-go/dysmsapi-20170525/v2 v2.0.18/go.mod h1:di54xjBFHvKiQQo7st3TUmiMy0ywne5TOHup786Rhes=
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q=
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
|
||||
github.com/alibabacloud-go/openapi-util v0.0.11/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
|
||||
github.com/alibabacloud-go/openapi-util v0.1.1 h1:ujGErJjG8ncRW6XtBBMphzHTvCxn4DjrVw4m04HsS28=
|
||||
github.com/alibabacloud-go/openapi-util v0.1.1/go.mod h1:/UehBSE2cf1gYT43GV4E+RxTdLRzURImCYY0aRmlXpw=
|
||||
github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg=
|
||||
github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
|
||||
github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
|
||||
github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
|
||||
github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||
github.com/alibabacloud-go/tea v1.2.2 h1:aTsR6Rl3ANWPfqeQugPglfurloyBJY85eFy7Gc1+8oU=
|
||||
github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk=
|
||||
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
|
||||
github.com/alibabacloud-go/tea-utils v1.4.3/go.mod h1:KNcT0oXlZZxOXINnZBs6YvgOd5aYp9U67G+E3R8fcQw=
|
||||
github.com/alibabacloud-go/tea-utils v1.4.5 h1:h0/6Xd2f3bPE4XHTvkpjwxowIwRCJAJOqY6Eq8f3zfA=
|
||||
github.com/alibabacloud-go/tea-utils v1.4.5/go.mod h1:KNcT0oXlZZxOXINnZBs6YvgOd5aYp9U67G+E3R8fcQw=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.6/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
|
||||
github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0=
|
||||
github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
|
||||
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE=
|
||||
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||
github.com/alicebob/miniredis/v2 v2.34.0 h1:mBFWMaJSNL9RwdGRyEDoAAv8OQc5UlEhLDQggTglU/0=
|
||||
github.com/alicebob/miniredis/v2 v2.34.0/go.mod h1:kWShP4b58T1CW0Y5dViCd5ztzrDqRWqM3nksiyXk5s8=
|
||||
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
|
||||
github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM=
|
||||
github.com/aliyun/credentials-go v1.3.10 h1:45Xxrae/evfzQL9V10zL3xX31eqgLWEaIdCoPipOEQA=
|
||||
github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
|
||||
github.com/anaskhan96/go-password-encoder v0.0.0-20201010210601-c765b799fd72 h1:a93gW7OBt55SksMQVibqPWdu4Ly73KM4d3zoIUUX3cs=
|
||||
github.com/anaskhan96/go-password-encoder v0.0.0-20201010210601-c765b799fd72/go.mod h1:PsJICrlruG9QcJDYuZ0dO/2KtMDALzRbony8NkxZ2nE=
|
||||
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
|
||||
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
|
||||
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
||||
github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff h1:RmdPFa+slIr4SCBg4st/l/vZWVe9QJKMXGO60Bxbe04=
|
||||
github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff/go.mod h1:+RTT1BOk5P97fT2CiHkbFQwkK3mjsFAP6zCYV2aXtjw=
|
||||
github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/bytedance/sonic v1.12.7 h1:CQU8pxOy9HToxhndH0Kx/S1qU/CuS9GnKYrGioDcU1Q=
|
||||
github.com/bytedance/sonic v1.12.7/go.mod h1:tnbal4mxOMju17EGfknm2XyYcpyCnIROYOEYuemj13I=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0=
|
||||
github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/clbanning/mxj/v2 v2.5.6 h1:Jm4VaCI/+Ug5Q57IzEoZbwx4iQFA6wkXv72juUSeK+g=
|
||||
github.com/clbanning/mxj/v2 v2.5.6/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dhui/dktest v0.4.4 h1:+I4s6JRE1yGuqflzwqG+aIaMdgXIorCf5P98JnaAWa8=
|
||||
github.com/dhui/dktest v0.4.4/go.mod h1:4+22R4lgsdAXrDyaH4Nqx2JEz2hLp49MqQmm9HLCQhM=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4=
|
||||
github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/forgoer/openssl v1.6.0 h1:IueL+UfH0hKo99xFPojHLlO3QzRBQqFY+Cht0WwtOC0=
|
||||
github.com/forgoer/openssl v1.6.0/go.mod h1:9DZ4yOsQmveP0aXC/BpQ++Y5TKaz5yR9+emcxmIZNZs=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gin-contrib/sessions v1.0.1 h1:3hsJyNs7v7N8OtelFmYXFrulAf6zSR7nW/putcPEHxI=
|
||||
github.com/gin-contrib/sessions v1.0.1/go.mod h1:ouxSFM24/OgIud5MJYQJLpy6AwxQ5EYO9yLhbtObGkM=
|
||||
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
|
||||
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg=
|
||||
github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
|
||||
github.com/go-resty/resty/v2 v2.15.3 h1:bqff+hcqAflpiF591hhJzNdkRsFhlB96CYfBwSFvql8=
|
||||
github.com/go-resty/resty/v2 v2.15.3/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc=
|
||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8=
|
||||
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk=
|
||||
github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-migrate/migrate/v4 v4.18.2 h1:2VSCMz7x7mjyTXx3m2zPokOY82LTRgxK1yQYKo6wWQ8=
|
||||
github.com/golang-migrate/migrate/v4 v4.18.2/go.mod h1:2CM6tJvn2kqPXwnXO/d3rAQYiyoIm180VsO8PRX6Rpk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
|
||||
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/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 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o=
|
||||
github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||
github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
|
||||
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
||||
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hibiken/asynq v0.24.1 h1:+5iIEAyA9K/lcSPvx3qoPtsKJeKI5u9aOIvUmSsazEw=
|
||||
github.com/hibiken/asynq v0.24.1/go.mod h1:u5qVeSbrnfT+vtG5Mq8ZPzQu/BmCKMHvTGb91uy9Tts=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275 h1:IZycmTpoUtQK3PD60UYBwjaCUHUP7cML494ao9/O8+Q=
|
||||
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275/go.mod h1:zt6UU74K6Z6oMOYJbJzYpYucqdcQwSMPBEdSvGiaUMw=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nyaruka/phonenumbers v1.5.0 h1:0M+Gd9zl53QC4Nl5z1Yj1O/zPk2XXBUwR/vlzdXSJv4=
|
||||
github.com/nyaruka/phonenumbers v1.5.0/go.mod h1:gv+CtldaFz+G3vHHnasBSirAi3O2XLqZzVWz4V1pl2E=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA=
|
||||
github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk=
|
||||
github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4=
|
||||
github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/smartwalle/alipay/v3 v3.2.23 h1:i1VwJeu70EmwpsXXz6GZZnMAtRx5MTfn2dPoql/L3zE=
|
||||
github.com/smartwalle/alipay/v3 v3.2.23/go.mod h1:lVqFiupPf8YsAXaq5JXcwqnOUC2MCF+2/5vub+RlagE=
|
||||
github.com/smartwalle/ncrypto v1.0.4 h1:P2rqQxDepJwgeO5ShoC+wGcK2wNJDmcdBOWAksuIgx8=
|
||||
github.com/smartwalle/ncrypto v1.0.4/go.mod h1:Dwlp6sfeNaPMnOxMNayMTacvC5JGEVln3CVdiVDgbBk=
|
||||
github.com/smartwalle/ngx v1.0.9 h1:pUXDvWRZJIHVrCKA1uZ15YwNti+5P4GuJGbpJ4WvpMw=
|
||||
github.com/smartwalle/ngx v1.0.9/go.mod h1:mx/nz2Pk5j+RBs7t6u6k22MPiBG/8CtOMpCnALIG8Y0=
|
||||
github.com/smartwalle/nsign v1.0.9 h1:8poAgG7zBd8HkZy9RQDwasC6XZvJpDGQWSjzL2FZL6E=
|
||||
github.com/smartwalle/nsign v1.0.9/go.mod h1:eY6I4CJlyNdVMP+t6z1H6Jpd4m5/V+8xi44ufSTxXgc=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stripe/stripe-go/v81 v81.1.0 h1:OlpGPO2vhS2raLR/NuvHKeRUZ57FTkdZBTcd5Hhoyos=
|
||||
github.com/stripe/stripe-go/v81 v81.1.0/go.mod h1:C/F4jlmnGNacvYtBp/LUHCvVUJEZffFQCobkzwY1WOo=
|
||||
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||
github.com/twilio/twilio-go v1.23.11 h1:Q532m0rgWF1AzzF4Z4ejzTk5XeORWT+zLGzlklSk/iU=
|
||||
github.com/twilio/twilio-go v1.23.11/go.mod h1:zRkMjudW7v7MqQ3cWNZmSoZJ7EBjPZ4OpNh2zm7Q6ko=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
|
||||
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
|
||||
go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
|
||||
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4=
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA=
|
||||
go.opentelemetry.io/otel/exporters/zipkin v1.24.0 h1:3evrL5poBuh1KF51D9gO/S+N/1msnm4DaBqs/rpXUqY=
|
||||
go.opentelemetry.io/otel/exporters/zipkin v1.24.0/go.mod h1:0EHgD8R0+8yRhUYJOGR8Hfg2dpiJQxDOszd5smVO9wM=
|
||||
go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
|
||||
go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok=
|
||||
go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
|
||||
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/arch v0.13.0 h1:KCkqVVV1kGg0X87TFysjCJ8MxtZEIU4Ja/yXGeoECdA=
|
||||
golang.org/x/arch v0.13.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d h1:N0hmiNbwsSNwHBAvR3QB5w25pUwH4tK0Y/RltD1j1h4=
|
||||
golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
|
||||
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
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.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 h1:W5Xj/70xIA4x60O/IFyXivR5MGqblAb8R3w26pnD6No=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
|
||||
google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
|
||||
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
|
||||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
|
||||
gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c=
|
||||
gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc=
|
||||
gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
|
||||
gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gorm.io/gorm v1.23.0/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
gorm.io/plugin/soft_delete v1.2.1 h1:qx9D/c4Xu6w5KT8LviX8DgLcB9hkKl6JC9f44Tj7cGU=
|
||||
gorm.io/plugin/soft_delete v1.2.1/go.mod h1:Zv7vQctOJTGOsJ/bWgrN1n3od0GBAZgnLjEx+cApLGk=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U=
|
||||
k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
@@ -0,0 +1,273 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"embed"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"gorm.io/driver/mysql"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/perfect-panel/ppanel-server/initialize/migrate"
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/conf"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/orm"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v3"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
//go:embed templates/*.html
|
||||
var templateFS embed.FS
|
||||
|
||||
var initStatus = make(chan bool)
|
||||
var configPath string
|
||||
|
||||
func Config(path string) (chan bool, *http.Server) {
|
||||
// Set the configuration file path
|
||||
configPath = path
|
||||
// Create a new Gin instance
|
||||
r := gin.Default()
|
||||
|
||||
// Create a new HTTP server
|
||||
server := &http.Server{
|
||||
Addr: ":8080",
|
||||
Handler: r,
|
||||
}
|
||||
// Load templates
|
||||
tmpl := template.Must(template.ParseFS(templateFS, "templates/*.html"))
|
||||
r.SetHTMLTemplate(tmpl)
|
||||
|
||||
r.GET("/init", handleInit)
|
||||
r.POST("/init/config", handleInitConfig)
|
||||
r.POST("/init/mysql/test", HandleMySQLTest)
|
||||
r.POST("/init/redis/test", HandleRedisTest)
|
||||
// Handle 404
|
||||
r.NoRoute(func(c *gin.Context) {
|
||||
c.Redirect(http.StatusFound, "/init")
|
||||
})
|
||||
|
||||
go func(server *http.Server) {
|
||||
// Start the server
|
||||
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
log.Fatalf("listen: %s\n", err)
|
||||
}
|
||||
}(server)
|
||||
|
||||
return initStatus, server
|
||||
}
|
||||
|
||||
func handleInit(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "index.html", nil)
|
||||
}
|
||||
func handleInitConfig(c *gin.Context) {
|
||||
// Load configuration file
|
||||
|
||||
var cfg config.File
|
||||
conf.MustLoad(configPath, &cfg)
|
||||
var request struct {
|
||||
AdminEmail string `json:"adminEmail"`
|
||||
AdminPassword string `json:"adminPassword"`
|
||||
|
||||
MysqlHost string `json:"mysqlHost"`
|
||||
MysqlPort string `json:"mysqlPort"`
|
||||
MysqlDatabase string `json:"mysqlDatabase"`
|
||||
MysqlUser string `json:"mysqlUser"`
|
||||
MysqlPassword string `json:"mysqlPassword"`
|
||||
|
||||
RedisHost string `json:"redisHost"`
|
||||
RedisPort string `json:"redisPort"`
|
||||
RedisPassword string `json:"redisPassword"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": 400,
|
||||
"msg": "Invalid request",
|
||||
"data": nil,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
cfg.Debug = false
|
||||
// jwt secret
|
||||
cfg.JwtAuth.AccessSecret = uuid.New().String()
|
||||
// mysql
|
||||
cfg.MySQL.Addr = fmt.Sprintf("%s:%s", request.MysqlHost, request.MysqlPort)
|
||||
cfg.MySQL.Dbname = request.MysqlDatabase
|
||||
cfg.MySQL.Username = request.MysqlUser
|
||||
cfg.MySQL.Password = request.MysqlPassword
|
||||
// redis
|
||||
cfg.Redis.Host = fmt.Sprintf("%s:%s", request.RedisHost, request.RedisPort)
|
||||
cfg.Redis.Pass = request.RedisPassword
|
||||
|
||||
// save config
|
||||
fileData, err := yaml.Marshal(cfg)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"code": 500,
|
||||
"msg": "Configuration initialization failed",
|
||||
"data": nil,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// create mysql connection
|
||||
db, err := orm.ConnectMysql(orm.Mysql{
|
||||
Config: orm.Config{
|
||||
Addr: fmt.Sprintf("%s:%s", request.MysqlHost, request.MysqlPort),
|
||||
Username: request.MysqlUser,
|
||||
Password: request.MysqlPassword,
|
||||
Dbname: request.MysqlDatabase,
|
||||
Config: "charset%3Dutf8mb4%26parseTime%3Dtrue%26loc%3DLocal",
|
||||
MaxIdleConns: 10,
|
||||
MaxOpenConns: 10,
|
||||
SlowThreshold: 1000,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"code": 500,
|
||||
"msg": "MySQL connection failed",
|
||||
"data": nil,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", request.MysqlUser, request.MysqlPassword, request.MysqlHost, request.MysqlPort, request.MysqlDatabase)
|
||||
// migrate database
|
||||
if err = migrate.Migrate(dsn).Up(); err != nil {
|
||||
logger.Errorf("[Init Mysql] Migrate failed: %v", err.Error())
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 500,
|
||||
"msg": "Database migration failed",
|
||||
"data": nil,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// create admin user
|
||||
if err = migrate.CreateAdminUser(request.AdminEmail, request.AdminPassword, db); err != nil {
|
||||
logger.Errorf("[Init Mysql] Create admin user failed: %v", err.Error())
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 500,
|
||||
"msg": "Admin user creation failed",
|
||||
"data": nil,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// write to file
|
||||
if err = os.WriteFile(configPath, fileData, 0644); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"code": 500,
|
||||
"msg": "Configuration initialization failed",
|
||||
"data": nil,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 200,
|
||||
"msg": "Configuration initialized",
|
||||
"status": true,
|
||||
})
|
||||
initStatus <- true
|
||||
}
|
||||
|
||||
func HandleMySQLTest(c *gin.Context) {
|
||||
var request struct {
|
||||
Host string `json:"host"`
|
||||
Port string `json:"port"`
|
||||
Database string `json:"database"`
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": 400,
|
||||
"msg": "Invalid request",
|
||||
"data": nil,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", request.User, request.Password, request.Host, request.Port, request.Database)
|
||||
var status = true
|
||||
var message string
|
||||
var tx *sql.DB
|
||||
var tables []string
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
logger.Errorf("connect mysql failed, err: %v\n", err.Error())
|
||||
status = false
|
||||
message = "MySQL connection failed"
|
||||
goto result
|
||||
}
|
||||
tx, _ = db.DB()
|
||||
if err := tx.Ping(); err != nil {
|
||||
logger.Errorf("ping mysql failed, err: %v\n", err.Error())
|
||||
status = false
|
||||
message = "MySQL connection failed"
|
||||
}
|
||||
|
||||
tables, err = db.Migrator().GetTables()
|
||||
if err != nil {
|
||||
logger.Errorf("database table check failed, err: %v\n", err.Error())
|
||||
status = false
|
||||
message = "Database table check failed"
|
||||
goto result
|
||||
}
|
||||
if len(tables) > 0 {
|
||||
status = false
|
||||
message = "The database contains existing data. Please clear it before proceeding with the installation."
|
||||
goto result
|
||||
}
|
||||
|
||||
result:
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 200,
|
||||
"msg": message,
|
||||
"status": status,
|
||||
})
|
||||
}
|
||||
|
||||
func HandleRedisTest(c *gin.Context) {
|
||||
var request struct {
|
||||
Host string `json:"host"`
|
||||
Port string `json:"port"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"code": 400,
|
||||
"msg": "Invalid request",
|
||||
"data": nil,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
if err := tool.RedisPing(fmt.Sprintf("%s:%s", request.Host, request.Port), request.Password, 0); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 200,
|
||||
"msg": nil,
|
||||
"status": false,
|
||||
})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 200,
|
||||
"msg": nil,
|
||||
"status": true,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/internal/model/auth"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
)
|
||||
|
||||
// Email get email smtp config
|
||||
func Email(ctx *svc.ServiceContext) {
|
||||
logger.Debug("Email config initialization")
|
||||
method, err := ctx.AuthModel.FindOneByMethod(context.Background(), "email")
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to find email auth method: %v", err.Error()))
|
||||
}
|
||||
var cfg config.EmailConfig
|
||||
var emailConfig = new(auth.EmailAuthConfig)
|
||||
if err := emailConfig.Unmarshal(method.Config); err != nil {
|
||||
panic(fmt.Sprintf("failed to unmarshal email auth config: %v", err.Error()))
|
||||
}
|
||||
tool.DeepCopy(&cfg, emailConfig)
|
||||
cfg.Enable = *method.Enabled
|
||||
value, _ := json.Marshal(emailConfig.PlatformConfig)
|
||||
cfg.PlatformConfig = string(value)
|
||||
ctx.Config.Email = cfg
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
)
|
||||
|
||||
func StartInitSystemConfig(svc *svc.ServiceContext) {
|
||||
Migrate(svc)
|
||||
Site(svc)
|
||||
Node(svc)
|
||||
Email(svc)
|
||||
Invite(svc)
|
||||
Verify(svc)
|
||||
Subscribe(svc)
|
||||
Register(svc)
|
||||
Mobile(svc)
|
||||
TrafficDataToRedis(svc)
|
||||
if !svc.Config.Debug {
|
||||
Telegram(svc)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
)
|
||||
|
||||
func Invite(ctx *svc.ServiceContext) {
|
||||
// Initialize the system configuration
|
||||
logger.Debug("Register config initialization")
|
||||
configs, err := ctx.SystemModel.GetInviteConfig(context.Background())
|
||||
if err != nil {
|
||||
logger.Error("[Init Invite Config] Get Invite Config Error: ", logger.Field("error", err.Error()))
|
||||
return
|
||||
}
|
||||
var inviteConfig config.InviteConfig
|
||||
tool.SystemConfigSliceReflectToStruct(configs, &inviteConfig)
|
||||
ctx.Config.Invite = inviteConfig
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
-- 000001_init_schema.down.sql
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
DROP TABLE IF EXISTS `user_subscribe_log`;
|
||||
DROP TABLE IF EXISTS `user_subscribe`;
|
||||
DROP TABLE IF EXISTS `user_login_log`;
|
||||
DROP TABLE IF EXISTS `user_gift_amount_log`;
|
||||
DROP TABLE IF EXISTS `user_device`;
|
||||
DROP TABLE IF EXISTS `user_commission_log`;
|
||||
DROP TABLE IF EXISTS `user_balance_log`;
|
||||
DROP TABLE IF EXISTS `user_auth_methods`;
|
||||
DROP TABLE IF EXISTS `user`;
|
||||
DROP TABLE IF EXISTS `traffic_log`;
|
||||
DROP TABLE IF EXISTS `ticket_follow`;
|
||||
DROP TABLE IF EXISTS `ticket`;
|
||||
DROP TABLE IF EXISTS `system`;
|
||||
DROP TABLE IF EXISTS `subscribe_type`;
|
||||
DROP TABLE IF EXISTS `subscribe_group`;
|
||||
DROP TABLE IF EXISTS `subscribe`;
|
||||
DROP TABLE IF EXISTS `sms`;
|
||||
DROP TABLE IF EXISTS `server_rule_group`;
|
||||
DROP TABLE IF EXISTS `server_group`;
|
||||
DROP TABLE IF EXISTS `server`;
|
||||
DROP TABLE IF EXISTS `payment`;
|
||||
DROP TABLE IF EXISTS `order`;
|
||||
DROP TABLE IF EXISTS `message_log`;
|
||||
DROP TABLE IF EXISTS `document`;
|
||||
DROP TABLE IF EXISTS `coupon`;
|
||||
DROP TABLE IF EXISTS `auth_method`;
|
||||
DROP TABLE IF EXISTS `application_version`;
|
||||
DROP TABLE IF EXISTS `application_config`;
|
||||
DROP TABLE IF EXISTS `application`;
|
||||
DROP TABLE IF EXISTS `announcement`;
|
||||
DROP TABLE IF EXISTS `ads`;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -0,0 +1,559 @@
|
||||
-- 000001_init_schema.up.sql
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `ads`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Ads title',
|
||||
`type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Ads type',
|
||||
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Ads content',
|
||||
`target_url` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'Ads target url',
|
||||
`start_time` datetime DEFAULT NULL COMMENT 'Ads start time',
|
||||
`end_time` datetime DEFAULT NULL COMMENT 'Ads end time',
|
||||
`status` tinyint(1) DEFAULT '0' COMMENT 'Ads status,0 disable,1 enable',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `announcement`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Title',
|
||||
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Content',
|
||||
`show` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Show',
|
||||
`pinned` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Pinned',
|
||||
`popup` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Popup',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `application`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '应用名称',
|
||||
`icon` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '应用图标',
|
||||
`description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '更新描述',
|
||||
`subscribe_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '订阅类型',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT '创建时间',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `application_config`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`app_id` bigint NOT NULL DEFAULT '0' COMMENT 'App id',
|
||||
`encryption_key` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Encryption Key',
|
||||
`encryption_method` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Encryption Method',
|
||||
`domains` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
|
||||
`startup_picture` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
|
||||
`startup_picture_skip_time` bigint NOT NULL DEFAULT '0' COMMENT 'Startup Picture Skip Time',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `application_version`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '应用地址',
|
||||
`version` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '应用版本',
|
||||
`platform` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '应用平台',
|
||||
`is_default` tinyint(1) NOT NULL DEFAULT '0' COMMENT '默认版本',
|
||||
`description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '更新描述',
|
||||
`application_id` bigint DEFAULT NULL COMMENT '所属应用',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT '创建时间',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `fk_application_application_versions` (`application_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `auth_method`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`method` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'method',
|
||||
`config` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'OAuth Configuration',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Is Enabled',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uni_auth_method` (`method`)
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 9
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `coupon`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Coupon Name',
|
||||
`code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Coupon Code',
|
||||
`count` bigint NOT NULL DEFAULT '0' COMMENT 'Count Limit',
|
||||
`type` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Coupon Type: 1: Percentage 2: Fixed Amount',
|
||||
`discount` bigint NOT NULL DEFAULT '0' COMMENT 'Coupon Discount',
|
||||
`start_time` bigint NOT NULL DEFAULT '0' COMMENT 'Start Time',
|
||||
`expire_time` bigint NOT NULL DEFAULT '0' COMMENT 'Expire Time',
|
||||
`user_limit` bigint NOT NULL DEFAULT '0' COMMENT 'User Limit',
|
||||
`subscribe` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Subscribe Limit',
|
||||
`used_count` bigint NOT NULL DEFAULT '0' COMMENT 'Used Count',
|
||||
`enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Enable',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uni_coupon_code` (`code`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `document`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Document Title',
|
||||
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Document Content',
|
||||
`tags` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Document Tags',
|
||||
`show` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Show',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `message_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'email' COMMENT 'Message Type',
|
||||
`platform` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'smtp' COMMENT 'Platform',
|
||||
`to` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'To',
|
||||
`subject` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Subject',
|
||||
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Content',
|
||||
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Status',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `order`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`parent_id` bigint DEFAULT NULL COMMENT 'Parent Order Id',
|
||||
`user_id` bigint NOT NULL DEFAULT '0' COMMENT 'User Id',
|
||||
`order_no` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Order No',
|
||||
`type` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Order Type: 1: Subscribe, 2: Renewal, 3: ResetTraffic, 4: Recharge',
|
||||
`quantity` bigint NOT NULL DEFAULT '1' COMMENT 'Quantity',
|
||||
`price` bigint NOT NULL DEFAULT '0' COMMENT 'Original price',
|
||||
`amount` bigint NOT NULL DEFAULT '0' COMMENT 'Order Amount',
|
||||
`gift_amount` bigint NOT NULL DEFAULT '0' COMMENT 'User Gift Amount',
|
||||
`discount` bigint NOT NULL DEFAULT '0' COMMENT 'Discount Amount',
|
||||
`coupon` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Coupon',
|
||||
`coupon_discount` bigint NOT NULL DEFAULT '0' COMMENT 'Coupon Discount Amount',
|
||||
`commission` bigint NOT NULL DEFAULT '0' COMMENT 'Order Commission',
|
||||
`payment_id` bigint NOT NULL DEFAULT '-1' COMMENT 'Payment Id',
|
||||
`method` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Payment Method',
|
||||
`fee_amount` bigint NOT NULL DEFAULT '0' COMMENT 'Fee Amount',
|
||||
`trade_no` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Trade No',
|
||||
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Order Status: 1: Pending, 2: Paid, 3:Close, 4: Failed, 5:Finished',
|
||||
`subscribe_id` bigint NOT NULL DEFAULT '0' COMMENT 'Subscribe Id',
|
||||
`subscribe_token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Renewal Subscribe Token',
|
||||
`is_new` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Is New Order',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uni_order_order_no` (`order_no`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `payment`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Payment Name',
|
||||
`platform` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Payment Platform',
|
||||
`description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Payment Description',
|
||||
`icon` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'Payment Icon',
|
||||
`domain` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'Notification Domain',
|
||||
`config` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Payment Configuration',
|
||||
`fee_mode` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Fee Mode: 0: No Fee 1: Percentage 2: Fixed Amount 3: Percentage + Fixed Amount',
|
||||
`fee_percent` bigint DEFAULT '0' COMMENT 'Fee Percentage',
|
||||
`fee_amount` bigint DEFAULT '0' COMMENT 'Fixed Fee Amount',
|
||||
`enable` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Is Enabled',
|
||||
`token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Payment Token',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uni_payment_token` (`token`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `server`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Node Name',
|
||||
`tags` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Tags',
|
||||
`country` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Country',
|
||||
`city` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'City',
|
||||
`latitude` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'latitude',
|
||||
`longitude` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'longitude',
|
||||
`server_addr` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Server Address',
|
||||
`relay_mode` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'none' COMMENT 'Relay Mode',
|
||||
`relay_node` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Relay Node',
|
||||
`speed_limit` bigint NOT NULL DEFAULT '0' COMMENT 'Speed Limit',
|
||||
`traffic_ratio` decimal(4, 2) NOT NULL DEFAULT '0.00' COMMENT 'Traffic Ratio',
|
||||
`group_id` bigint DEFAULT NULL COMMENT 'Group ID',
|
||||
`protocol` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Protocol',
|
||||
`config` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Config',
|
||||
`enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Enabled',
|
||||
`sort` bigint NOT NULL DEFAULT '0' COMMENT 'Sort',
|
||||
`last_reported_at` datetime(3) DEFAULT NULL COMMENT 'Last Reported Time',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_group_id` (`group_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `server_group`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Group Name',
|
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'Group Description',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
-- if `sms` not exist, create it
|
||||
CREATE TABLE IF NOT EXISTS `sms`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
|
||||
`platform` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
|
||||
`area_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
|
||||
`telephone` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
|
||||
`status` tinyint(1) DEFAULT '1',
|
||||
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `subscribe`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Subscribe Name',
|
||||
`description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Subscribe Description',
|
||||
`unit_price` bigint NOT NULL DEFAULT '0' COMMENT 'Unit Price',
|
||||
`unit_time` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Unit Time',
|
||||
`discount` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Discount',
|
||||
`replacement` bigint NOT NULL DEFAULT '0' COMMENT 'Replacement',
|
||||
`inventory` bigint NOT NULL DEFAULT '0' COMMENT 'Inventory',
|
||||
`traffic` bigint NOT NULL DEFAULT '0' COMMENT 'Traffic',
|
||||
`speed_limit` bigint NOT NULL DEFAULT '0' COMMENT 'Speed Limit',
|
||||
`device_limit` bigint NOT NULL DEFAULT '0' COMMENT 'Device Limit',
|
||||
`quota` bigint NOT NULL DEFAULT '0' COMMENT 'Quota',
|
||||
`group_id` bigint DEFAULT NULL COMMENT 'Group Id',
|
||||
`server_group` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Server Group',
|
||||
`server` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Server',
|
||||
`show` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Show portal page',
|
||||
`sell` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Sell',
|
||||
`sort` bigint NOT NULL DEFAULT '0' COMMENT 'Sort',
|
||||
`deduction_ratio` bigint DEFAULT '0' COMMENT 'Deduction Ratio',
|
||||
`allow_deduction` tinyint(1) DEFAULT '1' COMMENT 'Allow deduction',
|
||||
`reset_cycle` bigint DEFAULT '0' COMMENT 'Reset Cycle: 0: No Reset, 1: 1st, 2: Monthly, 3: Yearly',
|
||||
`renewal_reset` tinyint(1) DEFAULT '0' COMMENT 'Renew Reset',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `subscribe_group`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Group Name',
|
||||
`description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Group Description',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `subscribe_type`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '订阅类型',
|
||||
`mark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '订阅标识',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT '创建时间',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 15
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `system`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`category` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Category',
|
||||
`key` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Key Name',
|
||||
`value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Key Value',
|
||||
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Type',
|
||||
`desc` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Description',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uni_system_key` (`key`),
|
||||
KEY `index_key` (`key`)
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 42
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `ticket`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Title',
|
||||
`description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Description',
|
||||
`user_id` bigint NOT NULL DEFAULT '0' COMMENT 'UserId',
|
||||
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Status',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `ticket_follow`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`ticket_id` bigint NOT NULL DEFAULT '0' COMMENT 'TicketId',
|
||||
`from` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'From',
|
||||
`type` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Type: 1 text, 2 image',
|
||||
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Content',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Create Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `traffic_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`server_id` bigint NOT NULL COMMENT 'Server ID',
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`subscribe_id` bigint NOT NULL COMMENT 'Subscription ID',
|
||||
`download` bigint DEFAULT '0' COMMENT 'Download Traffic',
|
||||
`upload` bigint DEFAULT '0' COMMENT 'Upload Traffic',
|
||||
`timestamp` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Traffic Log Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_subscribe_id` (`subscribe_id`),
|
||||
KEY `idx_server_id` (`server_id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'User Password',
|
||||
`avatar` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'User Avatar',
|
||||
`balance` bigint DEFAULT '0' COMMENT 'User Balance',
|
||||
`telegram` bigint DEFAULT NULL COMMENT 'Telegram Account',
|
||||
`refer_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'Referral Code',
|
||||
`referer_id` bigint DEFAULT NULL COMMENT 'Referrer ID',
|
||||
`commission` bigint DEFAULT '0' COMMENT 'Commission',
|
||||
`gift_amount` bigint DEFAULT '0' COMMENT 'User Gift Amount',
|
||||
`enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Is Account Enabled',
|
||||
`is_admin` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Is Admin',
|
||||
`valid_email` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Is Email Verified',
|
||||
`enable_email_notify` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Enable Email Notifications',
|
||||
`enable_telegram_notify` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Enable Telegram Notifications',
|
||||
`enable_balance_notify` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Enable Balance Change Notifications',
|
||||
`enable_login_notify` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Enable Login Notifications',
|
||||
`enable_subscribe_notify` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Enable Subscription Notifications',
|
||||
`enable_trade_notify` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Enable Trade Notifications',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
`deleted_at` datetime(3) DEFAULT NULL COMMENT 'Deletion Time',
|
||||
`is_del` bigint unsigned DEFAULT NULL COMMENT '1: Normal 0: Deleted',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_referer` (`referer_id`)
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 2
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_auth_methods`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`auth_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Auth Type 1: apple 2: google 3: github 4: facebook 5: telegram 6: email 7: phone',
|
||||
`auth_identifier` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Auth Identifier',
|
||||
`verified` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Is Verified',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `idx_auth_identifier` (`auth_identifier`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 2
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_balance_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`amount` bigint NOT NULL COMMENT 'Amount',
|
||||
`type` tinyint(1) NOT NULL COMMENT 'Type: 1: Recharge 2: Withdraw 3: Payment 4: Refund 5: Reward',
|
||||
`order_id` bigint DEFAULT NULL COMMENT 'Order ID',
|
||||
`balance` bigint NOT NULL COMMENT 'Balance',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_commission_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`order_no` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Order No.',
|
||||
`amount` bigint NOT NULL COMMENT 'Amount',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_device`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`subscribe_id` bigint DEFAULT NULL COMMENT 'Subscribe ID',
|
||||
`ip` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Device Ip.',
|
||||
`Identifier` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Device Identifier.',
|
||||
`user_agent` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Device User Agent.',
|
||||
`online` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Online',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'EnableDeviceNumber',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_gift_amount_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`user_subscribe_id` bigint DEFAULT NULL COMMENT 'Deduction User Subscribe ID',
|
||||
`order_no` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Order No.',
|
||||
`type` tinyint(1) NOT NULL COMMENT 'Type: 1: Increase 2: Reduce',
|
||||
`amount` bigint NOT NULL COMMENT 'Amount',
|
||||
`balance` bigint NOT NULL COMMENT 'Balance',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'Remark',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_login_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`login_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Login IP',
|
||||
`user_agent` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'UserAgent',
|
||||
`success` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Login Success',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_subscribe`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`order_id` bigint NOT NULL COMMENT 'Order ID',
|
||||
`subscribe_id` bigint NOT NULL COMMENT 'Subscription ID',
|
||||
`start_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Subscription Start Time',
|
||||
`expire_time` datetime(3) DEFAULT NULL COMMENT 'Subscription Expire Time',
|
||||
`traffic` bigint DEFAULT '0' COMMENT 'Traffic',
|
||||
`download` bigint DEFAULT '0' COMMENT 'Download Traffic',
|
||||
`upload` bigint DEFAULT '0' COMMENT 'Upload Traffic',
|
||||
`token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'Token',
|
||||
`uuid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'UUID',
|
||||
`status` tinyint(1) DEFAULT '0' COMMENT 'Subscription Status: 0: Pending 1: Active 2: Finished 3: Expired 4: Deducted',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uni_user_subscribe_token` (`token`),
|
||||
UNIQUE KEY `uni_user_subscribe_uuid` (`uuid`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_order_id` (`order_id`),
|
||||
KEY `idx_subscribe_id` (`subscribe_id`),
|
||||
KEY `idx_token` (`token`),
|
||||
KEY `idx_uuid` (`uuid`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_subscribe_log`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`user_id` bigint NOT NULL COMMENT 'User ID',
|
||||
`user_subscribe_id` bigint NOT NULL COMMENT 'User Subscribe ID',
|
||||
`token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Token',
|
||||
`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'IP',
|
||||
`user_agent` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'UserAgent',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_user_subscribe_id` (`user_subscribe_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `server_rule_group`
|
||||
(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Rule Group Name',
|
||||
`icon` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Rule Group Icon',
|
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'Rule Group Description',
|
||||
`enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Rule Group Enable',
|
||||
`created_at` datetime(3) DEFAULT NULL COMMENT 'Creation Time',
|
||||
`updated_at` datetime(3) DEFAULT NULL COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `unique_name` (`name`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -0,0 +1,21 @@
|
||||
-- 000002_init_data.down.sql
|
||||
SET
|
||||
FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
DELETE
|
||||
FROM `auth_method`
|
||||
WHERE `id` IN (1, 2, 3, 4, 5, 6, 7, 8);
|
||||
DELETE
|
||||
FROM `payment`
|
||||
WHERE `id` = -1;
|
||||
DELETE
|
||||
FROM `subscribe_type`
|
||||
WHERE `id` IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
|
||||
DELETE
|
||||
FROM `system`
|
||||
WHERE `id` IN
|
||||
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
|
||||
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41);
|
||||
|
||||
SET
|
||||
FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -0,0 +1,127 @@
|
||||
-- 000002_init_data.up.sql
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- auth_method
|
||||
INSERT IGNORE INTO `auth_method` (`id`, `method`, `config`, `enabled`, `created_at`, `updated_at`)
|
||||
VALUES (1, 'email',
|
||||
'{"platform":"smtp","platform_config":{"host":"","port":0,"user":"","pass":"","from":"","ssl":false},"enable_verify":false,"enable_notify":false,"enable_domain_suffix":false,"domain_suffix_list":"","verify_email_template":"","expiration_email_template":"","maintenance_email_template":"","traffic_exceed_email_template":""}',
|
||||
1, '2025-04-22 14:25:16.642', '2025-04-22 14:25:16.642'),
|
||||
(2, 'mobile',
|
||||
'{"platform":"AlibabaCloud","platform_config":{"access":"","secret":"","sign_name":"","endpoint":"","template_code":""},"enable_whitelist":false,"whitelist":[]}',
|
||||
0, '2025-04-22 14:25:16.642', '2025-04-22 14:25:16.642'),
|
||||
(3, 'apple', '{"team_id":"","key_id":"","client_id":"","client_secret":"","redirect_url":""}', 0,
|
||||
'2025-04-22 14:25:16.642', '2025-04-22 14:25:16.642'),
|
||||
(4, 'google', '{"client_id":"","client_secret":"","redirect_url":""}', 0, '2025-04-22 14:25:16.642',
|
||||
'2025-04-22 14:25:16.642'),
|
||||
(5, 'github', '{"client_id":"","client_secret":"","redirect_url":""}', 0, '2025-04-22 14:25:16.642',
|
||||
'2025-04-22 14:25:16.642'),
|
||||
(6, 'facebook', '{"client_id":"","client_secret":"","redirect_url":""}', 0, '2025-04-22 14:25:16.642',
|
||||
'2025-04-22 14:25:16.642'),
|
||||
(7, 'telegram', '{"bot_token":"","enable_notify":false,"webhook_domain":""}', 0, '2025-04-22 14:25:16.642',
|
||||
'2025-04-22 14:25:16.642'),
|
||||
(8, 'device', '{"show_ads":false,"only_real_device":false,"enable_security":false,"security_secret":""}', 0,
|
||||
'2025-04-22 14:25:16.642', '2025-04-22 14:25:16.642');
|
||||
|
||||
-- payment
|
||||
INSERT IGNORE INTO `payment` (`id`, `name`, `platform`, `description`, `icon`, `domain`, `config`, `fee_mode`,
|
||||
`fee_percent`, `fee_amount`, `enable`, `token`)
|
||||
VALUES (-1, 'Balance', 'balance', '', '', '', '', 0, 0, 0, 1, '');
|
||||
|
||||
-- subscribe_type
|
||||
INSERT IGNORE INTO `subscribe_type` (`id`, `name`, `mark`, `created_at`, `updated_at`)
|
||||
VALUES (1, 'Clash', 'Clash', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(2, 'Hiddify', 'Hiddify', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(3, 'Loon', 'Loon', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(4, 'NekoBox', 'NekoBox', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(5, 'NekoRay', 'NekoRay', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(6, 'Netch', 'Netch', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(7, 'Quantumult', 'Quantumult', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(8, 'Shadowrocket', 'Shadowrocket', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(9, 'Singhandle', 'Singhandle', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(10, 'Surfboard', 'Surfboard', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(11, 'Surge', 'Surge', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(12, 'V2box', 'V2box', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(13, 'V2rayN', 'V2rayN', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648'),
|
||||
(14, 'V2rayNg', 'V2rayNg', '2025-04-22 14:25:16.648', '2025-04-22 14:25:16.648');
|
||||
|
||||
-- system
|
||||
INSERT IGNORE INTO `system` (`id`, `category`, `key`, `value`, `type`, `desc`, `created_at`, `updated_at`)
|
||||
VALUES (1, 'site', 'SiteLogo', '/favicon.svg', 'string', 'Site Logo', '2025-04-22 14:25:16.637',
|
||||
'2025-04-22 14:25:16.637'),
|
||||
(2, 'site', 'SiteName', 'Perfect Panel', 'string', 'Site Name', '2025-04-22 14:25:16.637',
|
||||
'2025-04-22 14:25:16.637'),
|
||||
(3, 'site', 'SiteDesc',
|
||||
'PPanel is a pure, professional, and perfect open-source proxy panel tool, designed to be your ideal choice for learning and practical use.',
|
||||
'string', 'Site Description', '2025-04-22 14:25:16.637', '2025-04-22 14:25:16.637'),
|
||||
(4, 'site', 'Host', '', 'string', 'Site Host', '2025-04-22 14:25:16.637', '2025-04-22 14:25:16.637'),
|
||||
(5, 'site', 'Keywords', 'Perfect Panel,PPanel', 'string', 'Site Keywords', '2025-04-22 14:25:16.637',
|
||||
'2025-04-22 14:25:16.637'),
|
||||
(6, 'site', 'CustomHTML', '', 'string', 'Custom HTML', '2025-04-22 14:25:16.637', '2025-04-22 14:25:16.637'),
|
||||
(7, 'tos', 'TosContent', 'Welcome to use Perfect Panel', 'string', 'Terms of Service', '2025-04-22 14:25:16.637',
|
||||
'2025-04-22 14:25:16.637'),
|
||||
(8, 'tos', 'PrivacyPolicy', '', 'string', 'PrivacyPolicy', '2025-04-22 14:25:16.637', '2025-04-22 14:25:16.637'),
|
||||
(9, 'ad', 'WebAD', 'false', 'bool', 'Display ad on the web', '2025-04-22 14:25:16.637',
|
||||
'2025-04-22 14:25:16.637'),
|
||||
(10, 'subscribe', 'SingleModel', 'false', 'bool', '是否单订阅模式', '2025-04-22 14:25:16.639',
|
||||
'2025-04-22 14:25:16.639'),
|
||||
(11, 'subscribe', 'SubscribePath', '/api/subscribe', 'string', '订阅路径', '2025-04-22 14:25:16.639',
|
||||
'2025-04-22 14:25:16.639'),
|
||||
(12, 'subscribe', 'SubscribeDomain', '', 'string', '订阅域名', '2025-04-22 14:25:16.639',
|
||||
'2025-04-22 14:25:16.639'),
|
||||
(13, 'subscribe', 'PanDomain', 'false', 'bool', '是否使用泛域名', '2025-04-22 14:25:16.639',
|
||||
'2025-04-22 14:25:16.639'),
|
||||
(14, 'verify', 'TurnstileSiteKey', '', 'string', 'TurnstileSiteKey', '2025-04-22 14:25:16.639',
|
||||
'2025-04-22 14:25:16.639'),
|
||||
(15, 'verify', 'TurnstileSecret', '', 'string', 'TurnstileSecret', '2025-04-22 14:25:16.639',
|
||||
'2025-04-22 14:25:16.639'),
|
||||
(16, 'verify', 'EnableLoginVerify', 'false', 'bool', 'is enable login verify', '2025-04-22 14:25:16.639',
|
||||
'2025-04-22 14:25:16.639'),
|
||||
(17, 'verify', 'EnableRegisterVerify', 'false', 'bool', 'is enable register verify', '2025-04-22 14:25:16.639',
|
||||
'2025-04-22 14:25:16.639'),
|
||||
(18, 'verify', 'EnableResetPasswordVerify', 'false', 'bool', 'is enable reset password verify',
|
||||
'2025-04-22 14:25:16.639', '2025-04-22 14:25:16.639'),
|
||||
(19, 'server', 'NodeSecret', '12345678', 'string', 'node secret', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(20, 'server', 'NodePullInterval', '10', 'int', 'node pull interval', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(21, 'server', 'NodePushInterval', '60', 'int', 'node push interval', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(22, 'server', 'NodeMultiplierConfig', '[]', 'string', 'node multiplier config', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(23, 'invite', 'ForcedInvite', 'false', 'bool', 'Forced invite', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(24, 'invite', 'ReferralPercentage', '20', 'int', 'Referral percentage', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(25, 'invite', 'OnlyFirstPurchase', 'false', 'bool', 'Only first purchase', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(26, 'register', 'StopRegister', 'false', 'bool', 'is stop register', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(27, 'register', 'EnableTrial', 'false', 'bool', 'is enable trial', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(28, 'register', 'TrialSubscribe', '', 'int', 'Trial subscription', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(29, 'register', 'TrialTime', '24', 'int', 'Trial time', '2025-04-22 14:25:16.640', '2025-04-22 14:25:16.640'),
|
||||
(30, 'register', 'TrialTimeUnit', 'Hour', 'string', 'Trial time unit', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(31, 'register', 'EnableIpRegisterLimit', 'false', 'bool', 'is enable IP register limit',
|
||||
'2025-04-22 14:25:16.640', '2025-04-22 14:25:16.640'),
|
||||
(32, 'register', 'IpRegisterLimit', '3', 'int', 'IP Register Limit', '2025-04-22 14:25:16.640',
|
||||
'2025-04-22 14:25:16.640'),
|
||||
(33, 'register', 'IpRegisterLimitDuration', '64', 'int', 'IP Register Limit Duration (minutes)',
|
||||
'2025-04-22 14:25:16.640', '2025-04-22 14:25:16.640'),
|
||||
(34, 'currency', 'Currency', 'USD', 'string', 'Currency', '2025-04-22 14:25:16.641', '2025-04-22 14:25:16.641'),
|
||||
(35, 'currency', 'CurrencySymbol', '$', 'string', 'Currency Symbol', '2025-04-22 14:25:16.641',
|
||||
'2025-04-22 14:25:16.641'),
|
||||
(36, 'currency', 'CurrencyUnit', 'USD', 'string', 'Currency Unit', '2025-04-22 14:25:16.641',
|
||||
'2025-04-22 14:25:16.641'),
|
||||
(37, 'currency', 'AccessKey', '', 'string', 'Exchangerate Access Key', '2025-04-22 14:25:16.641',
|
||||
'2025-04-22 14:25:16.641'),
|
||||
(38, 'verify_code', 'VerifyCodeExpireTime', '300', 'int', 'Verify code expire time', '2025-04-22 14:25:16.641',
|
||||
'2025-04-22 14:25:16.641'),
|
||||
(39, 'verify_code', 'VerifyCodeLimit', '15', 'int', 'limits of verify code', '2025-04-22 14:25:16.641',
|
||||
'2025-04-22 14:25:16.641'),
|
||||
(40, 'verify_code', 'VerifyCodeInterval', '60', 'int', 'Interval of verify code', '2025-04-22 14:25:16.641',
|
||||
'2025-04-22 14:25:16.641'),
|
||||
(41, 'system', 'Version', '0.2.0(02002)', 'string', 'System Version', '2025-04-22 14:25:16.642',
|
||||
'2025-04-22 14:25:16.642');
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -0,0 +1,72 @@
|
||||
-- migrations/02003_update_payment.down.sql
|
||||
-- Purpose: Revert updates to payment and order tables
|
||||
-- Author: PPanel Team, 2025-04-21
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- Drop payment_id column from order table (if exists)
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'order'
|
||||
AND COLUMN_NAME = 'payment_id');
|
||||
SET @sql = IF(@column_exists > 0,
|
||||
'ALTER TABLE `order` DROP COLUMN `payment_id`',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Drop platform column from payment table (if exists)
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'payment'
|
||||
AND COLUMN_NAME = 'platform');
|
||||
SET @sql = IF(@column_exists > 0,
|
||||
'ALTER TABLE `payment` DROP COLUMN `platform`',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Drop description column from payment table (if exists)
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'payment'
|
||||
AND COLUMN_NAME = 'description');
|
||||
SET @sql = IF(@column_exists > 0,
|
||||
'ALTER TABLE `payment` DROP COLUMN `description`',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Drop token column from payment table (if exists)
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'payment'
|
||||
AND COLUMN_NAME = 'token');
|
||||
SET @sql = IF(@column_exists > 0,
|
||||
'ALTER TABLE `payment` DROP COLUMN `token`',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Optionally restore mark column (if needed, adjust definition as per original schema)
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'payment'
|
||||
AND COLUMN_NAME = 'mark');
|
||||
SET @sql = IF(@column_exists = 0,
|
||||
'ALTER TABLE `payment` ADD COLUMN `mark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT \'Payment Mark\' AFTER `name`',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -0,0 +1,72 @@
|
||||
-- 2025-04-22 16:16:00
|
||||
-- Purpose: Update payment table
|
||||
-- Author: PPanel Team, 2025-04-21
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- Alter the order table to add a payment_id column (if not exists)
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'order'
|
||||
AND COLUMN_NAME = 'payment_id');
|
||||
SET @sql = IF(@column_exists = 0,
|
||||
'ALTER TABLE `order` ADD COLUMN `payment_id` bigint NOT NULL DEFAULT \'-1\' COMMENT \'Payment Id\' AFTER `commission`',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Alter the payment table to add a platform column (if not exists)
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'payment'
|
||||
AND COLUMN_NAME = 'platform');
|
||||
SET @sql = IF(@column_exists = 0,
|
||||
'ALTER TABLE `payment` ADD COLUMN `platform` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT \'Payment Platform\' AFTER `name`',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Drop the mark column from the payment table (only if exists)
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'payment'
|
||||
AND COLUMN_NAME = 'mark');
|
||||
SET @sql = IF(@column_exists > 0,
|
||||
'ALTER TABLE `payment` DROP COLUMN `mark`',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Alter the payment table to add a description column (if not exists)
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'payment'
|
||||
AND COLUMN_NAME = 'description');
|
||||
SET @sql = IF(@column_exists = 0,
|
||||
'ALTER TABLE `payment` ADD COLUMN `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT \'Payment Description\' AFTER `platform`',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Alter the payment table to add a token column (if not exists)
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'payment'
|
||||
AND COLUMN_NAME = 'token');
|
||||
SET @sql = IF(@column_exists = 0,
|
||||
'ALTER TABLE `payment` ADD COLUMN `token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT \'Payment Token\' AFTER `description`',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -0,0 +1,4 @@
|
||||
-- migrations/02003_rebuild_rule.up.sql
|
||||
-- Purpose: Back rebuilding server rule table
|
||||
-- Author: PPanel Team, 2025-04-21
|
||||
DROP TABLE IF EXISTS server_rule_group;
|
||||
@@ -0,0 +1,22 @@
|
||||
-- migrations/02003_rebuild_rule.up.sql
|
||||
-- Purpose: rebuilding server rule table
|
||||
-- Author: PPanel Team, 2025-04-21
|
||||
|
||||
DROP TABLE IF EXISTS `server_rule_group`;
|
||||
|
||||
CREATE TABLE `server_rule_group`
|
||||
(
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Rule Group Name',
|
||||
`icon` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Rule Group Icon',
|
||||
`tags` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Selected Node Tags',
|
||||
`rules` MEDIUMTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT 'Rules',
|
||||
`enable` TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'Rule Group Enable',
|
||||
`created_at` DATETIME(3) COMMENT 'Creation Time',
|
||||
`updated_at` DATETIME(3) COMMENT 'Update Time',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uni_server_rule_group_name` (`name`),
|
||||
INDEX `idx_enable` (`enable`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
@@ -0,0 +1,52 @@
|
||||
-- migrations/02004_create_user_device_online_record.down.sql
|
||||
-- Purpose: Drop user device online record table
|
||||
-- Author: PPanel Team, 2025-04-22
|
||||
|
||||
DROP TABLE IF EXISTS `user_device_online_record`;
|
||||
|
||||
-- User subscribe table migration for removing finished_at column
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'user_subscribe'
|
||||
AND COLUMN_NAME = 'finished_at');
|
||||
SET @sql = IF(@column_exists > 0,
|
||||
'ALTER TABLE `user_subscribe` DROP COLUMN `finished_at`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Application config table migration for removing invitation_link column
|
||||
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'application_config'
|
||||
AND COLUMN_NAME = 'invitation_link');
|
||||
|
||||
SET @sql = IF(@column_exists > 0,
|
||||
'ALTER TABLE `application_config` DROP COLUMN `invitation_link`',
|
||||
'SELECT 1'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Application config table migration for removing kr_website_id column
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'application_config'
|
||||
AND COLUMN_NAME = 'kr_website_id');
|
||||
|
||||
SET @sql = IF(@column_exists > 0,
|
||||
'ALTER TABLE `application_config` DROP COLUMN `kr_website_id`',
|
||||
'SELECT 1'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@@ -0,0 +1,69 @@
|
||||
-- migrations/02005_create_user_device_online_record.up.sql
|
||||
-- Purpose: Create table for tracking user device online records
|
||||
-- Author: PPanel Team, 2025-04-22
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_device_online_record`
|
||||
(
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`user_id` BIGINT NOT NULL COMMENT 'User ID',
|
||||
`identifier` VARCHAR(255) NOT NULL COMMENT 'Device Identifier',
|
||||
`online_time` DATETIME COMMENT 'Online Time',
|
||||
`offline_time` DATETIME COMMENT 'Offline Time',
|
||||
`online_seconds` BIGINT COMMENT 'Offline Seconds',
|
||||
`duration_days` BIGINT COMMENT 'Duration Days',
|
||||
`created_at` DATETIME COMMENT 'Creation Time'
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
|
||||
|
||||
-- User subscribe table migration for adding finished_at column
|
||||
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'user_subscribe'
|
||||
AND COLUMN_NAME = 'finished_at');
|
||||
|
||||
SET @sql = IF(@column_exists = 0,
|
||||
'ALTER TABLE `user_subscribe` ADD COLUMN `finished_at` DATETIME NULL COMMENT ''Subscribe Finished Time'' AFTER `expire_time`',
|
||||
'SELECT 1'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
|
||||
-- Application config table migration for adding Link column
|
||||
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'application_config'
|
||||
AND COLUMN_NAME = 'invitation_link');
|
||||
|
||||
SET @sql = IF(@column_exists = 0,
|
||||
'ALTER TABLE `application_config` ADD COLUMN `invitation_link` TEXT NULL DEFAULT NULL COMMENT ''Invitation Link'' AFTER `startup_picture_skip_time`',
|
||||
'SELECT 1'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Application config table migration for adding kr_website_id column
|
||||
SET @column_exists = (SELECT COUNT(*)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'application_config'
|
||||
AND COLUMN_NAME = 'kr_website_id');
|
||||
|
||||
SET @sql = IF(@column_exists = 0,
|
||||
'ALTER TABLE `application_config` ADD COLUMN `kr_website_id` VARCHAR(255) NULL DEFAULT NULL COMMENT ''KR Website ID'' AFTER `invitation_link`',
|
||||
'SELECT 1'
|
||||
);
|
||||
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- migrations/02008_create_user_reset_subscribe_log.down.sql
|
||||
-- Purpose: Drop user_reset_subscribe_log table
|
||||
-- Author: PPanel Team, 2025-04-22
|
||||
|
||||
DROP TABLE IF EXISTS `user_reset_subscribe_log`;
|
||||
@@ -0,0 +1,17 @@
|
||||
-- migrations/02008_create_user_reset_subscribe_log.up.sql
|
||||
-- Purpose: Create user_reset_subscribe_log table
|
||||
-- Author: PPanel Team, 2025-04-22
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `user_reset_subscribe_log`
|
||||
(
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
`user_id` BIGINT NOT NULL COMMENT 'User ID',
|
||||
`type` TINYINT(1) NOT NULL COMMENT 'Type: 1: Auto 2: Advance 3: Paid',
|
||||
`order_no` VARCHAR(255) DEFAULT NULL COMMENT 'Order No.',
|
||||
`user_subscribe_id` BIGINT NOT NULL COMMENT 'User Subscribe ID',
|
||||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation Time',
|
||||
INDEX `idx_user_id` (`user_id`),
|
||||
INDEX `idx_user_subscribe_id` (`user_subscribe_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci;
|
||||
@@ -0,0 +1,42 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/model/user"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/uuidx"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// CreateAdminUser create admin user
|
||||
func CreateAdminUser(email, password string, tx *gorm.DB) error {
|
||||
enable := true
|
||||
return tx.Transaction(func(tx *gorm.DB) error {
|
||||
// Prevent duplicate creation
|
||||
if tx.Model(&user.User{}).Find(&user.User{}).RowsAffected != 0 {
|
||||
logger.Info("User already exists, skip creating administrator account")
|
||||
return nil
|
||||
}
|
||||
|
||||
u := user.User{
|
||||
Password: tool.EncodePassWord(password),
|
||||
IsAdmin: &enable,
|
||||
ReferCode: uuidx.UserInviteCode(time.Now().Unix()),
|
||||
}
|
||||
if err := tx.Model(&user.User{}).Save(&u).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
method := user.AuthMethods{
|
||||
UserId: u.Id,
|
||||
AuthType: "email",
|
||||
AuthIdentifier: email,
|
||||
Verified: true,
|
||||
}
|
||||
if err := tx.Model(&user.AuthMethods{}).Save(&method).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package migrate
|
||||
@@ -0,0 +1,29 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
_ "github.com/golang-migrate/migrate/v4/database/mysql"
|
||||
"github.com/golang-migrate/migrate/v4/source/iofs"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
)
|
||||
|
||||
//go:embed database/*.sql
|
||||
var sqlFiles embed.FS
|
||||
var NoChange = migrate.ErrNoChange
|
||||
|
||||
func Migrate(dsn string) *migrate.Migrate {
|
||||
d, err := iofs.New(sqlFiles, "database")
|
||||
if err != nil {
|
||||
logger.Errorf("[Migrate] iofs.New error: %v", err.Error())
|
||||
panic(err)
|
||||
}
|
||||
client, err := migrate.NewWithSourceInstance("iofs", d, fmt.Sprintf("mysql://%s", dsn))
|
||||
if err != nil {
|
||||
logger.Errorf("[Migrate] NewWithSourceInstance error: %v", err.Error())
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/orm"
|
||||
)
|
||||
|
||||
func getDSN() string {
|
||||
|
||||
cfg := orm.Config{
|
||||
Addr: "127.0.0.1",
|
||||
Username: "root",
|
||||
Password: "mylove520",
|
||||
Dbname: "vpnboard",
|
||||
}
|
||||
mc := orm.Mysql{
|
||||
Config: cfg,
|
||||
}
|
||||
return mc.Dsn()
|
||||
}
|
||||
|
||||
func TestMigrate(t *testing.T) {
|
||||
t.Skipf("skip test")
|
||||
m := Migrate(getDSN())
|
||||
err := m.Migrate(2004)
|
||||
if err != nil {
|
||||
t.Errorf("failed to migrate: %v", err)
|
||||
} else {
|
||||
t.Log("migrate success")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ExecuteSQLFile 执行嵌入的 SQL 文件,去除注释
|
||||
func ExecuteSQLFile(tx *gorm.DB, path string) error {
|
||||
// 读取 SQL 文件内容
|
||||
sqlContent, err := sqlFiles.ReadFile(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read embedded SQL file: %v", err)
|
||||
}
|
||||
|
||||
// 清除注释内容
|
||||
cleanedSQL := removeComments(string(sqlContent))
|
||||
|
||||
// 将清除注释后的内容按分号分割成多个 SQL 语句
|
||||
sqlStatements := splitSQLStatements(cleanedSQL)
|
||||
|
||||
// 遍历 SQL 语句并执行
|
||||
for _, stmt := range sqlStatements {
|
||||
stmt = strings.TrimSpace(stmt)
|
||||
if stmt == "" {
|
||||
continue
|
||||
}
|
||||
// 执行 SQL 语句
|
||||
if err := tx.Exec(stmt).Error; err != nil {
|
||||
return fmt.Errorf("failed to execute SQL statement: %v \nSQL: %s", err.Error(), stmt)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// removeComments 去除 SQL 代码中的注释
|
||||
func removeComments(sql string) string {
|
||||
var result strings.Builder
|
||||
inSingleLineComment := false
|
||||
inMultiLineComment := false
|
||||
length := len(sql)
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
// 处理 -- 单行注释
|
||||
if !inMultiLineComment && !inSingleLineComment && i+1 < length && sql[i] == '-' && sql[i+1] == '-' {
|
||||
inSingleLineComment = true
|
||||
i++ // 跳过 '-'
|
||||
continue
|
||||
}
|
||||
|
||||
// 结束单行注释(支持 \r\n 和 \n)
|
||||
if inSingleLineComment && (sql[i] == '\n' || sql[i] == '\r') {
|
||||
inSingleLineComment = false
|
||||
}
|
||||
|
||||
// 处理 /* 多行注释 */
|
||||
if !inSingleLineComment && !inMultiLineComment && i+1 < length && sql[i] == '/' && sql[i+1] == '*' {
|
||||
inMultiLineComment = true
|
||||
i++ // 跳过 '*'
|
||||
continue
|
||||
}
|
||||
|
||||
// 结束多行注释
|
||||
if inMultiLineComment && i+1 < length && sql[i] == '*' && sql[i+1] == '/' {
|
||||
inMultiLineComment = false
|
||||
i++ // 跳过 '/'
|
||||
continue
|
||||
}
|
||||
|
||||
// 不是注释内容时,将字符添加到结果中
|
||||
if !inSingleLineComment && !inMultiLineComment {
|
||||
result.WriteByte(sql[i])
|
||||
}
|
||||
}
|
||||
|
||||
// 去除多余的空白行
|
||||
lines := strings.Split(result.String(), "\n")
|
||||
var cleanedLines []string
|
||||
for _, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if trimmed != "" {
|
||||
cleanedLines = append(cleanedLines, trimmed)
|
||||
}
|
||||
}
|
||||
return strings.Join(cleanedLines, "\n")
|
||||
}
|
||||
|
||||
// splitSQLStatements 更安全地分割 SQL 语句
|
||||
func splitSQLStatements(sql string) []string {
|
||||
statements := strings.Split(sql, ";")
|
||||
var results []string
|
||||
for _, stmt := range statements {
|
||||
trimmed := strings.TrimSpace(stmt)
|
||||
if trimmed != "" {
|
||||
results = append(results, trimmed)
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/internal/model/auth"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
)
|
||||
|
||||
func Mobile(ctx *svc.ServiceContext) {
|
||||
logger.Debug("Mobile config initialization")
|
||||
method, err := ctx.AuthModel.FindOneByMethod(context.Background(), "mobile")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var cfg config.MobileConfig
|
||||
var mobileConfig auth.MobileAuthConfig
|
||||
if err := mobileConfig.Unmarshal(method.Config); err != nil {
|
||||
panic(fmt.Sprintf("failed to unmarshal mobile auth config: %v", err.Error()))
|
||||
}
|
||||
tool.DeepCopy(&cfg, mobileConfig)
|
||||
cfg.Enable = *method.Enabled
|
||||
value, _ := json.Marshal(mobileConfig.PlatformConfig)
|
||||
cfg.PlatformConfig = string(value)
|
||||
ctx.Config.Mobile = cfg
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package initialize
|
||||
@@ -0,0 +1,51 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/internal/model/system"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/nodeMultiplier"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
)
|
||||
|
||||
func Node(ctx *svc.ServiceContext) {
|
||||
logger.Debug("Node config initialization")
|
||||
configs, err := ctx.SystemModel.GetNodeConfig(context.Background())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var nodeConfig config.NodeConfig
|
||||
tool.SystemConfigSliceReflectToStruct(configs, &nodeConfig)
|
||||
ctx.Config.Node = nodeConfig
|
||||
|
||||
// Manager initialization
|
||||
if ctx.DB.Model(&system.System{}).Where("`key` = ?", "NodeMultiplierConfig").Find(&system.System{}).RowsAffected == 0 {
|
||||
if err := ctx.DB.Model(&system.System{}).Create(&system.System{
|
||||
Key: "NodeMultiplierConfig",
|
||||
Value: "[]",
|
||||
Type: "string",
|
||||
Desc: "Node Multiplier Config",
|
||||
Category: "server",
|
||||
}).Error; err != nil {
|
||||
logger.Errorf("Create Node Multiplier Config Error: %s", err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
nodeMultiplierData, err := ctx.SystemModel.FindNodeMultiplierConfig(context.Background())
|
||||
if err != nil {
|
||||
|
||||
logger.Error("Get Node Multiplier Config Error: ", logger.Field("error", err.Error()))
|
||||
return
|
||||
}
|
||||
var periods []nodeMultiplier.TimePeriod
|
||||
if err := json.Unmarshal([]byte(nodeMultiplierData.Value), &periods); err != nil {
|
||||
logger.Error("Unmarshal Node Multiplier Config Error: ", logger.Field("error", err.Error()), logger.Field("value", nodeMultiplierData.Value))
|
||||
}
|
||||
ctx.NodeMultiplierManager = nodeMultiplier.NewNodeMultiplierManager(periods)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
)
|
||||
|
||||
func OAuth(svc *svc.ServiceContext) {
|
||||
logger.Debug("OAuth config initialization")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
)
|
||||
|
||||
func Register(ctx *svc.ServiceContext) {
|
||||
logger.Debug("Register config initialization")
|
||||
configs, err := ctx.SystemModel.GetRegisterConfig(context.Background())
|
||||
if err != nil {
|
||||
logger.Errorf("[Init Register Config] Get Register Config Error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
var registerConfig config.RegisterConfig
|
||||
tool.SystemConfigSliceReflectToStruct(configs, ®isterConfig)
|
||||
ctx.Config.Register = registerConfig
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
)
|
||||
|
||||
func Site(ctx *svc.ServiceContext) {
|
||||
logger.Debug("initialize site config")
|
||||
configs, err := ctx.SystemModel.GetSiteConfig(context.Background())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var siteConfig config.SiteConfig
|
||||
tool.SystemConfigSliceReflectToStruct(configs, &siteConfig)
|
||||
ctx.Config.Site = siteConfig
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/model/cache"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
)
|
||||
|
||||
func TrafficDataToRedis(svcCtx *svc.ServiceContext) {
|
||||
ctx := context.Background()
|
||||
// 统计昨天的节点流量数据排行榜前10
|
||||
nodeData, err := svcCtx.TrafficLogModel.TopServersTrafficByDay(ctx, time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day()-1, 0, 0, 0, 0, time.Local), 10)
|
||||
if err != nil {
|
||||
logger.Errorw("统计昨天的流量数据失败", logger.Field("error", err.Error()))
|
||||
}
|
||||
var nodeCacheData []cache.NodeTodayTrafficRank
|
||||
for _, node := range nodeData {
|
||||
serverInfo, err := svcCtx.ServerModel.FindOne(ctx, node.ServerId)
|
||||
if err != nil {
|
||||
logger.Errorw("查询节点信息失败", logger.Field("error", err.Error()))
|
||||
continue
|
||||
}
|
||||
nodeCacheData = append(nodeCacheData, cache.NodeTodayTrafficRank{
|
||||
ID: node.ServerId,
|
||||
Name: serverInfo.Name,
|
||||
Upload: node.Upload,
|
||||
Download: node.Download,
|
||||
Total: node.Upload + node.Download,
|
||||
})
|
||||
}
|
||||
// 写入缓存
|
||||
if err = svcCtx.NodeCache.UpdateYesterdayNodeTotalTrafficRank(ctx, nodeCacheData); err != nil {
|
||||
logger.Errorw("写入昨天的流量数据到缓存失败", logger.Field("error", err.Error()))
|
||||
}
|
||||
// 统计昨天的用户流量数据排行榜前10
|
||||
userData, err := svcCtx.TrafficLogModel.TopUsersTrafficByDay(ctx, time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day()-1, 0, 0, 0, 0, time.Local), 10)
|
||||
if err != nil {
|
||||
logger.Errorw("统计昨天的流量数据失败", logger.Field("error", err.Error()))
|
||||
}
|
||||
var userCacheData []cache.UserTodayTrafficRank
|
||||
for _, user := range userData {
|
||||
userCacheData = append(userCacheData, cache.UserTodayTrafficRank{
|
||||
SID: user.SubscribeId,
|
||||
Upload: user.Upload,
|
||||
Download: user.Download,
|
||||
Total: user.Upload + user.Download,
|
||||
})
|
||||
}
|
||||
// 写入缓存
|
||||
if err = svcCtx.NodeCache.UpdateYesterdayUserTotalTrafficRank(ctx, userCacheData); err != nil {
|
||||
logger.Errorw("写入昨天的流量数据到缓存失败", logger.Field("error", err.Error()))
|
||||
}
|
||||
logger.Infow("初始化昨天的流量数据到缓存成功")
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
)
|
||||
|
||||
func Subscribe(svc *svc.ServiceContext) {
|
||||
logger.Debug("Subscribe config initialization")
|
||||
configs, err := svc.SystemModel.GetSubscribeConfig(context.Background())
|
||||
if err != nil {
|
||||
logger.Error("[Init Subscribe Config] Get Subscribe Config Error: ", logger.Field("error", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
var subscribeConfig config.SubscribeConfig
|
||||
tool.SystemConfigSliceReflectToStruct(configs, &subscribeConfig)
|
||||
svc.Config.Subscribe = subscribeConfig
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package initialize
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
|
||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/internal/logic/telegram"
|
||||
"github.com/perfect-panel/ppanel-server/internal/model/auth"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
)
|
||||
|
||||
func Telegram(svc *svc.ServiceContext) {
|
||||
|
||||
method, err := svc.AuthModel.FindOneByMethod(context.Background(), "telegram")
|
||||
if err != nil {
|
||||
logger.Errorf("[Init Telegram Config] Get Telegram Config Error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
var tg config.Telegram
|
||||
|
||||
tgConfig := new(auth.TelegramAuthConfig)
|
||||
if err = tgConfig.Unmarshal(method.Config); err != nil {
|
||||
logger.Errorf("[Init Telegram Config] Unmarshal Telegram Config Error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if tgConfig.BotToken == "" {
|
||||
logger.Debug("[Init Telegram Config] Telegram Token is empty")
|
||||
return
|
||||
}
|
||||
|
||||
bot, err := tgbotapi.NewBotAPI(tg.BotToken)
|
||||
if err != nil {
|
||||
logger.Error("[Init Telegram Config] New Bot API Error: ", logger.Field("error", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if tgConfig.WebHookDomain == "" || svc.Config.Debug {
|
||||
// set Long Polling mode
|
||||
updateConfig := tgbotapi.NewUpdate(0)
|
||||
updateConfig.Timeout = 60
|
||||
updates := bot.GetUpdatesChan(updateConfig)
|
||||
go func() {
|
||||
for update := range updates {
|
||||
if update.Message != nil {
|
||||
ctx := context.Background()
|
||||
l := telegram.NewTelegramLogic(ctx, svc)
|
||||
l.TelegramLogic(&update)
|
||||
}
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
wh, err := tgbotapi.NewWebhook(fmt.Sprintf("%s/v1/telegram/webhook?secret=%s", tgConfig.WebHookDomain, tool.Md5Encode(tgConfig.BotToken, false)))
|
||||
if err != nil {
|
||||
logger.Errorf("[Init Telegram Config] New Webhook Error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
_, err = bot.Request(wh)
|
||||
if err != nil {
|
||||
logger.Errorf("[Init Telegram Config] Request Webhook Error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
user, err := bot.GetMe()
|
||||
if err != nil {
|
||||
logger.Error("[Init Telegram Config] Get Bot Info Error: ", logger.Field("error", err.Error()))
|
||||
return
|
||||
}
|
||||
svc.Config.Telegram.BotID = user.ID
|
||||
svc.Config.Telegram.BotName = user.UserName
|
||||
svc.Config.Telegram.EnableNotify = tg.EnableNotify
|
||||
svc.Config.Telegram.WebHookDomain = tg.WebHookDomain
|
||||
svc.TelegramBot = bot
|
||||
|
||||
logger.Info("[Init Telegram Config] Webhook set success")
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user