mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-08 00:50:28 +08:00
Compare commits
325 Commits
Author | SHA1 | Date | |
---|---|---|---|
da69d94445 | |||
b8b915abe1 | |||
5d1548e989 | |||
a0dc6e06cd | |||
ae130788ec | |||
f075d0fd74 | |||
65d4946042 | |||
26acece8af | |||
48a0c8473f | |||
082ae3c91e | |||
1ee2ff1d30 | |||
c0d9969013 | |||
1bdee13150 | |||
d668022af0 | |||
e227875c2b | |||
e473de3162 | |||
c5ef841d3f | |||
d46288b591 | |||
b968bf033c | |||
eca2527bc0 | |||
ef836acfe9 | |||
a51f0d7c08 | |||
e3c36beaf4 | |||
19dce838d1 | |||
b41d8652f0 | |||
e705eecffe | |||
2bb2c36f22 | |||
1bb3d2dea9 | |||
96566a626b | |||
042e52bd16 | |||
e207fd243b | |||
30b7fd963f | |||
ca314bbfb5 | |||
812c44e070 | |||
78e45d07cf | |||
0856977b92 | |||
a44a4b0300 | |||
4b29dd8c41 | |||
165e2e33e3 | |||
d13a307ad5 | |||
27bd771fed | |||
9f3ee275a8 | |||
fcda64ad7d | |||
d815bf92bd | |||
7867060b71 | |||
8890d1d7c7 | |||
6e6a0a074a | |||
cff3007992 | |||
fe448cbcf4 | |||
2ab25df950 | |||
b895926754 | |||
5bb7a4153f | |||
b7cd598ee8 | |||
b10fb97c92 | |||
b337b908ea | |||
ba9d1e2388 | |||
29ec1d2d9c | |||
84a03f6c8e | |||
56ff06bbea | |||
7e756b8ee2 | |||
19ba37e0c2 | |||
b98ce19211 | |||
37d1a73c0c | |||
727877cf54 | |||
939b416717 | |||
f115843fbb | |||
aa6a4dc74f | |||
462a82a3d5 | |||
262aeba7e2 | |||
61c2fd5412 | |||
d542208eb8 | |||
f818200c95 | |||
5bc2e91344 | |||
295f732b18 | |||
770ae47471 | |||
2ce4f96355 | |||
07ed834b27 | |||
8d686411ee | |||
ce722897f1 | |||
a8381e875b | |||
4c81fd7d16 | |||
25ee4226d3 | |||
9d5b019243 | |||
6bb7b545b4 | |||
25d56ee8d5 | |||
7e5952c804 | |||
80bf29d79a | |||
971e53dfd8 | |||
654b903d7a | |||
2f72e6971b | |||
d4b587b93e | |||
ac7a510949 | |||
d86f3c88c7 | |||
7c77519069 | |||
2bdf467e3a | |||
52b692c8ad | |||
304643736b | |||
b0f572c51a | |||
19d351d157 | |||
d0751bf2fa | |||
290cc60f00 | |||
6a1ec51978 | |||
dffa68cbce | |||
fad209a7a3 | |||
8b222ce2e3 | |||
c5293f428d | |||
146aec9ee8 | |||
50a52de856 | |||
8f7a8d7d4f | |||
23f3fe1e3c | |||
59ff5e02ab | |||
8d41508d6b | |||
04f70cf012 | |||
83724c73f9 | |||
33e419e133 | |||
b832c304ae | |||
4c7f6fda37 | |||
e4a54fe375 | |||
87da3dad76 | |||
44ad88353f | |||
a955fb57d6 | |||
d2960ad66b | |||
5243aabf43 | |||
d3a2c2a66e | |||
0a9058a585 | |||
225719810b | |||
c634d4a891 | |||
3dc01ec85d | |||
a7324f1da1 | |||
6da452d7e0 | |||
5abcf913e6 | |||
58455e688e | |||
4d6f68eddc | |||
67f3c5a489 | |||
9c48582e0c | |||
645c631db9 | |||
3128e68df4 | |||
2247c6a883 | |||
04709f731b | |||
ebe1887e8b | |||
a7a8805713 | |||
ceabbe27b4 | |||
7393b90155 | |||
0098c05fb3 | |||
34324d9f72 | |||
28b381e01e | |||
40039e0412 | |||
116420adb2 | |||
07c1e3b836 | |||
a447d64bf2 | |||
4116b1d305 | |||
1490044295 | |||
79f2af405a | |||
575a248c41 | |||
7083904634 | |||
3d50255060 | |||
e295da774f | |||
a3cee496b4 | |||
084a5c3e6b | |||
6670450439 | |||
e1331f314d | |||
604033aa02 | |||
729c20393c | |||
a90b27b74a | |||
5707e38912 | |||
ed959bd8c7 | |||
b6cdc46023 | |||
c661a57cb2 | |||
8456b7f7c4 | |||
e8d2906e3c | |||
1edb91b3a3 | |||
94b6eb803d | |||
cfce5289ed | |||
10f1c37730 | |||
6035b98653 | |||
e158b58ffa | |||
a399184cfc | |||
2f9f946c87 | |||
d8b60f838e | |||
7599e2715a | |||
35676455bc | |||
8128671c8c | |||
ee54dec3b3 | |||
d278bc9651 | |||
b23bd0b189 | |||
409be85264 | |||
0395b7e1a9 | |||
4536fd0636 | |||
af9ae7dbb7 | |||
e266696b32 | |||
e108d26ec7 | |||
349ce7f1d4 | |||
8da50b7893 | |||
2394c8e2b4 | |||
c62983d734 | |||
5948782cdd | |||
674d1619dd | |||
11b8b65ca0 | |||
411d76798d | |||
7b0b426a76 | |||
a383af0ebc | |||
f02875e1b1 | |||
e2921419b9 | |||
42864700ec | |||
c1fe547939 | |||
267833d9f9 | |||
2d3d1167bb | |||
ef5abdfa8f | |||
580d43101e | |||
fdf2b880cb | |||
80a2263b18 | |||
1f11d22c1c | |||
b6988286b5 | |||
64f787fab5 | |||
39c6bd5850 | |||
7312c5ce3c | |||
0bc5b90218 | |||
f3b3376a3c | |||
feec6abd88 | |||
c50042c85a | |||
ef4c3833a4 | |||
67a5adf585 | |||
08a1e7ae32 | |||
7d979cbaf0 | |||
80c0940e30 | |||
a4fe2a6485 | |||
8e9ed1205b | |||
a341c65bb1 | |||
91fa024f0b | |||
aedef1eea1 | |||
70f2988f09 | |||
2dcdfbe6d3 | |||
c92d34e27c | |||
dfbf7753c3 | |||
ba732b3075 | |||
ca13247572 | |||
108fdc174f | |||
a741c5179a | |||
6676cc8ff3 | |||
13de019d08 | |||
53ad454962 | |||
fb203a6f30 | |||
f716a0985f | |||
340fbe135d | |||
79119760f2 | |||
4dd67a8dcb | |||
deed857788 | |||
802995ed16 | |||
b14554a5ba | |||
4665ffa759 | |||
f914e8e929 | |||
dc33b41107 | |||
ee8dd23a56 | |||
08d0269e30 | |||
8e5cd18c91 | |||
32b4d98c2a | |||
2ea58cd639 | |||
45d2745b67 | |||
cba338eef2 | |||
c428de6e42 | |||
9bca6bb72e | |||
cd966116d4 | |||
9abf1b9d73 | |||
6aaba6debd | |||
77565712e0 | |||
d025259db7 | |||
aafdc546fa | |||
539ca2d731 | |||
ea326b3513 | |||
98ef766fb4 | |||
e94ada9ea2 | |||
4ea482223d | |||
d55ae7d1d2 | |||
d72e00605f | |||
be74cb621f | |||
13404d6035 | |||
afa9c530ad | |||
1600615aca | |||
2bb8491499 | |||
293283ed25 | |||
9cb519d1e9 | |||
fb9b8f1662 | |||
2fec3f72ae | |||
11695220a8 | |||
155660b0d7 | |||
1c72f5300c | |||
3dd56195d9 | |||
8865244262 | |||
3400fa1e9c | |||
bdc5c92ef0 | |||
4e3eedf246 | |||
8e98fc5a9f | |||
6f6159be07 | |||
3e4dbc2dcb | |||
48b5b27982 | |||
1839252c30 | |||
1fff1db6a7 | |||
a0b0e186b7 | |||
8c7f235ee1 | |||
a0a762aa6f | |||
2eec53a6d0 | |||
117dec4542 | |||
895cdd024d | |||
f0b0891ac9 | |||
10449e89ab | |||
6e70f0fc58 | |||
2bca424370 | |||
de49a45e19 | |||
f7243f879b | |||
7f3b2500b3 | |||
208dc11d25 | |||
503d244166 | |||
475b6da35a | |||
b9404f14dc | |||
0baae87390 | |||
06759041a8 | |||
cf4e76f9dc | |||
81f2d01dc1 | |||
61773d3173 | |||
ec29621547 | |||
b8e324cadf | |||
f37fd6ba87 | |||
b4bf734fe8 | |||
f0431701c9 | |||
aa5078de15 |
47
.github/workflows/build.yml
vendored
47
.github/workflows/build.yml
vendored
@ -34,7 +34,11 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14.17.0'
|
||||
node-version: 16
|
||||
# cache
|
||||
- uses: c-hive/gha-yarn-cache@v2
|
||||
with:
|
||||
directory: ./web
|
||||
- run: yarn install && CI=false yarn run build
|
||||
working-directory: ./web
|
||||
|
||||
@ -53,11 +57,30 @@ jobs:
|
||||
go build -race -ldflags "-extldflags '-static'"
|
||||
working-directory: ./
|
||||
|
||||
linter:
|
||||
name: Go-Linter
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ go-tests ]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.16.5'
|
||||
|
||||
# gen a dummy config file
|
||||
- run: touch dummy.yml
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: latest
|
||||
args: --disable-all -c dummy.yml -E=gofumpt --max-same-issues=0 --timeout 5m --modules-download-mode=mod
|
||||
|
||||
release-and-push:
|
||||
name: Release And Push
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push'
|
||||
needs: [ frontend, backend ]
|
||||
needs: [ frontend, backend, linter ]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
@ -66,7 +89,7 @@ jobs:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 12
|
||||
node-version: 16
|
||||
|
||||
- name: Fetch Previous version
|
||||
id: get-previous-tag
|
||||
@ -102,26 +125,36 @@ jobs:
|
||||
|
||||
fi
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' &&steps.should_push.outputs.push=='true'
|
||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
|
||||
- name: Push to Docker Hub
|
||||
uses: docker/build-push-action@v2
|
||||
uses: docker/build-push-action@v3
|
||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
||||
with:
|
||||
target: STANDARD
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: casbin/casdoor:${{steps.get-current-tag.outputs.tag }},casbin/casdoor:latest
|
||||
|
||||
- name: Push All In One Version to Docker Hub
|
||||
uses: docker/build-push-action@v2
|
||||
uses: docker/build-push-action@v3
|
||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
||||
with:
|
||||
target: ALLINONE
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: casbin/casdoor-all-in-one:${{steps.get-current-tag.outputs.tag }},casbin/casdoor-all-in-one:latest
|
||||
|
21
.github/workflows/sync.yml
vendored
21
.github/workflows/sync.yml
vendored
@ -33,3 +33,24 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_PROJECT_ID: '463556'
|
||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
|
||||
- name: crowdin backend action
|
||||
uses: crowdin/github-action@1.4.8
|
||||
with:
|
||||
upload_translations: true
|
||||
|
||||
download_translations: true
|
||||
push_translations: true
|
||||
commit_message: 'refactor: New Crowdin Backend translations by Github Action'
|
||||
|
||||
localization_branch_name: l10n_crowdin_action
|
||||
create_pull_request: true
|
||||
pull_request_title: 'refactor: New Crowdin Backend translations'
|
||||
|
||||
crowdin_branch_name: l10n_branch
|
||||
config: './crowdin.yml'
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_PROJECT_ID: '463556'
|
||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -27,3 +27,6 @@ logs/
|
||||
files/
|
||||
lastupdate.tmp
|
||||
commentsRouter*.go
|
||||
|
||||
# ignore build result
|
||||
casdoor
|
@ -31,7 +31,7 @@ run:
|
||||
- api
|
||||
# skip-files:
|
||||
# - ".*_test\\.go$"
|
||||
modules-download-mode: vendor
|
||||
modules-download-mode: mod
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
lll:
|
||||
|
42
Dockerfile
42
Dockerfile
@ -2,7 +2,7 @@ FROM node:16.13.0 AS FRONT
|
||||
WORKDIR /web
|
||||
COPY ./web .
|
||||
RUN yarn config set registry https://registry.npmmirror.com
|
||||
RUN yarn install && yarn run build
|
||||
RUN yarn install --frozen-lockfile --network-timeout 1000000 && yarn run build
|
||||
|
||||
|
||||
FROM golang:1.17.5 AS BACK
|
||||
@ -13,14 +13,30 @@ RUN ./build.sh
|
||||
|
||||
FROM alpine:latest AS STANDARD
|
||||
LABEL MAINTAINER="https://casdoor.org/"
|
||||
ARG USER=casdoor
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ENV BUILDX_ARCH="${TARGETOS:-linux}_${TARGETARCH:-amd64}"
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=BACK /go/src/casdoor/server ./server
|
||||
COPY --from=BACK /go/src/casdoor/swagger ./swagger
|
||||
COPY --from=BACK /go/src/casdoor/conf/app.conf ./conf/app.conf
|
||||
COPY --from=FRONT /web/build ./web/build
|
||||
VOLUME /app/files /app/logs
|
||||
ENTRYPOINT ["/app/server"]
|
||||
RUN sed -i 's/https/http/' /etc/apk/repositories
|
||||
RUN apk add --update sudo
|
||||
RUN apk add curl
|
||||
RUN apk add ca-certificates && update-ca-certificates
|
||||
|
||||
RUN adduser -D $USER -u 1000 \
|
||||
&& echo "$USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USER \
|
||||
&& chmod 0440 /etc/sudoers.d/$USER \
|
||||
&& mkdir logs \
|
||||
&& chown -R $USER:$USER logs
|
||||
|
||||
USER 1000
|
||||
WORKDIR /
|
||||
COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/server_${BUILDX_ARCH} ./server
|
||||
COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/swagger ./swagger
|
||||
COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/conf/app.conf ./conf/app.conf
|
||||
COPY --from=FRONT --chown=$USER:$USER /web/build ./web/build
|
||||
|
||||
ENTRYPOINT ["/server"]
|
||||
|
||||
|
||||
FROM debian:latest AS db
|
||||
@ -33,11 +49,15 @@ RUN apt update \
|
||||
|
||||
FROM db AS ALLINONE
|
||||
LABEL MAINTAINER="https://casdoor.org/"
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ENV BUILDX_ARCH="${TARGETOS:-linux}_${TARGETARCH:-amd64}"
|
||||
|
||||
ENV MYSQL_ROOT_PASSWORD=123456
|
||||
RUN apt update
|
||||
RUN apt install -y ca-certificates && update-ca-certificates
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=BACK /go/src/casdoor/server ./server
|
||||
WORKDIR /
|
||||
COPY --from=BACK /go/src/casdoor/server_${BUILDX_ARCH} ./server
|
||||
COPY --from=BACK /go/src/casdoor/swagger ./swagger
|
||||
COPY --from=BACK /go/src/casdoor/docker-entrypoint.sh /docker-entrypoint.sh
|
||||
COPY --from=BACK /go/src/casdoor/conf/app.conf ./conf/app.conf
|
||||
|
31
README.md
31
README.md
@ -8,7 +8,7 @@
|
||||
<img alt="docker pull casbin/casdoor" src="https://img.shields.io/docker/pulls/casbin/casdoor.svg">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/actions/workflows/build.yml">
|
||||
<img alt="GitHub Workflow Status (branch)" src="https://github.com/casbin/jcasbin/workflows/build/badge.svg?style=flat-square">
|
||||
<img alt="GitHub Workflow Status (branch)" src="https://github.com/casdoor/casdoor/workflows/Build/badge.svg?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/releases/latest">
|
||||
<img alt="GitHub Release" src="https://img.shields.io/github/v/release/casbin/casdoor.svg">
|
||||
@ -42,47 +42,32 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
## Online demo
|
||||
|
||||
- International: https://door.casdoor.org (read-only)
|
||||
- Asian mirror: https://door.casdoor.com (read-only)
|
||||
- Asian mirror: https://demo.casdoor.com (read-write, will restore for every 5 minutes)
|
||||
|
||||
|
||||
- Read-only site: https://door.casdoor.com (any modification operation will fail)
|
||||
- Writable site: https://demo.casdoor.com (original data will be restored for every 5 minutes)
|
||||
|
||||
## Documentation
|
||||
|
||||
- International: https://casdoor.org
|
||||
- Asian mirror: https://docs.casdoor.cn
|
||||
|
||||
|
||||
https://casdoor.org
|
||||
|
||||
## Install
|
||||
|
||||
- By source code: https://casdoor.org/docs/basic/server-installation
|
||||
- By Docker: https://casdoor.org/docs/basic/try-with-docker
|
||||
|
||||
|
||||
|
||||
## How to connect to Casdoor?
|
||||
|
||||
https://casdoor.org/docs/how-to-connect/overview
|
||||
|
||||
|
||||
|
||||
## Casdoor Public API
|
||||
|
||||
- Docs: https://casdoor.org/docs/basic/public-api
|
||||
- Swagger: https://door.casdoor.com/swagger
|
||||
|
||||
|
||||
|
||||
## Integrations
|
||||
|
||||
https://casdoor.org/docs/integration/apisix
|
||||
|
||||
https://casdoor.org/docs/category/integrations
|
||||
|
||||
## How to contact?
|
||||
|
||||
@ -90,17 +75,13 @@ https://casdoor.org/docs/integration/apisix
|
||||
- Forum: https://forum.casbin.com
|
||||
- Contact: https://tawk.to/chat/623352fea34c2456412b8c51/1fuc7od6e
|
||||
|
||||
|
||||
|
||||
## Contribute
|
||||
|
||||
For casdoor, if you have any questions, you can give Issues, or you can also directly start Pull Requests(but we recommend giving issues first to communicate with the community).
|
||||
|
||||
### I18n translation
|
||||
|
||||
If you are contributing to casdoor, please note that we use [Crowdin](https://crowdin.com/project/casdoor-site) as translating platform and i18next as translating tool. When you add some words using i18next in the ```web/``` directory, please remember to add what you have added to the ```web/src/locales/en/data.json``` file.
|
||||
|
||||
|
||||
If you are contributing to casdoor, please note that we use [Crowdin](https://crowdin.com/project/casdoor-site) as translating platform and i18next as translating tool. When you add some words using i18next in the `web/` directory, please remember to add what you have added to the `web/src/locales/en/data.json` file.
|
||||
|
||||
## License
|
||||
|
||||
|
9
SECURITY.md
Normal file
9
SECURITY.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
We are grateful for security researchers and users reporting a vulnerability to us first. To ensure that your request is handled in a timely manner and we can keep users safe, please follow the below guidelines.
|
||||
|
||||
- **Please do not report security vulnerabilities directly on GitHub.**
|
||||
|
||||
- To report a vulnerability, please email [admin@casdoor.org](admin@casdoor.org).
|
@ -15,10 +15,14 @@
|
||||
package authz
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
xormadapter "github.com/casbin/xorm-adapter/v2"
|
||||
xormadapter "github.com/casbin/xorm-adapter/v3"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
stringadapter "github.com/qiangmzsx/string-adapter/v2"
|
||||
)
|
||||
|
||||
@ -28,7 +32,9 @@ func InitAuthz() {
|
||||
var err error
|
||||
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
a, err := xormadapter.NewAdapterWithTableName(conf.GetConfigString("driverName"), conf.GetBeegoConfDataSourceName()+conf.GetConfigString("dbName"), "casbin_rule", tableNamePrefix, true)
|
||||
driverName := conf.GetConfigString("driverName")
|
||||
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
|
||||
a, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, "casbin_rule", tableNamePrefix, true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -68,7 +74,7 @@ m = (r.subOwner == p.subOwner || p.subOwner == "*") && \
|
||||
|
||||
Enforcer.ClearPolicy()
|
||||
|
||||
//if len(Enforcer.GetPolicy()) == 0 {
|
||||
// if len(Enforcer.GetPolicy()) == 0 {
|
||||
if true {
|
||||
ruleText := `
|
||||
p, built-in, *, *, *, *, *
|
||||
@ -78,20 +84,24 @@ p, *, *, POST, /api/get-email-and-phone, *, *
|
||||
p, *, *, POST, /api/login, *, *
|
||||
p, *, *, GET, /api/get-app-login, *, *
|
||||
p, *, *, POST, /api/logout, *, *
|
||||
p, *, *, GET, /api/logout, *, *
|
||||
p, *, *, GET, /api/get-account, *, *
|
||||
p, *, *, GET, /api/userinfo, *, *
|
||||
p, *, *, POST, /api/webhook, *, *
|
||||
p, *, *, GET, /api/get-webhook-event, *, *
|
||||
p, *, *, *, /api/login/oauth, *, *
|
||||
p, *, *, GET, /api/get-application, *, *
|
||||
p, *, *, GET, /api/get-applications, *, *
|
||||
p, *, *, GET, /api/get-organization-applications, *, *
|
||||
p, *, *, GET, /api/get-user, *, *
|
||||
p, *, *, GET, /api/get-user-application, *, *
|
||||
p, *, *, GET, /api/get-resources, *, *
|
||||
p, *, *, GET, /api/get-records, *, *
|
||||
p, *, *, GET, /api/get-product, *, *
|
||||
p, *, *, POST, /api/buy-product, *, *
|
||||
p, *, *, GET, /api/get-payment, *, *
|
||||
p, *, *, POST, /api/update-payment, *, *
|
||||
p, *, *, POST, /api/invoice-payment, *, *
|
||||
p, *, *, GET, /api/get-providers, *, *
|
||||
p, *, *, POST, /api/notify-payment, *, *
|
||||
p, *, *, POST, /api/unlink, *, *
|
||||
p, *, *, POST, /api/set-password, *, *
|
||||
p, *, *, POST, /api/send-verification-code, *, *
|
||||
@ -105,6 +115,9 @@ p, *, *, GET, /api/get-saml-login, *, *
|
||||
p, *, *, POST, /api/acs, *, *
|
||||
p, *, *, GET, /api/saml/metadata, *, *
|
||||
p, *, *, *, /cas, *, *
|
||||
p, *, *, *, /api/webauthn, *, *
|
||||
p, *, *, GET, /api/get-release, *, *
|
||||
p, *, *, GET, /api/get-default-application, *, *
|
||||
`
|
||||
|
||||
sa := stringadapter.NewAdapter(ruleText)
|
||||
@ -125,6 +138,18 @@ p, *, *, *, /cas, *, *
|
||||
}
|
||||
|
||||
func IsAllowed(subOwner string, subName string, method string, urlPath string, objOwner string, objName string) bool {
|
||||
if conf.IsDemoMode() {
|
||||
if !isAllowedInDemoMode(subOwner, subName, method, urlPath, objOwner, objName) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
userId := fmt.Sprintf("%s/%s", subOwner, subName)
|
||||
user := object.GetUser(userId)
|
||||
if user != nil && user.IsAdmin && (subOwner == objOwner || (objOwner == "admin" && subOwner == objName)) {
|
||||
return true
|
||||
}
|
||||
|
||||
res, err := Enforcer.Enforce(subOwner, subName, method, urlPath, objOwner, objName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -132,3 +157,22 @@ func IsAllowed(subOwner string, subName string, method string, urlPath string, o
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func isAllowedInDemoMode(subOwner string, subName string, method string, urlPath string, objOwner string, objName string) bool {
|
||||
if method == "POST" {
|
||||
if strings.HasPrefix(urlPath, "/api/login") || urlPath == "/api/logout" || urlPath == "/api/signup" || urlPath == "/api/send-verification-code" {
|
||||
return true
|
||||
} else if urlPath == "/api/update-user" {
|
||||
// Allow ordinary users to update their own information
|
||||
if subOwner == objOwner && subName == objName && !(subOwner == "built-in" && subName == "admin") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// If method equals GET
|
||||
return true
|
||||
}
|
||||
|
7
build.sh
7
build.sh
@ -1,11 +1,12 @@
|
||||
#!/bin/bash
|
||||
#try to connect to google to determine whether user need to use proxy
|
||||
curl www.google.com -o /dev/null --connect-timeout 5 2 > /dev/null
|
||||
curl www.google.com -o /dev/null --connect-timeout 5 2> /dev/null
|
||||
if [ $? == 0 ]
|
||||
then
|
||||
echo "Successfully connected to Google, no need to use Go proxy"
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o server .
|
||||
else
|
||||
echo "Google is blocked, Go proxy is enabled: GOPROXY=https://goproxy.cn,direct"
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOPROXY=https://goproxy.cn,direct go build -ldflags="-w -s" -o server .
|
||||
export GOPROXY="https://goproxy.cn,direct"
|
||||
fi
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o server_linux_amd64 .
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-w -s" -o server_linux_arm64 .
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
@ -31,8 +31,7 @@ import (
|
||||
|
||||
const AliyunCaptchaVerifyUrl = "http://afs.aliyuncs.com"
|
||||
|
||||
type AliyunCaptchaProvider struct {
|
||||
}
|
||||
type AliyunCaptchaProvider struct{}
|
||||
|
||||
func NewAliyunCaptchaProvider() *AliyunCaptchaProvider {
|
||||
captcha := &AliyunCaptchaProvider{}
|
||||
@ -81,7 +80,7 @@ func (captcha *AliyunCaptchaProvider) VerifyCaptcha(token, clientSecret string)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -16,8 +16,7 @@ package captcha
|
||||
|
||||
import "github.com/casdoor/casdoor/object"
|
||||
|
||||
type DefaultCaptchaProvider struct {
|
||||
}
|
||||
type DefaultCaptchaProvider struct{}
|
||||
|
||||
func NewDefaultCaptchaProvider() *DefaultCaptchaProvider {
|
||||
captcha := &DefaultCaptchaProvider{}
|
||||
|
81
captcha/geetest.go
Normal file
81
captcha/geetest.go
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package captcha
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
const GEETESTCaptchaVerifyUrl = "http://gcaptcha4.geetest.com/validate"
|
||||
|
||||
type GEETESTCaptchaProvider struct{}
|
||||
|
||||
func NewGEETESTCaptchaProvider() *GEETESTCaptchaProvider {
|
||||
captcha := &GEETESTCaptchaProvider{}
|
||||
return captcha
|
||||
}
|
||||
|
||||
func (captcha *GEETESTCaptchaProvider) VerifyCaptcha(token, clientSecret string) (bool, error) {
|
||||
pathData, err := url.ParseQuery(token)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
signToken := util.GetHmacSha256(clientSecret, pathData["lot_number"][0])
|
||||
|
||||
formData := make(url.Values)
|
||||
formData["lot_number"] = []string{pathData["lot_number"][0]}
|
||||
formData["captcha_output"] = []string{pathData["captcha_output"][0]}
|
||||
formData["pass_token"] = []string{pathData["pass_token"][0]}
|
||||
formData["gen_time"] = []string{pathData["gen_time"][0]}
|
||||
formData["sign_token"] = []string{signToken}
|
||||
captchaId := pathData["captcha_id"][0]
|
||||
|
||||
cli := http.Client{Timeout: time.Second * 5}
|
||||
resp, err := cli.PostForm(fmt.Sprintf("%s?captcha_id=%s", GEETESTCaptchaVerifyUrl, captchaId), formData)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
return false, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
type captchaResponse struct {
|
||||
Result string `json:"result"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
captchaResp := &captchaResponse{}
|
||||
err = json.Unmarshal(body, captchaResp)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if captchaResp.Result == "success" {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, errors.New(captchaResp.Reason)
|
||||
}
|
@ -17,7 +17,7 @@ package captcha
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@ -25,8 +25,7 @@ import (
|
||||
|
||||
const HCaptchaVerifyUrl = "https://hcaptcha.com/siteverify"
|
||||
|
||||
type HCaptchaProvider struct {
|
||||
}
|
||||
type HCaptchaProvider struct{}
|
||||
|
||||
func NewHCaptchaProvider() *HCaptchaProvider {
|
||||
captcha := &HCaptchaProvider{}
|
||||
@ -44,7 +43,7 @@ func (captcha *HCaptchaProvider) VerifyCaptcha(token, clientSecret string) (bool
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
package captcha
|
||||
|
||||
import "fmt"
|
||||
|
||||
type CaptchaProvider interface {
|
||||
VerifyCaptcha(token, clientSecret string) (bool, error)
|
||||
}
|
||||
@ -27,6 +29,19 @@ func GetCaptchaProvider(captchaType string) CaptchaProvider {
|
||||
return NewHCaptchaProvider()
|
||||
} else if captchaType == "Aliyun Captcha" {
|
||||
return NewAliyunCaptchaProvider()
|
||||
} else if captchaType == "GEETEST" {
|
||||
return NewGEETESTCaptchaProvider()
|
||||
} else if captchaType == "Cloudflare Turnstile" {
|
||||
return NewCloudflareTurnstileProvider()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func VerifyCaptchaByCaptchaType(captchaType, token, clientSecret string) (bool, error) {
|
||||
provider := GetCaptchaProvider(captchaType)
|
||||
if provider == nil {
|
||||
return false, fmt.Errorf("invalid captcha provider: %s", captchaType)
|
||||
}
|
||||
|
||||
return provider.VerifyCaptcha(token, clientSecret)
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ package captcha
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@ -25,8 +25,7 @@ import (
|
||||
|
||||
const ReCaptchaVerifyUrl = "https://recaptcha.net/recaptcha/api/siteverify"
|
||||
|
||||
type ReCaptchaProvider struct {
|
||||
}
|
||||
type ReCaptchaProvider struct{}
|
||||
|
||||
func NewReCaptchaProvider() *ReCaptchaProvider {
|
||||
captcha := &ReCaptchaProvider{}
|
||||
@ -44,7 +43,7 @@ func (captcha *ReCaptchaProvider) VerifyCaptcha(token, clientSecret string) (boo
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
66
captcha/turnstile.go
Normal file
66
captcha/turnstile.go
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package captcha
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const CloudflareTurnstileVerifyUrl = "https://challenges.cloudflare.com/turnstile/v0/siteverify"
|
||||
|
||||
type CloudflareTurnstileProvider struct{}
|
||||
|
||||
func NewCloudflareTurnstileProvider() *CloudflareTurnstileProvider {
|
||||
captcha := &CloudflareTurnstileProvider{}
|
||||
return captcha
|
||||
}
|
||||
|
||||
func (captcha *CloudflareTurnstileProvider) VerifyCaptcha(token, clientSecret string) (bool, error) {
|
||||
reqData := url.Values{
|
||||
"secret": {clientSecret},
|
||||
"response": {token},
|
||||
}
|
||||
resp, err := http.PostForm(CloudflareTurnstileVerifyUrl, reqData)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
type captchaResponse struct {
|
||||
Success bool `json:"success"`
|
||||
ErrorCodes []string `json:"error-codes"`
|
||||
}
|
||||
captchaResp := &captchaResponse{}
|
||||
err = json.Unmarshal(body, captchaResp)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if len(captchaResp.ErrorCodes) > 0 {
|
||||
return false, errors.New(strings.Join(captchaResp.ErrorCodes, ","))
|
||||
}
|
||||
|
||||
return captchaResp.Success, nil
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
appname = casdoor
|
||||
httpport = 8000
|
||||
runmode = dev
|
||||
SessionOn = true
|
||||
copyrequestbody = true
|
||||
driverName = mysql
|
||||
dataSourceName = root:123456@tcp(localhost:3306)/
|
||||
@ -12,8 +11,14 @@ redisEndpoint =
|
||||
defaultStorageProvider =
|
||||
isCloudIntranet = false
|
||||
authState = "casdoor"
|
||||
sock5Proxy = "127.0.0.1:10808"
|
||||
socks5Proxy = "127.0.0.1:10808"
|
||||
verificationCodeTimeout = 10
|
||||
initScore = 2000
|
||||
logPostOnly = true
|
||||
origin =
|
||||
origin =
|
||||
staticBaseUrl = "https://cdn.casbin.org"
|
||||
isDemoMode = false
|
||||
batchSize = 100
|
||||
ldapServerPort = 389
|
||||
languages = en,zh,es,fr,de,ja,ko,ru
|
||||
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
||||
|
84
conf/conf.go
84
conf/conf.go
@ -15,20 +15,62 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/beego/beego"
|
||||
)
|
||||
|
||||
type Quota struct {
|
||||
Organization int `json:"organization"`
|
||||
User int `json:"user"`
|
||||
Application int `json:"application"`
|
||||
Provider int `json:"provider"`
|
||||
}
|
||||
|
||||
var quota = &Quota{-1, -1, -1, -1}
|
||||
|
||||
func init() {
|
||||
// this array contains the beego configuration items that may be modified via env
|
||||
presetConfigItems := []string{"httpport", "appname"}
|
||||
for _, key := range presetConfigItems {
|
||||
if value, ok := os.LookupEnv(key); ok {
|
||||
err := beego.AppConfig.Set(key, value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
initQuota()
|
||||
}
|
||||
|
||||
func initQuota() {
|
||||
res := beego.AppConfig.String("quota")
|
||||
if res != "" {
|
||||
err := json.Unmarshal([]byte(res), quota)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetConfigString(key string) string {
|
||||
if value, ok := os.LookupEnv(key); ok {
|
||||
return value
|
||||
}
|
||||
return beego.AppConfig.String(key)
|
||||
|
||||
res := beego.AppConfig.String(key)
|
||||
if res == "" {
|
||||
if key == "staticBaseUrl" {
|
||||
res = "https://cdn.casbin.org"
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func GetConfigBool(key string) (bool, error) {
|
||||
@ -47,17 +89,7 @@ func GetConfigInt64(key string) (int64, error) {
|
||||
return num, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
//this array contains the beego configuration items that may be modified via env
|
||||
var presetConfigItems = []string{"httpport", "appname"}
|
||||
for _, key := range presetConfigItems {
|
||||
if value, ok := os.LookupEnv(key); ok {
|
||||
beego.AppConfig.Set(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetBeegoConfDataSourceName() string {
|
||||
func GetConfigDataSourceName() string {
|
||||
dataSourceName := GetConfigString("dataSourceName")
|
||||
|
||||
runningInDocker := os.Getenv("RUNNING_IN_DOCKER")
|
||||
@ -72,3 +104,29 @@ func GetBeegoConfDataSourceName() string {
|
||||
|
||||
return dataSourceName
|
||||
}
|
||||
|
||||
func IsDemoMode() bool {
|
||||
return strings.ToLower(GetConfigString("isDemoMode")) == "true"
|
||||
}
|
||||
|
||||
func GetConfigBatchSize() int {
|
||||
res, err := strconv.Atoi(GetConfigString("batchSize"))
|
||||
if err != nil {
|
||||
res = 100
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func GetConfigQuota() *Quota {
|
||||
return quota
|
||||
}
|
||||
|
||||
func GetConfigRealDataSourceName(driverName string) string {
|
||||
var dataSourceName string
|
||||
if driverName != "mysql" {
|
||||
dataSourceName = GetConfigDataSourceName()
|
||||
} else {
|
||||
dataSourceName = GetConfigDataSourceName() + GetConfigString("dbName")
|
||||
}
|
||||
return dataSourceName
|
||||
}
|
||||
|
@ -11,13 +11,14 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package conf
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/beego/beego"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -32,7 +33,7 @@ func TestGetConfString(t *testing.T) {
|
||||
{"Should be return value", "key", "value"},
|
||||
}
|
||||
|
||||
//do some set up job
|
||||
// do some set up job
|
||||
|
||||
os.Setenv("appname", "casbin")
|
||||
os.Setenv("key", "value")
|
||||
@ -58,7 +59,7 @@ func TestGetConfInt(t *testing.T) {
|
||||
{"Should be return 8000", "verificationCodeTimeout", 10},
|
||||
}
|
||||
|
||||
//do some set up job
|
||||
// do some set up job
|
||||
os.Setenv("httpport", "8001")
|
||||
|
||||
err := beego.LoadAppConfig("ini", "app.conf")
|
||||
@ -79,13 +80,9 @@ func TestGetConfBool(t *testing.T) {
|
||||
input string
|
||||
expected interface{}
|
||||
}{
|
||||
{"Should be return false", "SessionOn", false},
|
||||
{"Should be return false", "copyrequestbody", true},
|
||||
}
|
||||
|
||||
//do some set up job
|
||||
os.Setenv("SessionOn", "false")
|
||||
|
||||
err := beego.LoadAppConfig("ini", "app.conf")
|
||||
assert.Nil(t, err)
|
||||
for _, scenery := range scenarios {
|
||||
@ -96,3 +93,19 @@ func TestGetConfBool(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetConfigQuota(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
description string
|
||||
expected *Quota
|
||||
}{
|
||||
{"default", &Quota{-1, -1, -1, -1}},
|
||||
}
|
||||
|
||||
err := beego.LoadAppConfig("ini", "app.conf")
|
||||
assert.Nil(t, err)
|
||||
for _, scenery := range scenarios {
|
||||
quota := GetConfigQuota()
|
||||
assert.Equal(t, scenery.expected, quota)
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,10 @@ type RequestForm struct {
|
||||
RelayState string `json:"relayState"`
|
||||
SamlRequest string `json:"samlRequest"`
|
||||
SamlResponse string `json:"samlResponse"`
|
||||
|
||||
CaptchaType string `json:"captchaType"`
|
||||
CaptchaToken string `json:"captchaToken"`
|
||||
ClientSecret string `json:"clientSecret"`
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
@ -98,33 +102,34 @@ type Captcha struct {
|
||||
// @router /signup [post]
|
||||
func (c *ApiController) Signup() {
|
||||
if c.GetSessionUsername() != "" {
|
||||
c.ResponseError("Please sign out first before signing up", c.GetSessionUsername())
|
||||
c.ResponseError(c.T("account:Please sign out first before signing up"), c.GetSessionUsername())
|
||||
return
|
||||
}
|
||||
|
||||
var form RequestForm
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &form)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||
if !application.EnableSignUp {
|
||||
c.ResponseError("The application does not allow to sign up new account")
|
||||
c.ResponseError(c.T("account:The application does not allow to sign up new account"))
|
||||
return
|
||||
}
|
||||
|
||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", form.Organization))
|
||||
msg := object.CheckUserSignup(application, organization, form.Username, form.Password, form.Name, form.FirstName, form.LastName, form.Email, form.Phone, form.Affiliation)
|
||||
msg := object.CheckUserSignup(application, organization, form.Username, form.Password, form.Name, form.FirstName, form.LastName, form.Email, form.Phone, form.Affiliation, c.GetAcceptLanguage())
|
||||
if msg != "" {
|
||||
c.ResponseError(msg)
|
||||
return
|
||||
}
|
||||
|
||||
if application.IsSignupItemVisible("Email") && application.GetSignupItemRule("Email") != "No verification" && form.Email != "" {
|
||||
checkResult := object.CheckVerificationCode(form.Email, form.EmailCode)
|
||||
checkResult := object.CheckVerificationCode(form.Email, form.EmailCode, c.GetAcceptLanguage())
|
||||
if len(checkResult) != 0 {
|
||||
c.ResponseError(fmt.Sprintf("Email: %s", checkResult))
|
||||
c.ResponseError(c.T("account:Email: %s"), checkResult)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -132,9 +137,9 @@ func (c *ApiController) Signup() {
|
||||
var checkPhone string
|
||||
if application.IsSignupItemVisible("Phone") && form.Phone != "" {
|
||||
checkPhone = fmt.Sprintf("+%s%s", form.PhonePrefix, form.Phone)
|
||||
checkResult := object.CheckVerificationCode(checkPhone, form.PhoneCode)
|
||||
checkResult := object.CheckVerificationCode(checkPhone, form.PhoneCode, c.GetAcceptLanguage())
|
||||
if len(checkResult) != 0 {
|
||||
c.ResponseError(fmt.Sprintf("Phone: %s", checkResult))
|
||||
c.ResponseError(c.T("account:Phone: %s"), checkResult)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -156,6 +161,12 @@ func (c *ApiController) Signup() {
|
||||
username = id
|
||||
}
|
||||
|
||||
initScore, err := getInitScore(organization)
|
||||
if err != nil {
|
||||
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
||||
return
|
||||
}
|
||||
|
||||
user := &object.User{
|
||||
Owner: form.Organization,
|
||||
Name: username,
|
||||
@ -171,7 +182,7 @@ func (c *ApiController) Signup() {
|
||||
Affiliation: form.Affiliation,
|
||||
IdCard: form.IdCard,
|
||||
Region: form.Region,
|
||||
Score: getInitScore(),
|
||||
Score: initScore,
|
||||
IsAdmin: false,
|
||||
IsGlobalAdmin: false,
|
||||
IsForbidden: false,
|
||||
@ -198,7 +209,7 @@ func (c *ApiController) Signup() {
|
||||
|
||||
affected := object.AddUser(user)
|
||||
if !affected {
|
||||
c.ResponseError(fmt.Sprintf("Failed to create user, user information is invalid: %s", util.StructToJson(user)))
|
||||
c.ResponseError(c.T("account:Invalid information"), util.StructToJson(user))
|
||||
return
|
||||
}
|
||||
|
||||
@ -217,7 +228,7 @@ func (c *ApiController) Signup() {
|
||||
record.User = user.Name
|
||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||
|
||||
userId := fmt.Sprintf("%s/%s", user.Owner, user.Name)
|
||||
userId := user.GetId()
|
||||
util.LogInfo(c.Ctx, "API: [%s] is signed up as new user", userId)
|
||||
|
||||
c.ResponseOk(userId)
|
||||
@ -228,14 +239,13 @@ func (c *ApiController) Signup() {
|
||||
// @Tag Login API
|
||||
// @Description logout the current user
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /logout [post]
|
||||
// @router /logout [get,post]
|
||||
func (c *ApiController) Logout() {
|
||||
user := c.GetSessionUsername()
|
||||
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
||||
|
||||
application := c.GetSessionApplication()
|
||||
c.SetSessionUsername("")
|
||||
c.SetSessionData(nil)
|
||||
c.ClearUserSession()
|
||||
|
||||
if application == nil || application.Name == "app-built-in" || application.HomepageUrl == "" {
|
||||
c.ResponseOk(user)
|
||||
@ -251,15 +261,14 @@ func (c *ApiController) Logout() {
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /get-account [get]
|
||||
func (c *ApiController) GetAccount() {
|
||||
userId, ok := c.RequireSignedIn()
|
||||
user, ok := c.RequireSignedInUser()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
user := object.GetUser(userId)
|
||||
if user == nil {
|
||||
c.ResponseError(fmt.Sprintf("The user: %s doesn't exist", userId))
|
||||
return
|
||||
managedAccounts := c.Input().Get("managedAccounts")
|
||||
if managedAccounts == "1" {
|
||||
user = object.ExtendManagedAccountsWithUser(user)
|
||||
}
|
||||
|
||||
organization := object.GetMaskedOrganization(object.GetOrganizationByUser(user))
|
||||
@ -274,6 +283,7 @@ func (c *ApiController) GetAccount() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetUserinfo
|
||||
// UserInfo
|
||||
// @Title UserInfo
|
||||
// @Tag Account API
|
||||
@ -281,18 +291,16 @@ func (c *ApiController) GetAccount() {
|
||||
// @Success 200 {object} object.Userinfo The Response object
|
||||
// @router /userinfo [get]
|
||||
func (c *ApiController) GetUserinfo() {
|
||||
userId, ok := c.RequireSignedIn()
|
||||
user, ok := c.RequireSignedInUser()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
scope, aud := c.GetSessionOidc()
|
||||
host := c.Ctx.Request.Host
|
||||
resp, err := object.GetUserInfo(userId, scope, aud, host)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = resp
|
||||
userInfo := object.GetUserInfo(user, scope, aud, host)
|
||||
|
||||
c.Data["json"] = userInfo
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
@ -304,7 +312,7 @@ func (c *ApiController) GetCaptcha() {
|
||||
applicationId := c.Input().Get("applicationId")
|
||||
isCurrentProvider := c.Input().Get("isCurrentProvider")
|
||||
|
||||
captchaProvider, err := object.GetCaptchaProviderByApplication(applicationId, isCurrentProvider)
|
||||
captchaProvider, err := object.GetCaptchaProviderByApplication(applicationId, isCurrentProvider, c.GetAcceptLanguage())
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -46,7 +46,7 @@ func (c *ApiController) GetApplications() {
|
||||
if organization == "" {
|
||||
applications = object.GetApplications(owner)
|
||||
} else {
|
||||
applications = object.GetApplicationsByOrganizationName(owner, organization)
|
||||
applications = object.GetOrganizationApplications(owner, organization)
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
||||
@ -86,7 +86,7 @@ func (c *ApiController) GetUserApplication() {
|
||||
id := c.Input().Get("id")
|
||||
user := object.GetUser(id)
|
||||
if user == nil {
|
||||
c.ResponseError(fmt.Sprintf("The user: %s doesn't exist", id))
|
||||
c.ResponseError(fmt.Sprintf(c.T("application:The user: %s doesn't exist"), id))
|
||||
return
|
||||
}
|
||||
|
||||
@ -94,6 +94,42 @@ func (c *ApiController) GetUserApplication() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetOrganizationApplications
|
||||
// @Title GetOrganizationApplications
|
||||
// @Tag Application API
|
||||
// @Description get the detail of the organization's application
|
||||
// @Param organization query string true "The organization name"
|
||||
// @Success 200 {array} object.Application The Response object
|
||||
// @router /get-organization-applications [get]
|
||||
func (c *ApiController) GetOrganizationApplications() {
|
||||
userId := c.GetSessionUsername()
|
||||
organization := c.Input().Get("organization")
|
||||
owner := c.Input().Get("owner")
|
||||
limit := c.Input().Get("pageSize")
|
||||
page := c.Input().Get("p")
|
||||
field := c.Input().Get("field")
|
||||
value := c.Input().Get("value")
|
||||
sortField := c.Input().Get("sortField")
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
|
||||
if organization == "" {
|
||||
c.ResponseError(c.T("application:Parameter organization is missing"))
|
||||
return
|
||||
}
|
||||
|
||||
if limit == "" || page == "" {
|
||||
var applications []*object.Application
|
||||
applications = object.GetOrganizationApplications(owner, organization)
|
||||
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
||||
c.ServeJSON()
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetOrganizationApplicationCount(owner, organization, field, value)))
|
||||
applications := object.GetMaskedApplications(object.GetPaginationOrganizationApplications(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder), userId)
|
||||
c.ResponseOk(applications, paginator.Nums())
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateApplication
|
||||
// @Title UpdateApplication
|
||||
// @Tag Application API
|
||||
@ -108,7 +144,8 @@ func (c *ApiController) UpdateApplication() {
|
||||
var application object.Application
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &application)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateApplication(id, &application))
|
||||
@ -126,7 +163,14 @@ func (c *ApiController) AddApplication() {
|
||||
var application object.Application
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &application)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
count := object.GetApplicationCount("", "", "")
|
||||
if err := checkQuotaForApplication(count); err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddApplication(&application))
|
||||
@ -144,7 +188,8 @@ func (c *ApiController) DeleteApplication() {
|
||||
var application object.Application
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &application)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteApplication(&application))
|
||||
|
@ -17,12 +17,16 @@ package controllers
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/captcha"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/idp"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
@ -31,6 +35,11 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
wechatScanType string
|
||||
lock sync.RWMutex
|
||||
)
|
||||
|
||||
func codeToResponse(code *object.Code) *Response {
|
||||
if code.Code == "" {
|
||||
return &Response{Status: "error", Msg: code.Message, Data: code.Code}
|
||||
@ -44,12 +53,22 @@ func tokenToResponse(token *object.Token) *Response {
|
||||
return &Response{Status: "error", Msg: "fail to get accessToken", Data: token.AccessToken}
|
||||
}
|
||||
return &Response{Status: "ok", Msg: "", Data: token.AccessToken}
|
||||
|
||||
}
|
||||
|
||||
// HandleLoggedIn ...
|
||||
func (c *ApiController) HandleLoggedIn(application *object.Application, user *object.User, form *RequestForm) (resp *Response) {
|
||||
userId := user.GetId()
|
||||
|
||||
allowed, err := object.CheckAccessPermission(userId, application)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error(), nil)
|
||||
return
|
||||
}
|
||||
if !allowed {
|
||||
c.ResponseError(c.T("auth:Unauthorized operation"))
|
||||
return
|
||||
}
|
||||
|
||||
if form.Type == ResponseTypeLogin {
|
||||
c.SetSessionUsername(userId)
|
||||
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
|
||||
@ -65,17 +84,17 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
||||
codeChallenge := c.Input().Get("code_challenge")
|
||||
|
||||
if challengeMethod != "S256" && challengeMethod != "null" && challengeMethod != "" {
|
||||
c.ResponseError("Challenge method should be S256")
|
||||
c.ResponseError(c.T("auth:Challenge method should be S256"))
|
||||
return
|
||||
}
|
||||
code := object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, c.Ctx.Request.Host)
|
||||
code := object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, c.Ctx.Request.Host, c.GetAcceptLanguage())
|
||||
resp = codeToResponse(code)
|
||||
|
||||
if application.EnableSigninSession || application.HasPromptPage() {
|
||||
// The prompt page needs the user to be signed in
|
||||
c.SetSessionUsername(userId)
|
||||
}
|
||||
} else if form.Type == ResponseTypeToken || form.Type == ResponseTypeIdToken { //implicit flow
|
||||
} else if form.Type == ResponseTypeToken || form.Type == ResponseTypeIdToken { // implicit flow
|
||||
if !object.IsGrantTypeValid(form.Type, application.GrantTypes) {
|
||||
resp = &Response{Status: "error", Msg: fmt.Sprintf("error: grant_type: %s is not supported in this application", form.Type), Data: ""}
|
||||
} else {
|
||||
@ -83,7 +102,6 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
||||
token, _ := object.GetTokenByUser(application, user, scope, c.Ctx.Request.Host)
|
||||
resp = tokenToResponse(token)
|
||||
}
|
||||
|
||||
} else if form.Type == ResponseTypeSaml { // saml flow
|
||||
res, redirectUrl, err := object.GetSamlResponse(application, user, form.SamlRequest, c.Ctx.Request.Host)
|
||||
if err != nil {
|
||||
@ -92,7 +110,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
||||
}
|
||||
resp = &Response{Status: "ok", Msg: "", Data: res, Data2: redirectUrl}
|
||||
} else if form.Type == ResponseTypeCas {
|
||||
//not oauth but CAS SSO protocol
|
||||
// not oauth but CAS SSO protocol
|
||||
service := c.Input().Get("service")
|
||||
resp = wrapErrorResponse(nil)
|
||||
if service != "" {
|
||||
@ -109,7 +127,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
||||
}
|
||||
|
||||
} else {
|
||||
resp = wrapErrorResponse(fmt.Errorf("Unknown response type: %s", form.Type))
|
||||
resp = wrapErrorResponse(fmt.Errorf("unknown response type: %s", form.Type))
|
||||
}
|
||||
|
||||
// if user did not check auto signin
|
||||
@ -142,7 +160,7 @@ func (c *ApiController) GetApplicationLogin() {
|
||||
scope := c.Input().Get("scope")
|
||||
state := c.Input().Get("state")
|
||||
|
||||
msg, application := object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state)
|
||||
msg, application := object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state, c.GetAcceptLanguage())
|
||||
application = object.GetMaskedApplication(application, "")
|
||||
if msg != "" {
|
||||
c.ResponseError(msg, application)
|
||||
@ -152,7 +170,7 @@ func (c *ApiController) GetApplicationLogin() {
|
||||
}
|
||||
|
||||
func setHttpClient(idProvider idp.IdProvider, providerType string) {
|
||||
if providerType == "GitHub" || providerType == "Google" || providerType == "Facebook" || providerType == "LinkedIn" || providerType == "Steam" {
|
||||
if providerType == "GitHub" || providerType == "Google" || providerType == "Facebook" || providerType == "LinkedIn" || providerType == "Steam" || providerType == "Line" {
|
||||
idProvider.SetHttpClient(proxy.ProxyHttpClient)
|
||||
} else {
|
||||
idProvider.SetHttpClient(proxy.DefaultHttpClient)
|
||||
@ -187,7 +205,7 @@ func (c *ApiController) Login() {
|
||||
if form.Username != "" {
|
||||
if form.Type == ResponseTypeLogin {
|
||||
if c.GetSessionUsername() != "" {
|
||||
c.ResponseError("Please sign out first before signing in", c.GetSessionUsername())
|
||||
c.ResponseError(c.T("auth:Please sign out first before signing in"), c.GetSessionUsername())
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -209,11 +227,11 @@ func (c *ApiController) Login() {
|
||||
if user != nil && util.GetMaskedEmail(user.Email) == form.Username {
|
||||
form.Username = user.Email
|
||||
}
|
||||
checkResult = object.CheckVerificationCode(form.Username, form.Code)
|
||||
checkResult = object.CheckVerificationCode(form.Username, form.Code, c.GetAcceptLanguage())
|
||||
} else {
|
||||
verificationCodeType = "phone"
|
||||
if len(form.PhonePrefix) == 0 {
|
||||
responseText := fmt.Sprintf("%s%s", verificationCodeType, "No phone prefix")
|
||||
responseText := fmt.Sprintf(c.T("auth:%s No phone prefix"), verificationCodeType)
|
||||
c.ResponseError(responseText)
|
||||
return
|
||||
}
|
||||
@ -221,7 +239,7 @@ func (c *ApiController) Login() {
|
||||
form.Username = user.Phone
|
||||
}
|
||||
checkPhone := fmt.Sprintf("+%s%s", form.PhonePrefix, form.Username)
|
||||
checkResult = object.CheckVerificationCode(checkPhone, form.Code)
|
||||
checkResult = object.CheckVerificationCode(checkPhone, form.Code, c.GetAcceptLanguage())
|
||||
}
|
||||
if len(checkResult) != 0 {
|
||||
responseText := fmt.Sprintf("%s%s", verificationCodeType, checkResult)
|
||||
@ -238,12 +256,31 @@ func (c *ApiController) Login() {
|
||||
|
||||
user = object.GetUserByFields(form.Organization, form.Username)
|
||||
if user == nil {
|
||||
c.ResponseError(fmt.Sprintf("The user: %s/%s doesn't exist", form.Organization, form.Username))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The user: %s/%s doesn't exist"), form.Organization, form.Username))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||
if application == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), form.Application))
|
||||
return
|
||||
}
|
||||
|
||||
if object.CheckToEnableCaptcha(application) {
|
||||
isHuman, err := captcha.VerifyCaptchaByCaptchaType(form.CaptchaType, form.CaptchaToken, form.ClientSecret)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if !isHuman {
|
||||
c.ResponseError(c.T("auth:Turing test failed."))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
password := form.Password
|
||||
user, msg = object.CheckUserPassword(form.Organization, form.Username, password)
|
||||
user, msg = object.CheckUserPassword(form.Organization, form.Username, password, c.GetAcceptLanguage())
|
||||
}
|
||||
|
||||
if msg != "" {
|
||||
@ -251,7 +288,7 @@ func (c *ApiController) Login() {
|
||||
} else {
|
||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||
if application == nil {
|
||||
c.ResponseError(fmt.Sprintf("The application: %s does not exist", form.Application))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), form.Application))
|
||||
return
|
||||
}
|
||||
|
||||
@ -265,15 +302,15 @@ func (c *ApiController) Login() {
|
||||
} else if form.Provider != "" {
|
||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||
if application == nil {
|
||||
c.ResponseError(fmt.Sprintf("The application: %s does not exist", form.Application))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), form.Application))
|
||||
return
|
||||
}
|
||||
|
||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", application.Organization))
|
||||
provider := object.GetProvider(fmt.Sprintf("admin/%s", form.Provider))
|
||||
provider := object.GetProvider(util.GetId("admin", form.Provider))
|
||||
providerItem := application.GetProviderItem(provider.Name)
|
||||
if !providerItem.IsProviderVisible() {
|
||||
c.ResponseError(fmt.Sprintf("The provider: %s is not enabled for the application", provider.Name))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The provider: %s is not enabled for the application"), provider.Name))
|
||||
return
|
||||
}
|
||||
|
||||
@ -297,14 +334,14 @@ func (c *ApiController) Login() {
|
||||
|
||||
idProvider := idp.GetIdProvider(provider.Type, provider.SubType, clientId, clientSecret, provider.AppId, form.RedirectUri, provider.Domain, provider.CustomAuthUrl, provider.CustomTokenUrl, provider.CustomUserInfoUrl)
|
||||
if idProvider == nil {
|
||||
c.ResponseError(fmt.Sprintf("The provider type: %s is not supported", provider.Type))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The provider type: %s is not supported"), provider.Type))
|
||||
return
|
||||
}
|
||||
|
||||
setHttpClient(idProvider, provider.Type)
|
||||
|
||||
if form.State != conf.GetConfigString("authState") && form.State != application.Name {
|
||||
c.ResponseError(fmt.Sprintf("state expected: \"%s\", but got: \"%s\"", conf.GetConfigString("authState"), form.State))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:State expected: %s, but got: %s"), conf.GetConfigString("authState"), form.State))
|
||||
return
|
||||
}
|
||||
|
||||
@ -316,13 +353,13 @@ func (c *ApiController) Login() {
|
||||
}
|
||||
|
||||
if !token.Valid() {
|
||||
c.ResponseError("Invalid token")
|
||||
c.ResponseError(c.T("auth:Invalid token"))
|
||||
return
|
||||
}
|
||||
|
||||
userInfo, err = idProvider.GetUserInfo(token)
|
||||
if err != nil {
|
||||
c.ResponseError(fmt.Sprintf("Failed to login in: %s", err.Error()))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:Failed to login in: %s"), err.Error()))
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -335,11 +372,11 @@ func (c *ApiController) Login() {
|
||||
user = object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
|
||||
}
|
||||
|
||||
if user != nil && user.IsDeleted == false {
|
||||
if user != nil && !user.IsDeleted {
|
||||
// Sign in via OAuth (want to sign up but already have account)
|
||||
|
||||
if user.IsForbidden {
|
||||
c.ResponseError("the user is forbidden to sign in, please contact the administrator")
|
||||
c.ResponseError(c.T("auth:The user is forbidden to sign in, please contact the administrator"))
|
||||
}
|
||||
|
||||
resp = c.HandleLoggedIn(application, user, &form)
|
||||
@ -351,12 +388,12 @@ func (c *ApiController) Login() {
|
||||
} else if provider.Category == "OAuth" {
|
||||
// Sign up via OAuth
|
||||
if !application.EnableSignUp {
|
||||
c.ResponseError(fmt.Sprintf("The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support", provider.Type, userInfo.Username, userInfo.DisplayName))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support"), provider.Type, userInfo.Username, userInfo.DisplayName))
|
||||
return
|
||||
}
|
||||
|
||||
if !providerItem.CanSignUp {
|
||||
c.ResponseError(fmt.Sprintf("The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %s, please use another way to sign up", provider.Type, userInfo.Username, userInfo.DisplayName, provider.Type))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up"), provider.Type, userInfo.Username, userInfo.DisplayName, provider.Type))
|
||||
return
|
||||
}
|
||||
|
||||
@ -375,6 +412,12 @@ func (c *ApiController) Login() {
|
||||
|
||||
properties := map[string]string{}
|
||||
properties["no"] = strconv.Itoa(len(object.GetUsers(application.Organization)) + 2)
|
||||
initScore, err := getInitScore(organization)
|
||||
if err != nil {
|
||||
c.ResponseError(fmt.Errorf(c.T("auth:Get init score failed, error: %w"), err).Error())
|
||||
return
|
||||
}
|
||||
|
||||
user = &object.User{
|
||||
Owner: application.Organization,
|
||||
Name: userInfo.Username,
|
||||
@ -385,7 +428,7 @@ func (c *ApiController) Login() {
|
||||
Avatar: userInfo.AvatarUrl,
|
||||
Address: []string{},
|
||||
Email: userInfo.Email,
|
||||
Score: getInitScore(),
|
||||
Score: initScore,
|
||||
IsAdmin: false,
|
||||
IsGlobalAdmin: false,
|
||||
IsForbidden: false,
|
||||
@ -398,7 +441,7 @@ func (c *ApiController) Login() {
|
||||
|
||||
affected := object.AddUser(user)
|
||||
if !affected {
|
||||
c.ResponseError(fmt.Sprintf("Failed to create user, user information is invalid: %s", util.StructToJson(user)))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:Failed to create user, user information is invalid: %s"), util.StructToJson(user)))
|
||||
return
|
||||
}
|
||||
|
||||
@ -419,17 +462,17 @@ func (c *ApiController) Login() {
|
||||
} else if provider.Category == "SAML" {
|
||||
resp = &Response{Status: "error", Msg: "The account does not exist"}
|
||||
}
|
||||
//resp = &Response{Status: "ok", Msg: "", Data: res}
|
||||
// resp = &Response{Status: "ok", Msg: "", Data: res}
|
||||
} else { // form.Method != "signup"
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError("The account does not exist", userInfo)
|
||||
c.ResponseError(c.T("auth:The account does not exist"), userInfo)
|
||||
return
|
||||
}
|
||||
|
||||
oldUser := object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
|
||||
if oldUser != nil {
|
||||
c.ResponseError(fmt.Sprintf("The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)", provider.Type, userInfo.Username, userInfo.DisplayName, oldUser.Name, oldUser.DisplayName))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)"), provider.Type, userInfo.Username, userInfo.DisplayName, oldUser.Name, oldUser.DisplayName))
|
||||
return
|
||||
}
|
||||
|
||||
@ -450,7 +493,7 @@ func (c *ApiController) Login() {
|
||||
// user already signed in to Casdoor, so let the user click the avatar button to do the quick sign-in
|
||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||
if application == nil {
|
||||
c.ResponseError(fmt.Sprintf("The application: %s does not exist", form.Application))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), form.Application))
|
||||
return
|
||||
}
|
||||
|
||||
@ -462,7 +505,7 @@ func (c *ApiController) Login() {
|
||||
record.User = user.Name
|
||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||
} else {
|
||||
c.ResponseError(fmt.Sprintf("unknown authentication type (not password or provider), form = %s", util.StructToJson(form)))
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:Unknown authentication type (not password or provider), form = %s"), util.StructToJson(form)))
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -474,7 +517,7 @@ func (c *ApiController) Login() {
|
||||
func (c *ApiController) GetSamlLogin() {
|
||||
providerId := c.Input().Get("id")
|
||||
relayState := c.Input().Get("relayState")
|
||||
authURL, method, err := object.GenerateSamlLoginUrl(providerId, relayState)
|
||||
authURL, method, err := object.GenerateSamlLoginUrl(providerId, relayState, c.GetAcceptLanguage())
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
}
|
||||
@ -495,3 +538,46 @@ func (c *ApiController) HandleSamlLogin() {
|
||||
slice[4], relayState, samlResponse)
|
||||
c.Redirect(targetUrl, 303)
|
||||
}
|
||||
|
||||
// HandleOfficialAccountEvent ...
|
||||
// @Tag HandleOfficialAccountEvent API
|
||||
// @Title HandleOfficialAccountEvent
|
||||
// @router /api/webhook [POST]
|
||||
func (c *ApiController) HandleOfficialAccountEvent() {
|
||||
respBytes, err := ioutil.ReadAll(c.Ctx.Request.Body)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
}
|
||||
var data struct {
|
||||
MsgType string `xml:"MsgType"`
|
||||
Event string `xml:"Event"`
|
||||
EventKey string `xml:"EventKey"`
|
||||
}
|
||||
err = xml.Unmarshal(respBytes, &data)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
}
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
if data.EventKey != "" {
|
||||
wechatScanType = data.Event
|
||||
c.Ctx.WriteString("")
|
||||
}
|
||||
}
|
||||
|
||||
// GetWebhookEventType ...
|
||||
// @Tag GetWebhookEventType API
|
||||
// @Title GetWebhookEventType
|
||||
// @router /api/get-webhook-event [GET]
|
||||
func (c *ApiController) GetWebhookEventType() {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
resp := &Response{
|
||||
Status: "ok",
|
||||
Msg: "",
|
||||
Data: wechatScanType,
|
||||
}
|
||||
c.Data["json"] = resp
|
||||
wechatScanType = ""
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
@ -18,16 +18,19 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/beego/beego"
|
||||
"github.com/beego/beego/logs"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
// ApiController
|
||||
// controller for handlers under /api uri
|
||||
type ApiController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
// RootController
|
||||
// controller for handlers directly under / (root)
|
||||
type RootController struct {
|
||||
ApiController
|
||||
@ -56,11 +59,11 @@ func (c *ApiController) IsGlobalAdmin() bool {
|
||||
func (c *ApiController) GetSessionUsername() string {
|
||||
// check if user session expired
|
||||
sessionData := c.GetSessionData()
|
||||
|
||||
if sessionData != nil &&
|
||||
sessionData.ExpireTime != 0 &&
|
||||
sessionData.ExpireTime < time.Now().Unix() {
|
||||
c.SetSessionUsername("")
|
||||
c.SetSessionData(nil)
|
||||
c.ClearUserSession()
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -81,13 +84,17 @@ func (c *ApiController) GetSessionApplication() *object.Application {
|
||||
return application
|
||||
}
|
||||
|
||||
func (c *ApiController) ClearUserSession() {
|
||||
c.SetSessionUsername("")
|
||||
c.SetSessionData(nil)
|
||||
}
|
||||
|
||||
func (c *ApiController) GetSessionOidc() (string, string) {
|
||||
sessionData := c.GetSessionData()
|
||||
if sessionData != nil &&
|
||||
sessionData.ExpireTime != 0 &&
|
||||
sessionData.ExpireTime < time.Now().Unix() {
|
||||
c.SetSessionUsername("")
|
||||
c.SetSessionData(nil)
|
||||
c.ClearUserSession()
|
||||
return "", ""
|
||||
}
|
||||
scopeValue := c.GetSession("scope")
|
||||
@ -118,7 +125,8 @@ func (c *ApiController) GetSessionData() *SessionData {
|
||||
sessionData := &SessionData{}
|
||||
err := util.JsonToStruct(session.(string), sessionData)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logs.Error("GetSessionData failed, error: %s", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return sessionData
|
||||
|
@ -31,7 +31,7 @@ const (
|
||||
InvalidProxyCallback string = "INVALID_PROXY_CALLBACK"
|
||||
InvalidTicket string = "INVALID_TICKET"
|
||||
InvalidService string = "INVALID_SERVICE"
|
||||
InteralError string = "INTERNAL_ERROR"
|
||||
InternalError string = "INTERNAL_ERROR"
|
||||
UnauthorizedService string = "UNAUTHORIZED_SERVICE"
|
||||
)
|
||||
|
||||
@ -44,14 +44,13 @@ func (c *RootController) CasValidate() {
|
||||
return
|
||||
}
|
||||
if ok, response, issuedService, _ := object.GetCasTokenByTicket(ticket); ok {
|
||||
//check whether service is the one for which we previously issued token
|
||||
// check whether service is the one for which we previously issued token
|
||||
if issuedService == service {
|
||||
c.Ctx.Output.Body([]byte(fmt.Sprintf("yes\n%s\n", response.User)))
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
//token not found
|
||||
// token not found
|
||||
c.Ctx.Output.Body([]byte("no\n"))
|
||||
}
|
||||
|
||||
@ -83,41 +82,41 @@ func (c *RootController) CasP3ServiceAndProxyValidate() {
|
||||
Xmlns: "http://www.yale.edu/tp/cas",
|
||||
}
|
||||
|
||||
//check whether all required parameters are met
|
||||
// check whether all required parameters are met
|
||||
if service == "" || ticket == "" {
|
||||
c.sendCasAuthenticationResponseErr(InvalidRequest, "service and ticket must exist", format)
|
||||
return
|
||||
}
|
||||
ok, response, issuedService, userId := object.GetCasTokenByTicket(ticket)
|
||||
//find the token
|
||||
// find the token
|
||||
if ok {
|
||||
//check whether service is the one for which we previously issued token
|
||||
// check whether service is the one for which we previously issued token
|
||||
if strings.HasPrefix(service, issuedService) {
|
||||
serviceResponse.Success = response
|
||||
} else {
|
||||
//service not match
|
||||
// service not match
|
||||
c.sendCasAuthenticationResponseErr(InvalidService, fmt.Sprintf("service %s and %s does not match", service, issuedService), format)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
//token not found
|
||||
// token not found
|
||||
c.sendCasAuthenticationResponseErr(InvalidTicket, fmt.Sprintf("Ticket %s not recognized", ticket), format)
|
||||
return
|
||||
}
|
||||
|
||||
if pgtUrl != "" && serviceResponse.Failure == nil {
|
||||
//that means we are in proxy web flow
|
||||
// that means we are in proxy web flow
|
||||
pgt := object.StoreCasTokenForPgt(serviceResponse.Success, service, userId)
|
||||
pgtiou := serviceResponse.Success.ProxyGrantingTicket
|
||||
//todo: check whether it is https
|
||||
// todo: check whether it is https
|
||||
pgtUrlObj, err := url.Parse(pgtUrl)
|
||||
if pgtUrlObj.Scheme != "https" {
|
||||
c.sendCasAuthenticationResponseErr(InvalidProxyCallback, "callback is not https", format)
|
||||
return
|
||||
}
|
||||
//make a request to pgturl passing pgt and pgtiou
|
||||
// make a request to pgturl passing pgt and pgtiou
|
||||
if err != nil {
|
||||
c.sendCasAuthenticationResponseErr(InteralError, err.Error(), format)
|
||||
c.sendCasAuthenticationResponseErr(InternalError, err.Error(), format)
|
||||
return
|
||||
}
|
||||
param := pgtUrlObj.Query()
|
||||
@ -127,13 +126,13 @@ func (c *RootController) CasP3ServiceAndProxyValidate() {
|
||||
|
||||
request, err := http.NewRequest("GET", pgtUrlObj.String(), nil)
|
||||
if err != nil {
|
||||
c.sendCasAuthenticationResponseErr(InteralError, err.Error(), format)
|
||||
c.sendCasAuthenticationResponseErr(InternalError, err.Error(), format)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(request)
|
||||
if err != nil || !(resp.StatusCode >= 200 && resp.StatusCode < 400) {
|
||||
//failed to send request
|
||||
// failed to send request
|
||||
c.sendCasAuthenticationResponseErr(InvalidProxyCallback, err.Error(), format)
|
||||
return
|
||||
}
|
||||
@ -184,7 +183,6 @@ func (c *RootController) CasProxy() {
|
||||
c.Data["xml"] = serviceResponse
|
||||
c.ServeXML()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (c *RootController) SamlValidate() {
|
||||
@ -212,11 +210,11 @@ func (c *RootController) SamlValidate() {
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(target, service) {
|
||||
c.ResponseError(fmt.Sprintf("service %s and %s do not match", target, service))
|
||||
c.ResponseError(fmt.Sprintf(c.T("cas:Service %s and %s do not match"), target, service))
|
||||
return
|
||||
}
|
||||
|
||||
envelopReponse := struct {
|
||||
envelopResponse := struct {
|
||||
XMLName xml.Name `xml:"SOAP-ENV:Envelope"`
|
||||
Xmlns string `xml:"xmlns:SOAP-ENV"`
|
||||
Body struct {
|
||||
@ -224,15 +222,15 @@ func (c *RootController) SamlValidate() {
|
||||
Content string `xml:",innerxml"`
|
||||
}
|
||||
}{}
|
||||
envelopReponse.Xmlns = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
envelopReponse.Body.Content = response
|
||||
envelopResponse.Xmlns = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
envelopResponse.Body.Content = response
|
||||
|
||||
data, err := xml.Marshal(envelopReponse)
|
||||
data, err := xml.Marshal(envelopResponse)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Ctx.Output.Body([]byte(data))
|
||||
c.Ctx.Output.Body(data)
|
||||
}
|
||||
|
||||
func (c *RootController) sendCasProxyResponseErr(code, msg, format string) {
|
||||
|
157
controllers/casbin_adapter.go
Normal file
157
controllers/casbin_adapter.go
Normal file
@ -0,0 +1,157 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
xormadapter "github.com/casbin/xorm-adapter/v3"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
func (c *ApiController) GetCasbinAdapters() {
|
||||
owner := c.Input().Get("owner")
|
||||
limit := c.Input().Get("pageSize")
|
||||
page := c.Input().Get("p")
|
||||
field := c.Input().Get("field")
|
||||
value := c.Input().Get("value")
|
||||
sortField := c.Input().Get("sortField")
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
if limit == "" || page == "" {
|
||||
adapters := object.GetCasbinAdapters(owner)
|
||||
c.ResponseOk(adapters)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetCasbinAdapterCount(owner, field, value)))
|
||||
adapters := object.GetPaginationCasbinAdapters(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
c.ResponseOk(adapters, paginator.Nums())
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ApiController) GetCasbinAdapter() {
|
||||
id := c.Input().Get("id")
|
||||
adapter := object.GetCasbinAdapter(id)
|
||||
c.ResponseOk(adapter)
|
||||
}
|
||||
|
||||
func (c *ApiController) UpdateCasbinAdapter() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var casbinAdapter object.CasbinAdapter
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateCasbinAdapter(id, &casbinAdapter))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) AddCasbinAdapter() {
|
||||
var casbinAdapter object.CasbinAdapter
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddCasbinAdapter(&casbinAdapter))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) DeleteCasbinAdapter() {
|
||||
var casbinAdapter object.CasbinAdapter
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteCasbinAdapter(&casbinAdapter))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) SyncPolicies() {
|
||||
id := c.Input().Get("id")
|
||||
adapter := object.GetCasbinAdapter(id)
|
||||
|
||||
policies, err := object.SyncPolicies(adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(policies)
|
||||
}
|
||||
|
||||
func (c *ApiController) UpdatePolicy() {
|
||||
id := c.Input().Get("id")
|
||||
adapter := object.GetCasbinAdapter(id)
|
||||
var policies []xormadapter.CasbinRule
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policies)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.UpdatePolicy(util.CasbinToSlice(policies[0]), util.CasbinToSlice(policies[1]), adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) AddPolicy() {
|
||||
id := c.Input().Get("id")
|
||||
adapter := object.GetCasbinAdapter(id)
|
||||
var policy xormadapter.CasbinRule
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.AddPolicy(util.CasbinToSlice(policy), adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) RemovePolicy() {
|
||||
id := c.Input().Get("id")
|
||||
adapter := object.GetCasbinAdapter(id)
|
||||
var policy xormadapter.CasbinRule
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.RemovePolicy(util.CasbinToSlice(policy), adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
@ -17,7 +17,7 @@ package controllers
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -48,6 +48,7 @@ func (c *ApiController) GetCerts() {
|
||||
}
|
||||
}
|
||||
|
||||
// GetCert
|
||||
// @Title GetCert
|
||||
// @Tag Cert API
|
||||
// @Description get cert
|
||||
@ -61,6 +62,7 @@ func (c *ApiController) GetCert() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdateCert
|
||||
// @Title UpdateCert
|
||||
// @Tag Cert API
|
||||
// @Description update cert
|
||||
@ -74,13 +76,15 @@ func (c *ApiController) UpdateCert() {
|
||||
var cert object.Cert
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &cert)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateCert(id, &cert))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddCert
|
||||
// @Title AddCert
|
||||
// @Tag Cert API
|
||||
// @Description add cert
|
||||
@ -91,13 +95,15 @@ func (c *ApiController) AddCert() {
|
||||
var cert object.Cert
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &cert)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddCert(&cert))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteCert
|
||||
// @Title DeleteCert
|
||||
// @Tag Cert API
|
||||
// @Description delete cert
|
||||
@ -108,7 +114,8 @@ func (c *ApiController) DeleteCert() {
|
||||
var cert object.Cert
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &cert)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteCert(&cert))
|
||||
|
78
controllers/enforcer.go
Normal file
78
controllers/enforcer.go
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
)
|
||||
|
||||
func (c *ApiController) Enforce() {
|
||||
var permissionRule object.PermissionRule
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permissionRule)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.Enforce(&permissionRule)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) BatchEnforce() {
|
||||
var permissionRules []object.PermissionRule
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permissionRules)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.BatchEnforce(permissionRules)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllObjects() {
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("enforcer:Please sign in first"))
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetAllObjects(userId)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllActions() {
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("enforcer:Please sign in first"))
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetAllActions(userId)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllRoles() {
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("enforcer:Please sign in first"))
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetAllRoles(userId)
|
||||
c.ServeJSON()
|
||||
}
|
@ -30,7 +30,7 @@ type LdapServer struct {
|
||||
}
|
||||
|
||||
type LdapResp struct {
|
||||
//Groups []LdapRespGroup `json:"groups"`
|
||||
// Groups []LdapRespGroup `json:"groups"`
|
||||
Users []object.LdapRespUser `json:"users"`
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ type LdapSyncResp struct {
|
||||
Failed []object.LdapRespUser `json:"failed"`
|
||||
}
|
||||
|
||||
// GetLdapUser
|
||||
// @Tag Account API
|
||||
// @Title GetLdapser
|
||||
// @router /get-ldap-user [post]
|
||||
@ -51,7 +52,7 @@ func (c *ApiController) GetLdapUser() {
|
||||
ldapServer := LdapServer{}
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldapServer)
|
||||
if err != nil || util.IsStrsEmpty(ldapServer.Host, ldapServer.Admin, ldapServer.Passwd, ldapServer.BaseDn) {
|
||||
c.ResponseError("Missing parameter")
|
||||
c.ResponseError(c.T("ldap:Missing parameter"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -88,7 +89,7 @@ func (c *ApiController) GetLdapUser() {
|
||||
Uid: user.Uid,
|
||||
Cn: user.Cn,
|
||||
GroupId: user.GidNumber,
|
||||
//GroupName: groupsMap[user.GidNumber].Cn,
|
||||
// GroupName: groupsMap[user.GidNumber].Cn,
|
||||
Uuid: user.Uuid,
|
||||
Email: util.GetMaxLenStr(user.Mail, user.Email, user.EmailAddress),
|
||||
Phone: util.GetMaxLenStr(user.TelephoneNumber, user.Mobile, user.MobileTelephoneNumber),
|
||||
@ -100,6 +101,7 @@ func (c *ApiController) GetLdapUser() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetLdaps
|
||||
// @Tag Account API
|
||||
// @Title GetLdaps
|
||||
// @router /get-ldaps [post]
|
||||
@ -110,6 +112,7 @@ func (c *ApiController) GetLdaps() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetLdap
|
||||
// @Tag Account API
|
||||
// @Title GetLdap
|
||||
// @router /get-ldap [post]
|
||||
@ -117,7 +120,7 @@ func (c *ApiController) GetLdap() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
if util.IsStrsEmpty(id) {
|
||||
c.ResponseError("Missing parameter")
|
||||
c.ResponseError(c.T("ldap:Missing parameter"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -125,6 +128,7 @@ func (c *ApiController) GetLdap() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddLdap
|
||||
// @Tag Account API
|
||||
// @Title AddLdap
|
||||
// @router /add-ldap [post]
|
||||
@ -132,17 +136,17 @@ func (c *ApiController) AddLdap() {
|
||||
var ldap object.Ldap
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldap)
|
||||
if err != nil {
|
||||
c.ResponseError("Missing parameter")
|
||||
c.ResponseError(c.T("ldap:Missing parameter"))
|
||||
return
|
||||
}
|
||||
|
||||
if util.IsStrsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
|
||||
c.ResponseError("Missing parameter")
|
||||
c.ResponseError(c.T("ldap:Missing parameter"))
|
||||
return
|
||||
}
|
||||
|
||||
if object.CheckLdapExist(&ldap) {
|
||||
c.ResponseError("Ldap server exist")
|
||||
c.ResponseError(c.T("ldap:Ldap server exist"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -159,6 +163,7 @@ func (c *ApiController) AddLdap() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdateLdap
|
||||
// @Tag Account API
|
||||
// @Title UpdateLdap
|
||||
// @router /update-ldap [post]
|
||||
@ -166,7 +171,7 @@ func (c *ApiController) UpdateLdap() {
|
||||
var ldap object.Ldap
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldap)
|
||||
if err != nil || util.IsStrsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
|
||||
c.ResponseError("Missing parameter")
|
||||
c.ResponseError(c.T("ldap:Missing parameter"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -186,6 +191,7 @@ func (c *ApiController) UpdateLdap() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteLdap
|
||||
// @Tag Account API
|
||||
// @Title DeleteLdap
|
||||
// @router /delete-ldap [post]
|
||||
@ -193,7 +199,8 @@ func (c *ApiController) DeleteLdap() {
|
||||
var ldap object.Ldap
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldap)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
object.GetLdapAutoSynchronizer().StopAutoSync(ldap.Id)
|
||||
@ -201,6 +208,7 @@ func (c *ApiController) DeleteLdap() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// SyncLdapUsers
|
||||
// @Tag Account API
|
||||
// @Title SyncLdapUsers
|
||||
// @router /sync-ldap-users [post]
|
||||
@ -210,7 +218,8 @@ func (c *ApiController) SyncLdapUsers() {
|
||||
var users []object.LdapRespUser
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &users)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
object.UpdateLdapSyncTime(ldapId)
|
||||
@ -223,6 +232,7 @@ func (c *ApiController) SyncLdapUsers() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// CheckLdapUsersExist
|
||||
// @Tag Account API
|
||||
// @Title CheckLdapUserExist
|
||||
// @router /check-ldap-users-exist [post]
|
||||
@ -231,7 +241,8 @@ func (c *ApiController) CheckLdapUsersExist() {
|
||||
var uuids []string
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &uuids)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
exist := object.CheckLdapUuidExist(owner, uuids)
|
||||
|
118
controllers/ldapserver.go
Normal file
118
controllers/ldapserver.go
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/forestmgy/ldapserver"
|
||||
"github.com/lor00x/goldap/message"
|
||||
)
|
||||
|
||||
func StartLdapServer() {
|
||||
server := ldapserver.NewServer()
|
||||
routes := ldapserver.NewRouteMux()
|
||||
|
||||
routes.Bind(handleBind)
|
||||
routes.Search(handleSearch).Label(" SEARCH****")
|
||||
|
||||
server.Handle(routes)
|
||||
server.ListenAndServe("0.0.0.0:" + conf.GetConfigString("ldapServerPort"))
|
||||
}
|
||||
|
||||
func handleBind(w ldapserver.ResponseWriter, m *ldapserver.Message) {
|
||||
r := m.GetBindRequest()
|
||||
res := ldapserver.NewBindResponse(ldapserver.LDAPResultSuccess)
|
||||
|
||||
if r.AuthenticationChoice() == "simple" {
|
||||
bindusername, bindorg, err := object.GetNameAndOrgFromDN(string(r.Name()))
|
||||
if err != "" {
|
||||
log.Printf("Bind failed ,ErrMsg=%s", err)
|
||||
res.SetResultCode(ldapserver.LDAPResultInvalidDNSyntax)
|
||||
res.SetDiagnosticMessage("bind failed ErrMsg: " + err)
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
bindpassword := string(r.AuthenticationSimple())
|
||||
binduser, err := object.CheckUserPassword(bindorg, bindusername, bindpassword, "en")
|
||||
if err != "" {
|
||||
log.Printf("Bind failed User=%s, Pass=%#v, ErrMsg=%s", string(r.Name()), r.Authentication(), err)
|
||||
res.SetResultCode(ldapserver.LDAPResultInvalidCredentials)
|
||||
res.SetDiagnosticMessage("invalid credentials ErrMsg: " + err)
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
if bindorg == "built-in" {
|
||||
m.Client.IsGlobalAdmin, m.Client.IsOrgAdmin = true, true
|
||||
} else if binduser.IsAdmin {
|
||||
m.Client.IsOrgAdmin = true
|
||||
}
|
||||
m.Client.IsAuthenticated = true
|
||||
m.Client.UserName = bindusername
|
||||
m.Client.OrgName = bindorg
|
||||
} else {
|
||||
res.SetResultCode(ldapserver.LDAPResultAuthMethodNotSupported)
|
||||
res.SetDiagnosticMessage("Authentication method not supported,Please use Simple Authentication")
|
||||
}
|
||||
w.Write(res)
|
||||
}
|
||||
|
||||
func handleSearch(w ldapserver.ResponseWriter, m *ldapserver.Message) {
|
||||
res := ldapserver.NewSearchResultDoneResponse(ldapserver.LDAPResultSuccess)
|
||||
if !m.Client.IsAuthenticated {
|
||||
res.SetResultCode(ldapserver.LDAPResultUnwillingToPerform)
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
r := m.GetSearchRequest()
|
||||
if r.FilterString() == "(objectClass=*)" {
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
name, org, errCode := object.GetUserNameAndOrgFromBaseDnAndFilter(string(r.BaseObject()), r.FilterString())
|
||||
if errCode != ldapserver.LDAPResultSuccess {
|
||||
res.SetResultCode(errCode)
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
// Handle Stop Signal (server stop / client disconnected / Abandoned request....)
|
||||
select {
|
||||
case <-m.Done:
|
||||
log.Print("Leaving handleSearch...")
|
||||
return
|
||||
default:
|
||||
}
|
||||
users, errCode := object.GetFilteredUsers(m, name, org)
|
||||
if errCode != ldapserver.LDAPResultSuccess {
|
||||
res.SetResultCode(errCode)
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(users); i++ {
|
||||
user := users[i]
|
||||
dn := fmt.Sprintf("cn=%s,%s", user.DisplayName, string(r.BaseObject()))
|
||||
e := ldapserver.NewSearchResultEntry(dn)
|
||||
e.AddAttribute("cn", message.AttributeValue(user.Name))
|
||||
e.AddAttribute("uid", message.AttributeValue(user.Name))
|
||||
e.AddAttribute("email", message.AttributeValue(user.Email))
|
||||
e.AddAttribute("mobile", message.AttributeValue(user.Phone))
|
||||
// e.AddAttribute("postalAddress", message.AttributeValue(user.Address[0]))
|
||||
w.Write(e)
|
||||
}
|
||||
w.Write(res)
|
||||
}
|
@ -21,14 +21,15 @@ import (
|
||||
)
|
||||
|
||||
type LinkForm struct {
|
||||
ProviderType string `json:"providerType"`
|
||||
ProviderType string `json:"providerType"`
|
||||
User object.User `json:"user"`
|
||||
}
|
||||
|
||||
// Unlink ...
|
||||
// @router /unlink [post]
|
||||
// @Tag Login API
|
||||
func (c *ApiController) Unlink() {
|
||||
userId, ok := c.RequireSignedIn()
|
||||
user, ok := c.RequireSignedInUser()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@ -36,20 +37,59 @@ func (c *ApiController) Unlink() {
|
||||
var form LinkForm
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &form)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
providerType := form.ProviderType
|
||||
|
||||
user := object.GetUser(userId)
|
||||
value := object.GetUserField(user, providerType)
|
||||
// the user will be unlinked from the provider
|
||||
unlinkedUser := form.User
|
||||
|
||||
if value == "" {
|
||||
c.ResponseError("Please link first", value)
|
||||
if user.Id != unlinkedUser.Id && !user.IsGlobalAdmin {
|
||||
// if the user is not the same as the one we are unlinking, we need to make sure the user is the global admin.
|
||||
c.ResponseError(c.T("link:You are not the global admin, you can't unlink other users"))
|
||||
return
|
||||
}
|
||||
|
||||
object.ClearUserOAuthProperties(user, providerType)
|
||||
if user.Id == unlinkedUser.Id && !user.IsGlobalAdmin {
|
||||
// if the user is unlinking themselves, should check the provider can be unlinked, if not, we should return an error.
|
||||
application := object.GetApplicationByUser(user)
|
||||
if application == nil {
|
||||
c.ResponseError(c.T("link:You can't unlink yourself, you are not a member of any application"))
|
||||
return
|
||||
}
|
||||
|
||||
object.LinkUserAccount(user, providerType, "")
|
||||
if len(application.Providers) == 0 {
|
||||
c.ResponseError(c.T("link:This application has no providers"))
|
||||
return
|
||||
}
|
||||
|
||||
provider := application.GetProviderItemByType(providerType)
|
||||
if provider == nil {
|
||||
c.ResponseError(c.T("link:This application has no providers of type") + providerType)
|
||||
return
|
||||
}
|
||||
|
||||
if !provider.CanUnlink {
|
||||
c.ResponseError(c.T("link:This provider can't be unlinked"))
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// only two situations can happen here
|
||||
// 1. the user is the global admin
|
||||
// 2. the user is unlinking themselves and provider can be unlinked
|
||||
|
||||
value := object.GetUserField(&unlinkedUser, providerType)
|
||||
|
||||
if value == "" {
|
||||
c.ResponseError(c.T("link:Please link first"), value)
|
||||
return
|
||||
}
|
||||
|
||||
object.ClearUserOAuthProperties(&unlinkedUser, providerType)
|
||||
|
||||
object.LinkUserAccount(&unlinkedUser, providerType, "")
|
||||
c.ResponseOk()
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ package controllers
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -76,7 +76,8 @@ func (c *ApiController) UpdateModel() {
|
||||
var model object.Model
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &model)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateModel(id, &model))
|
||||
@ -94,7 +95,8 @@ func (c *ApiController) AddModel() {
|
||||
var model object.Model
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &model)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddModel(&model))
|
||||
@ -112,7 +114,8 @@ func (c *ApiController) DeleteModel() {
|
||||
var model object.Model
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &model)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteModel(&model))
|
||||
|
@ -16,6 +16,7 @@ package controllers
|
||||
|
||||
import "github.com/casdoor/casdoor/object"
|
||||
|
||||
// GetOidcDiscovery
|
||||
// @Title GetOidcDiscovery
|
||||
// @Tag OIDC API
|
||||
// @Description Get Oidc Discovery
|
||||
@ -27,6 +28,7 @@ func (c *RootController) GetOidcDiscovery() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetJwks
|
||||
// @Title GetJwks
|
||||
// @Tag OIDC API
|
||||
// @Success 200 {object} jose.JSONWebKey
|
||||
|
@ -17,7 +17,7 @@ package controllers
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -76,7 +76,8 @@ func (c *ApiController) UpdateOrganization() {
|
||||
var organization object.Organization
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &organization)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateOrganization(id, &organization))
|
||||
@ -94,7 +95,14 @@ func (c *ApiController) AddOrganization() {
|
||||
var organization object.Organization
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &organization)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
count := object.GetOrganizationCount("", "", "")
|
||||
if err := checkQuotaForOrganization(count); err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddOrganization(&organization))
|
||||
@ -112,9 +120,31 @@ func (c *ApiController) DeleteOrganization() {
|
||||
var organization object.Organization
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &organization)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteOrganization(&organization))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetDefaultApplication ...
|
||||
// @Title GetDefaultApplication
|
||||
// @Tag Organization API
|
||||
// @Description get default application
|
||||
// @Param id query string true "organization id"
|
||||
// @Success 200 {object} Response The Response object
|
||||
// @router /get-default-application [get]
|
||||
func (c *ApiController) GetDefaultApplication() {
|
||||
userId := c.GetSessionUsername()
|
||||
id := c.Input().Get("id")
|
||||
|
||||
application, err := object.GetDefaultApplication(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
maskedApplication := object.GetMaskedApplication(application, userId)
|
||||
c.ResponseOk(maskedApplication)
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -67,6 +67,7 @@ func (c *ApiController) GetUserPayments() {
|
||||
c.ResponseOk(payments)
|
||||
}
|
||||
|
||||
// GetPayment
|
||||
// @Title GetPayment
|
||||
// @Tag Payment API
|
||||
// @Description get payment
|
||||
@ -80,6 +81,7 @@ func (c *ApiController) GetPayment() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdatePayment
|
||||
// @Title UpdatePayment
|
||||
// @Tag Payment API
|
||||
// @Description update payment
|
||||
@ -93,13 +95,15 @@ func (c *ApiController) UpdatePayment() {
|
||||
var payment object.Payment
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &payment)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdatePayment(id, &payment))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddPayment
|
||||
// @Title AddPayment
|
||||
// @Tag Payment API
|
||||
// @Description add payment
|
||||
@ -110,13 +114,15 @@ func (c *ApiController) AddPayment() {
|
||||
var payment object.Payment
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &payment)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddPayment(&payment))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeletePayment
|
||||
// @Title DeletePayment
|
||||
// @Tag Payment API
|
||||
// @Description delete payment
|
||||
@ -127,13 +133,15 @@ func (c *ApiController) DeletePayment() {
|
||||
var payment object.Payment
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &payment)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeletePayment(&payment))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// NotifyPayment
|
||||
// @Title NotifyPayment
|
||||
// @Tag Payment API
|
||||
// @Description notify payment
|
||||
@ -152,13 +160,15 @@ func (c *ApiController) NotifyPayment() {
|
||||
if ok {
|
||||
_, err := c.Ctx.ResponseWriter.Write([]byte("success"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
panic(fmt.Errorf("NotifyPayment() failed: %v", ok))
|
||||
}
|
||||
}
|
||||
|
||||
// InvoicePayment
|
||||
// @Title InvoicePayment
|
||||
// @Tag Payment API
|
||||
// @Description invoice payment
|
||||
|
@ -17,7 +17,7 @@ package controllers
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -48,6 +48,38 @@ func (c *ApiController) GetPermissions() {
|
||||
}
|
||||
}
|
||||
|
||||
// GetPermissionsBySubmitter
|
||||
// @Title GetPermissionsBySubmitter
|
||||
// @Tag Permission API
|
||||
// @Description get permissions by submitter
|
||||
// @Success 200 {array} object.Permission The Response object
|
||||
// @router /get-permissions-by-submitter [get]
|
||||
func (c *ApiController) GetPermissionsBySubmitter() {
|
||||
user, ok := c.RequireSignedInUser()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
permissions := object.GetPermissionsBySubmitter(user.Owner, user.Name)
|
||||
c.ResponseOk(permissions, len(permissions))
|
||||
return
|
||||
}
|
||||
|
||||
// GetPermissionsByRole
|
||||
// @Title GetPermissionsByRole
|
||||
// @Tag Permission API
|
||||
// @Description get permissions by role
|
||||
// @Param id query string true "The id of the role"
|
||||
// @Success 200 {array} object.Permission The Response object
|
||||
// @router /get-permissions-by-role [get]
|
||||
func (c *ApiController) GetPermissionsByRole() {
|
||||
id := c.Input().Get("id")
|
||||
permissions := object.GetPermissionsByRole(id)
|
||||
c.ResponseOk(permissions, len(permissions))
|
||||
return
|
||||
}
|
||||
|
||||
// GetPermission
|
||||
// @Title GetPermission
|
||||
// @Tag Permission API
|
||||
// @Description get permission
|
||||
@ -61,6 +93,7 @@ func (c *ApiController) GetPermission() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdatePermission
|
||||
// @Title UpdatePermission
|
||||
// @Tag Permission API
|
||||
// @Description update permission
|
||||
@ -74,13 +107,15 @@ func (c *ApiController) UpdatePermission() {
|
||||
var permission object.Permission
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permission)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdatePermission(id, &permission))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddPermission
|
||||
// @Title AddPermission
|
||||
// @Tag Permission API
|
||||
// @Description add permission
|
||||
@ -91,13 +126,15 @@ func (c *ApiController) AddPermission() {
|
||||
var permission object.Permission
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permission)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddPermission(&permission))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeletePermission
|
||||
// @Title DeletePermission
|
||||
// @Tag Permission API
|
||||
// @Description delete permission
|
||||
@ -108,7 +145,8 @@ func (c *ApiController) DeletePermission() {
|
||||
var permission object.Permission
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permission)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeletePermission(&permission))
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -49,6 +49,7 @@ func (c *ApiController) GetProducts() {
|
||||
}
|
||||
}
|
||||
|
||||
// GetProduct
|
||||
// @Title GetProduct
|
||||
// @Tag Product API
|
||||
// @Description get product
|
||||
@ -58,10 +59,14 @@ func (c *ApiController) GetProducts() {
|
||||
func (c *ApiController) GetProduct() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
c.Data["json"] = object.GetProduct(id)
|
||||
product := object.GetProduct(id)
|
||||
object.ExtendProductWithProviders(product)
|
||||
|
||||
c.Data["json"] = product
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdateProduct
|
||||
// @Title UpdateProduct
|
||||
// @Tag Product API
|
||||
// @Description update product
|
||||
@ -75,13 +80,15 @@ func (c *ApiController) UpdateProduct() {
|
||||
var product object.Product
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &product)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateProduct(id, &product))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddProduct
|
||||
// @Title AddProduct
|
||||
// @Tag Product API
|
||||
// @Description add product
|
||||
@ -92,13 +99,15 @@ func (c *ApiController) AddProduct() {
|
||||
var product object.Product
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &product)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddProduct(&product))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteProduct
|
||||
// @Title DeleteProduct
|
||||
// @Tag Product API
|
||||
// @Description delete product
|
||||
@ -109,13 +118,15 @@ func (c *ApiController) DeleteProduct() {
|
||||
var product object.Product
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &product)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteProduct(&product))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// BuyProduct
|
||||
// @Title BuyProduct
|
||||
// @Tag Product API
|
||||
// @Description buy product
|
||||
@ -130,13 +141,13 @@ func (c *ApiController) BuyProduct() {
|
||||
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError("Please login first")
|
||||
c.ResponseError(c.T("product:Please login first"))
|
||||
return
|
||||
}
|
||||
|
||||
user := object.GetUser(userId)
|
||||
if user == nil {
|
||||
c.ResponseError(fmt.Sprintf("The user: %s doesn't exist", userId))
|
||||
c.ResponseError(fmt.Sprintf(c.T("product:The user: %s doesn't exist"), userId))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,8 @@ package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -47,6 +48,31 @@ func (c *ApiController) GetProviders() {
|
||||
}
|
||||
}
|
||||
|
||||
// GetGlobalProviders
|
||||
// @Title GetGlobalProviders
|
||||
// @Tag Provider API
|
||||
// @Description get Global providers
|
||||
// @Success 200 {array} object.Provider The Response object
|
||||
// @router /get-global-providers [get]
|
||||
func (c *ApiController) GetGlobalProviders() {
|
||||
limit := c.Input().Get("pageSize")
|
||||
page := c.Input().Get("p")
|
||||
field := c.Input().Get("field")
|
||||
value := c.Input().Get("value")
|
||||
sortField := c.Input().Get("sortField")
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
if limit == "" || page == "" {
|
||||
c.Data["json"] = object.GetMaskedProviders(object.GetGlobalProviders())
|
||||
c.ServeJSON()
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetGlobalProviderCount(field, value)))
|
||||
providers := object.GetMaskedProviders(object.GetPaginationGlobalProviders(paginator.Offset(), limit, field, value, sortField, sortOrder))
|
||||
c.ResponseOk(providers, paginator.Nums())
|
||||
}
|
||||
}
|
||||
|
||||
// GetProvider
|
||||
// @Title GetProvider
|
||||
// @Tag Provider API
|
||||
// @Description get provider
|
||||
@ -55,11 +81,11 @@ func (c *ApiController) GetProviders() {
|
||||
// @router /get-provider [get]
|
||||
func (c *ApiController) GetProvider() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
c.Data["json"] = object.GetMaskedProvider(object.GetProvider(id))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdateProvider
|
||||
// @Title UpdateProvider
|
||||
// @Tag Provider API
|
||||
// @Description update provider
|
||||
@ -73,13 +99,15 @@ func (c *ApiController) UpdateProvider() {
|
||||
var provider object.Provider
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &provider)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateProvider(id, &provider))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddProvider
|
||||
// @Title AddProvider
|
||||
// @Tag Provider API
|
||||
// @Description add provider
|
||||
@ -90,13 +118,21 @@ func (c *ApiController) AddProvider() {
|
||||
var provider object.Provider
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &provider)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
count := object.GetProviderCount("", "", "")
|
||||
if err := checkQuotaForProvider(count); err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddProvider(&provider))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteProvider
|
||||
// @Title DeleteProvider
|
||||
// @Tag Provider API
|
||||
// @Description delete provider
|
||||
@ -107,7 +143,8 @@ func (c *ApiController) DeleteProvider() {
|
||||
var provider object.Provider
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &provider)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteProvider(&provider))
|
||||
|
@ -15,7 +15,9 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -29,6 +31,11 @@ import (
|
||||
// @Success 200 {object} object.Record The Response object
|
||||
// @router /get-records [get]
|
||||
func (c *ApiController) GetRecords() {
|
||||
organization, ok := c.RequireAdmin()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
limit := c.Input().Get("pageSize")
|
||||
page := c.Input().Get("p")
|
||||
field := c.Input().Get("field")
|
||||
@ -40,8 +47,9 @@ func (c *ApiController) GetRecords() {
|
||||
c.ServeJSON()
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetRecordCount(field, value)))
|
||||
records := object.GetPaginationRecords(paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
filterRecord := &object.Record{Organization: organization}
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetRecordCount(field, value, filterRecord)))
|
||||
records := object.GetPaginationRecords(paginator.Offset(), limit, field, value, sortField, sortOrder, filterRecord)
|
||||
c.ResponseOk(records, paginator.Nums())
|
||||
}
|
||||
}
|
||||
@ -59,9 +67,29 @@ func (c *ApiController) GetRecordsByFilter() {
|
||||
record := &object.Record{}
|
||||
err := util.JsonToStruct(body, record)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetRecordsByField(record)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddRecord
|
||||
// @Title AddRecord
|
||||
// @Tag Record API
|
||||
// @Description add a record
|
||||
// @Param body body object.Record true "The details of the record"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /add-record [post]
|
||||
func (c *ApiController) AddRecord() {
|
||||
var record object.Record
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &record)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddRecord(&record))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
@ -22,11 +22,12 @@ import (
|
||||
"mime"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
// GetResources
|
||||
// @router /get-resources [get]
|
||||
// @Tag Resource API
|
||||
// @Title GetResources
|
||||
@ -39,6 +40,15 @@ func (c *ApiController) GetResources() {
|
||||
value := c.Input().Get("value")
|
||||
sortField := c.Input().Get("sortField")
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
|
||||
userObj, ok := c.RequireSignedInUser()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if userObj.IsAdmin {
|
||||
user = ""
|
||||
}
|
||||
|
||||
if limit == "" || page == "" {
|
||||
c.Data["json"] = object.GetResources(owner, user)
|
||||
c.ServeJSON()
|
||||
@ -50,6 +60,7 @@ func (c *ApiController) GetResources() {
|
||||
}
|
||||
}
|
||||
|
||||
// GetResource
|
||||
// @Tag Resource API
|
||||
// @Title GetResource
|
||||
// @router /get-resource [get]
|
||||
@ -60,6 +71,7 @@ func (c *ApiController) GetResource() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdateResource
|
||||
// @Tag Resource API
|
||||
// @Title UpdateResource
|
||||
// @router /update-resource [post]
|
||||
@ -69,13 +81,15 @@ func (c *ApiController) UpdateResource() {
|
||||
var resource object.Resource
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &resource)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateResource(id, &resource))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddResource
|
||||
// @Tag Resource API
|
||||
// @Title AddResource
|
||||
// @router /add-resource [post]
|
||||
@ -83,13 +97,15 @@ func (c *ApiController) AddResource() {
|
||||
var resource object.Resource
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &resource)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddResource(&resource))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteResource
|
||||
// @Tag Resource API
|
||||
// @Title DeleteResource
|
||||
// @router /delete-resource [post]
|
||||
@ -97,7 +113,8 @@ func (c *ApiController) DeleteResource() {
|
||||
var resource object.Resource
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &resource)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
provider, _, ok := c.GetProviderFromContext("Storage")
|
||||
@ -105,7 +122,7 @@ func (c *ApiController) DeleteResource() {
|
||||
return
|
||||
}
|
||||
|
||||
err = object.DeleteFile(provider, resource.Name)
|
||||
err = object.DeleteFile(provider, resource.Name, c.GetAcceptLanguage())
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@ -115,6 +132,7 @@ func (c *ApiController) DeleteResource() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UploadResource
|
||||
// @Tag Resource API
|
||||
// @Title UploadResource
|
||||
// @router /upload-resource [post]
|
||||
@ -136,7 +154,7 @@ func (c *ApiController) UploadResource() {
|
||||
defer file.Close()
|
||||
|
||||
if username == "" || fullFilePath == "" {
|
||||
c.ResponseError(fmt.Sprintf("username or fullFilePath is empty: username = %s, fullFilePath = %s", username, fullFilePath))
|
||||
c.ResponseError(fmt.Sprintf(c.T("resource:Username or fullFilePath is empty: username = %s, fullFilePath = %s"), username, fullFilePath))
|
||||
return
|
||||
}
|
||||
|
||||
@ -147,7 +165,7 @@ func (c *ApiController) UploadResource() {
|
||||
return
|
||||
}
|
||||
|
||||
provider, user, ok := c.GetProviderFromContext("Storage")
|
||||
provider, _, ok := c.GetProviderFromContext("Storage")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
@ -162,6 +180,20 @@ func (c *ApiController) UploadResource() {
|
||||
fileType, _ = util.GetOwnerAndNameFromId(mimeType)
|
||||
}
|
||||
|
||||
if tag != "avatar" && tag != "termsOfUse" {
|
||||
ext := filepath.Ext(filepath.Base(fullFilePath))
|
||||
index := len(fullFilePath) - len(ext)
|
||||
for i := 1; ; i++ {
|
||||
_, objectKey := object.GetUploadFileUrl(provider, fullFilePath, true)
|
||||
if object.GetResourceCount(owner, username, "name", objectKey) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// duplicated fullFilePath found, change it
|
||||
fullFilePath = fullFilePath[:index] + fmt.Sprintf("-%d", i) + ext
|
||||
}
|
||||
}
|
||||
|
||||
fileUrl, objectKey, err := object.UploadFileSafe(provider, fullFilePath, fileBuffer)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
@ -193,12 +225,10 @@ func (c *ApiController) UploadResource() {
|
||||
|
||||
switch tag {
|
||||
case "avatar":
|
||||
user := object.GetUserNoCheck(util.GetId(owner, username))
|
||||
if user == nil {
|
||||
user = object.GetUserNoCheck(username)
|
||||
if user == nil {
|
||||
c.ResponseError("user is nil for tag: \"avatar\"")
|
||||
return
|
||||
}
|
||||
c.ResponseError(c.T("resource:User is nil for tag: avatar"))
|
||||
return
|
||||
}
|
||||
|
||||
user.Avatar = fileUrl
|
||||
|
@ -17,7 +17,7 @@ package controllers
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -48,6 +48,7 @@ func (c *ApiController) GetRoles() {
|
||||
}
|
||||
}
|
||||
|
||||
// GetRole
|
||||
// @Title GetRole
|
||||
// @Tag Role API
|
||||
// @Description get role
|
||||
@ -61,6 +62,7 @@ func (c *ApiController) GetRole() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdateRole
|
||||
// @Title UpdateRole
|
||||
// @Tag Role API
|
||||
// @Description update role
|
||||
@ -74,13 +76,15 @@ func (c *ApiController) UpdateRole() {
|
||||
var role object.Role
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &role)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateRole(id, &role))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddRole
|
||||
// @Title AddRole
|
||||
// @Tag Role API
|
||||
// @Description add role
|
||||
@ -91,13 +95,15 @@ func (c *ApiController) AddRole() {
|
||||
var role object.Role
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &role)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddRole(&role))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteRole
|
||||
// @Title DeleteRole
|
||||
// @Tag Role API
|
||||
// @Description delete role
|
||||
@ -108,7 +114,8 @@ func (c *ApiController) DeleteRole() {
|
||||
var role object.Role
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &role)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteRole(&role))
|
||||
|
@ -25,7 +25,7 @@ func (c *ApiController) GetSamlMeta() {
|
||||
paramApp := c.Input().Get("application")
|
||||
application := object.GetApplication(paramApp)
|
||||
if application == nil {
|
||||
c.ResponseError(fmt.Sprintf("err: application %s not found", paramApp))
|
||||
c.ResponseError(fmt.Sprintf(c.T("saml:Application %s not found"), paramApp))
|
||||
return
|
||||
}
|
||||
metadata, _ := object.GetSamlMeta(application, host)
|
||||
|
@ -60,7 +60,7 @@ func (c *ApiController) SendEmail() {
|
||||
var provider *object.Provider
|
||||
if emailForm.Provider != "" {
|
||||
// called by frontend's TestEmailWidget, provider name is set by frontend
|
||||
provider = object.GetProvider(fmt.Sprintf("admin/%s", emailForm.Provider))
|
||||
provider = object.GetProvider(util.GetId("admin", emailForm.Provider))
|
||||
} else {
|
||||
// called by Casdoor SDK via Client ID & Client Secret, so the used Email provider will be the application' Email provider or the default Email provider
|
||||
var ok bool
|
||||
@ -81,7 +81,7 @@ func (c *ApiController) SendEmail() {
|
||||
}
|
||||
|
||||
if util.IsStrsEmpty(emailForm.Title, emailForm.Content, emailForm.Sender) {
|
||||
c.ResponseError(fmt.Sprintf("Empty parameters for emailForm: %v", emailForm))
|
||||
c.ResponseError(fmt.Sprintf(c.T("service:Empty parameters for emailForm: %v"), emailForm))
|
||||
return
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ func (c *ApiController) SendEmail() {
|
||||
}
|
||||
|
||||
if len(invalidReceivers) != 0 {
|
||||
c.ResponseError(fmt.Sprintf("Invalid Email receivers: %s", invalidReceivers))
|
||||
c.ResponseError(fmt.Sprintf(c.T("service:Invalid Email receivers: %s"), invalidReceivers))
|
||||
return
|
||||
}
|
||||
|
||||
@ -141,7 +141,7 @@ func (c *ApiController) SendSms() {
|
||||
}
|
||||
|
||||
if len(invalidReceivers) != 0 {
|
||||
c.ResponseError(fmt.Sprintf("Invalid phone receivers: %s", invalidReceivers))
|
||||
c.ResponseError(fmt.Sprintf(c.T("service:Invalid phone receivers: %s"), invalidReceivers))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,8 @@ package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -47,6 +48,7 @@ func (c *ApiController) GetSyncers() {
|
||||
}
|
||||
}
|
||||
|
||||
// GetSyncer
|
||||
// @Title GetSyncer
|
||||
// @Tag Syncer API
|
||||
// @Description get syncer
|
||||
@ -60,6 +62,7 @@ func (c *ApiController) GetSyncer() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdateSyncer
|
||||
// @Title UpdateSyncer
|
||||
// @Tag Syncer API
|
||||
// @Description update syncer
|
||||
@ -73,13 +76,15 @@ func (c *ApiController) UpdateSyncer() {
|
||||
var syncer object.Syncer
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &syncer)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateSyncer(id, &syncer))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddSyncer
|
||||
// @Title AddSyncer
|
||||
// @Tag Syncer API
|
||||
// @Description add syncer
|
||||
@ -90,13 +95,15 @@ func (c *ApiController) AddSyncer() {
|
||||
var syncer object.Syncer
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &syncer)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddSyncer(&syncer))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteSyncer
|
||||
// @Title DeleteSyncer
|
||||
// @Tag Syncer API
|
||||
// @Description delete syncer
|
||||
@ -107,13 +114,15 @@ func (c *ApiController) DeleteSyncer() {
|
||||
var syncer object.Syncer
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &syncer)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteSyncer(&syncer))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// RunSyncer
|
||||
// @Title RunSyncer
|
||||
// @Tag Syncer API
|
||||
// @Description run syncer
|
||||
|
82
controllers/system_info.go
Normal file
82
controllers/system_info.go
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
type SystemInfo struct {
|
||||
MemoryUsed uint64 `json:"memory_used"`
|
||||
MemoryTotal uint64 `json:"memory_total"`
|
||||
CpuUsage []float64 `json:"cpu_usage"`
|
||||
}
|
||||
|
||||
// GetSystemInfo
|
||||
// @Title GetSystemInfo
|
||||
// @Tag System API
|
||||
// @Description get user's system info
|
||||
// @Param id query string true "The id of the user"
|
||||
// @Success 200 {object} object.SystemInfo The Response object
|
||||
// @router /get-system-info [get]
|
||||
func (c *ApiController) GetSystemInfo() {
|
||||
id := c.GetString("id")
|
||||
if id == "" {
|
||||
id = c.GetSessionUsername()
|
||||
}
|
||||
|
||||
user := object.GetUser(id)
|
||||
if user == nil || !user.IsGlobalAdmin {
|
||||
c.ResponseError(c.T("system_info:You are not authorized to access this resource"))
|
||||
return
|
||||
}
|
||||
|
||||
cpuUsage, err := util.GetCpuUsage()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
memoryUsed, memoryTotal, err := util.GetMemoryUsage()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = SystemInfo{
|
||||
CpuUsage: cpuUsage,
|
||||
MemoryUsed: memoryUsed,
|
||||
MemoryTotal: memoryTotal,
|
||||
}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GitRepoVersion
|
||||
// @Title GitRepoVersion
|
||||
// @Tag System API
|
||||
// @Description get local github repo's latest release version info
|
||||
// @Success 200 {string} local latest version hash of casdoor
|
||||
// @router /get-release [get]
|
||||
func (c *ApiController) GitRepoVersion() {
|
||||
version, err := util.GetGitRepoVersion()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = version
|
||||
c.ServeJSON()
|
||||
}
|
@ -18,7 +18,7 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -79,7 +79,8 @@ func (c *ApiController) UpdateToken() {
|
||||
var token object.Token
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateToken(id, &token))
|
||||
@ -97,7 +98,8 @@ func (c *ApiController) AddToken() {
|
||||
var token object.Token
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddToken(&token))
|
||||
@ -115,7 +117,8 @@ func (c *ApiController) DeleteToken() {
|
||||
var token object.Token
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteToken(&token))
|
||||
@ -147,12 +150,12 @@ func (c *ApiController) GetOAuthCode() {
|
||||
codeChallenge := c.Input().Get("code_challenge")
|
||||
|
||||
if challengeMethod != "S256" && challengeMethod != "null" && challengeMethod != "" {
|
||||
c.ResponseError("Challenge method should be S256")
|
||||
c.ResponseError(c.T("token:Challenge method should be S256"))
|
||||
return
|
||||
}
|
||||
host := c.Ctx.Request.Host
|
||||
|
||||
c.Data["json"] = object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, host)
|
||||
c.Data["json"] = object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, host, c.GetAcceptLanguage())
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
@ -165,6 +168,8 @@ func (c *ApiController) GetOAuthCode() {
|
||||
// @Param client_secret query string true "OAuth client secret"
|
||||
// @Param code query string true "OAuth code"
|
||||
// @Success 200 {object} object.TokenWrapper The Response object
|
||||
// @Success 400 {object} object.TokenError The Response object
|
||||
// @Success 401 {object} object.TokenError The Response object
|
||||
// @router /login/oauth/access_token [post]
|
||||
func (c *ApiController) GetOAuthToken() {
|
||||
grantType := c.Input().Get("grant_type")
|
||||
@ -199,7 +204,8 @@ func (c *ApiController) GetOAuthToken() {
|
||||
}
|
||||
host := c.Ctx.Request.Host
|
||||
|
||||
c.Data["json"] = object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, tag, avatar)
|
||||
c.Data["json"] = object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, tag, avatar, c.GetAcceptLanguage())
|
||||
c.SetTokenErrorHttpStatus()
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
@ -213,6 +219,8 @@ func (c *ApiController) GetOAuthToken() {
|
||||
// @Param client_id query string true "OAuth client id"
|
||||
// @Param client_secret query string false "OAuth client secret"
|
||||
// @Success 200 {object} object.TokenWrapper The Response object
|
||||
// @Success 400 {object} object.TokenError The Response object
|
||||
// @Success 401 {object} object.TokenError The Response object
|
||||
// @router /login/oauth/refresh_token [post]
|
||||
func (c *ApiController) RefreshToken() {
|
||||
grantType := c.Input().Get("grant_type")
|
||||
@ -235,6 +243,7 @@ func (c *ApiController) RefreshToken() {
|
||||
}
|
||||
|
||||
c.Data["json"] = object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
|
||||
c.SetTokenErrorHttpStatus()
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
@ -249,10 +258,10 @@ func (c *ApiController) RefreshToken() {
|
||||
// @router /login/oauth/logout [get]
|
||||
func (c *ApiController) TokenLogout() {
|
||||
token := c.Input().Get("id_token_hint")
|
||||
flag, application := object.DeleteTokenByAceessToken(token)
|
||||
flag, application := object.DeleteTokenByAccessToken(token)
|
||||
redirectUri := c.Input().Get("post_logout_redirect_uri")
|
||||
state := c.Input().Get("state")
|
||||
if application != nil && object.CheckRedirectUriValid(application, redirectUri) {
|
||||
if application != nil && application.IsRedirectUriValid(redirectUri) {
|
||||
c.Ctx.Redirect(http.StatusFound, redirectUri+"?state="+state)
|
||||
return
|
||||
}
|
||||
@ -263,13 +272,16 @@ func (c *ApiController) TokenLogout() {
|
||||
// IntrospectToken
|
||||
// @Title IntrospectToken
|
||||
// @Description The introspection endpoint is an OAuth 2.0 endpoint that takes a
|
||||
// parameter representing an OAuth 2.0 token and returns a JSON document
|
||||
// representing the meta information surrounding the
|
||||
// token, including whether this token is currently active.
|
||||
// This endpoint only support Basic Authorization.
|
||||
// parameter representing an OAuth 2.0 token and returns a JSON document
|
||||
// representing the meta information surrounding the
|
||||
// token, including whether this token is currently active.
|
||||
// This endpoint only support Basic Authorization.
|
||||
//
|
||||
// @Param token formData string true "access_token's value or refresh_token's value"
|
||||
// @Param token_type_hint formData string true "the token type access_token or refresh_token"
|
||||
// @Success 200 {object} object.IntrospectionResponse The Response object
|
||||
// @Success 400 {object} object.TokenError The Response object
|
||||
// @Success 401 {object} object.TokenError The Response object
|
||||
// @router /login/oauth/introspect [post]
|
||||
func (c *ApiController) IntrospectToken() {
|
||||
tokenValue := c.Input().Get("token")
|
||||
@ -278,13 +290,22 @@ func (c *ApiController) IntrospectToken() {
|
||||
clientId = c.Input().Get("client_id")
|
||||
clientSecret = c.Input().Get("client_secret")
|
||||
if clientId == "" || clientSecret == "" {
|
||||
c.ResponseError("empty clientId or clientSecret")
|
||||
c.ResponseError(c.T("token:Empty clientId or clientSecret"))
|
||||
c.Data["json"] = &object.TokenError{
|
||||
Error: object.InvalidRequest,
|
||||
}
|
||||
c.SetTokenErrorHttpStatus()
|
||||
c.ServeJSON()
|
||||
return
|
||||
}
|
||||
}
|
||||
application := object.GetApplicationByClientId(clientId)
|
||||
if application == nil || application.ClientSecret != clientSecret {
|
||||
c.ResponseError("invalid application or wrong clientSecret")
|
||||
c.ResponseError(c.T("token:Invalid application or wrong clientSecret"))
|
||||
c.Data["json"] = &object.TokenError{
|
||||
Error: object.InvalidClient,
|
||||
}
|
||||
c.SetTokenErrorHttpStatus()
|
||||
return
|
||||
}
|
||||
token := object.GetTokenByTokenAndApplication(tokenValue, application.Name)
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -80,19 +80,27 @@ func (c *ApiController) GetUsers() {
|
||||
// @Title GetUser
|
||||
// @Tag User API
|
||||
// @Description get user
|
||||
// @Param id query string true "The id of the user"
|
||||
// @Param id query string true "The id of the user"
|
||||
// @Param owner query string false "The owner of the user"
|
||||
// @Param email query string false "The email of the user"
|
||||
// @Param phone query string false "The phone of the user"
|
||||
// @Success 200 {object} object.User The Response object
|
||||
// @router /get-user [get]
|
||||
func (c *ApiController) GetUser() {
|
||||
id := c.Input().Get("id")
|
||||
owner := c.Input().Get("owner")
|
||||
email := c.Input().Get("email")
|
||||
userOwner, _ := util.GetOwnerAndNameFromId(id)
|
||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", userOwner))
|
||||
phone := c.Input().Get("phone")
|
||||
userId := c.Input().Get("userId")
|
||||
|
||||
owner := c.Input().Get("owner")
|
||||
if owner == "" {
|
||||
owner, _ = util.GetOwnerAndNameFromId(id)
|
||||
}
|
||||
|
||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", owner))
|
||||
if !organization.IsProfilePublic {
|
||||
requestUserId := c.GetSessionUsername()
|
||||
hasPermission, err := object.CheckUserPermission(requestUserId, id, false)
|
||||
hasPermission, err := object.CheckUserPermission(requestUserId, id, owner, false, c.GetAcceptLanguage())
|
||||
if !hasPermission {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@ -100,12 +108,19 @@ func (c *ApiController) GetUser() {
|
||||
}
|
||||
|
||||
var user *object.User
|
||||
if email == "" {
|
||||
user = object.GetUser(id)
|
||||
} else {
|
||||
switch {
|
||||
case email != "":
|
||||
user = object.GetUserByEmail(owner, email)
|
||||
case phone != "":
|
||||
user = object.GetUserByPhone(owner, phone)
|
||||
case userId != "":
|
||||
user = object.GetUserByUserId(owner, userId)
|
||||
default:
|
||||
user = object.GetUser(id)
|
||||
}
|
||||
|
||||
object.ExtendUserWithRolesAndPermissions(user)
|
||||
|
||||
c.Data["json"] = object.GetMaskedUser(user)
|
||||
c.ServeJSON()
|
||||
}
|
||||
@ -129,11 +144,12 @@ func (c *ApiController) UpdateUser() {
|
||||
var user object.User
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if user.DisplayName == "" {
|
||||
c.ResponseError("Display name cannot be empty")
|
||||
c.ResponseError(c.T("user:Display name cannot be empty"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -163,7 +179,20 @@ func (c *ApiController) AddUser() {
|
||||
var user object.User
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
count := object.GetUserCount("", "", "")
|
||||
if err := checkQuotaForUser(count); err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
msg := object.CheckUsername(user.Name, c.GetAcceptLanguage())
|
||||
if msg != "" {
|
||||
c.ResponseError(msg)
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddUser(&user))
|
||||
@ -181,7 +210,8 @@ func (c *ApiController) DeleteUser() {
|
||||
var user object.User
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteUser(&user))
|
||||
@ -200,12 +230,13 @@ func (c *ApiController) GetEmailAndPhone() {
|
||||
var form RequestForm
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &form)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
user := object.GetUserByFields(form.Organization, form.Username)
|
||||
if user == nil {
|
||||
c.ResponseError(fmt.Sprintf("The user: %s/%s doesn't exist", form.Organization, form.Username))
|
||||
c.ResponseError(fmt.Sprintf(c.T("user:The user: %s/%s doesn't exist"), form.Organization, form.Username))
|
||||
return
|
||||
}
|
||||
|
||||
@ -246,7 +277,7 @@ func (c *ApiController) SetPassword() {
|
||||
requestUserId := c.GetSessionUsername()
|
||||
userId := fmt.Sprintf("%s/%s", userOwner, userName)
|
||||
|
||||
hasPermission, err := object.CheckUserPermission(requestUserId, userId, true)
|
||||
hasPermission, err := object.CheckUserPermission(requestUserId, userId, userOwner, true, c.GetAcceptLanguage())
|
||||
if !hasPermission {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@ -255,7 +286,7 @@ func (c *ApiController) SetPassword() {
|
||||
targetUser := object.GetUser(userId)
|
||||
|
||||
if oldPassword != "" {
|
||||
msg := object.CheckPassword(targetUser, oldPassword)
|
||||
msg := object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
|
||||
if msg != "" {
|
||||
c.ResponseError(msg)
|
||||
return
|
||||
@ -263,12 +294,12 @@ func (c *ApiController) SetPassword() {
|
||||
}
|
||||
|
||||
if strings.Contains(newPassword, " ") {
|
||||
c.ResponseError("New password cannot contain blank space.")
|
||||
c.ResponseError(c.T("user:New password cannot contain blank space."))
|
||||
return
|
||||
}
|
||||
|
||||
if len(newPassword) <= 5 {
|
||||
c.ResponseError("New password must have at least 6 characters")
|
||||
c.ResponseError(c.T("user:New password must have at least 6 characters"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -278,6 +309,7 @@ func (c *ApiController) SetPassword() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// CheckUserPassword
|
||||
// @Title CheckUserPassword
|
||||
// @router /check-user-password [post]
|
||||
// @Tag User API
|
||||
@ -285,10 +317,11 @@ func (c *ApiController) CheckUserPassword() {
|
||||
var user object.User
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
_, msg := object.CheckUserPassword(user.Owner, user.Name, user.Password)
|
||||
_, msg := object.CheckUserPassword(user.Owner, user.Name, user.Password, c.GetAcceptLanguage())
|
||||
if msg == "" {
|
||||
c.ResponseOk()
|
||||
} else {
|
||||
|
@ -24,17 +24,18 @@ import (
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
func saveFile(path string, file *multipart.File) {
|
||||
func saveFile(path string, file *multipart.File) (err error) {
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
_, err = io.Copy(f, *file)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ApiController) UploadUsers() {
|
||||
@ -43,18 +44,23 @@ func (c *ApiController) UploadUsers() {
|
||||
|
||||
file, header, err := c.Ctx.Request.FormFile("file")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
fileId := fmt.Sprintf("%s_%s_%s", owner, user, util.RemoveExt(header.Filename))
|
||||
|
||||
path := util.GetUploadXlsxPath(fileId)
|
||||
util.EnsureFileFolderExists(path)
|
||||
saveFile(path, &file)
|
||||
err = saveFile(path, &file)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected := object.UploadUsers(owner, fileId)
|
||||
if affected {
|
||||
c.ResponseOk()
|
||||
} else {
|
||||
c.ResponseError("Failed to import users")
|
||||
c.ResponseError(c.T("user_upload:Failed to import users"))
|
||||
}
|
||||
}
|
||||
|
@ -17,15 +17,16 @@ package controllers
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/i18n"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
// ResponseOk ...
|
||||
func (c *ApiController) ResponseOk(data ...interface{}) {
|
||||
resp := Response{Status: "ok"}
|
||||
// ResponseJsonData ...
|
||||
func (c *ApiController) ResponseJsonData(resp *Response, data ...interface{}) {
|
||||
switch len(data) {
|
||||
case 2:
|
||||
resp.Data2 = data[1]
|
||||
@ -37,45 +38,101 @@ func (c *ApiController) ResponseOk(data ...interface{}) {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// ResponseOk ...
|
||||
func (c *ApiController) ResponseOk(data ...interface{}) {
|
||||
resp := &Response{Status: "ok"}
|
||||
c.ResponseJsonData(resp, data...)
|
||||
}
|
||||
|
||||
// ResponseError ...
|
||||
func (c *ApiController) ResponseError(error string, data ...interface{}) {
|
||||
resp := Response{Status: "error", Msg: error}
|
||||
switch len(data) {
|
||||
case 2:
|
||||
resp.Data2 = data[1]
|
||||
fallthrough
|
||||
case 1:
|
||||
resp.Data = data[0]
|
||||
resp := &Response{Status: "error", Msg: error}
|
||||
c.ResponseJsonData(resp, data...)
|
||||
}
|
||||
|
||||
func (c *ApiController) T(error string) string {
|
||||
return i18n.Translate(c.GetAcceptLanguage(), error)
|
||||
}
|
||||
|
||||
// GetAcceptLanguage ...
|
||||
func (c *ApiController) GetAcceptLanguage() string {
|
||||
lang := c.Ctx.Request.Header.Get("Accept-Language")
|
||||
if lang == "" || !strings.Contains(conf.GetConfigString("languages"), lang[0:2]) {
|
||||
lang = "en"
|
||||
}
|
||||
return lang[0:2]
|
||||
}
|
||||
|
||||
// SetTokenErrorHttpStatus ...
|
||||
func (c *ApiController) SetTokenErrorHttpStatus() {
|
||||
_, ok := c.Data["json"].(*object.TokenError)
|
||||
if ok {
|
||||
if c.Data["json"].(*object.TokenError).Error == object.InvalidClient {
|
||||
c.Ctx.Output.SetStatus(401)
|
||||
c.Ctx.Output.Header("WWW-Authenticate", "Basic realm=\"OAuth2\"")
|
||||
} else {
|
||||
c.Ctx.Output.SetStatus(400)
|
||||
}
|
||||
}
|
||||
_, ok = c.Data["json"].(*object.TokenWrapper)
|
||||
if ok {
|
||||
c.Ctx.Output.SetStatus(200)
|
||||
}
|
||||
c.Data["json"] = resp
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// RequireSignedIn ...
|
||||
func (c *ApiController) RequireSignedIn() (string, bool) {
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError("Please sign in first")
|
||||
c.ResponseError(c.T("util:Please login first"), "Please login first")
|
||||
return "", false
|
||||
}
|
||||
return userId, true
|
||||
}
|
||||
|
||||
func getInitScore() int {
|
||||
score, err := strconv.Atoi(conf.GetConfigString("initScore"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
// RequireSignedInUser ...
|
||||
func (c *ApiController) RequireSignedInUser() (*object.User, bool) {
|
||||
userId, ok := c.RequireSignedIn()
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return score
|
||||
user := object.GetUser(userId)
|
||||
if user == nil {
|
||||
c.ClearUserSession()
|
||||
c.ResponseError(fmt.Sprintf(c.T("util:The user: %s doesn't exist"), userId))
|
||||
return nil, false
|
||||
}
|
||||
return user, true
|
||||
}
|
||||
|
||||
// RequireAdmin ...
|
||||
func (c *ApiController) RequireAdmin() (string, bool) {
|
||||
user, ok := c.RequireSignedInUser()
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
|
||||
if user.Owner == "built-in" {
|
||||
return "", true
|
||||
}
|
||||
return user.Owner, true
|
||||
}
|
||||
|
||||
func getInitScore(organization *object.Organization) (int, error) {
|
||||
if organization != nil {
|
||||
return organization.InitScore, nil
|
||||
} else {
|
||||
return strconv.Atoi(conf.GetConfigString("initScore"))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, *object.User, bool) {
|
||||
providerName := c.Input().Get("provider")
|
||||
if providerName != "" {
|
||||
provider := object.GetProvider(util.GetId(providerName))
|
||||
provider := object.GetProvider(util.GetId("admin", providerName))
|
||||
if provider == nil {
|
||||
c.ResponseError(fmt.Sprintf("The provider: %s is not found", providerName))
|
||||
c.ResponseError(c.T("util:The provider: %s is not found"), providerName)
|
||||
return nil, nil, false
|
||||
}
|
||||
return provider, nil, true
|
||||
@ -88,15 +145,59 @@ func (c *ApiController) GetProviderFromContext(category string) (*object.Provide
|
||||
|
||||
application, user := object.GetApplicationByUserId(userId)
|
||||
if application == nil {
|
||||
c.ResponseError(fmt.Sprintf("No application is found for userId: \"%s\"", userId))
|
||||
c.ResponseError(fmt.Sprintf(c.T("util:No application is found for userId: %s"), userId))
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
provider := application.GetProviderByCategory(category)
|
||||
if provider == nil {
|
||||
c.ResponseError(fmt.Sprintf("No provider for category: \"%s\" is found for application: %s", category, application.Name))
|
||||
c.ResponseError(fmt.Sprintf(c.T("util:No provider for category: %s is found for application: %s"), category, application.Name))
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
return provider, user, true
|
||||
}
|
||||
|
||||
func checkQuotaForApplication(count int) error {
|
||||
quota := conf.GetConfigQuota().Application
|
||||
if quota == -1 {
|
||||
return nil
|
||||
}
|
||||
if count >= quota {
|
||||
return fmt.Errorf("application quota is exceeded")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkQuotaForOrganization(count int) error {
|
||||
quota := conf.GetConfigQuota().Organization
|
||||
if quota == -1 {
|
||||
return nil
|
||||
}
|
||||
if count >= quota {
|
||||
return fmt.Errorf("organization quota is exceeded")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkQuotaForProvider(count int) error {
|
||||
quota := conf.GetConfigQuota().Provider
|
||||
if quota == -1 {
|
||||
return nil
|
||||
}
|
||||
if count >= quota {
|
||||
return fmt.Errorf("provider quota is exceeded")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkQuotaForUser(count int) error {
|
||||
quota := conf.GetConfigQuota().User
|
||||
if quota == -1 {
|
||||
return nil
|
||||
}
|
||||
if count >= quota {
|
||||
return fmt.Errorf("user quota is exceeded")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -42,15 +42,32 @@ func (c *ApiController) getCurrentUser() *object.User {
|
||||
func (c *ApiController) SendVerificationCode() {
|
||||
destType := c.Ctx.Request.Form.Get("type")
|
||||
dest := c.Ctx.Request.Form.Get("dest")
|
||||
orgId := c.Ctx.Request.Form.Get("organizationId")
|
||||
checkType := c.Ctx.Request.Form.Get("checkType")
|
||||
checkId := c.Ctx.Request.Form.Get("checkId")
|
||||
checkKey := c.Ctx.Request.Form.Get("checkKey")
|
||||
checkUser := c.Ctx.Request.Form.Get("checkUser")
|
||||
applicationId := c.Ctx.Request.Form.Get("applicationId")
|
||||
method := c.Ctx.Request.Form.Get("method")
|
||||
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
||||
|
||||
if len(destType) == 0 || len(dest) == 0 || len(orgId) == 0 || !strings.Contains(orgId, "/") || len(checkType) == 0 {
|
||||
c.ResponseError("Missing parameter.")
|
||||
if destType == "" {
|
||||
c.ResponseError(c.T("verification:Missing parameter") + ": type.")
|
||||
return
|
||||
}
|
||||
if dest == "" {
|
||||
c.ResponseError(c.T("verification:Missing parameter") + ": dest.")
|
||||
return
|
||||
}
|
||||
if applicationId == "" {
|
||||
c.ResponseError(c.T("verification:Missing parameter") + ": applicationId.")
|
||||
return
|
||||
}
|
||||
if !strings.Contains(applicationId, "/") {
|
||||
c.ResponseError(c.T("verification:Wrong parameter") + ": applicationId.")
|
||||
return
|
||||
}
|
||||
if checkType == "" {
|
||||
c.ResponseError(c.T("verification:Missing parameter") + ": checkType.")
|
||||
return
|
||||
}
|
||||
|
||||
@ -58,7 +75,7 @@ func (c *ApiController) SendVerificationCode() {
|
||||
|
||||
if captchaProvider != nil {
|
||||
if checkKey == "" {
|
||||
c.ResponseError("Missing parameter: checkKey.")
|
||||
c.ResponseError(c.T("verification:Missing parameter") + ": checkKey.")
|
||||
return
|
||||
}
|
||||
isHuman, err := captchaProvider.VerifyCaptcha(checkKey, checkId)
|
||||
@ -68,24 +85,28 @@ func (c *ApiController) SendVerificationCode() {
|
||||
}
|
||||
|
||||
if !isHuman {
|
||||
c.ResponseError("Turing test failed.")
|
||||
c.ResponseError(c.T("verification:Turing test failed."))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
user := c.getCurrentUser()
|
||||
organization := object.GetOrganization(orgId)
|
||||
application := object.GetApplicationByOrganizationName(organization.Name)
|
||||
|
||||
if checkUser == "true" && user == nil && object.GetUserByFields(organization.Name, dest) == nil {
|
||||
c.ResponseError("Please login first")
|
||||
application := object.GetApplication(applicationId)
|
||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", application.Owner, application.Organization))
|
||||
if organization == nil {
|
||||
c.ResponseError(c.T("verification:Organization does not exist"))
|
||||
return
|
||||
}
|
||||
|
||||
sendResp := errors.New("Invalid dest type")
|
||||
if checkUser == "true" && user == nil && object.GetUserByFields(organization.Name, dest) == nil {
|
||||
c.ResponseError(c.T("verification:Please login first"))
|
||||
return
|
||||
}
|
||||
|
||||
sendResp := errors.New("invalid dest type")
|
||||
|
||||
if user == nil && checkUser != "" && checkUser != "true" {
|
||||
_, name := util.GetOwnerAndNameFromId(orgId)
|
||||
name := application.Organization
|
||||
user = object.GetUser(fmt.Sprintf("%s/%s", name, checkUser))
|
||||
}
|
||||
switch destType {
|
||||
@ -94,7 +115,13 @@ func (c *ApiController) SendVerificationCode() {
|
||||
dest = user.Email
|
||||
}
|
||||
if !util.IsEmailValid(dest) {
|
||||
c.ResponseError("Invalid Email address")
|
||||
c.ResponseError(c.T("verification:Email is invalid"))
|
||||
return
|
||||
}
|
||||
|
||||
userByEmail := object.GetUserByEmail(organization.Name, dest)
|
||||
if userByEmail == nil && method != "signup" && method != "reset" {
|
||||
c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -105,16 +132,17 @@ func (c *ApiController) SendVerificationCode() {
|
||||
dest = user.Phone
|
||||
}
|
||||
if !util.IsPhoneCnValid(dest) {
|
||||
c.ResponseError("Invalid phone number")
|
||||
return
|
||||
}
|
||||
org := object.GetOrganization(orgId)
|
||||
if org == nil {
|
||||
c.ResponseError("Missing parameter.")
|
||||
c.ResponseError(c.T("verification:Phone number is invalid"))
|
||||
return
|
||||
}
|
||||
|
||||
dest = fmt.Sprintf("+%s%s", org.PhonePrefix, dest)
|
||||
userByPhone := object.GetUserByPhone(organization.Name, dest)
|
||||
if userByPhone == nil && method != "signup" && method != "reset" {
|
||||
c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
|
||||
return
|
||||
}
|
||||
|
||||
dest = fmt.Sprintf("+%s%s", organization.PhonePrefix, dest)
|
||||
provider := application.GetSmsProvider()
|
||||
sendResp = object.SendVerificationCodeToPhone(organization, user, provider, remoteAddr, dest)
|
||||
}
|
||||
@ -133,35 +161,51 @@ func (c *ApiController) SendVerificationCode() {
|
||||
// @Title ResetEmailOrPhone
|
||||
// @router /api/reset-email-or-phone [post]
|
||||
func (c *ApiController) ResetEmailOrPhone() {
|
||||
userId, ok := c.RequireSignedIn()
|
||||
user, ok := c.RequireSignedInUser()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
user := object.GetUser(userId)
|
||||
if user == nil {
|
||||
c.ResponseError(fmt.Sprintf("The user: %s doesn't exist", userId))
|
||||
return
|
||||
}
|
||||
|
||||
destType := c.Ctx.Request.Form.Get("type")
|
||||
dest := c.Ctx.Request.Form.Get("dest")
|
||||
code := c.Ctx.Request.Form.Get("code")
|
||||
if len(dest) == 0 || len(code) == 0 || len(destType) == 0 {
|
||||
c.ResponseError("Missing parameter.")
|
||||
c.ResponseError(c.T("verification:Missing parameter"))
|
||||
return
|
||||
}
|
||||
|
||||
checkDest := dest
|
||||
org := object.GetOrganizationByUser(user)
|
||||
if destType == "phone" {
|
||||
org := object.GetOrganizationByUser(user)
|
||||
phoneItem := object.GetAccountItemByName("Phone", org)
|
||||
if phoneItem == nil {
|
||||
c.ResponseError(c.T("verification:Unable to get the phone modify rule."))
|
||||
return
|
||||
}
|
||||
|
||||
if pass, errMsg := object.CheckAccountItemModifyRule(phoneItem, user, c.GetAcceptLanguage()); !pass {
|
||||
c.ResponseError(errMsg)
|
||||
return
|
||||
}
|
||||
|
||||
phonePrefix := "86"
|
||||
if org != nil && org.PhonePrefix != "" {
|
||||
phonePrefix = org.PhonePrefix
|
||||
}
|
||||
checkDest = fmt.Sprintf("+%s%s", phonePrefix, dest)
|
||||
} else if destType == "email" {
|
||||
emailItem := object.GetAccountItemByName("Email", org)
|
||||
if emailItem == nil {
|
||||
c.ResponseError(c.T("verification:Unable to get the email modify rule."))
|
||||
return
|
||||
}
|
||||
|
||||
if pass, errMsg := object.CheckAccountItemModifyRule(emailItem, user, c.GetAcceptLanguage()); !pass {
|
||||
c.ResponseError(errMsg)
|
||||
return
|
||||
}
|
||||
}
|
||||
if ret := object.CheckVerificationCode(checkDest, code); len(ret) != 0 {
|
||||
if ret := object.CheckVerificationCode(checkDest, code, c.GetAcceptLanguage()); len(ret) != 0 {
|
||||
c.ResponseError(ret)
|
||||
return
|
||||
}
|
||||
@ -174,7 +218,7 @@ func (c *ApiController) ResetEmailOrPhone() {
|
||||
user.Phone = dest
|
||||
object.SetUserField(user, "phone", user.Phone)
|
||||
default:
|
||||
c.ResponseError("Unknown type.")
|
||||
c.ResponseError(c.T("verification:Unknown type"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -193,17 +237,17 @@ func (c *ApiController) VerifyCaptcha() {
|
||||
captchaToken := c.Ctx.Request.Form.Get("captchaToken")
|
||||
clientSecret := c.Ctx.Request.Form.Get("clientSecret")
|
||||
if captchaToken == "" {
|
||||
c.ResponseError("Missing parameter: captchaToken.")
|
||||
c.ResponseError(c.T("verification:Missing parameter") + ": captchaToken.")
|
||||
return
|
||||
}
|
||||
if clientSecret == "" {
|
||||
c.ResponseError("Missing parameter: clientSecret.")
|
||||
c.ResponseError(c.T("verification:Missing parameter") + ": clientSecret.")
|
||||
return
|
||||
}
|
||||
|
||||
provider := captcha.GetCaptchaProvider(captchaType)
|
||||
if provider == nil {
|
||||
c.ResponseError("Invalid captcha provider.")
|
||||
c.ResponseError(c.T("verification:Invalid captcha provider."))
|
||||
return
|
||||
}
|
||||
|
||||
|
155
controllers/webauthn.go
Normal file
155
controllers/webauthn.go
Normal file
@ -0,0 +1,155 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/duo-labs/webauthn/protocol"
|
||||
"github.com/duo-labs/webauthn/webauthn"
|
||||
)
|
||||
|
||||
// WebAuthnSignupBegin
|
||||
// @Title WebAuthnSignupBegin
|
||||
// @Tag User API
|
||||
// @Description WebAuthn Registration Flow 1st stage
|
||||
// @Success 200 {object} protocol.CredentialCreation The CredentialCreationOptions object
|
||||
// @router /webauthn/signup/begin [get]
|
||||
func (c *ApiController) WebAuthnSignupBegin() {
|
||||
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||
user := c.getCurrentUser()
|
||||
if user == nil {
|
||||
c.ResponseError(c.T("webauthn:Please login first"))
|
||||
return
|
||||
}
|
||||
|
||||
registerOptions := func(credCreationOpts *protocol.PublicKeyCredentialCreationOptions) {
|
||||
credCreationOpts.CredentialExcludeList = user.CredentialExcludeList()
|
||||
}
|
||||
options, sessionData, err := webauthnObj.BeginRegistration(
|
||||
user,
|
||||
registerOptions,
|
||||
)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.SetSession("registration", *sessionData)
|
||||
c.Data["json"] = options
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// WebAuthnSignupFinish
|
||||
// @Title WebAuthnSignupFinish
|
||||
// @Tag User API
|
||||
// @Description WebAuthn Registration Flow 2nd stage
|
||||
// @Param body body protocol.CredentialCreationResponse true "authenticator attestation Response"
|
||||
// @Success 200 {object} Response "The Response object"
|
||||
// @router /webauthn/signup/finish [post]
|
||||
func (c *ApiController) WebAuthnSignupFinish() {
|
||||
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||
user := c.getCurrentUser()
|
||||
if user == nil {
|
||||
c.ResponseError(c.T("webauthn:Please login first"))
|
||||
return
|
||||
}
|
||||
sessionObj := c.GetSession("registration")
|
||||
sessionData, ok := sessionObj.(webauthn.SessionData)
|
||||
if !ok {
|
||||
c.ResponseError(c.T("webauthn:Please call WebAuthnSigninBegin first"))
|
||||
return
|
||||
}
|
||||
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
||||
|
||||
credential, err := webauthnObj.FinishRegistration(user, sessionData, c.Ctx.Request)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
isGlobalAdmin := c.IsGlobalAdmin()
|
||||
user.AddCredentials(*credential, isGlobalAdmin)
|
||||
c.ResponseOk()
|
||||
}
|
||||
|
||||
// WebAuthnSigninBegin
|
||||
// @Title WebAuthnSigninBegin
|
||||
// @Tag Login API
|
||||
// @Description WebAuthn Login Flow 1st stage
|
||||
// @Param owner query string true "owner"
|
||||
// @Param name query string true "name"
|
||||
// @Success 200 {object} protocol.CredentialAssertion The CredentialAssertion object
|
||||
// @router /webauthn/signin/begin [get]
|
||||
func (c *ApiController) WebAuthnSigninBegin() {
|
||||
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||
userOwner := c.Input().Get("owner")
|
||||
userName := c.Input().Get("name")
|
||||
user := object.GetUserByFields(userOwner, userName)
|
||||
if user == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("webauthn:The user: %s/%s doesn't exist"), userOwner, userName))
|
||||
return
|
||||
}
|
||||
if len(user.WebauthnCredentials) == 0 {
|
||||
c.ResponseError(c.T("webauthn:Found no credentials for this user"))
|
||||
return
|
||||
}
|
||||
|
||||
options, sessionData, err := webauthnObj.BeginLogin(user)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.SetSession("authentication", *sessionData)
|
||||
c.Data["json"] = options
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// WebAuthnSigninFinish
|
||||
// @Title WebAuthnSigninBegin
|
||||
// @Tag Login API
|
||||
// @Description WebAuthn Login Flow 2nd stage
|
||||
// @Param body body protocol.CredentialAssertionResponse true "authenticator assertion Response"
|
||||
// @Success 200 {object} Response "The Response object"
|
||||
// @router /webauthn/signin/finish [post]
|
||||
func (c *ApiController) WebAuthnSigninFinish() {
|
||||
responseType := c.Input().Get("responseType")
|
||||
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||
sessionObj := c.GetSession("authentication")
|
||||
sessionData, ok := sessionObj.(webauthn.SessionData)
|
||||
if !ok {
|
||||
c.ResponseError(c.T("webauthn:Please call WebAuthnSigninBegin first"))
|
||||
return
|
||||
}
|
||||
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
||||
userId := string(sessionData.UserID)
|
||||
user := object.GetUser(userId)
|
||||
_, err := webauthnObj.FinishLogin(user, sessionData, c.Ctx.Request)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.SetSessionUsername(userId)
|
||||
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
|
||||
|
||||
application := object.GetApplicationByUser(user)
|
||||
var form RequestForm
|
||||
form.Type = responseType
|
||||
resp := c.HandleLoggedIn(application, user, &form)
|
||||
c.Data["json"] = resp
|
||||
c.ServeJSON()
|
||||
}
|
@ -17,7 +17,7 @@ package controllers
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/astaxie/beego/utils/pagination"
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@ -48,6 +48,7 @@ func (c *ApiController) GetWebhooks() {
|
||||
}
|
||||
}
|
||||
|
||||
// GetWebhook
|
||||
// @Title GetWebhook
|
||||
// @Tag Webhook API
|
||||
// @Description get webhook
|
||||
@ -61,6 +62,7 @@ func (c *ApiController) GetWebhook() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdateWebhook
|
||||
// @Title UpdateWebhook
|
||||
// @Tag Webhook API
|
||||
// @Description update webhook
|
||||
@ -74,13 +76,15 @@ func (c *ApiController) UpdateWebhook() {
|
||||
var webhook object.Webhook
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &webhook)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateWebhook(id, &webhook))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// AddWebhook
|
||||
// @Title AddWebhook
|
||||
// @Tag Webhook API
|
||||
// @Description add webhook
|
||||
@ -91,13 +95,15 @@ func (c *ApiController) AddWebhook() {
|
||||
var webhook object.Webhook
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &webhook)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddWebhook(&webhook))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteWebhook
|
||||
// @Title DeleteWebhook
|
||||
// @Tag Webhook API
|
||||
// @Description delete webhook
|
||||
@ -108,7 +114,8 @@ func (c *ApiController) DeleteWebhook() {
|
||||
var webhook object.Webhook
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &webhook)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteWebhook(&webhook))
|
||||
|
@ -24,7 +24,6 @@ func NewArgon2idCredManager() *Argon2idCredManager {
|
||||
}
|
||||
|
||||
func (cm *Argon2idCredManager) GetHashedPassword(password string, userSalt string, organizationSalt string) string {
|
||||
|
||||
hash, err := argon2id.CreateHash(password, argon2id.DefaultParams)
|
||||
if err != nil {
|
||||
return ""
|
||||
|
@ -17,6 +17,7 @@ package cred
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
)
|
||||
|
||||
@ -36,4 +37,4 @@ func (cm *Pbkdf2SaltCredManager) GetHashedPassword(password string, userSalt str
|
||||
|
||||
func (cm *Pbkdf2SaltCredManager) IsPasswordCorrect(plainPwd string, hashedPwd string, userSalt string, organizationSalt string) bool {
|
||||
return hashedPwd == cm.GetHashedPassword(plainPwd, userSalt, organizationSalt)
|
||||
}
|
||||
}
|
||||
|
10
crowdin.yml
Normal file
10
crowdin.yml
Normal file
@ -0,0 +1,10 @@
|
||||
project_id: '491513'
|
||||
api_token_env: 'CROWDIN_PERSONAL_TOKEN'
|
||||
preserve_hierarchy: true
|
||||
files: [
|
||||
# JSON translation files
|
||||
{
|
||||
source: '/i18n/locales/en/data.json',
|
||||
translation: '/i18n/locales/%two_letters_code%/data.json',
|
||||
},
|
||||
]
|
70
deployment/deploy.go
Normal file
70
deployment/deploy.go
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package deployment
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/storage"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/casdoor/oss"
|
||||
)
|
||||
|
||||
func deployStaticFiles(provider *object.Provider) {
|
||||
storageProvider := storage.GetStorageProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.RegionId, provider.Bucket, provider.Endpoint)
|
||||
if storageProvider == nil {
|
||||
panic(fmt.Sprintf("the provider type: %s is not supported", provider.Type))
|
||||
}
|
||||
|
||||
uploadFolder(storageProvider, "js")
|
||||
uploadFolder(storageProvider, "css")
|
||||
updateHtml(provider.Domain)
|
||||
}
|
||||
|
||||
func uploadFolder(storageProvider oss.StorageInterface, folder string) {
|
||||
path := fmt.Sprintf("../web/build/static/%s/", folder)
|
||||
filenames := util.ListFiles(path)
|
||||
|
||||
for _, filename := range filenames {
|
||||
if !strings.HasSuffix(filename, folder) {
|
||||
continue
|
||||
}
|
||||
|
||||
file, err := os.Open(path + filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
objectKey := fmt.Sprintf("static/%s/%s", folder, filename)
|
||||
_, err = storageProvider.Put(objectKey, file)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Uploaded [%s] to [%s]\n", path, objectKey)
|
||||
}
|
||||
}
|
||||
|
||||
func updateHtml(domainPath string) {
|
||||
htmlPath := "../web/build/index.html"
|
||||
html := util.ReadStringFromPath(htmlPath)
|
||||
html = strings.Replace(html, "\"/static/", fmt.Sprintf("\"%s", domainPath), -1)
|
||||
util.WriteStringToPath(html, htmlPath)
|
||||
|
||||
fmt.Printf("Updated HTML to [%s]\n", html)
|
||||
}
|
30
deployment/deploy_test.go
Normal file
30
deployment/deploy_test.go
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !skipCi
|
||||
// +build !skipCi
|
||||
|
||||
package deployment
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
func TestDeployStaticFiles(t *testing.T) {
|
||||
provider := object.GetProvider(util.GetId("admin", "provider_storage_aliyun_oss"))
|
||||
deployStaticFiles(provider)
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
#!/bin/bash
|
||||
if [ "${MYSQL_ROOT_PASSWORD}" = "" ] ;then MYSQL_ROOT_PASSWORD=123456 ;fi
|
||||
|
||||
service mariadb start
|
||||
|
||||
mysqladmin -u root password ${MYSQL_ROOT_PASSWORD}
|
||||
|
||||
exec /app/server --createDatabase=true
|
||||
exec /server --createDatabase=true
|
||||
|
32
go.mod
32
go.mod
@ -5,41 +5,53 @@ go 1.16
|
||||
require (
|
||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b
|
||||
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
|
||||
github.com/astaxie/beego v1.12.3
|
||||
github.com/aws/aws-sdk-go v1.44.4
|
||||
github.com/beego/beego v1.12.11
|
||||
github.com/beevik/etree v1.1.0
|
||||
github.com/casbin/casbin/v2 v2.30.1
|
||||
github.com/casbin/xorm-adapter/v2 v2.5.1
|
||||
github.com/casdoor/go-sms-sender v0.2.0
|
||||
github.com/casdoor/goth v1.69.0-FIX1
|
||||
github.com/casbin/xorm-adapter/v3 v3.0.1
|
||||
github.com/casdoor/go-sms-sender v0.5.1
|
||||
github.com/casdoor/oss v1.2.0
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc
|
||||
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b
|
||||
github.com/forestmgy/ldapserver v1.1.0
|
||||
github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df
|
||||
github.com/go-ldap/ldap/v3 v3.3.0
|
||||
github.com/go-pay/gopay v1.5.72
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/go-cmp v0.5.8 // indirect
|
||||
github.com/google/uuid v1.2.0
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||
github.com/lestrrat-go/jwx v0.9.0
|
||||
github.com/lestrrat-go/jwx v1.2.21
|
||||
github.com/lib/pq v1.8.0
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
|
||||
github.com/markbates/goth v1.75.2
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||
github.com/qiangmzsx/string-adapter/v2 v2.1.0
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/russellhaering/gosaml2 v0.6.0
|
||||
github.com/russellhaering/goxmldsig v1.1.1
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/tealeg/xlsx v1.0.5
|
||||
github.com/thanhpk/randstr v1.0.4
|
||||
golang.org/x/crypto v0.0.0-20220208233918-bba287dce954
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0
|
||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||
xorm.io/builder v0.3.12 // indirect
|
||||
xorm.io/core v0.7.2
|
||||
xorm.io/xorm v1.0.4
|
||||
xorm.io/xorm v1.0.5
|
||||
)
|
||||
|
134
go.sum
134
go.sum
@ -74,13 +74,13 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.61.1075/go.mod h1:pUKYbK5JQ+1Dfxk80P0q
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/astaxie/beego v1.12.3 h1:SAQkdD2ePye+v8Gn1r4X6IKZM1wd28EyUOVQ3PDSOOQ=
|
||||
github.com/astaxie/beego v1.12.3/go.mod h1:p3qIm0Ryx7zeBHLljmd7omloyca1s4yu1a8kM1FkpIA=
|
||||
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
|
||||
github.com/aws/aws-sdk-go v1.44.4 h1:ePN0CVJMdiz2vYUcJH96eyxRrtKGSDMgyhP6rah2OgE=
|
||||
github.com/aws/aws-sdk-go v1.44.4/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
|
||||
github.com/beego/beego v1.12.11 h1:MWKcnpavb7iAIS0m6uuEq6pHKkYvGNw/5umIUKqL7jM=
|
||||
github.com/beego/beego v1.12.11/go.mod h1:QURFL1HldOcCZAxnc1cZ7wrplsYR5dKPHFjmk6WkLAs=
|
||||
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
|
||||
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
|
||||
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
|
||||
@ -96,12 +96,10 @@ github.com/casbin/casbin/v2 v2.1.0/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n
|
||||
github.com/casbin/casbin/v2 v2.28.3/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
||||
github.com/casbin/casbin/v2 v2.30.1 h1:P5HWadDL7olwUXNdcuKUBk+x75Y2eitFxYTcLNKeKF0=
|
||||
github.com/casbin/casbin/v2 v2.30.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
||||
github.com/casbin/xorm-adapter/v2 v2.5.1 h1:BkpIxRHKa0s3bSMx173PpuU7oTs+Zw7XmD0BIta0HGM=
|
||||
github.com/casbin/xorm-adapter/v2 v2.5.1/go.mod h1:AeH4dBKHC9/zYxzdPVHhPDzF8LYLqjDdb767CWJoV54=
|
||||
github.com/casdoor/go-sms-sender v0.2.0 h1:52bin4EBOPzOee64s9UK7jxd22FODvT9/+Y/Z+PSHpg=
|
||||
github.com/casdoor/go-sms-sender v0.2.0/go.mod h1:fsZsNnALvFIo+HFcE1U/oCQv4ZT42FdglXKMsEm3WSk=
|
||||
github.com/casdoor/goth v1.69.0-FIX1 h1:24Y3tfaJxWGJbxickGe3F9y2c8X1PgsQynhxGXV1f9Q=
|
||||
github.com/casdoor/goth v1.69.0-FIX1/go.mod h1:Om55nRo8CkeDkPSNBbzXW4G5uI28ZUkSk5S69dPek3s=
|
||||
github.com/casbin/xorm-adapter/v3 v3.0.1 h1:0l0zkYxo6cNuIdrBZgFxlje1TRvmheYa/zIp+sGPK58=
|
||||
github.com/casbin/xorm-adapter/v3 v3.0.1/go.mod h1:1BL7rHEDXrxO+vQdSo/ZaWKRivXl7YTos67GdMYcd20=
|
||||
github.com/casdoor/go-sms-sender v0.5.1 h1:1/Wp1OLkVAVY4lEGQhekSNetSAWhnPcxYPV7xpCZgC0=
|
||||
github.com/casdoor/go-sms-sender v0.5.1/go.mod h1:kBykbqwgRDXbXdMAIxmZKinVM1WjdqEbej5LAbUbcfI=
|
||||
github.com/casdoor/oss v1.2.0 h1:ozLAE+nnNdFQBWbzH8U9spzaO8h8NrB57lBcdyMUUQ8=
|
||||
github.com/casdoor/oss v1.2.0/go.mod h1:qii35VBuxnR/uEuYSKpS0aJ8htQFOcCVsZ4FHgHLuss=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
@ -111,11 +109,13 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7 h1:Puu1hUwfps3+1CUzYdAZXijuvLuRMirgiXdf3zsM2Ig=
|
||||
github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
|
||||
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
|
||||
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||
github.com/couchbase/go-couchbase v0.0.0-20201216133707-c04035124b17/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A=
|
||||
github.com/couchbase/gomemcached v0.1.2-0.20201224031647-c432ccf49f32/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
|
||||
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -123,7 +123,13 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f h1:q/DpyjJjZs94bziQ7YkBmIlpqbVP7yw179rnzoNVX1M=
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWWHQYQ3QU9bw9Y9OPNfxccGzfb41qjvVeXtY=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d h1:1iy2qD6JEhHKKhUOA9IWs7mjco7lnw2qx8FsRI2wirE=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b h1:L63RATZFZuFMXy6ixnKmv3eNAXwYQF6HW1vd4IYsQqQ=
|
||||
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b/go.mod h1:EYSpSkwoEcryMmQGfhol2IiB3IMN9IIIaNd/wcAQMGQ=
|
||||
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
|
||||
@ -132,9 +138,13 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/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/forestmgy/ldapserver v1.1.0 h1:gvil4nuLhqPEL8SugCkFhRyA0/lIvRdwZSqlrw63ll4=
|
||||
github.com/forestmgy/ldapserver v1.1.0/go.mod h1:1RZ8lox1QSY7rmbjdmy+sYQXY4Lp7SpGzpdE3+j3IyM=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ=
|
||||
github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
|
||||
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
@ -149,6 +159,8 @@ github.com/go-ldap/ldap/v3 v3.3.0 h1:lwx+SJpgOHd8tG6SumBQZXCmNX51zM8B1cfxJ5gv4tQ
|
||||
github.com/go-ldap/ldap/v3 v3.3.0/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-pay/gopay v1.5.72 h1:3zm64xMBhJBa8rXbm//q5UiGgOa4WO5XYEnU394N2Zw=
|
||||
github.com/go-pay/gopay v1.5.72/go.mod h1:0qOGIJuFW7PKDOjmecwKyW0mgsVImgwB9yPJj0ilpn8=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
@ -162,10 +174,16 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/goccy/go-json v0.9.6 h1:5/4CtRQdtsX0sal8fdVhTaiMN01Ri8BExZZ8iRmHQ6E=
|
||||
github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@ -177,8 +195,9 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
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.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@ -195,12 +214,15 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
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/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE=
|
||||
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
|
||||
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=
|
||||
@ -208,8 +230,9 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
@ -227,7 +250,6 @@ github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
@ -261,7 +283,6 @@ github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
|
||||
@ -280,14 +301,28 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/lestrrat-go/jwx v0.9.0 h1:Fnd0EWzTm0kFrBPzE/PEPp9nzllES5buMkksPMjEKpM=
|
||||
github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/YNA/UnBk=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
|
||||
github.com/lestrrat-go/blackmagic v1.0.0 h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4=
|
||||
github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
|
||||
github.com/lestrrat-go/httpcc v1.0.0 h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc=
|
||||
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
|
||||
github.com/lestrrat-go/iter v1.0.1 h1:q8faalr2dY6o8bV45uwrxq12bRa1ezKrB6oM9FUgN4A=
|
||||
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
|
||||
github.com/lestrrat-go/jwx v1.2.21 h1:n+yG95UMm5ZFsDdvsZmui+bqat4Cj/di4ys6XbgSlE8=
|
||||
github.com/lestrrat-go/jwx v1.2.21/go.mod h1:9cfxnOH7G1gN75CaJP2hKGcxFEx5sPh1abRIA/ZJVh4=
|
||||
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
|
||||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
|
||||
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 h1:wIONC+HMNRqmWBjuMxhatuSzHaljStc4gjDeKycxy0A=
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0=
|
||||
github.com/markbates/going v1.0.0 h1:DQw0ZP7NbNlFGcKbcE/IVSOAFzScxRtLpd0rLMzLhq0=
|
||||
github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA=
|
||||
github.com/markbates/goth v1.75.2 h1:C7KloBMMk50JyXaHhzfqWYLW6+bDcSVIvUGHXneLWro=
|
||||
github.com/markbates/goth v1.75.2/go.mod h1:X6xdNgpapSENS0O35iTBBcMHoJDQDfI9bJl+APCkYMc=
|
||||
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911 h1:erppMjjp69Rertg1zlgRbLJH1u+eCmRPxKjMZ5I8/Ro=
|
||||
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
|
||||
github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI=
|
||||
@ -298,6 +333,8 @@ github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJK
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
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=
|
||||
@ -318,7 +355,6 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
|
||||
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@ -363,28 +399,31 @@ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
|
||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
||||
github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
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 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
|
||||
@ -393,15 +432,26 @@ github.com/tencentcloud/tencentcloud-sdk-go v1.0.154 h1:THBgwGwUQtsw6L53cSSA2wwL
|
||||
github.com/tencentcloud/tencentcloud-sdk-go v1.0.154/go.mod h1:asUz5BPXxgoPGaRgZaVm1iGcUAuHyYUo1nXqKa83cvI=
|
||||
github.com/thanhpk/randstr v1.0.4 h1:IN78qu/bR+My+gHCvMEXhR/i5oriVHcTB/BJJIRTsNo=
|
||||
github.com/thanhpk/randstr v1.0.4/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U=
|
||||
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
|
||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
|
||||
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
||||
github.com/twilio/twilio-go v0.26.0 h1:wFW4oTe3/LKt6bvByP7eio8JsjtaLHjMQKOUEzQry7U=
|
||||
github.com/twilio/twilio-go v0.26.0/go.mod h1:lz62Hopu4vicpQ056H5TJ0JE4AP0rS3sQ35/ejmgOwE=
|
||||
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.19 h1:jJp+aJgK0e//rZ9I0K2Y7ufJwvuZRo/AQsYDynXMNgA=
|
||||
github.com/volcengine/volc-sdk-golang v1.0.19/go.mod h1:+GGi447k4p1I5PNdbpG2GLaF0Ui9vIInTojMM0IfSS4=
|
||||
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
||||
github.com/wendal/errors v0.0.0-20181209125328-7f31f4b264ec/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
@ -413,16 +463,19 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220208233918-bba287dce954 h1:BkypuErRT9A9I/iljuaG3/zdMjd/J6m8tKKJQtGfSdA=
|
||||
golang.org/x/crypto v0.0.0-20220208233918-bba287dce954/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -453,6 +506,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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=
|
||||
@ -485,8 +539,8 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
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-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
||||
@ -508,6 +562,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -521,7 +576,9 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -543,12 +600,17 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
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/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -607,10 +669,10 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
|
||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/tools v0.0.0-20200929161345-d7fc70abf50f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
@ -708,8 +770,8 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
|
||||
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.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.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/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
@ -723,8 +785,9 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/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.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
@ -735,10 +798,11 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI=
|
||||
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
|
||||
xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw=
|
||||
xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM=
|
||||
xorm.io/xorm v1.0.3/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
||||
xorm.io/xorm v1.0.4 h1:UBXA4I3NhiyjXfPqxXUkS2t5hMta9SSPATeMMaZg9oA=
|
||||
xorm.io/xorm v1.0.4/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
||||
xorm.io/xorm v1.0.5 h1:LRr5PfOUb4ODPR63YwbowkNDwcolT2LnkwP/TUaMaB0=
|
||||
xorm.io/xorm v1.0.5/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
||||
|
@ -83,7 +83,7 @@ func parseToData() *I18nData {
|
||||
|
||||
data := I18nData{}
|
||||
for _, word := range allWords {
|
||||
tokens := strings.Split(word, ":")
|
||||
tokens := strings.SplitN(word, ":", 2)
|
||||
namespace := tokens[0]
|
||||
key := tokens[1]
|
||||
|
||||
|
115
i18n/generate_backend.go
Normal file
115
i18n/generate_backend.go
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
var (
|
||||
reI18nBackendObject *regexp.Regexp
|
||||
re18nBackendController *regexp.Regexp
|
||||
)
|
||||
|
||||
func init() {
|
||||
reI18nBackendObject, _ = regexp.Compile("i18n.Translate\\((.*?)\"\\)")
|
||||
re18nBackendController, _ = regexp.Compile("c.T\\((.*?)\"\\)")
|
||||
}
|
||||
|
||||
func GetAllI18nStrings(fileContent string, path string) []string {
|
||||
res := []string{}
|
||||
if strings.Contains(path, "object") {
|
||||
matches := reI18nBackendObject.FindAllStringSubmatch(fileContent, -1)
|
||||
if matches == nil {
|
||||
return res
|
||||
}
|
||||
for _, match := range matches {
|
||||
match := strings.SplitN(match[1], ",", 2)
|
||||
res = append(res, match[1][2:])
|
||||
}
|
||||
} else {
|
||||
matches := re18nBackendController.FindAllStringSubmatch(fileContent, -1)
|
||||
if matches == nil {
|
||||
return res
|
||||
}
|
||||
for _, match := range matches {
|
||||
res = append(res, match[1][1:])
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func getAllGoFilePaths() []string {
|
||||
path := "../"
|
||||
|
||||
res := []string{}
|
||||
err := filepath.Walk(path,
|
||||
func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(info.Name(), ".go") {
|
||||
return nil
|
||||
}
|
||||
|
||||
res = append(res, path)
|
||||
// fmt.Println(path, info.Name())
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func getErrName(paths []string) map[string]string {
|
||||
ErrName := make(map[string]string)
|
||||
for i := 0; i < len(paths); i++ {
|
||||
content := util.ReadStringFromPath(paths[i])
|
||||
words := GetAllI18nStrings(content, paths[i])
|
||||
for j := 0; j < len(words); j++ {
|
||||
ErrName[words[j]] = paths[i]
|
||||
}
|
||||
}
|
||||
return ErrName
|
||||
}
|
||||
|
||||
func getI18nJSONData(errName map[string]string) *I18nData {
|
||||
data := I18nData{}
|
||||
for k, v := range errName {
|
||||
var index int
|
||||
if strings.Contains(v, "/") {
|
||||
index = strings.LastIndex(v, "/")
|
||||
} else {
|
||||
index = strings.LastIndex(v, "\\")
|
||||
}
|
||||
namespace := v[index+1 : len(v)-3]
|
||||
key := k[len(namespace)+1:]
|
||||
// fmt.Printf("k=%s,v=%s,namespace=%s,key=%s\n", k, v, namespace, key)
|
||||
if _, ok := data[namespace]; !ok {
|
||||
data[namespace] = map[string]string{}
|
||||
}
|
||||
data[namespace][key] = key
|
||||
}
|
||||
return &data
|
||||
}
|
@ -14,7 +14,10 @@
|
||||
|
||||
package i18n
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func applyToOtherLanguage(dataEn *I18nData, lang string) {
|
||||
dataOther := readI18nFile(lang)
|
||||
@ -24,7 +27,7 @@ func applyToOtherLanguage(dataEn *I18nData, lang string) {
|
||||
writeI18nFile(lang, dataEn)
|
||||
}
|
||||
|
||||
func TestGenerateI18nStrings(t *testing.T) {
|
||||
func TestGenerateI18nStringsForFrontend(t *testing.T) {
|
||||
dataEn := parseToData()
|
||||
writeI18nFile("en", dataEn)
|
||||
|
||||
@ -35,3 +38,27 @@ func TestGenerateI18nStrings(t *testing.T) {
|
||||
applyToOtherLanguage(dataEn, "ru")
|
||||
applyToOtherLanguage(dataEn, "zh")
|
||||
}
|
||||
|
||||
func TestGenerateI18nStringsForBackend(t *testing.T) {
|
||||
paths := getAllGoFilePaths()
|
||||
|
||||
errName := getErrName(paths)
|
||||
|
||||
dataEn := getI18nJSONData(errName)
|
||||
|
||||
writeI18nFile("backend_en", dataEn)
|
||||
|
||||
applyToOtherLanguage(dataEn, "backend_de")
|
||||
applyToOtherLanguage(dataEn, "backend_es")
|
||||
applyToOtherLanguage(dataEn, "backend_fr")
|
||||
applyToOtherLanguage(dataEn, "backend_ja")
|
||||
applyToOtherLanguage(dataEn, "backend_ko")
|
||||
applyToOtherLanguage(dataEn, "backend_ru")
|
||||
applyToOtherLanguage(dataEn, "backend_zh")
|
||||
|
||||
fmt.Println("Total Err Words:", len(errName))
|
||||
|
||||
for i := range errName {
|
||||
fmt.Println(i)
|
||||
}
|
||||
}
|
||||
|
172
i18n/locales/de/data.json
Normal file
172
i18n/locales/de/data.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"account": {
|
||||
"Email: %s": "Email: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid information": "Invalid information",
|
||||
"Phone: %s": "Phone: %s",
|
||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"application": {
|
||||
"Parameter organization is missing": "Parameter organization is missing",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"auth": {
|
||||
"%s No phone prefix": "%s No phone prefix",
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid token": "Invalid token",
|
||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account does not exist": "The account does not exist",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user doesn't exist": "The user doesn't exist",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"check_util": {
|
||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||
},
|
||||
"enforcer": {
|
||||
"Please sign in first": "Please sign in first"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist",
|
||||
"Missing parameter": "Missing parameter"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"product": {
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"system_info": {
|
||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||
},
|
||||
"token": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"Please login first": "Please login first",
|
||||
"The provider: %s is not found": "The provider: %s is not found",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
}
|
||||
}
|
172
i18n/locales/en/data.json
Normal file
172
i18n/locales/en/data.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"account": {
|
||||
"Email: %s": "Email: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid information": "Invalid information",
|
||||
"Phone: %s": "Phone: %s",
|
||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"application": {
|
||||
"Parameter organization is missing": "Parameter organization is missing",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"auth": {
|
||||
"%s No phone prefix": "%s No phone prefix",
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid token": "Invalid token",
|
||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account does not exist": "The account does not exist",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user doesn't exist": "The user doesn't exist",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"check_util": {
|
||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||
},
|
||||
"enforcer": {
|
||||
"Please sign in first": "Please sign in first"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist",
|
||||
"Missing parameter": "Missing parameter"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"product": {
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"system_info": {
|
||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||
},
|
||||
"token": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"Please login first": "Please login first",
|
||||
"The provider: %s is not found": "The provider: %s is not found",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
}
|
||||
}
|
172
i18n/locales/es/data.json
Normal file
172
i18n/locales/es/data.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"account": {
|
||||
"Email: %s": "Email: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid information": "Invalid information",
|
||||
"Phone: %s": "Phone: %s",
|
||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"application": {
|
||||
"Parameter organization is missing": "Parameter organization is missing",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"auth": {
|
||||
"%s No phone prefix": "%s No phone prefix",
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid token": "Invalid token",
|
||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account does not exist": "The account does not exist",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user doesn't exist": "The user doesn't exist",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"check_util": {
|
||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||
},
|
||||
"enforcer": {
|
||||
"Please sign in first": "Please sign in first"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist",
|
||||
"Missing parameter": "Missing parameter"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"product": {
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"system_info": {
|
||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||
},
|
||||
"token": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"Please login first": "Please login first",
|
||||
"The provider: %s is not found": "The provider: %s is not found",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
}
|
||||
}
|
172
i18n/locales/fr/data.json
Normal file
172
i18n/locales/fr/data.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"account": {
|
||||
"Email: %s": "Email: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid information": "Invalid information",
|
||||
"Phone: %s": "Phone: %s",
|
||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"application": {
|
||||
"Parameter organization is missing": "Parameter organization is missing",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"auth": {
|
||||
"%s No phone prefix": "%s No phone prefix",
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid token": "Invalid token",
|
||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account does not exist": "The account does not exist",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user doesn't exist": "The user doesn't exist",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"check_util": {
|
||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||
},
|
||||
"enforcer": {
|
||||
"Please sign in first": "Please sign in first"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist",
|
||||
"Missing parameter": "Missing parameter"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"product": {
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"system_info": {
|
||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||
},
|
||||
"token": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"Please login first": "Please login first",
|
||||
"The provider: %s is not found": "The provider: %s is not found",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
}
|
||||
}
|
172
i18n/locales/ja/data.json
Normal file
172
i18n/locales/ja/data.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"account": {
|
||||
"Email: %s": "Email: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid information": "Invalid information",
|
||||
"Phone: %s": "Phone: %s",
|
||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"application": {
|
||||
"Parameter organization is missing": "Parameter organization is missing",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"auth": {
|
||||
"%s No phone prefix": "%s No phone prefix",
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid token": "Invalid token",
|
||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account does not exist": "The account does not exist",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user doesn't exist": "The user doesn't exist",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"check_util": {
|
||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||
},
|
||||
"enforcer": {
|
||||
"Please sign in first": "Please sign in first"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist",
|
||||
"Missing parameter": "Missing parameter"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"product": {
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"system_info": {
|
||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||
},
|
||||
"token": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"Please login first": "Please login first",
|
||||
"The provider: %s is not found": "The provider: %s is not found",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
}
|
||||
}
|
172
i18n/locales/ko/data.json
Normal file
172
i18n/locales/ko/data.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"account": {
|
||||
"Email: %s": "Email: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid information": "Invalid information",
|
||||
"Phone: %s": "Phone: %s",
|
||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"application": {
|
||||
"Parameter organization is missing": "Parameter organization is missing",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"auth": {
|
||||
"%s No phone prefix": "%s No phone prefix",
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid token": "Invalid token",
|
||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account does not exist": "The account does not exist",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user doesn't exist": "The user doesn't exist",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"check_util": {
|
||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||
},
|
||||
"enforcer": {
|
||||
"Please sign in first": "Please sign in first"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist",
|
||||
"Missing parameter": "Missing parameter"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"product": {
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"system_info": {
|
||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||
},
|
||||
"token": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"Please login first": "Please login first",
|
||||
"The provider: %s is not found": "The provider: %s is not found",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
}
|
||||
}
|
172
i18n/locales/ru/data.json
Normal file
172
i18n/locales/ru/data.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"account": {
|
||||
"Email: %s": "Email: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid information": "Invalid information",
|
||||
"Phone: %s": "Phone: %s",
|
||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"application": {
|
||||
"Parameter organization is missing": "Parameter organization is missing",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"auth": {
|
||||
"%s No phone prefix": "%s No phone prefix",
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Invalid token": "Invalid token",
|
||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account does not exist": "The account does not exist",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user doesn't exist": "The user doesn't exist",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"check_util": {
|
||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||
},
|
||||
"enforcer": {
|
||||
"Please sign in first": "Please sign in first"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist",
|
||||
"Missing parameter": "Missing parameter"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"product": {
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"system_info": {
|
||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||
},
|
||||
"token": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"Please login first": "Please login first",
|
||||
"The provider: %s is not found": "The provider: %s is not found",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Please login first": "Please login first",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||
}
|
||||
}
|
172
i18n/locales/zh/data.json
Normal file
172
i18n/locales/zh/data.json
Normal file
@ -0,0 +1,172 @@
|
||||
{
|
||||
"account": {
|
||||
"Email: %s": "邮件: %s",
|
||||
"Get init score failed, error: %w": "初始化分数失败: %w",
|
||||
"Invalid information": "无效信息",
|
||||
"Phone: %s": "电话: %s",
|
||||
"Please sign out first before signing up": "请在登陆前登出",
|
||||
"The application does not allow to sign up new account": "该应用不允许注册新账户"
|
||||
},
|
||||
"application": {
|
||||
"Parameter organization is missing": "Organization参数丢失",
|
||||
"The user: %s doesn't exist": "用户不存在: %s"
|
||||
},
|
||||
"auth": {
|
||||
"%s No phone prefix": "%s 无此电话前缀",
|
||||
"Challenge method should be S256": "Challenge 方法应该为 S256",
|
||||
"Failed to create user, user information is invalid: %s": "创建用户失败,用户信息无效: %s",
|
||||
"Failed to login in: %s": "无法登录: %s",
|
||||
"Get init score failed, error: %w": "初始化分数失败: %w",
|
||||
"Invalid token": "无效token",
|
||||
"Please sign out first before signing in": "请在登陆前登出",
|
||||
"State expected: %s, but got: %s": "期望状态位: %s, 实际状态为: %s",
|
||||
"The account does not exist": "账户不存在",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "提供商账户: %s 与用户名: %s (%s) 不存在且 不允许通过 %s 注册新账户, 请使用其他方式注册",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "提供商账户: %s 与用户名: %s (%s) 不存在且 不允许注册新账户, 请联系IT支持",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "提供商账户: %s 与用户名: %s (%s) 已经与其他账户绑定: %s (%s)",
|
||||
"The application: %s does not exist": "应用 %s 不存在",
|
||||
"The provider type: %s is not supported": "不支持该类型的提供商: %s",
|
||||
"The provider: %s is not enabled for the application": "提供商: %s 未被启用",
|
||||
"The user is forbidden to sign in, please contact the administrator": "该用户被禁止登陆,请联系管理员",
|
||||
"The user: %s/%s doesn't exist": "用户不存在: %s/%s",
|
||||
"Turing test failed.": "真人验证失败",
|
||||
"Unauthorized operation": "未授权的操作",
|
||||
"Unknown authentication type (not password or provider), form = %s": "未授权的操作"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "服务 %s 与 %s 不匹配"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "联系方式不可为空",
|
||||
"DisplayName cannot be blank": "展示名称不可为空",
|
||||
"DisplayName is not valid real name": "展示名称无效",
|
||||
"Email already exists": "该邮箱已存在",
|
||||
"Email cannot be empty": "邮箱不可为空",
|
||||
"Email is invalid": "无效邮箱",
|
||||
"Empty username.": "用户名不可为空",
|
||||
"FirstName cannot be blank": "名不可以为空",
|
||||
"LastName cannot be blank": "姓不可以为空",
|
||||
"Ldap user name or password incorrect": "Ldap密码错误",
|
||||
"Multiple accounts with same uid, please check your ldap server": "多个帐户具有相同的uid,请检查您的 ldap 服务器",
|
||||
"Organization does not exist": "组织不存在",
|
||||
"Password must have at least 6 characters": "新密码至少为6位",
|
||||
"Phone already exists": "该电话已存在",
|
||||
"Phone cannot be empty": "电话不可为空",
|
||||
"Phone number is invalid": "无效电话",
|
||||
"Please login first": "请先登录",
|
||||
"Session outdated, please login again": "Session已过期,请重新登陆",
|
||||
"The user doesn't exist": "用户不存在",
|
||||
"The user is forbidden to sign in, please contact the administrator": "该用户被禁止登陆,请联系管理员",
|
||||
"The user: %s doesn't exist": "用户不存在: %s",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "用户名只能包含字母数字字符、下划线或连字符,不能有连续的连字符或下划线,也不能以连字符或下划线开头或结尾",
|
||||
"Username already exists": "用户名已存在",
|
||||
"Username cannot be an email address": "用户名不可以是邮箱地址",
|
||||
"Username cannot contain white spaces": "用户名不可以包含空格",
|
||||
"Username cannot start with a digit": "用户名禁止使用数字作为第一个字符",
|
||||
"Username is too long (maximum is 39 characters).": "用户名过长(最大长度为39个字符)",
|
||||
"Username must have at least 2 characters": "用户名至少要有2个字符",
|
||||
"You don't have the permission to do this": "用户名至少要有2个字符",
|
||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "输入密码错误次数已达上限,请在 %d 分 %d 秒后重试",
|
||||
"unsupported password type: %s": "不支持的密码类型: %s"
|
||||
},
|
||||
"check_util": {
|
||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "输入密码错误次数已达上限,请在 %d 分后重试",
|
||||
"password is incorrect, you have %d remaining chances": "密码错误,您还有 %d 次尝试的机会"
|
||||
},
|
||||
"enforcer": {
|
||||
"Please sign in first": "请先登录"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap服务器已存在",
|
||||
"Missing parameter": "参数丢失"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "请先绑定",
|
||||
"This application has no providers": "该应用无提供商",
|
||||
"This application has no providers of type": "应用没有该类型的提供商",
|
||||
"This provider can't be unlinked": "该提供商不可被链接",
|
||||
"You are not the global admin, you can't unlink other users": "您不是全局管理员,无法取消链接其他用户",
|
||||
"You can't unlink yourself, you are not a member of any application": "您无法取消链接,您不是任何应用程序的成员"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "您无法取消链接,您不是任何应用程序的成员",
|
||||
"The %s is immutable.": "%s是不可变的",
|
||||
"Unknown modify rule %s.": "未知的修改规则"
|
||||
},
|
||||
"product": {
|
||||
"Please login first": "请先登录",
|
||||
"The user: %s doesn't exist": "用户不存在: %s"
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "无效的Application ID",
|
||||
"the provider: %s does not exist": "提供商: %s 不存在"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "用户头像标签为空",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "username或FilePath为空: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "应用 %s 未找到"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "提供商 %s类型不是SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "邮件参数为空: %v",
|
||||
"Invalid Email receivers: %s": " 无效的邮箱接收者: %s",
|
||||
"Invalid phone receivers: %s": "无效的电话接收者: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "object key :%s 不被允许",
|
||||
"The provider type: %s is not supported": "提供商类型: %s 尚未支持"
|
||||
},
|
||||
"system_info": {
|
||||
"You are not authorized to access this resource": "您无权获取此资源"
|
||||
},
|
||||
"token": {
|
||||
"Challenge method should be S256": "Challenge 方法应该为 S256",
|
||||
"Empty clientId or clientSecret": "clientId或clientSecret为空",
|
||||
"Grant_type: %s is not supported in this application": "此应用中不支持此授权类型: %s",
|
||||
"Invalid application or wrong clientSecret": "无效应用或错误的clientSecret",
|
||||
"Invalid client_id": "无效的ClientId",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "重定向 URI:%s 在可列表中未找到"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "展示名称不可为空",
|
||||
"New password cannot contain blank space.": "新密码不可以包含空格",
|
||||
"New password must have at least 6 characters": "新密码至少需要6位字符",
|
||||
"The user: %s/%s doesn't exist": "用户不存在: %s/%s"
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "导入用户失败"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "找不到该用户的应用程序 %s",
|
||||
"No provider for category: %s is found for application: %s": "找不到该用户的应用程序 %s",
|
||||
"Please login first": "请先登录",
|
||||
"The provider: %s is not found": "该提供商未找到: %s",
|
||||
"The user: %s doesn't exist": "用户不存在: %s"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "验证码还未发送",
|
||||
"Email is invalid": "非法的邮箱",
|
||||
"Invalid captcha provider.": "非法的验证码提供商",
|
||||
"Missing parameter": "参数丢失",
|
||||
"Organization does not exist": "组织不存在",
|
||||
"Phone number is invalid": "非法的电话号码",
|
||||
"Please login first": "请先登录",
|
||||
"Turing test failed.": "验证码还未发送",
|
||||
"Unable to get the email modify rule.": "无法得到邮箱修改规则",
|
||||
"Unable to get the phone modify rule.": "无法得到电话修改规则",
|
||||
"Unknown type": "未知类型",
|
||||
"Wrong parameter": "参数错误",
|
||||
"You should verify your code in %d min!": "请在 %d 分钟内输入正确验证码",
|
||||
"the user does not exist, please sign up first": "用户不存在,请先注册"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "该用户没有WebAuthn凭据",
|
||||
"Please call WebAuthnSigninBegin first": "请先调用 WebAuthnSigninBegi",
|
||||
"Please login first": "请先登录",
|
||||
"The user: %s/%s doesn't exist": "用户: %s/%s 不存在"
|
||||
}
|
||||
}
|
34
i18n/util.go
34
i18n/util.go
@ -15,14 +15,26 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
//go:embed locales/*/data.json
|
||||
var f embed.FS
|
||||
|
||||
var langMap = make(map[string]map[string]map[string]string) // for example : langMap[en][account][Invalid information] = Invalid information
|
||||
|
||||
func getI18nFilePath(language string) string {
|
||||
return fmt.Sprintf("../web/src/locales/%s/data.json", language)
|
||||
if strings.Contains(language, "backend") {
|
||||
// change language from 'backend_en' to 'en'
|
||||
language = language[8:]
|
||||
return fmt.Sprintf("../i18n/locales/%s/data.json", language)
|
||||
} else {
|
||||
return fmt.Sprintf("../web/src/locales/%s/data.json", language)
|
||||
}
|
||||
}
|
||||
|
||||
func readI18nFile(language string) *I18nData {
|
||||
@ -39,6 +51,7 @@ func readI18nFile(language string) *I18nData {
|
||||
func writeI18nFile(language string, data *I18nData) {
|
||||
s := util.StructToJsonFormatted(data)
|
||||
s = strings.ReplaceAll(s, "\\u0026", "&")
|
||||
s += "\n"
|
||||
println(s)
|
||||
|
||||
util.WriteStringToPath(s, getI18nFilePath(language))
|
||||
@ -61,3 +74,22 @@ func applyData(data1 *I18nData, data2 *I18nData) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Translate(lang string, error string) string {
|
||||
parts := strings.SplitN(error, ":", 2)
|
||||
if !strings.Contains(error, ":") || len(parts) != 2 {
|
||||
return "Translate Error: " + error
|
||||
}
|
||||
if langMap[lang] != nil {
|
||||
return langMap[lang][parts[0]][parts[1]]
|
||||
} else {
|
||||
file, _ := f.ReadFile("locales/" + lang + "/data.json")
|
||||
data := I18nData{}
|
||||
err := util.JsonToStruct(string(file), &data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
langMap[lang] = data
|
||||
return langMap[lang][parts[0]][parts[1]]
|
||||
}
|
||||
}
|
||||
|
23
idp/adfs.go
23
idp/adfs.go
@ -15,10 +15,10 @@
|
||||
package idp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -59,12 +59,12 @@ func (idp *AdfsIdProvider) SetHttpClient(client *http.Client) {
|
||||
}
|
||||
|
||||
func (idp *AdfsIdProvider) getConfig(hostUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
AuthURL: fmt.Sprintf("%s/adfs/oauth2/authorize", hostUrl),
|
||||
TokenURL: fmt.Sprintf("%s/adfs/oauth2/token", hostUrl),
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Endpoint: endpoint,
|
||||
}
|
||||
|
||||
@ -77,6 +77,7 @@ type AdfsToken struct {
|
||||
ErrMsg string `json:"error_description"`
|
||||
}
|
||||
|
||||
// GetToken
|
||||
// get more detail via: https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios#request-an-access-token
|
||||
func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
payload := url.Values{}
|
||||
@ -88,7 +89,7 @@ func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -109,6 +110,7 @@ func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
return token, nil
|
||||
}
|
||||
|
||||
// GetUserInfo
|
||||
// Since the userinfo endpoint of ADFS only returns sub,
|
||||
// the id_token is used to resolve the userinfo
|
||||
func (idp *AdfsIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
@ -116,16 +118,17 @@ func (idp *AdfsIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keyset, err := jwk.Parse(resp.Body)
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
keyset, err := jwk.ParseKey(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tokenSrc := []byte(token.AccessToken)
|
||||
publicKey, _ := keyset.Keys[0].Materialize()
|
||||
id_token, _ := jwt.Parse(bytes.NewReader(tokenSrc), jwt.WithVerify(jwa.RS256, publicKey))
|
||||
sid, _ := id_token.Get("sid")
|
||||
upn, _ := id_token.Get("upn")
|
||||
name, _ := id_token.Get("unique_name")
|
||||
publicKey, _ := keyset.PublicKey()
|
||||
idToken, _ := jwt.Parse(tokenSrc, jwt.WithVerify(jwa.RS256, publicKey))
|
||||
sid, _ := idToken.Get("sid")
|
||||
upn, _ := idToken.Get("upn")
|
||||
name, _ := idToken.Get("unique_name")
|
||||
userinfo := &UserInfo{
|
||||
Id: sid.(string),
|
||||
Username: name.(string),
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
@ -56,12 +55,12 @@ func (idp *AlipayIdProvider) SetHttpClient(client *http.Client) {
|
||||
|
||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||
func (idp *AlipayIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
AuthURL: "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm",
|
||||
TokenURL: "https://openapi.alipay.com/gateway.do",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"", ""},
|
||||
Endpoint: endpoint,
|
||||
ClientID: clientId,
|
||||
@ -205,8 +204,7 @@ func (idp *AlipayIdProvider) postWithBody(body interface{}, targetUrl string) ([
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
@ -46,12 +46,12 @@ func (idp *BaiduIdProvider) SetHttpClient(client *http.Client) {
|
||||
}
|
||||
|
||||
func (idp *BaiduIdProvider) getConfig() *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
AuthURL: "https://openapi.baidu.com/oauth/2.0/authorize",
|
||||
TokenURL: "https://openapi.baidu.com/oauth/2.0/token",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"email"},
|
||||
Endpoint: endpoint,
|
||||
}
|
||||
@ -97,7 +97,7 @@ func (idp *BaiduIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@ -47,12 +46,12 @@ func (idp *BilibiliIdProvider) SetHttpClient(client *http.Client) {
|
||||
|
||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||
func (idp *BilibiliIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: "https://api.bilibili.com/x/account-oauth2/v1/token",
|
||||
AuthURL: "http://member.bilibili.com/arcopen/fn/user/account/info",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"", ""},
|
||||
Endpoint: endpoint,
|
||||
ClientID: clientId,
|
||||
@ -76,6 +75,7 @@ type BilibiliIdProviderTokenResponse struct {
|
||||
Data BilibiliProviderToken `json:"data"`
|
||||
}
|
||||
|
||||
// GetToken
|
||||
/*
|
||||
{
|
||||
"code": 0,
|
||||
@ -104,7 +104,6 @@ func (idp *BilibiliIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
}
|
||||
|
||||
data, err := idp.postWithBody(pTokenParams, idp.Config.Endpoint.TokenURL)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -144,7 +143,7 @@ func (idp *BilibiliIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
type BilibiliUserInfo struct {
|
||||
Name string `json:"name"`
|
||||
Face string `json:"face"`
|
||||
OpenId string `json:"openid`
|
||||
OpenId string `json:"openid"`
|
||||
}
|
||||
|
||||
type BilibiliUserInfoResponse struct {
|
||||
@ -167,12 +166,11 @@ func (idp *BilibiliIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
||||
userInfoUrl := fmt.Sprintf("%s?%s", idp.Config.Endpoint.AuthURL, params.Encode())
|
||||
|
||||
resp, err := idp.Client.Get(userInfoUrl)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -206,7 +204,7 @@ func (idp *BilibiliIdProvider) postWithBody(body interface{}, url string) ([]byt
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ package idp
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
@ -71,8 +71,7 @@ func (idp *CasdoorIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -82,7 +81,7 @@ func (idp *CasdoorIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//check if token is expired
|
||||
// check if token is expired
|
||||
if pToken.ExpiresIn <= 0 {
|
||||
return nil, fmt.Errorf("%s", pToken.AccessToken)
|
||||
}
|
||||
@ -91,7 +90,6 @@ func (idp *CasdoorIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
Expiry: time.Unix(time.Now().Unix()+int64(pToken.ExpiresIn), 0),
|
||||
}
|
||||
return token, nil
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -125,7 +123,7 @@ func (idp *CasdoorIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//add accesstoken to bearer token
|
||||
// add accesstoken to bearer token
|
||||
request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken))
|
||||
resp, err := idp.Client.Do(request)
|
||||
if err != nil {
|
||||
@ -133,7 +131,7 @@ func (idp *CasdoorIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -155,5 +153,4 @@ func (idp *CasdoorIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error
|
||||
AvatarUrl: cdUserinfo.AvatarUrl,
|
||||
}
|
||||
return userInfo, nil
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
_ "net/url"
|
||||
_ "time"
|
||||
@ -36,7 +36,7 @@ func NewCustomIdProvider(clientId string, clientSecret string, redirectUrl strin
|
||||
idp := &CustomIdProvider{}
|
||||
idp.UserInfoUrl = userInfoUrl
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
ClientID: clientId,
|
||||
ClientSecret: clientSecret,
|
||||
RedirectURL: redirectUrl,
|
||||
@ -76,7 +76,7 @@ func (idp *CustomIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//add accessToken to request header
|
||||
// add accessToken to request header
|
||||
request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken))
|
||||
resp, err := idp.Client.Do(request)
|
||||
if err != nil {
|
||||
@ -84,7 +84,7 @@ func (idp *CustomIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -15,10 +15,12 @@
|
||||
package idp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@ -48,12 +50,12 @@ func (idp *DingTalkIdProvider) SetHttpClient(client *http.Client) {
|
||||
|
||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||
func (idp *DingTalkIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
AuthURL: "https://api.dingtalk.com/v1.0/contact/users/me",
|
||||
TokenURL: "https://api.dingtalk.com/v1.0/oauth2/userAccessToken",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
// DingTalk not allow to set scopes,here it is just a placeholder,
|
||||
// convenient to use later
|
||||
Scopes: []string{"", ""},
|
||||
@ -101,7 +103,7 @@ func (idp *DingTalkIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
|
||||
token := &oauth2.Token{
|
||||
AccessToken: pToken.AccessToken,
|
||||
Expiry: time.Unix(time.Now().Unix()+int64(pToken.ExpiresIn), 0),
|
||||
Expiry: time.Unix(time.Now().Unix()+pToken.ExpiresIn, 0),
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
@ -122,6 +124,7 @@ func (idp *DingTalkIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
type DingTalkUserResponse struct {
|
||||
Nick string `json:"nick"`
|
||||
OpenId string `json:"openId"`
|
||||
UnionId string `json:"unionId"`
|
||||
AvatarUrl string `json:"avatarUrl"`
|
||||
Email string `json:"email"`
|
||||
Errmsg string `json:"message"`
|
||||
@ -145,7 +148,7 @@ func (idp *DingTalkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -163,10 +166,14 @@ func (idp *DingTalkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
||||
Id: dtUserInfo.OpenId,
|
||||
Username: dtUserInfo.Nick,
|
||||
DisplayName: dtUserInfo.Nick,
|
||||
UnionId: dtUserInfo.UnionId,
|
||||
Email: dtUserInfo.Email,
|
||||
AvatarUrl: dtUserInfo.AvatarUrl,
|
||||
}
|
||||
|
||||
isUserInOrg, err := idp.isUserInOrg(userInfo.UnionId)
|
||||
if !isUserInOrg {
|
||||
return nil, err
|
||||
}
|
||||
return &userInfo, nil
|
||||
}
|
||||
|
||||
@ -180,7 +187,7 @@ func (idp *DingTalkIdProvider) postWithBody(body interface{}, url string) ([]byt
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -193,3 +200,64 @@ func (idp *DingTalkIdProvider) postWithBody(body interface{}, url string) ([]byt
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (idp *DingTalkIdProvider) getInnerAppAccessToken() string {
|
||||
appKey := idp.Config.ClientID
|
||||
appSecret := idp.Config.ClientSecret
|
||||
body := make(map[string]string)
|
||||
body["appKey"] = appKey
|
||||
body["appSecret"] = appSecret
|
||||
bodyData, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
reader := bytes.NewReader(bodyData)
|
||||
request, err := http.NewRequest("POST", "https://api.dingtalk.com/v1.0/oauth2/accessToken", reader)
|
||||
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
||||
resp, err := idp.Client.Do(request)
|
||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
var data struct {
|
||||
ExpireIn int `json:"expireIn"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
}
|
||||
err = json.Unmarshal(respBytes, &data)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
return data.AccessToken
|
||||
}
|
||||
|
||||
func (idp *DingTalkIdProvider) isUserInOrg(unionId string) (bool, error) {
|
||||
body := make(map[string]string)
|
||||
body["unionid"] = unionId
|
||||
bodyData, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
reader := bytes.NewReader(bodyData)
|
||||
accessToken := idp.getInnerAppAccessToken()
|
||||
request, _ := http.NewRequest("POST", "https://oapi.dingtalk.com/topapi/user/getbyunionid?access_token="+accessToken, reader)
|
||||
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
||||
resp, err := idp.Client.Do(request)
|
||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
var data struct {
|
||||
ErrCode int `json:"errcode"`
|
||||
ErrMessage string `json:"errmsg"`
|
||||
}
|
||||
err = json.Unmarshal(respBytes, &data)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
if data.ErrCode == 60121 {
|
||||
return false, fmt.Errorf("the user is not found in the organization where clientId and clientSecret belong")
|
||||
} else if data.ErrCode != 0 {
|
||||
return false, fmt.Errorf(data.ErrMessage)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
@ -42,12 +42,12 @@ func (idp *DouyinIdProvider) SetHttpClient(client *http.Client) {
|
||||
}
|
||||
|
||||
func (idp *DouyinIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: "https://open.douyin.com/oauth/access_token",
|
||||
AuthURL: "https://open.douyin.com/platform/oauth/connect",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"user_info"},
|
||||
Endpoint: endpoint,
|
||||
ClientID: clientId,
|
||||
@ -98,7 +98,7 @@ func (idp *DouyinIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -177,7 +177,7 @@ func (idp *DouyinIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -46,11 +46,11 @@ func (idp *FacebookIdProvider) SetHttpClient(client *http.Client) {
|
||||
|
||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||
func (idp *FacebookIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: "https://graph.facebook.com/oauth/access_token",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"email,public_profile"},
|
||||
Endpoint: endpoint,
|
||||
ClientID: clientId,
|
||||
@ -62,15 +62,16 @@ func (idp *FacebookIdProvider) getConfig(clientId string, clientSecret string, r
|
||||
}
|
||||
|
||||
type FacebookAccessToken struct {
|
||||
AccessToken string `json:"access_token"` //Interface call credentials
|
||||
TokenType string `json:"token_type"` //Access token type
|
||||
ExpiresIn int64 `json:"expires_in"` //access_token interface call credential timeout time, unit (seconds)
|
||||
AccessToken string `json:"access_token"` // Interface call credentials
|
||||
TokenType string `json:"token_type"` // Access token type
|
||||
ExpiresIn int64 `json:"expires_in"` // access_token interface call credential timeout time, unit (seconds)
|
||||
}
|
||||
|
||||
type FacebookCheckToken struct {
|
||||
Data string `json:"data"`
|
||||
}
|
||||
|
||||
// FacebookCheckTokenData
|
||||
// Get more detail via: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#checktoken
|
||||
type FacebookCheckTokenData struct {
|
||||
UserId string `json:"user_id"`
|
||||
|
@ -19,7 +19,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@ -49,11 +48,11 @@ func (idp *GiteeIdProvider) SetHttpClient(client *http.Client) {
|
||||
|
||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||
func (idp *GiteeIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: "https://gitee.com/oauth/token",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"user_info emails"},
|
||||
|
||||
Endpoint: endpoint,
|
||||
@ -93,7 +92,7 @@ func (idp *GiteeIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rbs, err := ioutil.ReadAll(resp.Body)
|
||||
rbs, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -49,12 +48,12 @@ func (idp *GithubIdProvider) SetHttpClient(client *http.Client) {
|
||||
}
|
||||
|
||||
func (idp *GithubIdProvider) getConfig() *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
AuthURL: "https://github.com/login/oauth/authorize",
|
||||
TokenURL: "https://github.com/login/oauth/access_token",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"user:email", "read:user"},
|
||||
Endpoint: endpoint,
|
||||
}
|
||||
@ -93,7 +92,6 @@ func (idp *GithubIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
}
|
||||
|
||||
return token, nil
|
||||
|
||||
}
|
||||
|
||||
//{
|
||||
@ -203,7 +201,7 @@ func (idp *GithubIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -237,7 +235,7 @@ func (idp *GithubIdProvider) postWithBody(body interface{}, url string) ([]byte,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ package idp
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@ -46,11 +46,11 @@ func (idp *GitlabIdProvider) SetHttpClient(client *http.Client) {
|
||||
|
||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||
func (idp *GitlabIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: "https://gitlab.com/oauth/token",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"read_user+profile"},
|
||||
Endpoint: endpoint,
|
||||
ClientID: clientId,
|
||||
@ -85,7 +85,7 @@ func (idp *GitlabIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -209,7 +209,7 @@ func (idp *GitlabIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
@ -47,12 +47,12 @@ func (idp *GoogleIdProvider) SetHttpClient(client *http.Client) {
|
||||
}
|
||||
|
||||
func (idp *GoogleIdProvider) getConfig() *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
AuthURL: "https://accounts.google.com/o/oauth2/auth",
|
||||
TokenURL: "https://accounts.google.com/o/oauth2/token",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"profile", "email"},
|
||||
Endpoint: endpoint,
|
||||
}
|
||||
@ -95,7 +95,7 @@ func (idp *GoogleIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
79
idp/goth.go
79
idp/goth.go
@ -22,35 +22,35 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/casdoor/goth"
|
||||
"github.com/casdoor/goth/providers/amazon"
|
||||
"github.com/casdoor/goth/providers/apple"
|
||||
"github.com/casdoor/goth/providers/azuread"
|
||||
"github.com/casdoor/goth/providers/bitbucket"
|
||||
"github.com/casdoor/goth/providers/digitalocean"
|
||||
"github.com/casdoor/goth/providers/discord"
|
||||
"github.com/casdoor/goth/providers/dropbox"
|
||||
"github.com/casdoor/goth/providers/facebook"
|
||||
"github.com/casdoor/goth/providers/gitea"
|
||||
"github.com/casdoor/goth/providers/github"
|
||||
"github.com/casdoor/goth/providers/gitlab"
|
||||
"github.com/casdoor/goth/providers/google"
|
||||
"github.com/casdoor/goth/providers/heroku"
|
||||
"github.com/casdoor/goth/providers/instagram"
|
||||
"github.com/casdoor/goth/providers/kakao"
|
||||
"github.com/casdoor/goth/providers/line"
|
||||
"github.com/casdoor/goth/providers/linkedin"
|
||||
"github.com/casdoor/goth/providers/microsoftonline"
|
||||
"github.com/casdoor/goth/providers/paypal"
|
||||
"github.com/casdoor/goth/providers/salesforce"
|
||||
"github.com/casdoor/goth/providers/shopify"
|
||||
"github.com/casdoor/goth/providers/slack"
|
||||
"github.com/casdoor/goth/providers/steam"
|
||||
"github.com/casdoor/goth/providers/tumblr"
|
||||
"github.com/casdoor/goth/providers/twitter"
|
||||
"github.com/casdoor/goth/providers/yahoo"
|
||||
"github.com/casdoor/goth/providers/yandex"
|
||||
"github.com/casdoor/goth/providers/zoom"
|
||||
"github.com/markbates/goth"
|
||||
"github.com/markbates/goth/providers/amazon"
|
||||
"github.com/markbates/goth/providers/apple"
|
||||
"github.com/markbates/goth/providers/azureadv2"
|
||||
"github.com/markbates/goth/providers/bitbucket"
|
||||
"github.com/markbates/goth/providers/digitalocean"
|
||||
"github.com/markbates/goth/providers/discord"
|
||||
"github.com/markbates/goth/providers/dropbox"
|
||||
"github.com/markbates/goth/providers/facebook"
|
||||
"github.com/markbates/goth/providers/gitea"
|
||||
"github.com/markbates/goth/providers/github"
|
||||
"github.com/markbates/goth/providers/gitlab"
|
||||
"github.com/markbates/goth/providers/google"
|
||||
"github.com/markbates/goth/providers/heroku"
|
||||
"github.com/markbates/goth/providers/instagram"
|
||||
"github.com/markbates/goth/providers/kakao"
|
||||
"github.com/markbates/goth/providers/line"
|
||||
"github.com/markbates/goth/providers/linkedin"
|
||||
"github.com/markbates/goth/providers/microsoftonline"
|
||||
"github.com/markbates/goth/providers/paypal"
|
||||
"github.com/markbates/goth/providers/salesforce"
|
||||
"github.com/markbates/goth/providers/shopify"
|
||||
"github.com/markbates/goth/providers/slack"
|
||||
"github.com/markbates/goth/providers/steam"
|
||||
"github.com/markbates/goth/providers/tumblr"
|
||||
"github.com/markbates/goth/providers/twitter"
|
||||
"github.com/markbates/goth/providers/yahoo"
|
||||
"github.com/markbates/goth/providers/yandex"
|
||||
"github.com/markbates/goth/providers/zoom"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
@ -74,8 +74,8 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
|
||||
}
|
||||
case "AzureAD":
|
||||
idp = GothIdProvider{
|
||||
Provider: azuread.New(clientId, clientSecret, redirectUrl, nil),
|
||||
Session: &azuread.Session{},
|
||||
Provider: azureadv2.New(clientId, clientSecret, redirectUrl, azureadv2.ProviderOptions{Tenant: "common"}),
|
||||
Session: &azureadv2.Session{},
|
||||
}
|
||||
case "Bitbucket":
|
||||
idp = GothIdProvider{
|
||||
@ -202,12 +202,15 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
|
||||
Provider: zoom.New(clientId, clientSecret, redirectUrl),
|
||||
Session: &zoom.Session{},
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
return &idp
|
||||
}
|
||||
|
||||
//Goth's idp all implement the Client method, but since the goth.Provider interface does not provide to modify idp's client method, reflection is required
|
||||
// SetHttpClient
|
||||
// Goth's idp all implement the Client method, but since the goth.Provider interface does not provide to modify idp's client method, reflection is required
|
||||
func (idp *GothIdProvider) SetHttpClient(client *http.Client) {
|
||||
idpClient := reflect.ValueOf(idp.Provider).Elem().FieldByName("HTTPClient")
|
||||
idpClient.Set(reflect.ValueOf(client))
|
||||
@ -225,8 +228,8 @@ func (idp *GothIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
//Need to construct variables supported by goth
|
||||
//to call the function to obtain accessToken
|
||||
// Need to construct variables supported by goth
|
||||
// to call the function to obtain accessToken
|
||||
value = url.Values{}
|
||||
value.Add("code", code)
|
||||
}
|
||||
@ -235,7 +238,7 @@ func (idp *GothIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//Get ExpiresAt's value
|
||||
// Get ExpiresAt's value
|
||||
valueOfExpire := reflect.ValueOf(idp.Session).Elem().FieldByName("ExpiresAt")
|
||||
if valueOfExpire.IsValid() {
|
||||
expireAt = valueOfExpire.Interface().(time.Time)
|
||||
@ -264,8 +267,8 @@ func getUser(gothUser goth.User, provider string) *UserInfo {
|
||||
Email: gothUser.Email,
|
||||
AvatarUrl: gothUser.AvatarURL,
|
||||
}
|
||||
//Some idp return an empty Name
|
||||
//so construct the Name with firstname and lastname or nickname
|
||||
// Some idp return an empty Name
|
||||
// so construct the Name with firstname and lastname or nickname
|
||||
if user.Username == "" {
|
||||
if gothUser.FirstName != "" && gothUser.LastName != "" {
|
||||
user.Username = getName(gothUser.FirstName, gothUser.LastName)
|
||||
@ -281,7 +284,7 @@ func getUser(gothUser goth.User, provider string) *UserInfo {
|
||||
}
|
||||
}
|
||||
if provider == "steam" {
|
||||
user.Username = user.DisplayName
|
||||
user.Username = user.Id
|
||||
user.Email = ""
|
||||
}
|
||||
return &user
|
||||
|
@ -17,7 +17,7 @@ package idp
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
@ -43,7 +43,7 @@ func (idp *InfoflowInternalIdProvider) SetHttpClient(client *http.Client) {
|
||||
}
|
||||
|
||||
func (idp *InfoflowInternalIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
ClientID: clientId,
|
||||
ClientSecret: clientSecret,
|
||||
RedirectURL: redirectUrl,
|
||||
@ -58,6 +58,7 @@ type InfoflowInterToken struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
}
|
||||
|
||||
// GetToken
|
||||
// get more detail via: https://qy.baidu.com/doc/index.html#/inner_quickstart/flow?id=%E8%8E%B7%E5%8F%96accesstoken
|
||||
func (idp *InfoflowInternalIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
pTokenParams := &struct {
|
||||
@ -69,7 +70,7 @@ func (idp *InfoflowInternalIdProvider) GetToken(code string) (*oauth2.Token, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -137,9 +138,10 @@ type InfoflowInternalUserInfo struct {
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// GetUserInfo
|
||||
// get more detail via: https://qy.baidu.com/doc/index.html#/inner_serverapi/contacts?id=%e8%8e%b7%e5%8f%96%e6%88%90%e5%91%98
|
||||
func (idp *InfoflowInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
//Get userid first
|
||||
// Get userid first
|
||||
accessToken := token.AccessToken
|
||||
code := token.Extra("code").(string)
|
||||
resp, err := idp.Client.Get(fmt.Sprintf("https://qy.im.baidu.com/api/user/getuserinfo?access_token=%s&code=%s&agentid=%s", accessToken, code, idp.AgentId))
|
||||
@ -147,7 +149,7 @@ func (idp *InfoflowInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserIn
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -159,13 +161,13 @@ func (idp *InfoflowInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserIn
|
||||
if userResp.Errcode != 0 {
|
||||
return nil, fmt.Errorf("userIdResp.Errcode = %d, userIdResp.Errmsg = %s", userResp.Errcode, userResp.Errmsg)
|
||||
}
|
||||
//Use userid and accesstoken to get user information
|
||||
// Use userid and accesstoken to get user information
|
||||
resp, err = idp.Client.Get(fmt.Sprintf("https://api.im.baidu.com/api/user/get?access_token=%s&userid=%s", accessToken, userResp.UserId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err = ioutil.ReadAll(resp.Body)
|
||||
data, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@ -47,7 +46,7 @@ func (idp *InfoflowIdProvider) SetHttpClient(client *http.Client) {
|
||||
}
|
||||
|
||||
func (idp *InfoflowIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
ClientID: clientId,
|
||||
ClientSecret: clientSecret,
|
||||
RedirectURL: redirectUrl,
|
||||
@ -63,6 +62,7 @@ type InfoflowToken struct {
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
}
|
||||
|
||||
// GetToken
|
||||
// get more detail via: https://qy.baidu.com/doc/index.html#/third_serverapi/authority
|
||||
func (idp *InfoflowIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
pTokenParams := &struct {
|
||||
@ -134,9 +134,10 @@ type InfoflowUserInfo struct {
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// GetUserInfo
|
||||
// get more detail via: https://qy.baidu.com/doc/index.html#/third_serverapi/contacts?id=%e8%8e%b7%e5%8f%96%e6%88%90%e5%91%98
|
||||
func (idp *InfoflowIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
//Get userid first
|
||||
// Get userid first
|
||||
accessToken := token.AccessToken
|
||||
code := token.Extra("code").(string)
|
||||
resp, err := idp.Client.Get(fmt.Sprintf("https://api.im.baidu.com/api/user/getuserinfo?access_token=%s&code=%s&agentid=%s", accessToken, code, idp.AgentId))
|
||||
@ -144,7 +145,7 @@ func (idp *InfoflowIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -156,13 +157,13 @@ func (idp *InfoflowIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
||||
if userResp.Errcode != 0 {
|
||||
return nil, fmt.Errorf("userIdResp.Errcode = %d, userIdResp.Errmsg = %s", userResp.Errcode, userResp.Errmsg)
|
||||
}
|
||||
//Use userid and accesstoken to get user information
|
||||
// Use userid and accesstoken to get user information
|
||||
resp, err = idp.Client.Get(fmt.Sprintf("https://api.im.baidu.com/api/user/get?access_token=%s&userid=%s", accessToken, userResp.UserId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err = ioutil.ReadAll(resp.Body)
|
||||
data, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -197,7 +198,7 @@ func (idp *InfoflowIdProvider) postWithBody(body interface{}, url string) ([]byt
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ package idp
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@ -45,11 +44,11 @@ func (idp *LarkIdProvider) SetHttpClient(client *http.Client) {
|
||||
|
||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||
func (idp *LarkIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{},
|
||||
Endpoint: endpoint,
|
||||
ClientID: clientId,
|
||||
@ -173,7 +172,7 @@ func (idp *LarkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
data, err = ioutil.ReadAll(resp.Body)
|
||||
data, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -204,7 +203,7 @@ func (idp *LarkIdProvider) postWithBody(body interface{}, url string) ([]byte, e
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@ -47,11 +46,11 @@ func (idp *LinkedInIdProvider) SetHttpClient(client *http.Client) {
|
||||
|
||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||
func (idp *LinkedInIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: "https://www.linkedIn.com/oauth/v2/accessToken",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"email,public_profile"},
|
||||
Endpoint: endpoint,
|
||||
ClientID: clientId,
|
||||
@ -63,8 +62,8 @@ func (idp *LinkedInIdProvider) getConfig(clientId string, clientSecret string, r
|
||||
}
|
||||
|
||||
type LinkedInAccessToken struct {
|
||||
AccessToken string `json:"access_token"` //Interface call credentials
|
||||
ExpiresIn int64 `json:"expires_in"` //access_token interface call credential timeout time, unit (seconds)
|
||||
AccessToken string `json:"access_token"` // Interface call credentials
|
||||
ExpiresIn int64 `json:"expires_in"` // access_token interface call credential timeout time, unit (seconds)
|
||||
}
|
||||
|
||||
// GetToken use code get access_token (*operation of getting code ought to be done in front)
|
||||
@ -85,7 +84,7 @@ func (idp *LinkedInIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rbs, err := ioutil.ReadAll(resp.Body)
|
||||
rbs, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -323,7 +322,7 @@ func (idp *LinkedInIdProvider) GetUrlRespWithAuthorization(url, token string) ([
|
||||
}
|
||||
}(resp.Body)
|
||||
|
||||
bs, err := ioutil.ReadAll(resp.Body)
|
||||
bs, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
10
idp/okta.go
10
idp/okta.go
@ -17,7 +17,7 @@ package idp
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
@ -48,12 +48,12 @@ func (idp *OktaIdProvider) SetHttpClient(client *http.Client) {
|
||||
}
|
||||
|
||||
func (idp *OktaIdProvider) getConfig(hostUrl string, clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: fmt.Sprintf("%s/v1/token", hostUrl),
|
||||
AuthURL: fmt.Sprintf("%s/v1/authorize", hostUrl),
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
// openid is required for authentication requests
|
||||
// get more details via: https://developer.okta.com/docs/reference/api/oidc/#reserved-scopes
|
||||
Scopes: []string{"openid", "profile", "email"},
|
||||
@ -114,7 +114,7 @@ func (idp *OktaIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -178,7 +178,7 @@ func (idp *OktaIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ type UserInfo struct {
|
||||
Id string
|
||||
Username string
|
||||
DisplayName string
|
||||
UnionId string
|
||||
Email string
|
||||
AvatarUrl string
|
||||
}
|
||||
@ -97,7 +98,7 @@ func GetIdProvider(typ string, subType string, clientId string, clientSecret str
|
||||
return nil
|
||||
}
|
||||
|
||||
var gothList = []string{"Apple", "AzureAd", "Slack", "Steam"}
|
||||
var gothList = []string{"Apple", "AzureAD", "Slack", "Steam", "Line"}
|
||||
|
||||
func isGothSupport(provider string) bool {
|
||||
for _, value := range gothList {
|
||||
|
12
idp/qq.go
12
idp/qq.go
@ -18,7 +18,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
@ -48,11 +48,11 @@ func (idp *QqIdProvider) SetHttpClient(client *http.Client) {
|
||||
}
|
||||
|
||||
func (idp *QqIdProvider) getConfig() *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: "https://graph.qq.com/oauth2.0/token",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"get_user_info"},
|
||||
Endpoint: endpoint,
|
||||
}
|
||||
@ -75,7 +75,7 @@ func (idp *QqIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
tokenContent, err := ioutil.ReadAll(resp.Body)
|
||||
tokenContent, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -148,7 +148,7 @@ func (idp *QqIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
openIdBody, err := ioutil.ReadAll(resp.Body)
|
||||
openIdBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -167,7 +167,7 @@ func (idp *QqIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
userInfoBody, err := ioutil.ReadAll(resp.Body)
|
||||
userInfoBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -16,14 +16,17 @@ package idp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/skip2/go-qrcode"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
@ -47,11 +50,11 @@ func (idp *WeChatIdProvider) SetHttpClient(client *http.Client) {
|
||||
|
||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||
func (idp *WeChatIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: "https://graph.qq.com/oauth2.0/token",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"snsapi_login"},
|
||||
Endpoint: endpoint,
|
||||
ClientID: clientId,
|
||||
@ -63,12 +66,12 @@ func (idp *WeChatIdProvider) getConfig(clientId string, clientSecret string, red
|
||||
}
|
||||
|
||||
type WechatAccessToken struct {
|
||||
AccessToken string `json:"access_token"` //Interface call credentials
|
||||
ExpiresIn int64 `json:"expires_in"` //access_token interface call credential timeout time, unit (seconds)
|
||||
RefreshToken string `json:"refresh_token"` //User refresh access_token
|
||||
Openid string `json:"openid"` //Unique ID of authorized user
|
||||
Scope string `json:"scope"` //The scope of user authorization, separated by commas. (,)
|
||||
Unionid string `json:"unionid"` //This field will appear if and only if the website application has been authorized by the user's UserInfo.
|
||||
AccessToken string `json:"access_token"` // Interface call credentials
|
||||
ExpiresIn int64 `json:"expires_in"` // access_token interface call credential timeout time, unit (seconds)
|
||||
RefreshToken string `json:"refresh_token"` // User refresh access_token
|
||||
Openid string `json:"openid"` // Unique ID of authorized user
|
||||
Scope string `json:"scope"` // The scope of user authorization, separated by commas. (,)
|
||||
Unionid string `json:"unionid"` // This field will appear if and only if the website application has been authorized by the user's UserInfo.
|
||||
}
|
||||
|
||||
// GetToken use code get access_token (*operation of getting code ought to be done in front)
|
||||
@ -144,7 +147,7 @@ type WechatUserInfo struct {
|
||||
City string `json:"city"` // City filled in by general user's personal data
|
||||
Province string `json:"province"` // Province filled in by ordinary user's personal information
|
||||
Country string `json:"country"` // Country, such as China is CN
|
||||
Headimgurl string `json:"headimgurl"` // User avatar, the last value represents the size of the square avatar (there are optional values of 0, 46, 64, 96, 132, 0 represents a 640*640 square avatar), this item is empty when the user does not have a avatar
|
||||
Headimgurl string `json:"headimgurl"` // User avatar, the last value represents the size of the square avatar (there are optional values of 0, 46, 64, 96, 132, 0 represents a 640*640 square avatar), this item is empty when the user does not have an avatar
|
||||
Privilege []string `json:"privilege"` // User Privilege information, json array, such as Wechat Woka user (chinaunicom)
|
||||
Unionid string `json:"unionid"` // Unified user identification. For an application under a WeChat open platform account, the unionid of the same user is unique.
|
||||
}
|
||||
@ -191,3 +194,54 @@ func (idp *WeChatIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
||||
}
|
||||
return &userInfo, nil
|
||||
}
|
||||
|
||||
func GetWechatOfficialAccountAccessToken(clientId string, clientSecret string) (string, error) {
|
||||
accessTokenUrl := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", clientId, clientSecret)
|
||||
request, err := http.NewRequest("GET", accessTokenUrl, nil)
|
||||
client := new(http.Client)
|
||||
resp, err := client.Do(request)
|
||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var data struct {
|
||||
ExpireIn int `json:"expires_in"`
|
||||
AccessToken string `json:"access_token"`
|
||||
}
|
||||
err = json.Unmarshal(respBytes, &data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return data.AccessToken, nil
|
||||
}
|
||||
|
||||
func GetWechatOfficialAccountQRCode(clientId string, clientSecret string) (string, error) {
|
||||
accessToken, err := GetWechatOfficialAccountAccessToken(clientId, clientSecret)
|
||||
client := new(http.Client)
|
||||
params := "{\"action_name\": \"QR_LIMIT_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"test\"}}}"
|
||||
bodyData := bytes.NewReader([]byte(params))
|
||||
qrCodeUrl := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", accessToken)
|
||||
requeset, err := http.NewRequest("POST", qrCodeUrl, bodyData)
|
||||
resp, err := client.Do(requeset)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var data struct {
|
||||
Ticket string `json:"ticket"`
|
||||
ExpireSeconds int `json:"expire_seconds"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
err = json.Unmarshal(respBytes, &data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var png []byte
|
||||
png, err = qrcode.Encode(data.URL, qrcode.Medium, 256)
|
||||
base64Image := base64.StdEncoding.EncodeToString(png)
|
||||
return base64Image, nil
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ package idp
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
@ -42,7 +42,7 @@ func (idp *WeChatMiniProgramIdProvider) SetHttpClient(client *http.Client) {
|
||||
}
|
||||
|
||||
func (idp *WeChatMiniProgramIdProvider) getConfig(clientId string, clientSecret string) *oauth2.Config {
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
ClientID: clientId,
|
||||
ClientSecret: clientSecret,
|
||||
}
|
||||
@ -65,7 +65,7 @@ func (idp *WeChatMiniProgramIdProvider) GetSessionByCode(code string) (*WeChatMi
|
||||
return nil, err
|
||||
}
|
||||
defer sessionResponse.Body.Close()
|
||||
data, err := ioutil.ReadAll(sessionResponse.Body)
|
||||
data, err := io.ReadAll(sessionResponse.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -78,5 +78,4 @@ func (idp *WeChatMiniProgramIdProvider) GetSessionByCode(code string) (*WeChatMi
|
||||
return nil, fmt.Errorf("err: %s", session.Errmsg)
|
||||
}
|
||||
return &session, nil
|
||||
|
||||
}
|
||||
|
@ -17,14 +17,15 @@ package idp
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
//This idp is using wecom internal application api as idp
|
||||
// WeComInternalIdProvider
|
||||
// This idp is using wecom internal application api as idp
|
||||
type WeComInternalIdProvider struct {
|
||||
Client *http.Client
|
||||
Config *oauth2.Config
|
||||
@ -44,7 +45,7 @@ func (idp *WeComInternalIdProvider) SetHttpClient(client *http.Client) {
|
||||
}
|
||||
|
||||
func (idp *WeComInternalIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
ClientID: clientId,
|
||||
ClientSecret: clientSecret,
|
||||
RedirectURL: redirectUrl,
|
||||
@ -72,7 +73,7 @@ func (idp *WeComInternalIdProvider) GetToken(code string) (*oauth2.Token, error)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -115,7 +116,7 @@ type WecomInternalUserInfo struct {
|
||||
}
|
||||
|
||||
func (idp *WeComInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
//Get userid first
|
||||
// Get userid first
|
||||
accessToken := token.AccessToken
|
||||
code := token.Extra("code").(string)
|
||||
resp, err := idp.Client.Get(fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=%s&code=%s", accessToken, code))
|
||||
@ -123,7 +124,7 @@ func (idp *WeComInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -138,13 +139,13 @@ func (idp *WeComInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo,
|
||||
if userResp.OpenId != "" {
|
||||
return nil, fmt.Errorf("not an internal user")
|
||||
}
|
||||
//Use userid and accesstoken to get user information
|
||||
// Use userid and accesstoken to get user information
|
||||
resp, err = idp.Client.Get(fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=%s&userid=%s", accessToken, userResp.UserId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err = ioutil.ReadAll(resp.Body)
|
||||
data, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@ -46,11 +45,11 @@ func (idp *WeComIdProvider) SetHttpClient(client *http.Client) {
|
||||
|
||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||
func (idp *WeComIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: "https://graph.qq.com/oauth2.0/token",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{"snsapi_login"},
|
||||
Endpoint: endpoint,
|
||||
ClientID: clientId,
|
||||
@ -195,7 +194,7 @@ func (idp *WeComIdProvider) postWithBody(body interface{}, url string) ([]byte,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@ -48,11 +47,11 @@ func (idp *WeiBoIdProvider) SetHttpClient(client *http.Client) {
|
||||
|
||||
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||
func (idp *WeiBoIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||
var endpoint = oauth2.Endpoint{
|
||||
endpoint := oauth2.Endpoint{
|
||||
TokenURL: "https://api.weibo.com/oauth2/access_token",
|
||||
}
|
||||
|
||||
var config = &oauth2.Config{
|
||||
config := &oauth2.Config{
|
||||
Scopes: []string{""},
|
||||
Endpoint: endpoint,
|
||||
ClientID: clientId,
|
||||
@ -92,7 +91,7 @@ func (idp *WeiBoIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
return
|
||||
}
|
||||
}(resp.Body)
|
||||
bs, err := ioutil.ReadAll(resp.Body)
|
||||
bs, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
342
init_data.json.template
Normal file
342
init_data.json.template
Normal file
@ -0,0 +1,342 @@
|
||||
{
|
||||
"organizations": [
|
||||
{
|
||||
"owner": "",
|
||||
"name": "",
|
||||
"displayName": "",
|
||||
"websiteUrl": "",
|
||||
"favicon": "",
|
||||
"passwordType": "",
|
||||
"phonePrefix": "",
|
||||
"defaultAvatar": "",
|
||||
"tags": [""]
|
||||
}
|
||||
],
|
||||
"applications": [
|
||||
{
|
||||
"owner": "",
|
||||
"name": "",
|
||||
"displayName": "",
|
||||
"logo": "",
|
||||
"homepageUrl": "",
|
||||
"organization": "",
|
||||
"cert": "",
|
||||
"enablePassword": true,
|
||||
"enableSignUp": true,
|
||||
"clientId": "",
|
||||
"clientSecret": "",
|
||||
"providers": [
|
||||
{
|
||||
"name": "",
|
||||
"canSignUp": true,
|
||||
"canSignIn": true,
|
||||
"canUnlink": false,
|
||||
"prompted": false,
|
||||
"alertType": "None"
|
||||
}
|
||||
],
|
||||
"signupItems": [
|
||||
{
|
||||
"name": "ID",
|
||||
"visible": false,
|
||||
"required": true,
|
||||
"prompted": false,
|
||||
"rule": "Random"
|
||||
},
|
||||
{
|
||||
"name": "Username",
|
||||
"visible": true,
|
||||
"required": true,
|
||||
"prompted": false,
|
||||
"rule": "None"
|
||||
},
|
||||
{
|
||||
"name": "Display name",
|
||||
"visible": true,
|
||||
"required": true,
|
||||
"prompted": false,
|
||||
"rule": "None"
|
||||
},
|
||||
{
|
||||
"name": "Password",
|
||||
"visible": true,
|
||||
"required": true,
|
||||
"prompted": false,
|
||||
"rule": "None"
|
||||
},
|
||||
{
|
||||
"name": "Confirm password",
|
||||
"visible": true,
|
||||
"required": true,
|
||||
"prompted": false,
|
||||
"rule": "None"
|
||||
},
|
||||
{
|
||||
"name": "Email",
|
||||
"visible": true,
|
||||
"required": true,
|
||||
"prompted": false,
|
||||
"rule": "None"
|
||||
},
|
||||
{
|
||||
"name": "Phone",
|
||||
"visible": true,
|
||||
"required": true,
|
||||
"prompted": false,
|
||||
"rule": "None"
|
||||
},
|
||||
{
|
||||
"name": "Agreement",
|
||||
"visible": true,
|
||||
"required": true,
|
||||
"prompted": false,
|
||||
"rule": "None"
|
||||
}
|
||||
],
|
||||
"redirectUris": [""],
|
||||
"expireInHours": 168
|
||||
}
|
||||
],
|
||||
"users": [
|
||||
{
|
||||
"owner": "",
|
||||
"name": "",
|
||||
"type": "normal-user",
|
||||
"password": "",
|
||||
"displayName": "",
|
||||
"avatar": "",
|
||||
"email": "",
|
||||
"phone": "",
|
||||
"address": [],
|
||||
"affiliation": "",
|
||||
"tag": "",
|
||||
"score": 2000,
|
||||
"ranking": 1,
|
||||
"isAdmin": true,
|
||||
"isGlobalAdmin": true,
|
||||
"isForbidden": false,
|
||||
"isDeleted": false,
|
||||
"signupApplication": "",
|
||||
"createdIp": ""
|
||||
}
|
||||
],
|
||||
"providers": [
|
||||
{
|
||||
"owner": "",
|
||||
"name": "",
|
||||
"displayName": "",
|
||||
"category": "",
|
||||
"type": ""
|
||||
}
|
||||
],
|
||||
"certs": [
|
||||
{
|
||||
"owner": "",
|
||||
"name": "",
|
||||
"displayName": "",
|
||||
"scope": "JWT",
|
||||
"type": "x509",
|
||||
"cryptoAlgorithm": "RS256",
|
||||
"bitSize": 4096,
|
||||
"expireInYears": 20,
|
||||
"certificate": "",
|
||||
"privateKey": ""
|
||||
}
|
||||
],
|
||||
"ldaps": [
|
||||
{
|
||||
"id": "",
|
||||
"owner": "",
|
||||
"serverName": "",
|
||||
"host": "",
|
||||
"port": 389,
|
||||
"admin": "",
|
||||
"passwd": "",
|
||||
"baseDn": "",
|
||||
"autoSync": 0,
|
||||
"lastSync": ""
|
||||
}
|
||||
],
|
||||
"models": [
|
||||
{
|
||||
"owner": "",
|
||||
"name": "",
|
||||
"modelText": "",
|
||||
"displayName": ""
|
||||
}
|
||||
],
|
||||
"permissions": [
|
||||
{
|
||||
"actions": [
|
||||
""
|
||||
],
|
||||
"displayName": "",
|
||||
"effect": "",
|
||||
"isEnabled": true,
|
||||
"model": "",
|
||||
"name": "",
|
||||
"owner": "",
|
||||
"resourceType": "",
|
||||
"resources": [
|
||||
""
|
||||
],
|
||||
"roles": [
|
||||
""
|
||||
],
|
||||
"users": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"payments": [
|
||||
{
|
||||
"currency": "",
|
||||
"detail": "",
|
||||
"displayName": "",
|
||||
"invoiceRemark": "",
|
||||
"invoiceTaxId": "",
|
||||
"invoiceTitle": "",
|
||||
"invoiceType": "",
|
||||
"invoiceUrl": "",
|
||||
"message": "",
|
||||
"name": "",
|
||||
"organization": "",
|
||||
"owner": "",
|
||||
"payUrl": "",
|
||||
"personEmail": "",
|
||||
"personIdCard": "",
|
||||
"personName": "",
|
||||
"personPhone": "",
|
||||
"price": 0,
|
||||
"productDisplayName": "",
|
||||
"productName": "",
|
||||
"provider": "",
|
||||
"returnUrl": "",
|
||||
"state": "",
|
||||
"tag": "",
|
||||
"type": "",
|
||||
"user": ""
|
||||
}
|
||||
],
|
||||
"products": [
|
||||
{
|
||||
"currency": "",
|
||||
"detail": "",
|
||||
"displayName": "",
|
||||
"image": "",
|
||||
"name": "",
|
||||
"owner": "",
|
||||
"price": 0,
|
||||
"providers": [
|
||||
""
|
||||
],
|
||||
"quantity": 0,
|
||||
"returnUrl": "",
|
||||
"sold": 0,
|
||||
"state": "",
|
||||
"tag": ""
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"owner": "",
|
||||
"name": "",
|
||||
"user": "",
|
||||
"provider": "",
|
||||
"application": "",
|
||||
"tag": "",
|
||||
"parent": "",
|
||||
"fileName": "",
|
||||
"fileType": "",
|
||||
"fileFormat": "",
|
||||
"url": "",
|
||||
"description": ""
|
||||
}
|
||||
],
|
||||
"roles": [
|
||||
{
|
||||
"displayName": "",
|
||||
"isEnabled": true,
|
||||
"name": "",
|
||||
"owner": "",
|
||||
"roles": [
|
||||
""
|
||||
],
|
||||
"users": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"syncers": [
|
||||
{
|
||||
"affiliationTable": "",
|
||||
"avatarBaseUrl": "",
|
||||
"database": "",
|
||||
"databaseType": "",
|
||||
"errorText": "",
|
||||
"host": "",
|
||||
"isEnabled": true,
|
||||
"name": "",
|
||||
"organization": "",
|
||||
"owner": "",
|
||||
"password": "",
|
||||
"port": 0,
|
||||
"syncInterval": 0,
|
||||
"table": "",
|
||||
"tableColumns": [
|
||||
{
|
||||
"casdoorName": "",
|
||||
"isHashed": true,
|
||||
"name": "",
|
||||
"type": "",
|
||||
"values": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"tablePrimaryKey": "",
|
||||
"type": "",
|
||||
"user": ""
|
||||
}
|
||||
],
|
||||
"tokens": [
|
||||
{
|
||||
"accessToken": "",
|
||||
"application": "",
|
||||
"code": "",
|
||||
"codeChallenge": "",
|
||||
"codeExpireIn": 0,
|
||||
"codeIsUsed": true,
|
||||
"createdTime": "",
|
||||
"expiresIn": 0,
|
||||
"name": "",
|
||||
"organization": "",
|
||||
"owner": "",
|
||||
"refreshToken": "",
|
||||
"scope": "",
|
||||
"tokenType": "",
|
||||
"user": ""
|
||||
}
|
||||
],
|
||||
"webhooks": [
|
||||
{
|
||||
"contentType": "",
|
||||
"events": [
|
||||
""
|
||||
],
|
||||
"headers": [
|
||||
{
|
||||
"name": "",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"isEnabled": true,
|
||||
"isUserExtended": true,
|
||||
"method": "",
|
||||
"name": "",
|
||||
"organization": "",
|
||||
"owner": "",
|
||||
"url": ""
|
||||
}
|
||||
]
|
||||
}
|
23
main.go
23
main.go
@ -18,11 +18,12 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/logs"
|
||||
_ "github.com/astaxie/beego/session/redis"
|
||||
"github.com/beego/beego"
|
||||
"github.com/beego/beego/logs"
|
||||
_ "github.com/beego/beego/session/redis"
|
||||
"github.com/casdoor/casdoor/authz"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/controllers"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/proxy"
|
||||
"github.com/casdoor/casdoor/routers"
|
||||
@ -36,15 +37,17 @@ func main() {
|
||||
|
||||
object.InitAdapter(*createDatabase)
|
||||
object.InitDb()
|
||||
object.InitFromFile()
|
||||
object.InitDefaultStorageProvider()
|
||||
object.InitLdapAutoSynchronizer()
|
||||
proxy.InitHttpClient()
|
||||
authz.InitAuthz()
|
||||
|
||||
util.SafeGoroutine(func() {object.RunSyncUsersJob()})
|
||||
util.SafeGoroutine(func() { object.RunSyncUsersJob() })
|
||||
|
||||
// beego.DelStaticPath("/static")
|
||||
// beego.SetStaticPath("/static", "web/build/static")
|
||||
|
||||
//beego.DelStaticPath("/static")
|
||||
beego.SetStaticPath("/static", "web/build/static")
|
||||
beego.BConfig.WebConfig.DirectoryIndex = true
|
||||
beego.SetStaticPath("/swagger", "swagger")
|
||||
beego.SetStaticPath("/files", "files")
|
||||
@ -55,6 +58,7 @@ func main() {
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.RecordMessage)
|
||||
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id"
|
||||
if conf.GetConfigString("redisEndpoint") == "" {
|
||||
beego.BConfig.WebConfig.Session.SessionProvider = "file"
|
||||
@ -64,14 +68,17 @@ func main() {
|
||||
beego.BConfig.WebConfig.Session.SessionProviderConfig = conf.GetConfigString("redisEndpoint")
|
||||
}
|
||||
beego.BConfig.WebConfig.Session.SessionCookieLifeTime = 3600 * 24 * 30
|
||||
//beego.BConfig.WebConfig.Session.SessionCookieSameSite = http.SameSiteNoneMode
|
||||
// beego.BConfig.WebConfig.Session.SessionCookieSameSite = http.SameSiteNoneMode
|
||||
|
||||
err := logs.SetLogger("file", `{"filename":"logs/casdoor.log","maxdays":99999,"perm":"0770"}`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
port := beego.AppConfig.DefaultInt("httpport", 8000)
|
||||
//logs.SetLevel(logs.LevelInformational)
|
||||
// logs.SetLevel(logs.LevelInformational)
|
||||
logs.SetLogFuncCall(false)
|
||||
|
||||
go controllers.StartLdapServer()
|
||||
|
||||
beego.Run(fmt.Sprintf(":%v", port))
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user