diff --git a/.github/workflows/docker-image-amd64.yml b/.github/workflows/docker-image-amd64.yml index 1a77775c..43705321 100644 --- a/.github/workflows/docker-image-amd64.yml +++ b/.github/workflows/docker-image-amd64.yml @@ -1,54 +1,54 @@ -name: Publish Docker image (amd64) - -on: - push: - tags: - - '*' - workflow_dispatch: - inputs: - name: - description: 'reason' - required: false -jobs: - push_to_registries: - name: Push Docker image to multiple registries - runs-on: ubuntu-latest - permissions: - packages: write - contents: read - steps: - - name: Check out the repo - uses: actions/checkout@v3 - - - name: Save version info - run: | - git describe --tags > VERSION - - - name: Log in to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Log in to the Container registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: | - justsong/gin-template - ghcr.io/${{ github.repository }} - - - name: Build and push Docker images - uses: docker/build-push-action@v3 - with: - context: . - push: true - tags: ${{ steps.meta.outputs.tags }} +name: Publish Docker image (amd64) + +on: + push: + tags: + - '*' + workflow_dispatch: + inputs: + name: + description: 'reason' + required: false +jobs: + push_to_registries: + name: Push Docker image to multiple registries + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + steps: + - name: Check out the repo + uses: actions/checkout@v3 + + - name: Save version info + run: | + git describe --tags > VERSION + + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Log in to the Container registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: | + ghcr.io/rain-kl/atsflare + ghcr.io/${{ github.repository }} + + - name: Build and push Docker images + uses: docker/build-push-action@v3 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.github/workflows/docker-image-arm64.yml b/.github/workflows/docker-image-arm64.yml index 8b57711b..91e84156 100644 --- a/.github/workflows/docker-image-arm64.yml +++ b/.github/workflows/docker-image-arm64.yml @@ -1,62 +1,62 @@ -name: Publish Docker image (arm64) - -on: - push: - tags: - - '*' - - '!*-alpha*' - workflow_dispatch: - inputs: - name: - description: 'reason' - required: false -jobs: - push_to_registries: - name: Push Docker image to multiple registries - runs-on: ubuntu-latest - permissions: - packages: write - contents: read - steps: - - name: Check out the repo - uses: actions/checkout@v3 - - - name: Save version info - run: | - git describe --tags > VERSION - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Log in to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Log in to the Container registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: | - justsong/gin-template - ghcr.io/${{ github.repository }} - - - name: Build and push Docker images - uses: docker/build-push-action@v3 - with: - context: . - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ steps.meta.outputs.tags }} +name: Publish Docker image (arm64) + +on: + push: + tags: + - '*' + - '!*-alpha*' + workflow_dispatch: + inputs: + name: + description: 'reason' + required: false +jobs: + push_to_registries: + name: Push Docker image to multiple registries + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + steps: + - name: Check out the repo + uses: actions/checkout@v3 + + - name: Save version info + run: | + git describe --tags > VERSION + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Log in to the Container registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: | + ghcr.io/rain-kl/atsflare + ghcr.io/${{ github.repository }} + + - name: Build and push Docker images + uses: docker/build-push-action@v3 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.github/workflows/linux-release.yml b/.github/workflows/linux-release.yml index 31435487..50d642c6 100644 --- a/.github/workflows/linux-release.yml +++ b/.github/workflows/linux-release.yml @@ -1,54 +1,54 @@ -name: Linux Release -permissions: - contents: write - -on: - push: - tags: - - '*' - - '!*-alpha*' -jobs: - release: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - uses: actions/setup-node@v3 - with: - node-version: 16 - - name: Build Frontend - env: - CI: "" - run: | - cd web - npm install - REACT_APP_VERSION=$(git describe --tags) npm run build - cd .. - - name: Set up Go - uses: actions/setup-go@v3 - with: - go-version: '>=1.18.0' - - name: Build Backend (amd64) - run: | - go mod download - go build -ldflags "-s -w -X 'gin-template/common.Version=$(git describe --tags)' -extldflags '-static'" -o gin-template - - - name: Build Backend (arm64) - run: | - sudo apt-get update - sudo apt-get install gcc-aarch64-linux-gnu - CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w -X 'gin-template/common.Version=$(git describe --tags)' -extldflags '-static'" -o gin-template-arm64 - - - name: Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: | - gin-template - gin-template-arm64 - draft: false - generate_release_notes: true - env: +name: Linux Release +permissions: + contents: write + +on: + push: + tags: + - '*' + - '!*-alpha*' +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/setup-node@v3 + with: + node-version: 16 + - name: Build Frontend + env: + CI: "" + run: | + cd web + npm install + REACT_APP_VERSION=$(git describe --tags) npm run build + cd .. + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '>=1.18.0' + - name: Build Backend (amd64) + run: | + go mod download + go build -ldflags "-s -w -X 'atsflare/common.Version=$(git describe --tags)' -extldflags '-static'" -o atsflare + + - name: Build Backend (arm64) + run: | + sudo apt-get update + sudo apt-get install gcc-aarch64-linux-gnu + CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w -X 'atsflare/common.Version=$(git describe --tags)' -extldflags '-static'" -o atsflare-arm64 + + - name: Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: | + atsflare + atsflare-arm64 + draft: false + generate_release_notes: true + env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/macos-release.yml b/.github/workflows/macos-release.yml index fdd6eb0a..5bb0feef 100644 --- a/.github/workflows/macos-release.yml +++ b/.github/workflows/macos-release.yml @@ -1,45 +1,45 @@ -name: macOS Release -permissions: - contents: write - -on: - push: - tags: - - '*' - - '!*-alpha*' -jobs: - release: - runs-on: macos-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - uses: actions/setup-node@v3 - with: - node-version: 16 - - name: Build Frontend - env: - CI: "" - run: | - cd web - npm install - REACT_APP_VERSION=$(git describe --tags) npm run build - cd .. - - name: Set up Go - uses: actions/setup-go@v3 - with: - go-version: '>=1.18.0' - - name: Build Backend - run: | - go mod download - go build -ldflags "-X 'gin-template/common.Version=$(git describe --tags)'" -o gin-template-macos - - name: Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: gin-template-macos - draft: false - generate_release_notes: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +name: macOS Release +permissions: + contents: write + +on: + push: + tags: + - '*' + - '!*-alpha*' +jobs: + release: + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/setup-node@v3 + with: + node-version: 16 + - name: Build Frontend + env: + CI: "" + run: | + cd web + npm install + REACT_APP_VERSION=$(git describe --tags) npm run build + cd .. + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '>=1.18.0' + - name: Build Backend + run: | + go mod download + go build -ldflags "-X 'atsflare/common.Version=$(git describe --tags)'" -o atsflare-macos + - name: Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: atsflare-macos + draft: false + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/windows-release.yml b/.github/workflows/windows-release.yml index 00882d62..185c18df 100644 --- a/.github/workflows/windows-release.yml +++ b/.github/workflows/windows-release.yml @@ -1,48 +1,48 @@ -name: Windows Release -permissions: - contents: write - -on: - push: - tags: - - '*' - - '!*-alpha*' -jobs: - release: - runs-on: windows-latest - defaults: - run: - shell: bash - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - uses: actions/setup-node@v3 - with: - node-version: 16 - - name: Build Frontend - env: - CI: "" - run: | - cd web - npm install - REACT_APP_VERSION=$(git describe --tags) npm run build - cd .. - - name: Set up Go - uses: actions/setup-go@v3 - with: - go-version: '>=1.18.0' - - name: Build Backend - run: | - go mod download - go build -ldflags "-s -w -X 'gin-template/common.Version=$(git describe --tags)'" -o gin-template.exe - - name: Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - files: gin-template.exe - draft: false - generate_release_notes: true - env: +name: Windows Release +permissions: + contents: write + +on: + push: + tags: + - '*' + - '!*-alpha*' +jobs: + release: + runs-on: windows-latest + defaults: + run: + shell: bash + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/setup-node@v3 + with: + node-version: 16 + - name: Build Frontend + env: + CI: "" + run: | + cd web + npm install + REACT_APP_VERSION=$(git describe --tags) npm run build + cd .. + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '>=1.18.0' + - name: Build Backend + run: | + go mod download + go build -ldflags "-s -w -X 'atsflare/common.Version=$(git describe --tags)'" -o atsflare.exe + - name: Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + with: + files: atsflare.exe + draft: false + generate_release_notes: true + env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/README.en.md b/README.en.md index 2060c4f5..3c4a035a 100644 --- a/README.en.md +++ b/README.en.md @@ -1,98 +1,93 @@ -

- 中文 | English -

- -

- gin-template logo -

- -
- -# Gin Template - -_✨ Template for Gin & React projects ✨_ - -
- -

- - license - - - release - - - docker pull - - - release - - - GoReportCard - -

- -

- Download - · - Tutorial - · - Feedback - · - Demo -

- -## Features -+ [x] Built-in user management. -+ [x] Built-in file management. -+ [x] [GitHub OAuth](https://github.com/settings/applications/new). -+ [x] WeChat official account authorization (need [wechat-server](https://github.com/songquanpeng/wechat-server)). -+ [x] Email verification & password reset. -+ [x] Request rate limiting. -+ [x] Static files caching. -+ [x] Mobile friendly UI. -+ [x] Token based authorization. -+ [x] Use GitHub Actions to build releases & Docker images. -+ [x] Cloudflare Turnstile user validation. - -## Deployment -### Manual deployment -1. Download built binary from [GitHub Releases](https://github.com/songquanpeng/gin-template/releases/latest) or build from source: - ```shell - git clone https://github.com/songquanpeng/gin-template.git - go mod download - go build -ldflags "-s -w" -o gin-template - ```` -2. Run it: - ```shell - chmod u+x gin-template - ./gin-template --port 3000 --log-dir ./logs - ``` -3. Visit [http://localhost:3000/](http://localhost:3000/) and login. The username for the initial account is `root` and the password is `123456`. - -### Deploy with Docker -Execute: `docker run -d --restart always -p 3000:3000 -v /home/ubuntu/data/gin-template:/data -v /etc/ssl/certs:/etc/ssl/certs:ro justsong/gin-template` - -Data will be saved in `/home/ubuntu/data/gin-template`. - -## Configurations -The system works out of the box. - -You can configure the system by set environment variables or specify command line arguments. - -After the system starts, use `root` user to log in to the system and do further configuration. - -### Environment Variables -1. `REDIS_CONN_STRING`: when set, Redis will be used as the storage for request rate limitation instead of memory storage. - + Example: `REDIS_CONN_STRING=redis://default:redispw@localhost:49153` -2. `SESSION_SECRET`: when set, a fixed session key will be used so that the logged-in users' cookie remains valid across system reboots. - + Example: `SESSION_SECRET=random_string` -3. `SQL_DSN`: when set, the target SQL database will be used instead of SQLite. - + Example: `SQL_DSN=root:123456@tcp(localhost:3306)/gin-template` - -### Command line Arguments -1. `--port `: specify the port number, the default value is `3000`. - + Example: `--port 3000` -2. `--log-dir `: specify the log dir, if not set, the log won't be saved. - + Example: `--log-dir ./logs` +

+ 中文 | English +

+ +

+ ATSFlare logo +

+ +
+ +# ATSFlare + +_✨ Internal Nginx control plane for reverse proxy management ✨_ + +
+ +

+ + license + + + release + + + release + + + GoReportCard + +

+ +

+ Download + · + Tutorial + · + Feedback +

+ +## Features ++ [x] Built-in user management. ++ [x] Built-in file management. ++ [x] [GitHub OAuth](https://github.com/settings/applications/new). ++ [x] WeChat official account authorization (need [wechat-server](https://github.com/songquanpeng/wechat-server)). ++ [x] Email verification & password reset. ++ [x] Request rate limiting. ++ [x] Static files caching. ++ [x] Mobile friendly UI. ++ [x] Token based authorization. ++ [x] Use GitHub Actions to build releases & Docker images. ++ [x] Cloudflare Turnstile user validation. + +## Deployment +### Manual deployment +1. Download built binary from [GitHub Releases](https://github.com/Rain-kl/ATSFlare/releases/latest) or build from source: + ```shell + git clone https://github.com/Rain-kl/ATSFlare.git + go mod download + go build -ldflags "-s -w" -o atsflare + ```` +2. Run it: + ```shell + chmod u+x atsflare + ./atsflare --port 3000 --log-dir ./logs + ``` +3. Visit [http://localhost:3000/](http://localhost:3000/) and login. The username for the initial account is `root` and the password is `123456`. + +### Deploy with Docker +Execute: `docker run -d --restart always -p 3000:3000 -v /home/ubuntu/data/atsflare:/data -v /etc/ssl/certs:/etc/ssl/certs:ro ghcr.io/rain-kl/atsflare` + +Data will be saved in `/home/ubuntu/data/atsflare`. + +## Configurations +The system works out of the box. + +You can configure the system by set environment variables or specify command line arguments. + +After the system starts, use `root` user to log in to the system and do further configuration. + +### Environment Variables +1. `REDIS_CONN_STRING`: when set, Redis will be used as the storage for request rate limitation instead of memory storage. + + Example: `REDIS_CONN_STRING=redis://default:redispw@localhost:49153` +2. `SESSION_SECRET`: when set, a fixed session key will be used so that the logged-in users' cookie remains valid across system reboots. + + Example: `SESSION_SECRET=random_string` +3. `SQL_DSN`: when set, the target SQL database will be used instead of SQLite. + + Example: `SQL_DSN=root:123456@tcp(localhost:3306)/atsflare` + +### Command line Arguments +1. `--port `: specify the port number, the default value is `3000`. + + Example: `--port 3000` +2. `--log-dir `: specify the log dir, if not set, the log won't be saved. + + Example: `--log-dir ./logs` 3. `--version`: print the version and exit. \ No newline at end of file diff --git a/atsf_server/Dockerfile b/atsf_server/Dockerfile index 7b2dc9ae..71efbcf4 100644 --- a/atsf_server/Dockerfile +++ b/atsf_server/Dockerfile @@ -1,31 +1,31 @@ -FROM node:16 as builder - -WORKDIR /build -COPY ./web . -COPY ./VERSION . -RUN npm install -RUN REACT_APP_VERSION=$(cat VERSION) npm run build - -FROM golang AS builder2 - -ENV GO111MODULE=on \ - CGO_ENABLED=1 \ - GOOS=linux - -WORKDIR /build -COPY . . -COPY --from=builder /build/build ./web/build -RUN go mod download -RUN go build -ldflags "-s -w -X 'gin-template/common.Version=$(cat VERSION)' -extldflags '-static'" -o gin-template - -FROM alpine - -RUN apk update \ - && apk upgrade \ - && apk add --no-cache ca-certificates tzdata \ - && update-ca-certificates 2>/dev/null || true -ENV PORT=3000 -COPY --from=builder2 /build/gin-template / -EXPOSE 3000 -WORKDIR /data -ENTRYPOINT ["/gin-template"] +FROM node:16 as builder + +WORKDIR /build +COPY ./web . +COPY ./VERSION . +RUN npm install +RUN REACT_APP_VERSION=$(cat VERSION) npm run build + +FROM golang AS builder2 + +ENV GO111MODULE=on \ + CGO_ENABLED=1 \ + GOOS=linux + +WORKDIR /build +COPY . . +COPY --from=builder /build/build ./web/build +RUN go mod download +RUN go build -ldflags "-s -w -X 'atsflare/common.Version=$(cat VERSION)' -extldflags '-static'" -o atsflare + +FROM alpine + +RUN apk update \ + && apk upgrade \ + && apk add --no-cache ca-certificates tzdata \ + && update-ca-certificates 2>/dev/null || true +ENV PORT=3000 +COPY --from=builder2 /build/atsflare / +EXPOSE 3000 +WORKDIR /data +ENTRYPOINT ["/atsflare"] diff --git a/atsf_server/common/init.go b/atsf_server/common/init.go index 7f926cc1..a208bdde 100644 --- a/atsf_server/common/init.go +++ b/atsf_server/common/init.go @@ -20,10 +20,10 @@ var ( var UploadPath = "upload" func printHelp() { - fmt.Println("Gin Template " + Version + " - Your next project starts from here.") + fmt.Println("ATSFlare " + Version + " - Internal Nginx Control Plane.") fmt.Println("Copyright (C) 2023 JustSong. All rights reserved.") - fmt.Println("GitHub: https://github.com/songquanpeng/gin-template") - fmt.Println("Usage: gin-template [--port ] [--log-dir ] [--version] [--help]") + fmt.Println("GitHub: https://github.com/Rain-kl/ATSFlare") + fmt.Println("Usage: atsflare [--port ] [--log-dir ] [--version] [--help]") } func init() { diff --git a/atsf_server/controller/agent.go b/atsf_server/controller/agent.go index e446cf1f..e6417acb 100644 --- a/atsf_server/controller/agent.go +++ b/atsf_server/controller/agent.go @@ -1,9 +1,9 @@ package controller import ( + "atsflare/model" + "atsflare/service" "encoding/json" - "gin-template/model" - "gin-template/service" "github.com/gin-gonic/gin" "net/http" ) diff --git a/atsf_server/controller/config_version.go b/atsf_server/controller/config_version.go index 7a674fc1..d4debcba 100644 --- a/atsf_server/controller/config_version.go +++ b/atsf_server/controller/config_version.go @@ -1,7 +1,7 @@ package controller import ( - "gin-template/service" + "atsflare/service" "github.com/gin-gonic/gin" "net/http" "strconv" diff --git a/atsf_server/controller/file.go b/atsf_server/controller/file.go index 0c1e2efb..2514890e 100644 --- a/atsf_server/controller/file.go +++ b/atsf_server/controller/file.go @@ -1,9 +1,9 @@ package controller import ( + "atsflare/common" + "atsflare/model" "fmt" - "gin-template/common" - "gin-template/model" "github.com/gin-gonic/gin" "net/http" "path/filepath" diff --git a/atsf_server/controller/github.go b/atsf_server/controller/github.go index 780de43b..d2930c47 100644 --- a/atsf_server/controller/github.go +++ b/atsf_server/controller/github.go @@ -1,12 +1,12 @@ package controller import ( + "atsflare/common" + "atsflare/model" "bytes" "encoding/json" "errors" "fmt" - "gin-template/common" - "gin-template/model" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "net/http" diff --git a/atsf_server/controller/managed_domain.go b/atsf_server/controller/managed_domain.go index 15ec4321..d9d37371 100644 --- a/atsf_server/controller/managed_domain.go +++ b/atsf_server/controller/managed_domain.go @@ -1,8 +1,8 @@ package controller import ( + "atsflare/service" "encoding/json" - "gin-template/service" "github.com/gin-gonic/gin" "net/http" "strconv" diff --git a/atsf_server/controller/misc.go b/atsf_server/controller/misc.go index 6e4c15d1..d7368489 100644 --- a/atsf_server/controller/misc.go +++ b/atsf_server/controller/misc.go @@ -1,10 +1,10 @@ package controller import ( + "atsflare/common" + "atsflare/model" "encoding/json" "fmt" - "gin-template/common" - "gin-template/model" "github.com/gin-gonic/gin" "net/http" ) diff --git a/atsf_server/controller/node.go b/atsf_server/controller/node.go index cb48adb5..39943667 100644 --- a/atsf_server/controller/node.go +++ b/atsf_server/controller/node.go @@ -1,8 +1,8 @@ package controller import ( + "atsflare/service" "encoding/json" - "gin-template/service" "github.com/gin-gonic/gin" "net/http" "strconv" diff --git a/atsf_server/controller/option.go b/atsf_server/controller/option.go index 394f2896..e627ec60 100644 --- a/atsf_server/controller/option.go +++ b/atsf_server/controller/option.go @@ -1,9 +1,9 @@ package controller import ( + "atsflare/common" + "atsflare/model" "encoding/json" - "gin-template/common" - "gin-template/model" "github.com/gin-gonic/gin" "net/http" "strings" diff --git a/atsf_server/controller/proxy_route.go b/atsf_server/controller/proxy_route.go index e5c273a9..7ddd2e28 100644 --- a/atsf_server/controller/proxy_route.go +++ b/atsf_server/controller/proxy_route.go @@ -1,8 +1,8 @@ package controller import ( + "atsflare/service" "encoding/json" - "gin-template/service" "github.com/gin-gonic/gin" "net/http" "strconv" diff --git a/atsf_server/controller/tls_certificate.go b/atsf_server/controller/tls_certificate.go index 5dddbc1d..5b38c0ec 100644 --- a/atsf_server/controller/tls_certificate.go +++ b/atsf_server/controller/tls_certificate.go @@ -1,8 +1,8 @@ package controller import ( + "atsflare/service" "encoding/json" - "gin-template/service" "github.com/gin-gonic/gin" "net/http" "strconv" diff --git a/atsf_server/controller/user.go b/atsf_server/controller/user.go index 767d3fc8..d22fb5bd 100644 --- a/atsf_server/controller/user.go +++ b/atsf_server/controller/user.go @@ -1,9 +1,9 @@ package controller import ( + "atsflare/common" + "atsflare/model" "encoding/json" - "gin-template/common" - "gin-template/model" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "github.com/google/uuid" diff --git a/atsf_server/controller/wechat.go b/atsf_server/controller/wechat.go index f7d8dfc2..04a9d17a 100644 --- a/atsf_server/controller/wechat.go +++ b/atsf_server/controller/wechat.go @@ -1,11 +1,11 @@ package controller import ( + "atsflare/common" + "atsflare/model" "encoding/json" "errors" "fmt" - "gin-template/common" - "gin-template/model" "github.com/gin-gonic/gin" "net/http" "strconv" diff --git a/atsf_server/go.mod b/atsf_server/go.mod index 7273f694..a3a40087 100644 --- a/atsf_server/go.mod +++ b/atsf_server/go.mod @@ -1,4 +1,4 @@ -module gin-template +module atsflare // +heroku goVersion go1.18 go 1.18 diff --git a/atsf_server/main.go b/atsf_server/main.go index 056faeff..9444c350 100644 --- a/atsf_server/main.go +++ b/atsf_server/main.go @@ -1,85 +1,85 @@ -package main - -import ( - "embed" - "fmt" - "gin-template/common" - "gin-template/middleware" - "gin-template/model" - "gin-template/router" - "github.com/gin-contrib/sessions" - "github.com/gin-contrib/sessions/cookie" - "github.com/gin-contrib/sessions/redis" - "github.com/gin-gonic/gin" - "log" - "os" - "strconv" -) - -//go:embed web/build -var buildFS embed.FS - -//go:embed web/build/index.html -var indexPage []byte - -func main() { - common.SetupGinLog() - common.SysLog("Gin Template " + common.Version + " started") - if os.Getenv("GIN_MODE") != "debug" { - gin.SetMode(gin.ReleaseMode) - } - // Initialize SQL Database - err := model.InitDB() - if err != nil { - common.FatalLog(err) - } - defer func() { - err := model.CloseDB() - if err != nil { - common.FatalLog(err) - } - }() - - // Initialize Redis - err = common.InitRedisClient() - if err != nil { - common.FatalLog(err) - } - - // Initialize options - model.InitOptionMap() - - // Initialize HTTP server - server := gin.Default() - //server.Use(gzip.Gzip(gzip.DefaultCompression)) - server.Use(middleware.CORS()) - - // Initialize session store - if common.RedisEnabled { - opt := common.ParseRedisOption() - store, _ := redis.NewStore(opt.MinIdleConns, opt.Network, opt.Addr, opt.Password, []byte(common.SessionSecret)) - server.Use(sessions.Sessions("session", store)) - } else { - store := cookie.NewStore([]byte(common.SessionSecret)) - server.Use(sessions.Sessions("session", store)) - } - - router.SetRouter(server, buildFS, indexPage) - var port = os.Getenv("PORT") - if port == "" { - port = strconv.Itoa(*common.Port) - } - common.SysLog(fmt.Sprintf("server config: port=%s gin_mode=%s sqlite_path=%s redis_enabled=%t upload_path=%s log_dir=%s agent_token_configured=%t node_offline_threshold=%s", port, gin.Mode(), common.SQLitePath, common.RedisEnabled, common.UploadPath, valueOrDefault(*common.LogDir, "stdout"), common.AgentToken != "", common.NodeOfflineThreshold)) - common.SysLog(fmt.Sprintf("server listening on :%s", port)) - err = server.Run(":" + port) - if err != nil { - log.Println(err) - } -} - -func valueOrDefault(value string, fallback string) string { - if value == "" { - return fallback - } - return value -} +package main + +import ( + "atsflare/common" + "atsflare/middleware" + "atsflare/model" + "atsflare/router" + "embed" + "fmt" + "github.com/gin-contrib/sessions" + "github.com/gin-contrib/sessions/cookie" + "github.com/gin-contrib/sessions/redis" + "github.com/gin-gonic/gin" + "log" + "os" + "strconv" +) + +//go:embed web/build +var buildFS embed.FS + +//go:embed web/build/index.html +var indexPage []byte + +func main() { + common.SetupGinLog() + common.SysLog("ATSFlare " + common.Version + " started") + if os.Getenv("GIN_MODE") != "debug" { + gin.SetMode(gin.ReleaseMode) + } + // Initialize SQL Database + err := model.InitDB() + if err != nil { + common.FatalLog(err) + } + defer func() { + err := model.CloseDB() + if err != nil { + common.FatalLog(err) + } + }() + + // Initialize Redis + err = common.InitRedisClient() + if err != nil { + common.FatalLog(err) + } + + // Initialize options + model.InitOptionMap() + + // Initialize HTTP server + server := gin.Default() + //server.Use(gzip.Gzip(gzip.DefaultCompression)) + server.Use(middleware.CORS()) + + // Initialize session store + if common.RedisEnabled { + opt := common.ParseRedisOption() + store, _ := redis.NewStore(opt.MinIdleConns, opt.Network, opt.Addr, opt.Password, []byte(common.SessionSecret)) + server.Use(sessions.Sessions("session", store)) + } else { + store := cookie.NewStore([]byte(common.SessionSecret)) + server.Use(sessions.Sessions("session", store)) + } + + router.SetRouter(server, buildFS, indexPage) + var port = os.Getenv("PORT") + if port == "" { + port = strconv.Itoa(*common.Port) + } + common.SysLog(fmt.Sprintf("server config: port=%s gin_mode=%s sqlite_path=%s redis_enabled=%t upload_path=%s log_dir=%s agent_token_configured=%t node_offline_threshold=%s", port, gin.Mode(), common.SQLitePath, common.RedisEnabled, common.UploadPath, valueOrDefault(*common.LogDir, "stdout"), common.AgentToken != "", common.NodeOfflineThreshold)) + common.SysLog(fmt.Sprintf("server listening on :%s", port)) + err = server.Run(":" + port) + if err != nil { + log.Println(err) + } +} + +func valueOrDefault(value string, fallback string) string { + if value == "" { + return fallback + } + return value +} diff --git a/atsf_server/middleware/agent-auth.go b/atsf_server/middleware/agent-auth.go index 5920a40b..d7827a98 100644 --- a/atsf_server/middleware/agent-auth.go +++ b/atsf_server/middleware/agent-auth.go @@ -1,7 +1,7 @@ package middleware import ( - "gin-template/service" + "atsflare/service" "github.com/gin-gonic/gin" "net/http" ) diff --git a/atsf_server/middleware/auth.go b/atsf_server/middleware/auth.go index 07cedecd..9d387568 100644 --- a/atsf_server/middleware/auth.go +++ b/atsf_server/middleware/auth.go @@ -1,8 +1,8 @@ package middleware import ( - "gin-template/common" - "gin-template/model" + "atsflare/common" + "atsflare/model" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "net/http" diff --git a/atsf_server/middleware/cors.go b/atsf_server/middleware/cors.go index 170cca3e..f4737e97 100644 --- a/atsf_server/middleware/cors.go +++ b/atsf_server/middleware/cors.go @@ -7,6 +7,6 @@ import ( func CORS() gin.HandlerFunc { config := cors.DefaultConfig() - config.AllowOrigins = []string{"https://gin-template.vercel.app", "http://localhost:3000/"} + config.AllowOrigins = []string{"https://atsflare.vercel.app", "http://localhost:3000/"} return cors.New(config) } diff --git a/atsf_server/middleware/rate-limit.go b/atsf_server/middleware/rate-limit.go index 410ed19e..f5d04fc3 100644 --- a/atsf_server/middleware/rate-limit.go +++ b/atsf_server/middleware/rate-limit.go @@ -1,9 +1,9 @@ package middleware import ( + "atsflare/common" "context" "fmt" - "gin-template/common" "github.com/gin-gonic/gin" "net/http" "time" diff --git a/atsf_server/middleware/turnstile-check.go b/atsf_server/middleware/turnstile-check.go index b7401b79..92f570d4 100644 --- a/atsf_server/middleware/turnstile-check.go +++ b/atsf_server/middleware/turnstile-check.go @@ -1,8 +1,8 @@ package middleware import ( + "atsflare/common" "encoding/json" - "gin-template/common" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "net/http" diff --git a/atsf_server/model/file.go b/atsf_server/model/file.go index 56dceb13..0bea76be 100644 --- a/atsf_server/model/file.go +++ b/atsf_server/model/file.go @@ -1,50 +1,50 @@ -package model - -import ( - "gin-template/common" - "gorm.io/gorm" - "os" - "path" -) - -type File struct { - Id int `json:"id"` - Filename string `json:"filename" gorm:"index"` - Description string `json:"description"` - Uploader string `json:"uploader" gorm:"index"` - UploaderId int `json:"uploader_id" gorm:"index"` - Link string `json:"link" gorm:"unique;index"` - UploadTime string `json:"upload_time"` - DownloadCounter int `json:"download_counter"` -} - -func GetAllFiles(startIdx int, num int) ([]*File, error) { - var files []*File - var err error - err = DB.Order("id desc").Limit(num).Offset(startIdx).Find(&files).Error - return files, err -} - -func SearchFiles(keyword string) (files []*File, err error) { - err = DB.Select([]string{"id", "filename", "description", "uploader", "uploader_id", "link", "upload_time", "download_counter"}).Where( - "filename LIKE ? or uploader LIKE ? or uploader_id = ?", keyword+"%", keyword+"%", keyword).Find(&files).Error - return files, err -} - -func (file *File) Insert() error { - var err error - err = DB.Create(file).Error - return err -} - -// Delete Make sure link is valid! Because we will use os.Remove to delete it! -func (file *File) Delete() error { - var err error - err = DB.Delete(file).Error - err = os.Remove(path.Join(common.UploadPath, file.Link)) - return err -} - -func UpdateDownloadCounter(link string) { - DB.Model(&File{}).Where("link = ?", link).UpdateColumn("download_counter", gorm.Expr("download_counter + 1")) -} +package model + +import ( + "atsflare/common" + "gorm.io/gorm" + "os" + "path" +) + +type File struct { + Id int `json:"id"` + Filename string `json:"filename" gorm:"index"` + Description string `json:"description"` + Uploader string `json:"uploader" gorm:"index"` + UploaderId int `json:"uploader_id" gorm:"index"` + Link string `json:"link" gorm:"unique;index"` + UploadTime string `json:"upload_time"` + DownloadCounter int `json:"download_counter"` +} + +func GetAllFiles(startIdx int, num int) ([]*File, error) { + var files []*File + var err error + err = DB.Order("id desc").Limit(num).Offset(startIdx).Find(&files).Error + return files, err +} + +func SearchFiles(keyword string) (files []*File, err error) { + err = DB.Select([]string{"id", "filename", "description", "uploader", "uploader_id", "link", "upload_time", "download_counter"}).Where( + "filename LIKE ? or uploader LIKE ? or uploader_id = ?", keyword+"%", keyword+"%", keyword).Find(&files).Error + return files, err +} + +func (file *File) Insert() error { + var err error + err = DB.Create(file).Error + return err +} + +// Delete Make sure link is valid! Because we will use os.Remove to delete it! +func (file *File) Delete() error { + var err error + err = DB.Delete(file).Error + err = os.Remove(path.Join(common.UploadPath, file.Link)) + return err +} + +func UpdateDownloadCounter(link string) { + DB.Model(&File{}).Where("link = ?", link).UpdateColumn("download_counter", gorm.Expr("download_counter + 1")) +} diff --git a/atsf_server/model/main.go b/atsf_server/model/main.go index 335e450e..45146a5d 100644 --- a/atsf_server/model/main.go +++ b/atsf_server/model/main.go @@ -1,7 +1,7 @@ package model import ( - "gin-template/common" + "atsflare/common" "github.com/glebarez/sqlite" "gorm.io/driver/mysql" "gorm.io/gorm" diff --git a/atsf_server/model/option.go b/atsf_server/model/option.go index 8a89963e..20d3efb4 100644 --- a/atsf_server/model/option.go +++ b/atsf_server/model/option.go @@ -1,7 +1,7 @@ package model import ( - "gin-template/common" + "atsflare/common" "strconv" "strings" ) diff --git a/atsf_server/model/user.go b/atsf_server/model/user.go index b5dd9900..7ce73904 100644 --- a/atsf_server/model/user.go +++ b/atsf_server/model/user.go @@ -1,8 +1,8 @@ package model import ( + "atsflare/common" "errors" - "gin-template/common" "strings" ) diff --git a/atsf_server/router/api-router.go b/atsf_server/router/api-router.go index 8bdf7396..9022426f 100644 --- a/atsf_server/router/api-router.go +++ b/atsf_server/router/api-router.go @@ -1,8 +1,8 @@ package router import ( - "gin-template/controller" - "gin-template/middleware" + "atsflare/controller" + "atsflare/middleware" "github.com/gin-gonic/gin" ) diff --git a/atsf_server/router/api_phase1_test.go b/atsf_server/router/api_phase1_test.go index d0f9d6ba..ea08fae5 100644 --- a/atsf_server/router/api_phase1_test.go +++ b/atsf_server/router/api_phase1_test.go @@ -1,6 +1,10 @@ package router_test import ( + "atsflare/common" + "atsflare/model" + "atsflare/router" + "atsflare/service" "bytes" "crypto/rand" "crypto/rsa" @@ -8,10 +12,6 @@ import ( "crypto/x509/pkix" "encoding/json" "encoding/pem" - "gin-template/common" - "gin-template/model" - "gin-template/router" - "gin-template/service" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" diff --git a/atsf_server/router/api_phase2_managed_domain_test.go b/atsf_server/router/api_phase2_managed_domain_test.go index e8efd228..8b33bcc8 100644 --- a/atsf_server/router/api_phase2_managed_domain_test.go +++ b/atsf_server/router/api_phase2_managed_domain_test.go @@ -1,8 +1,8 @@ package router_test import ( - "gin-template/common" - "gin-template/router" + "atsflare/common" + "atsflare/router" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" diff --git a/atsf_server/router/api_phase2_test.go b/atsf_server/router/api_phase2_test.go index aad77515..8eb4b387 100644 --- a/atsf_server/router/api_phase2_test.go +++ b/atsf_server/router/api_phase2_test.go @@ -1,12 +1,12 @@ package router_test import ( + "atsflare/common" + "atsflare/model" + "atsflare/router" + "atsflare/service" "bytes" "encoding/json" - "gin-template/common" - "gin-template/model" - "gin-template/router" - "gin-template/service" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" diff --git a/atsf_server/router/web-router.go b/atsf_server/router/web-router.go index 1cb06633..ff836efb 100644 --- a/atsf_server/router/web-router.go +++ b/atsf_server/router/web-router.go @@ -1,10 +1,10 @@ package router import ( + "atsflare/common" + "atsflare/controller" + "atsflare/middleware" "embed" - "gin-template/common" - "gin-template/controller" - "gin-template/middleware" "github.com/gin-contrib/static" "github.com/gin-gonic/gin" "net/http" diff --git a/atsf_server/service/agent.go b/atsf_server/service/agent.go index 3606c2a6..c21ad13b 100644 --- a/atsf_server/service/agent.go +++ b/atsf_server/service/agent.go @@ -1,10 +1,10 @@ package service import ( + "atsflare/common" + "atsflare/model" "encoding/json" "errors" - "gin-template/common" - "gin-template/model" "strings" "time" diff --git a/atsf_server/service/config_version.go b/atsf_server/service/config_version.go index 95dfe702..f0601a9d 100644 --- a/atsf_server/service/config_version.go +++ b/atsf_server/service/config_version.go @@ -1,12 +1,12 @@ package service import ( + "atsflare/model" "crypto/sha256" "encoding/hex" "encoding/json" "errors" "fmt" - "gin-template/model" "sort" "strings" "time" diff --git a/atsf_server/service/https_phase1_test.go b/atsf_server/service/https_phase1_test.go index 71f87601..4945506e 100644 --- a/atsf_server/service/https_phase1_test.go +++ b/atsf_server/service/https_phase1_test.go @@ -1,13 +1,13 @@ package service import ( + "atsflare/common" + "atsflare/model" "crypto/rand" "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/pem" - "gin-template/common" - "gin-template/model" "math/big" "path/filepath" "strings" diff --git a/atsf_server/service/managed_domain.go b/atsf_server/service/managed_domain.go index 7543d9a5..2901c525 100644 --- a/atsf_server/service/managed_domain.go +++ b/atsf_server/service/managed_domain.go @@ -1,9 +1,9 @@ package service import ( + "atsflare/model" "errors" "fmt" - "gin-template/model" "sort" "strings" "unicode" diff --git a/atsf_server/service/node.go b/atsf_server/service/node.go index d432602d..b6e8fc2e 100644 --- a/atsf_server/service/node.go +++ b/atsf_server/service/node.go @@ -1,11 +1,11 @@ package service import ( + "atsflare/common" + "atsflare/model" "crypto/rand" "encoding/hex" "errors" - "gin-template/common" - "gin-template/model" "strings" "time" ) diff --git a/atsf_server/service/proxy_route.go b/atsf_server/service/proxy_route.go index 42fb6daa..2d4e2d5e 100644 --- a/atsf_server/service/proxy_route.go +++ b/atsf_server/service/proxy_route.go @@ -1,9 +1,9 @@ package service import ( + "atsflare/model" "encoding/json" "errors" - "gin-template/model" "net/url" "regexp" "strings" diff --git a/atsf_server/service/tls_certificate.go b/atsf_server/service/tls_certificate.go index 1948be73..2400c157 100644 --- a/atsf_server/service/tls_certificate.go +++ b/atsf_server/service/tls_certificate.go @@ -1,10 +1,10 @@ package service import ( + "atsflare/model" "crypto/tls" "errors" "fmt" - "gin-template/model" "mime/multipart" "strings" ) diff --git a/atsf_server/web/src/App.js b/atsf_server/web/src/App.js index 38ed8f3f..c9836599 100644 --- a/atsf_server/web/src/App.js +++ b/atsf_server/web/src/App.js @@ -41,9 +41,7 @@ function App() { const res = await API.get('/api/status'); const { success, data } = res.data; if (success) { - console.log( - `GitHub 仓库地址:https://github.com/songquanpeng/gin-template` - ); + console.log(`GitHub 仓库地址:https://github.com/Rain-kl/ATSFlare`); localStorage.setItem('status', JSON.stringify(data)); statusDispatch({ type: 'set', payload: data }); localStorage.setItem('system_name', data.system_name); diff --git a/atsf_server/web/src/components/Footer.js b/atsf_server/web/src/components/Footer.js index 854211ec..a744947a 100644 --- a/atsf_server/web/src/components/Footer.js +++ b/atsf_server/web/src/components/Footer.js @@ -1,41 +1,38 @@ -import React from 'react'; - -import { Container, Segment } from 'semantic-ui-react'; -import { getFooterHTML, getSystemName } from '../helpers'; - -const Footer = () => { - const systemName = getSystemName(); - const footer = getFooterHTML(); - - return ( - - - {footer ? ( -
- ) : ( - - )} -
-
- ); -}; - -export default Footer; +import React from 'react'; + +import { Container, Segment } from 'semantic-ui-react'; +import { getFooterHTML, getSystemName } from '../helpers'; + +const Footer = () => { + const systemName = getSystemName(); + const footer = getFooterHTML(); + + return ( + + + {footer ? ( +
+ ) : ( + + )} +
+
+ ); +}; + +export default Footer; diff --git a/atsf_server/web/src/components/OtherSetting.js b/atsf_server/web/src/components/OtherSetting.js index 8d6b833a..d2c2b020 100644 --- a/atsf_server/web/src/components/OtherSetting.js +++ b/atsf_server/web/src/components/OtherSetting.js @@ -1,190 +1,189 @@ -import React, { useEffect, useState } from 'react'; -import { Button, Divider, Form, Grid, Header, Modal } from 'semantic-ui-react'; -import { API, showError, showSuccess } from '../helpers'; -import { marked } from 'marked'; - -const OtherSetting = () => { - let [inputs, setInputs] = useState({ - Footer: '', - Notice: '', - About: '', - SystemName: '', - HomePageLink: '', - }); - let [loading, setLoading] = useState(false); - const [showUpdateModal, setShowUpdateModal] = useState(false); - const [updateData, setUpdateData] = useState({ - tag_name: '', - content: '', - }); - - const getOptions = async () => { - const res = await API.get('/api/option/'); - const { success, message, data } = res.data; - if (success) { - let newInputs = {}; - data.forEach((item) => { - if (item.key in inputs) { - newInputs[item.key] = item.value; - } - }); - setInputs(newInputs); - } else { - showError(message); - } - }; - - useEffect(() => { - getOptions().then(); - }, []); - - const updateOption = async (key, value) => { - setLoading(true); - const res = await API.put('/api/option', { - key, - value, - }); - const { success, message } = res.data; - if (success) { - setInputs((inputs) => ({ ...inputs, [key]: value })); - } else { - showError(message); - } - setLoading(false); - }; - - const handleInputChange = async (e, { name, value }) => { - setInputs((inputs) => ({ ...inputs, [name]: value })); - }; - - const submitNotice = async () => { - await updateOption('Notice', inputs.Notice); - }; - - const submitFooter = async () => { - await updateOption('Footer', inputs.Footer); - }; - - const submitSystemName = async () => { - await updateOption('SystemName', inputs.SystemName); - }; - - const submitHomePageLink = async () => { - await updateOption('HomePageLink', inputs.HomePageLink); - }; - - const submitAbout = async () => { - await updateOption('About', inputs.About); - }; - - const openGitHubRelease = () => { - window.location = - 'https://github.com/songquanpeng/gin-template/releases/latest'; - }; - - const checkUpdate = async () => { - const res = await API.get( - 'https://api.github.com/repos/songquanpeng/gin-template/releases/latest' - ); - const { tag_name, body } = res.data; - if (tag_name === process.env.REACT_APP_VERSION) { - showSuccess(`已是最新版本:${tag_name}`); - } else { - setUpdateData({ - tag_name: tag_name, - content: marked.parse(body), - }); - setShowUpdateModal(true); - } - }; - - return ( - - -
-
通用设置
- 检查更新 - - - - 保存公告 - -
个性化设置
- - - - 设置系统名称 - - - - 设置首页链接 - - - - 保存关于 - - - - 设置页脚 - -
- setShowUpdateModal(false)} - onOpen={() => setShowUpdateModal(true)} - open={showUpdateModal} - > - 新版本:{updateData.tag_name} - - -
-
-
- - - +