mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-09 01:13:41 +08:00
Compare commits
237 Commits
Author | SHA1 | Date | |
---|---|---|---|
dd51bbbabf | |||
5318519bf8 | |||
d7c40459c0 | |||
de2932b5fb | |||
f4c873ffe6 | |||
97c7f2631a | |||
93f0425759 | |||
6a00657e42 | |||
88130bf020 | |||
5e99007fc9 | |||
66aca3124c | |||
61deb75c84 | |||
b8db07db4d | |||
a681c267b3 | |||
5fb6ea0ab4 | |||
0f6b7984d4 | |||
ba9d6e5d78 | |||
a4524e9996 | |||
b469928780 | |||
dc6fe13f75 | |||
8227762988 | |||
d92b072ed0 | |||
1161310f81 | |||
48ba5f91ed | |||
53df2c2704 | |||
78066da208 | |||
60096468fe | |||
39d6bc10f7 | |||
177f2f2f11 | |||
79b393afee | |||
5bb12a30d4 | |||
fdb68bf9c8 | |||
37748850c8 | |||
8968396ae5 | |||
f5395f15f9 | |||
73e44df867 | |||
0b575ccf84 | |||
9b7f465a47 | |||
b1fe28fb83 | |||
530d054adb | |||
a2b9f9baaf | |||
a2d20fcb63 | |||
b118a3bb76 | |||
280867d0cb | |||
30fa2f7d81 | |||
518288691d | |||
ffa54247cd | |||
0199ad9aaa | |||
b9d171718f | |||
e841d0ba8e | |||
e5a9594f90 | |||
c542929835 | |||
86dea71efd | |||
9e536850fd | |||
fddd4a12b8 | |||
2d6fae32be | |||
741cff99df | |||
cad9c28e92 | |||
524cf4dda5 | |||
077a1cb8b7 | |||
00efdf1d03 | |||
aa543f1abb | |||
1d1d3049bd | |||
4f497d44a5 | |||
369de36987 | |||
e3f28e8b4c | |||
3373174c65 | |||
2fb79e4092 | |||
5846e337c7 | |||
44f4de1440 | |||
27adeb4620 | |||
5c107db43b | |||
27187b3a54 | |||
14fcedcc5d | |||
e7c015f288 | |||
c4819602ec | |||
dea03cdd15 | |||
21f394847e | |||
9bef9691fb | |||
141f22a707 | |||
02329d342a | |||
b9d3e2184c | |||
28caf8550e | |||
79159dc809 | |||
63081641d6 | |||
698f24f762 | |||
5499e62d7f | |||
f8905ae64c | |||
a42594859f | |||
46e0bc1a39 | |||
ffe2330238 | |||
ec53616dc8 | |||
067276d739 | |||
468ceb6b71 | |||
b31a317585 | |||
396b6fb65f | |||
be637fca81 | |||
374928e719 | |||
5c103e8cd3 | |||
85b86e8831 | |||
08864686f3 | |||
dc06eb9948 | |||
b068202e74 | |||
cb16567c7b | |||
4eb725d47a | |||
ce72a172b0 | |||
5521962e0c | |||
37b8b09cc0 | |||
482eb61168 | |||
8819a8697b | |||
85cb68eb66 | |||
b25b5f0249 | |||
947dcf6e75 | |||
113c27db73 | |||
badfe34755 | |||
a5f9f61381 | |||
2ce8c93ead | |||
da41ac7275 | |||
fd0c70a827 | |||
c4a6f07672 | |||
a67f541171 | |||
192968bac8 | |||
23d4488b64 | |||
23f4684e1d | |||
1a91e7b0f9 | |||
811999b6cc | |||
7786018051 | |||
6c72f86d03 | |||
5b151f4ec4 | |||
e9b7d1266f | |||
2d4998228c | |||
d3ed6c348b | |||
a22e05dcc1 | |||
0ac2b69f5a | |||
d090e9c860 | |||
8ebb158765 | |||
ea2f053630 | |||
988b14c6b5 | |||
a9e72ac3cb | |||
498cd02d49 | |||
a389842f59 | |||
6c69daa666 | |||
53c89bbe89 | |||
9442aa9f7a | |||
8a195715d0 | |||
b985bab3f3 | |||
477a090aa0 | |||
e082cf10e0 | |||
3215b88eae | |||
9703f3f712 | |||
140737b2f6 | |||
b285144a64 | |||
49c6ce2221 | |||
2398e69012 | |||
ade9de8256 | |||
1bf5497d08 | |||
cf10738f45 | |||
ac00713c20 | |||
febb27f765 | |||
49a981f787 | |||
34b1945180 | |||
b320cca789 | |||
b38654a45a | |||
f77fafae24 | |||
8b6b5ffe81 | |||
a147fa3e0b | |||
9d03665523 | |||
0106c7f7fa | |||
6713dad0af | |||
6ef2b51782 | |||
1732cd8538 | |||
a10548fe73 | |||
f6a7888f83 | |||
93efaa5459 | |||
0bfe683108 | |||
8a4758c22d | |||
ee3b46e91c | |||
37744d6cd7 | |||
98defe617b | |||
96cbf51ca0 | |||
22b57fdd23 | |||
b68e291f37 | |||
9960b4933b | |||
432a5496f2 | |||
45db4deb6b | |||
3f53591751 | |||
d7569684f6 | |||
a616127909 | |||
f2e2b960ff | |||
fbc603876f | |||
9ea77c63d1 | |||
53243a30f3 | |||
cbdeb91ee8 | |||
2dd1dc582f | |||
f3d4b45a0f | |||
2ee4aebd96 | |||
150e3e30d5 | |||
1055d7781b | |||
1c296e9b6f | |||
3d80ec721f | |||
43d849086f | |||
69b144d80f | |||
52a66ef044 | |||
ec0a8e16f7 | |||
80a8000057 | |||
77091a3ae5 | |||
983da685a2 | |||
3d567c3d45 | |||
440d87d70c | |||
e4208d7fd9 | |||
4de716fef3 | |||
070aa8a65f | |||
684cbdb951 | |||
9aec69ef47 | |||
98411ef67b | |||
71279f548d | |||
0096e47351 | |||
814d3f749b | |||
ec0f457c7f | |||
0033ae1ff1 | |||
d06d7c5c09 | |||
23c4fd8183 | |||
e3558894c3 | |||
2fd2d88d20 | |||
d0c424db0a | |||
6a9d1e0fe5 | |||
938e8e2699 | |||
620383cf33 | |||
de6cd380eb | |||
7e0bce2d0f | |||
1461268a51 | |||
5ec49dc883 | |||
5c89705d9e | |||
06e3b8481f | |||
81a8b91e3f | |||
56787fab90 | |||
1319216625 |
52
.github/workflows/build.yml
vendored
52
.github/workflows/build.yml
vendored
@ -1,6 +1,6 @@
|
|||||||
name: Build
|
name: Build
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [ push, pull_request ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
cache-dependency-path: ./web/yarn.lock
|
cache-dependency-path: ./web/yarn.lock
|
||||||
- run: yarn install && CI=false yarn run build
|
- run: yarn install && CI=false yarn run build
|
||||||
@ -101,7 +101,7 @@ jobs:
|
|||||||
working-directory: ./
|
working-directory: ./
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
cache-dependency-path: ./web/yarn.lock
|
cache-dependency-path: ./web/yarn.lock
|
||||||
- run: yarn install
|
- run: yarn install
|
||||||
@ -127,7 +127,7 @@ jobs:
|
|||||||
release-and-push:
|
release-and-push:
|
||||||
name: Release And Push
|
name: Release And Push
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push'
|
if: github.repository == 'casbin/casdoor' && github.event_name == 'push'
|
||||||
needs: [ frontend, backend, linter, e2e ]
|
needs: [ frontend, backend, linter, e2e ]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@ -137,7 +137,7 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 18
|
||||||
|
|
||||||
- name: Fetch Previous version
|
- name: Fetch Previous version
|
||||||
id: get-previous-tag
|
id: get-previous-tag
|
||||||
@ -167,10 +167,8 @@ jobs:
|
|||||||
elif [ ${old_array[1]} != ${new_array[1]} ]
|
elif [ ${old_array[1]} != ${new_array[1]} ]
|
||||||
then
|
then
|
||||||
echo ::set-output name=push::'true'
|
echo ::set-output name=push::'true'
|
||||||
|
|
||||||
else
|
else
|
||||||
echo ::set-output name=push::'false'
|
echo ::set-output name=push::'false'
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
@ -184,27 +182,57 @@ jobs:
|
|||||||
|
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
if: github.repository == 'casbin/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
|
||||||
- name: Push to Docker Hub
|
- name: Push to Docker Hub
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
if: github.repository == 'casbin/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
target: STANDARD
|
target: STANDARD
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64
|
||||||
push: true
|
push: true
|
||||||
tags: casbin/casdoor:${{steps.get-current-tag.outputs.tag }},casbin/casdoor:latest
|
tags: casbin/casdoor:${{steps.get-current-tag.outputs.tag }},casbin/casdoor:latest
|
||||||
|
|
||||||
- name: Push All In One Version to Docker Hub
|
- name: Push All In One Version to Docker Hub
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
if: github.repository == 'casbin/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
target: ALLINONE
|
target: ALLINONE
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64
|
||||||
push: true
|
push: true
|
||||||
tags: casbin/casdoor-all-in-one:${{steps.get-current-tag.outputs.tag }},casbin/casdoor-all-in-one:latest
|
tags: casbin/casdoor-all-in-one:${{steps.get-current-tag.outputs.tag }},casbin/casdoor-all-in-one:latest
|
||||||
|
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
if: steps.should_push.outputs.push=='true'
|
||||||
|
with:
|
||||||
|
repository: casdoor/casdoor-helm
|
||||||
|
ref: 'master'
|
||||||
|
token: ${{ secrets.GH_BOT_TOKEN }}
|
||||||
|
|
||||||
|
- name: Update Helm Chart
|
||||||
|
if: steps.should_push.outputs.push=='true'
|
||||||
|
run: |
|
||||||
|
# Set the appVersion and version of the chart to the current tag
|
||||||
|
sed -i "s/appVersion: .*/appVersion: ${{steps.get-current-tag.outputs.tag }}/g" ./charts/casdoor/Chart.yaml
|
||||||
|
sed -i "s/version: .*/version: ${{steps.get-current-tag.outputs.tag }}/g" ./charts/casdoor/Chart.yaml
|
||||||
|
|
||||||
|
REGISTRY=oci://registry-1.docker.io/casbin
|
||||||
|
cd charts/casdoor
|
||||||
|
helm package .
|
||||||
|
PKG_NAME=$(ls *.tgz)
|
||||||
|
helm repo index . --url $REGISTRY --merge index.yaml
|
||||||
|
helm push $PKG_NAME $REGISTRY
|
||||||
|
rm $PKG_NAME
|
||||||
|
|
||||||
|
# Commit and push the changes back to the repository
|
||||||
|
git config --global user.name "casbin-bot"
|
||||||
|
git config --global user.email "bot@casbin.org"
|
||||||
|
git add Chart.yaml index.yaml
|
||||||
|
git commit -m "chore(helm): bump helm charts appVersion to ${{steps.get-current-tag.outputs.tag }}"
|
||||||
|
git tag ${{steps.get-current-tag.outputs.tag }}
|
||||||
|
git push origin HEAD:master --follow-tags
|
||||||
|
61
.github/workflows/migrate.yml
vendored
61
.github/workflows/migrate.yml
vendored
@ -1,61 +0,0 @@
|
|||||||
name: Migration Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'object/migrator**'
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- 'object/migrator**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
db-migrator-test:
|
|
||||||
name: db-migrator-test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
services:
|
|
||||||
mysql:
|
|
||||||
image: mysql:5.7
|
|
||||||
env:
|
|
||||||
MYSQL_DATABASE: casdoor
|
|
||||||
MYSQL_ROOT_PASSWORD: 123456
|
|
||||||
ports:
|
|
||||||
- 3306:3306
|
|
||||||
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/setup-go@v2
|
|
||||||
with:
|
|
||||||
go-version: '^1.16.5'
|
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- name: pull casdoor-master-latest
|
|
||||||
run: |
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install git
|
|
||||||
sudo apt install net-tools
|
|
||||||
sudo mkdir tmp
|
|
||||||
cd tmp
|
|
||||||
sudo git clone https://github.com/casdoor/casdoor.git
|
|
||||||
cd ..
|
|
||||||
working-directory: ./
|
|
||||||
- name: run casdoor-master-latest
|
|
||||||
run: |
|
|
||||||
sudo nohup go run main.go &
|
|
||||||
sudo sleep 2m
|
|
||||||
working-directory: ./tmp/casdoor
|
|
||||||
- name: stop casdoor-master-latest
|
|
||||||
run: |
|
|
||||||
sudo kill -9 `sudo netstat -anltp | grep 8000 | awk '{print $7}' | cut -d / -f 1`
|
|
||||||
working-directory: ./
|
|
||||||
- name: run casdoor-current-version
|
|
||||||
run: |
|
|
||||||
sudo nohup go run ./main.go &
|
|
||||||
sudo sleep 2m
|
|
||||||
working-directory: ./
|
|
||||||
- name: test port-8000
|
|
||||||
run: |
|
|
||||||
if [[ `sudo netstat -anltp | grep 8000 | awk '{print $7}'` == "" ]];then echo 'db-migrator-test fail' && exit 1;fi;
|
|
||||||
echo 'db-migrator-test pass'
|
|
||||||
working-directory: ./
|
|
2
.github/workflows/sync.yml
vendored
2
.github/workflows/sync.yml
vendored
@ -7,7 +7,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
synchronize-with-crowdin:
|
synchronize-with-crowdin:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push'
|
if: github.repository == 'casbin/casdoor' && github.event_name == 'push'
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -18,7 +18,7 @@ bin/
|
|||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
*.iml
|
*.iml
|
||||||
.vscode/
|
.vscode/settings.json
|
||||||
|
|
||||||
tmp/
|
tmp/
|
||||||
tmpFiles/
|
tmpFiles/
|
||||||
@ -30,5 +30,7 @@ commentsRouter*.go
|
|||||||
|
|
||||||
# ignore build result
|
# ignore build result
|
||||||
casdoor
|
casdoor
|
||||||
server_linux_arm64
|
server
|
||||||
server_linux_amd64
|
|
||||||
|
# include helm-chart
|
||||||
|
!manifests/casdoor
|
||||||
|
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Debug",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "${workspaceFolder}",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"debugAdapter": "dlv-dap",
|
||||||
|
"args": ["--createDatabase=true"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
15
Dockerfile
15
Dockerfile
@ -1,11 +1,10 @@
|
|||||||
FROM node:16.18.0 AS FRONT
|
FROM node:18.19.0 AS FRONT
|
||||||
WORKDIR /web
|
WORKDIR /web
|
||||||
COPY ./web .
|
COPY ./web .
|
||||||
RUN yarn config set registry https://registry.npmmirror.com
|
|
||||||
RUN yarn install --frozen-lockfile --network-timeout 1000000 && yarn run build
|
RUN yarn install --frozen-lockfile --network-timeout 1000000 && yarn run build
|
||||||
|
|
||||||
|
|
||||||
FROM golang:1.19.9 AS BACK
|
FROM golang:1.20.12 AS BACK
|
||||||
WORKDIR /go/src/casdoor
|
WORKDIR /go/src/casdoor
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN ./build.sh
|
RUN ./build.sh
|
||||||
@ -14,9 +13,6 @@ RUN go test -v -run TestGetVersionInfo ./util/system_test.go ./util/system.go >
|
|||||||
FROM alpine:latest AS STANDARD
|
FROM alpine:latest AS STANDARD
|
||||||
LABEL MAINTAINER="https://casdoor.org/"
|
LABEL MAINTAINER="https://casdoor.org/"
|
||||||
ARG USER=casdoor
|
ARG USER=casdoor
|
||||||
ARG TARGETOS
|
|
||||||
ARG TARGETARCH
|
|
||||||
ENV BUILDX_ARCH="${TARGETOS:-linux}_${TARGETARCH:-amd64}"
|
|
||||||
|
|
||||||
RUN sed -i 's/https/http/' /etc/apk/repositories
|
RUN sed -i 's/https/http/' /etc/apk/repositories
|
||||||
RUN apk add --update sudo
|
RUN apk add --update sudo
|
||||||
@ -31,7 +27,7 @@ RUN adduser -D $USER -u 1000 \
|
|||||||
|
|
||||||
USER 1000
|
USER 1000
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/server_${BUILDX_ARCH} ./server
|
COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/server ./server
|
||||||
COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/swagger ./swagger
|
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=BACK --chown=$USER:$USER /go/src/casdoor/conf/app.conf ./conf/app.conf
|
||||||
COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/version_info.txt ./go/src/casdoor/version_info.txt
|
COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/version_info.txt ./go/src/casdoor/version_info.txt
|
||||||
@ -50,15 +46,12 @@ RUN apt update \
|
|||||||
|
|
||||||
FROM db AS ALLINONE
|
FROM db AS ALLINONE
|
||||||
LABEL MAINTAINER="https://casdoor.org/"
|
LABEL MAINTAINER="https://casdoor.org/"
|
||||||
ARG TARGETOS
|
|
||||||
ARG TARGETARCH
|
|
||||||
ENV BUILDX_ARCH="${TARGETOS:-linux}_${TARGETARCH:-amd64}"
|
|
||||||
|
|
||||||
RUN apt update
|
RUN apt update
|
||||||
RUN apt install -y ca-certificates && update-ca-certificates
|
RUN apt install -y ca-certificates && update-ca-certificates
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
COPY --from=BACK /go/src/casdoor/server_${BUILDX_ARCH} ./server
|
COPY --from=BACK /go/src/casdoor/server ./server
|
||||||
COPY --from=BACK /go/src/casdoor/swagger ./swagger
|
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/docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
COPY --from=BACK /go/src/casdoor/conf/app.conf ./conf/app.conf
|
COPY --from=BACK /go/src/casdoor/conf/app.conf ./conf/app.conf
|
||||||
|
3
Makefile
3
Makefile
@ -86,6 +86,9 @@ docker-build: ## Build docker image with the manager.
|
|||||||
docker-push: ## Push docker image with the manager.
|
docker-push: ## Push docker image with the manager.
|
||||||
docker push ${REGISTRY}/${IMG}:${IMG_TAG}
|
docker push ${REGISTRY}/${IMG}:${IMG_TAG}
|
||||||
|
|
||||||
|
deps: ## Run dependencies for local development
|
||||||
|
docker compose up -d db
|
||||||
|
|
||||||
lint-install: ## Install golangci-lint
|
lint-install: ## Install golangci-lint
|
||||||
@# The following installs a specific version of golangci-lint, which is appropriate for a CI server to avoid different results from build to build
|
@# The following installs a specific version of golangci-lint, which is appropriate for a CI server to avoid different results from build to build
|
||||||
go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.40.1
|
go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.40.1
|
||||||
|
17
README.md
17
README.md
@ -1,5 +1,5 @@
|
|||||||
<h1 align="center" style="border-bottom: none;">📦⚡️ Casdoor</h1>
|
<h1 align="center" style="border-bottom: none;">📦⚡️ Casdoor</h1>
|
||||||
<h3 align="center">A UI-first centralized authentication / Single-Sign-On (SSO) platform based on OAuth 2.0 / OIDC.</h3>
|
<h3 align="center">An open-source UI-first Identity and Access Management (IAM) / Single-Sign-On (SSO) platform with web UI supporting OAuth 2.0, OIDC, SAML, CAS, LDAP, SCIM, WebAuthn, TOTP, MFA and RADIUS</h3>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="#badge">
|
<a href="#badge">
|
||||||
<img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
|
<img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
|
||||||
@ -42,6 +42,20 @@
|
|||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<sup>Sponsored by</sup>
|
||||||
|
<br>
|
||||||
|
<a href="https://stytch.com/docs?utm_source=oss-sponsorship&utm_medium=paid_sponsorship&utm_campaign=casbin">
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.casbin.org/img/stytch-white.png">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="https://cdn.casbin.org/img/stytch-charcoal.png">
|
||||||
|
<img src="https://cdn.casbin.org/img/stytch-charcoal.png" width="275">
|
||||||
|
</picture>
|
||||||
|
</a><br/>
|
||||||
|
<a href="https://stytch.com/docs?utm_source=oss-sponsorship&utm_medium=paid_sponsorship&utm_campaign=casbin"><b>Build auth with fraud prevention, faster.</b><br/> Try Stytch for API-first authentication, user & org management, multi-tenant SSO, MFA, device fingerprinting, and more.</a>
|
||||||
|
<br>
|
||||||
|
</p>
|
||||||
|
|
||||||
## Online demo
|
## Online demo
|
||||||
|
|
||||||
- Read-only site: https://door.casdoor.com (any modification operation will fail)
|
- Read-only site: https://door.casdoor.com (any modification operation will fail)
|
||||||
@ -55,6 +69,7 @@ https://casdoor.org
|
|||||||
|
|
||||||
- By source code: https://casdoor.org/docs/basic/server-installation
|
- By source code: https://casdoor.org/docs/basic/server-installation
|
||||||
- By Docker: https://casdoor.org/docs/basic/try-with-docker
|
- By Docker: https://casdoor.org/docs/basic/try-with-docker
|
||||||
|
- By Kubernetes Helm: https://casdoor.org/docs/basic/try-with-helm
|
||||||
|
|
||||||
## How to connect to Casdoor?
|
## How to connect to Casdoor?
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ p, *, *, GET, /api/get-saml-login, *, *
|
|||||||
p, *, *, POST, /api/acs, *, *
|
p, *, *, POST, /api/acs, *, *
|
||||||
p, *, *, GET, /api/saml/metadata, *, *
|
p, *, *, GET, /api/saml/metadata, *, *
|
||||||
p, *, *, *, /cas, *, *
|
p, *, *, *, /cas, *, *
|
||||||
|
p, *, *, *, /scim, *, *
|
||||||
p, *, *, *, /api/webauthn, *, *
|
p, *, *, *, /api/webauthn, *, *
|
||||||
p, *, *, GET, /api/get-release, *, *
|
p, *, *, GET, /api/get-release, *, *
|
||||||
p, *, *, GET, /api/get-default-application, *, *
|
p, *, *, GET, /api/get-default-application, *, *
|
||||||
@ -91,11 +92,14 @@ p, *, *, GET, /api/get-plan, *, *
|
|||||||
p, *, *, GET, /api/get-subscription, *, *
|
p, *, *, GET, /api/get-subscription, *, *
|
||||||
p, *, *, GET, /api/get-provider, *, *
|
p, *, *, GET, /api/get-provider, *, *
|
||||||
p, *, *, GET, /api/get-organization-names, *, *
|
p, *, *, GET, /api/get-organization-names, *, *
|
||||||
|
p, *, *, GET, /api/get-all-objects, *, *
|
||||||
|
p, *, *, GET, /api/get-all-actions, *, *
|
||||||
|
p, *, *, GET, /api/get-all-roles, *, *
|
||||||
`
|
`
|
||||||
|
|
||||||
sa := stringadapter.NewAdapter(ruleText)
|
sa := stringadapter.NewAdapter(ruleText)
|
||||||
// load all rules from string adapter to enforcer's memory
|
// load all rules from string adapter to enforcer's memory
|
||||||
err := sa.LoadPolicy(Enforcer.GetModel())
|
err = sa.LoadPolicy(Enforcer.GetModel())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -126,8 +130,14 @@ func IsAllowed(subOwner string, subName string, method string, urlPath string, o
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if user != nil && user.IsAdmin && (subOwner == objOwner || (objOwner == "admin")) {
|
if user != nil {
|
||||||
return true
|
if user.IsDeleted {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.IsAdmin && (subOwner == objOwner || (objOwner == "admin")) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := Enforcer.Enforce(subOwner, subName, method, urlPath, objOwner, objName)
|
res, err := Enforcer.Enforce(subOwner, subName, method, urlPath, objOwner, objName)
|
||||||
@ -140,11 +150,11 @@ func IsAllowed(subOwner string, subName string, method string, urlPath string, o
|
|||||||
|
|
||||||
func isAllowedInDemoMode(subOwner string, subName string, method string, urlPath string, objOwner string, objName string) bool {
|
func isAllowedInDemoMode(subOwner string, subName string, method string, urlPath string, objOwner string, objName string) bool {
|
||||||
if method == "POST" {
|
if method == "POST" {
|
||||||
if strings.HasPrefix(urlPath, "/api/login") || urlPath == "/api/logout" || urlPath == "/api/signup" || urlPath == "/api/send-verification-code" || urlPath == "/api/send-email" || urlPath == "/api/verify-captcha" {
|
if strings.HasPrefix(urlPath, "/api/login") || urlPath == "/api/logout" || urlPath == "/api/signup" || urlPath == "/api/callback" || urlPath == "/api/send-verification-code" || urlPath == "/api/send-email" || urlPath == "/api/verify-captcha" || urlPath == "/api/verify-code" || urlPath == "/api/check-user-password" || strings.HasPrefix(urlPath, "/api/mfa/") {
|
||||||
return true
|
return true
|
||||||
} else if urlPath == "/api/update-user" {
|
} else if urlPath == "/api/update-user" {
|
||||||
// Allow ordinary users to update their own information
|
// Allow ordinary users to update their own information
|
||||||
if subOwner == objOwner && subName == objName && !(subOwner == "built-in" && subName == "admin") {
|
if (subOwner == objOwner && subName == objName || subOwner == "app") && !(subOwner == "built-in" && subName == "admin") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
3
build.sh
3
build.sh
@ -8,5 +8,4 @@ else
|
|||||||
echo "Google is blocked, Go proxy is enabled: GOPROXY=https://goproxy.cn,direct"
|
echo "Google is blocked, Go proxy is enabled: GOPROXY=https://goproxy.cn,direct"
|
||||||
export GOPROXY="https://goproxy.cn,direct"
|
export GOPROXY="https://goproxy.cn,direct"
|
||||||
fi
|
fi
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o server_linux_amd64 .
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o server .
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-w -s" -o server_linux_arm64 .
|
|
||||||
|
@ -8,20 +8,23 @@ dbName = casdoor
|
|||||||
tableNamePrefix =
|
tableNamePrefix =
|
||||||
showSql = false
|
showSql = false
|
||||||
redisEndpoint =
|
redisEndpoint =
|
||||||
defaultStorageProvider =
|
defaultStorageProvider =
|
||||||
isCloudIntranet = false
|
isCloudIntranet = false
|
||||||
authState = "casdoor"
|
authState = "casdoor"
|
||||||
socks5Proxy = "127.0.0.1:10808"
|
socks5Proxy = "127.0.0.1:10808"
|
||||||
verificationCodeTimeout = 10
|
verificationCodeTimeout = 10
|
||||||
initScore = 2000
|
initScore = 0
|
||||||
logPostOnly = true
|
logPostOnly = true
|
||||||
origin =
|
origin =
|
||||||
|
originFrontend =
|
||||||
staticBaseUrl = "https://cdn.casbin.org"
|
staticBaseUrl = "https://cdn.casbin.org"
|
||||||
isDemoMode = false
|
isDemoMode = false
|
||||||
batchSize = 100
|
batchSize = 100
|
||||||
|
enableGzip = true
|
||||||
ldapServerPort = 389
|
ldapServerPort = 389
|
||||||
radiusServerPort = 1812
|
radiusServerPort = 1812
|
||||||
radiusSecret = "secret"
|
radiusSecret = "secret"
|
||||||
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
||||||
logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
|
logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
|
||||||
initDataFile = "./init_data.json"
|
initDataFile = "./init_data.json"
|
||||||
|
frontendBaseDir = "../casdoor"
|
@ -56,6 +56,17 @@ type Captcha struct {
|
|||||||
SubType string `json:"subType"`
|
SubType string `json:"subType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this API is used by "Api URL" of Flarum's FoF Passport plugin
|
||||||
|
// https://github.com/FriendsOfFlarum/passport
|
||||||
|
type LaravelResponse struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
EmailVerifiedAt string `json:"email_verified_at"`
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
// Signup
|
// Signup
|
||||||
// @Tag Login API
|
// @Tag Login API
|
||||||
// @Title Signup
|
// @Title Signup
|
||||||
@ -100,6 +111,16 @@ func (c *ApiController) Signup() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
invitation, msg := object.CheckInvitationCode(application, organization, &authForm, c.GetAcceptLanguage())
|
||||||
|
if msg != "" {
|
||||||
|
c.ResponseError(msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
invitationName := ""
|
||||||
|
if invitation != nil {
|
||||||
|
invitationName = invitation.Name
|
||||||
|
}
|
||||||
|
|
||||||
if application.IsSignupItemVisible("Email") && application.GetSignupItemRule("Email") != "No verification" && authForm.Email != "" {
|
if application.IsSignupItemVisible("Email") && application.GetSignupItemRule("Email") != "No verification" && authForm.Email != "" {
|
||||||
checkResult := object.CheckVerificationCode(authForm.Email, authForm.EmailCode, c.GetAcceptLanguage())
|
checkResult := object.CheckVerificationCode(authForm.Email, authForm.EmailCode, c.GetAcceptLanguage())
|
||||||
if checkResult.Code != object.VerificationSuccess {
|
if checkResult.Code != object.VerificationSuccess {
|
||||||
@ -168,6 +189,8 @@ func (c *ApiController) Signup() {
|
|||||||
SignupApplication: application.Name,
|
SignupApplication: application.Name,
|
||||||
Properties: map[string]string{},
|
Properties: map[string]string{},
|
||||||
Karma: 0,
|
Karma: 0,
|
||||||
|
Invitation: invitationName,
|
||||||
|
InvitationCode: authForm.InvitationCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(organization.Tags) > 0 {
|
if len(organization.Tags) > 0 {
|
||||||
@ -202,6 +225,15 @@ func (c *ApiController) Signup() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if invitation != nil {
|
||||||
|
invitation.UsedCount += 1
|
||||||
|
_, err := object.UpdateInvitation(invitation.GetId(), invitation)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if application.HasPromptPage() && user.Type == "normal-user" {
|
if application.HasPromptPage() && user.Type == "normal-user" {
|
||||||
// The prompt page needs the user to be signed in
|
// The prompt page needs the user to be signed in
|
||||||
c.SetSessionUsername(user.GetId())
|
c.SetSessionUsername(user.GetId())
|
||||||
@ -238,7 +270,7 @@ func (c *ApiController) Signup() {
|
|||||||
// @Param post_logout_redirect_uri query string false "post_logout_redirect_uri"
|
// @Param post_logout_redirect_uri query string false "post_logout_redirect_uri"
|
||||||
// @Param state query string false "state"
|
// @Param state query string false "state"
|
||||||
// @Success 200 {object} controllers.Response The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /logout [get,post]
|
// @router /logout [post]
|
||||||
func (c *ApiController) Logout() {
|
func (c *ApiController) Logout() {
|
||||||
// https://openid.net/specs/openid-connect-rpinitiated-1_0-final.html
|
// https://openid.net/specs/openid-connect-rpinitiated-1_0-final.html
|
||||||
accessToken := c.Input().Get("id_token_hint")
|
accessToken := c.Input().Get("id_token_hint")
|
||||||
@ -282,17 +314,15 @@ func (c *ApiController) Logout() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
affected, application, token, err := object.ExpireTokenByAccessToken(accessToken)
|
_, application, token, err := object.ExpireTokenByAccessToken(accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if token == nil {
|
||||||
if !affected {
|
|
||||||
c.ResponseError(c.T("token:Token not found, invalid accessToken"))
|
c.ResponseError(c.T("token:Token not found, invalid accessToken"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if application == nil {
|
if application == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist")), token.Application)
|
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist")), token.Application)
|
||||||
return
|
return
|
||||||
@ -319,7 +349,15 @@ func (c *ApiController) Logout() {
|
|||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
if application.IsRedirectUriValid(redirectUri) {
|
if application.IsRedirectUriValid(redirectUri) {
|
||||||
c.Ctx.Redirect(http.StatusFound, fmt.Sprintf("%s?state=%s", strings.TrimRight(redirectUri, "/"), state))
|
redirectUrl := redirectUri
|
||||||
|
if state != "" {
|
||||||
|
if strings.Contains(redirectUri, "?") {
|
||||||
|
redirectUrl = fmt.Sprintf("%s&state=%s", strings.TrimSuffix(redirectUri, "/"), state)
|
||||||
|
} else {
|
||||||
|
redirectUrl = fmt.Sprintf("%s?state=%s", strings.TrimSuffix(redirectUri, "/"), state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.Ctx.Redirect(http.StatusFound, redirectUrl)
|
||||||
} else {
|
} else {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), redirectUri))
|
c.ResponseError(fmt.Sprintf(c.T("token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), redirectUri))
|
||||||
return
|
return
|
||||||
@ -412,7 +450,7 @@ func (c *ApiController) GetUserinfo() {
|
|||||||
// @Title UserInfo2
|
// @Title UserInfo2
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Description return Laravel compatible user information according to OAuth 2.0
|
// @Description return Laravel compatible user information according to OAuth 2.0
|
||||||
// @Success 200 {object} LaravelResponse The Response object
|
// @Success 200 {object} controllers.LaravelResponse The Response object
|
||||||
// @router /user [get]
|
// @router /user [get]
|
||||||
func (c *ApiController) GetUserinfo2() {
|
func (c *ApiController) GetUserinfo2() {
|
||||||
user, ok := c.RequireSignedInUser()
|
user, ok := c.RequireSignedInUser()
|
||||||
@ -420,17 +458,6 @@ func (c *ApiController) GetUserinfo2() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// this API is used by "Api URL" of Flarum's FoF Passport plugin
|
|
||||||
// https://github.com/FriendsOfFlarum/passport
|
|
||||||
type LaravelResponse struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
EmailVerifiedAt string `json:"email_verified_at"`
|
|
||||||
CreatedAt string `json:"created_at"`
|
|
||||||
UpdatedAt string `json:"updated_at"`
|
|
||||||
}
|
|
||||||
|
|
||||||
response := LaravelResponse{
|
response := LaravelResponse{
|
||||||
Id: user.Id,
|
Id: user.Id,
|
||||||
Name: user.Name,
|
Name: user.Name,
|
||||||
@ -447,7 +474,8 @@ func (c *ApiController) GetUserinfo2() {
|
|||||||
// GetCaptcha ...
|
// GetCaptcha ...
|
||||||
// @Tag Login API
|
// @Tag Login API
|
||||||
// @Title GetCaptcha
|
// @Title GetCaptcha
|
||||||
// @router /api/get-captcha [get]
|
// @router /get-captcha [get]
|
||||||
|
// @Success 200 {object} object.Userinfo The Response object
|
||||||
func (c *ApiController) GetCaptcha() {
|
func (c *ApiController) GetCaptcha() {
|
||||||
applicationId := c.Input().Get("applicationId")
|
applicationId := c.Input().Get("applicationId")
|
||||||
isCurrentProvider := c.Input().Get("isCurrentProvider")
|
isCurrentProvider := c.Input().Get("isCurrentProvider")
|
||||||
@ -473,7 +501,7 @@ func (c *ApiController) GetCaptcha() {
|
|||||||
Type: captchaProvider.Type,
|
Type: captchaProvider.Type,
|
||||||
SubType: captchaProvider.SubType,
|
SubType: captchaProvider.SubType,
|
||||||
ClientId: captchaProvider.ClientId,
|
ClientId: captchaProvider.ClientId,
|
||||||
ClientSecret: captchaProvider.ClientSecret,
|
ClientSecret: "***",
|
||||||
ClientId2: captchaProvider.ClientId2,
|
ClientId2: captchaProvider.ClientId2,
|
||||||
ClientSecret2: captchaProvider.ClientSecret2,
|
ClientSecret2: captchaProvider.ClientSecret2,
|
||||||
})
|
})
|
||||||
|
@ -173,6 +173,12 @@ func (c *ApiController) GetOrganizationApplications() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applications, err = object.GetAllowedApplications(applications, userId)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.ResponseOk(object.GetMaskedApplications(applications, userId))
|
c.ResponseOk(object.GetMaskedApplications(applications, userId))
|
||||||
} else {
|
} else {
|
||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
|
@ -34,6 +34,7 @@ import (
|
|||||||
"github.com/casdoor/casdoor/proxy"
|
"github.com/casdoor/casdoor/proxy"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -154,7 +155,8 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
resp = &Response{Status: "error", Msg: fmt.Sprintf("error: grant_type: %s is not supported in this application", form.Type), Data: ""}
|
resp = &Response{Status: "error", Msg: fmt.Sprintf("error: grant_type: %s is not supported in this application", form.Type), Data: ""}
|
||||||
} else {
|
} else {
|
||||||
scope := c.Input().Get("scope")
|
scope := c.Input().Get("scope")
|
||||||
token, _ := object.GetTokenByUser(application, user, scope, c.Ctx.Request.Host)
|
nonce := c.Input().Get("nonce")
|
||||||
|
token, _ := object.GetTokenByUser(application, user, scope, nonce, c.Ctx.Request.Host)
|
||||||
resp = tokenToResponse(token)
|
resp = tokenToResponse(token)
|
||||||
}
|
}
|
||||||
} else if form.Type == ResponseTypeSaml { // saml flow
|
} else if form.Type == ResponseTypeSaml { // saml flow
|
||||||
@ -220,7 +222,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
// @Param redirectUri query string true "redirect uri"
|
// @Param redirectUri query string true "redirect uri"
|
||||||
// @Param scope query string true "scope"
|
// @Param scope query string true "scope"
|
||||||
// @Param state query string true "state"
|
// @Param state query string true "state"
|
||||||
// @Success 200 {object} Response The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /get-app-login [get]
|
// @router /get-app-login [get]
|
||||||
func (c *ApiController) GetApplicationLogin() {
|
func (c *ApiController) GetApplicationLogin() {
|
||||||
clientId := c.Input().Get("clientId")
|
clientId := c.Input().Get("clientId")
|
||||||
@ -331,8 +333,6 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var user *object.User
|
var user *object.User
|
||||||
var msg string
|
|
||||||
|
|
||||||
if authForm.Password == "" {
|
if authForm.Password == "" {
|
||||||
if user, err = object.GetUserByFields(authForm.Organization, authForm.Username); err != nil {
|
if user, err = object.GetUserByFields(authForm.Organization, authForm.Username); err != nil {
|
||||||
c.ResponseError(err.Error(), nil)
|
c.ResponseError(err.Error(), nil)
|
||||||
@ -342,7 +342,28 @@ func (c *ApiController) Login() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var application *object.Application
|
||||||
|
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error(), nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if application == nil {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
verificationCodeType := object.GetVerifyType(authForm.Username)
|
verificationCodeType := object.GetVerifyType(authForm.Username)
|
||||||
|
if verificationCodeType == object.VerifyTypeEmail && !application.IsCodeSigninViaEmailEnabled() {
|
||||||
|
c.ResponseError(c.T("auth:The login method: login with email is not enabled for the application"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if verificationCodeType == object.VerifyTypePhone && !application.IsCodeSigninViaSmsEnabled() {
|
||||||
|
c.ResponseError(c.T("auth:The login method: login with SMS is not enabled for the application"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var checkDest string
|
var checkDest string
|
||||||
if verificationCodeType == object.VerifyTypePhone {
|
if verificationCodeType == object.VerifyTypePhone {
|
||||||
authForm.CountryCode = user.GetCountryCode(authForm.CountryCode)
|
authForm.CountryCode = user.GetCountryCode(authForm.CountryCode)
|
||||||
@ -354,20 +375,21 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check result through Email or Phone
|
// check result through Email or Phone
|
||||||
checkResult := object.CheckSigninCode(user, checkDest, authForm.Code, c.GetAcceptLanguage())
|
err = object.CheckSigninCode(user, checkDest, authForm.Code, c.GetAcceptLanguage())
|
||||||
if len(checkResult) != 0 {
|
if err != nil {
|
||||||
c.ResponseError(fmt.Sprintf("%s - %s", verificationCodeType, checkResult))
|
c.ResponseError(fmt.Sprintf("%s - %s", verificationCodeType, err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable the verification code
|
// disable the verification code
|
||||||
err := object.DisableVerificationCode(checkDest)
|
err = object.DisableVerificationCode(checkDest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error(), nil)
|
c.ResponseError(err.Error(), nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
|
var application *object.Application
|
||||||
|
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error(), nil)
|
c.ResponseError(err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -377,16 +399,31 @@ func (c *ApiController) Login() {
|
|||||||
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !application.EnablePassword {
|
if authForm.SigninMethod == "Password" && !application.IsPasswordEnabled() {
|
||||||
c.ResponseError(c.T("auth:The login method: login with password is not enabled for the application"))
|
c.ResponseError(c.T("auth:The login method: login with password is not enabled for the application"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if authForm.SigninMethod == "LDAP" && !application.IsLdapEnabled() {
|
||||||
|
c.ResponseError(c.T("auth:The login method: login with LDAP is not enabled for the application"))
|
||||||
|
return
|
||||||
|
}
|
||||||
var enableCaptcha bool
|
var enableCaptcha bool
|
||||||
if enableCaptcha, err = object.CheckToEnableCaptcha(application, authForm.Organization, authForm.Username); err != nil {
|
if enableCaptcha, err = object.CheckToEnableCaptcha(application, authForm.Organization, authForm.Username); err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
} else if enableCaptcha {
|
} else if enableCaptcha {
|
||||||
isHuman, err := captcha.VerifyCaptchaByCaptchaType(authForm.CaptchaType, authForm.CaptchaToken, authForm.ClientSecret)
|
captchaProvider, err := object.GetCaptchaProviderByApplication(util.GetId(application.Owner, application.Name), "false", c.GetAcceptLanguage())
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if captchaProvider.Type != "Default" {
|
||||||
|
authForm.ClientSecret = captchaProvider.ClientSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
var isHuman bool
|
||||||
|
isHuman, err = captcha.VerifyCaptchaByCaptchaType(authForm.CaptchaType, authForm.CaptchaToken, authForm.ClientSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -399,13 +436,22 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
password := authForm.Password
|
password := authForm.Password
|
||||||
user, msg = object.CheckUserPassword(authForm.Organization, authForm.Username, password, c.GetAcceptLanguage(), enableCaptcha)
|
isSigninViaLdap := authForm.SigninMethod == "LDAP"
|
||||||
|
var isPasswordWithLdapEnabled bool
|
||||||
|
if authForm.SigninMethod == "Password" {
|
||||||
|
isPasswordWithLdapEnabled = application.IsPasswordWithLdapEnabled()
|
||||||
|
} else {
|
||||||
|
isPasswordWithLdapEnabled = false
|
||||||
|
}
|
||||||
|
user, err = object.CheckUserPassword(authForm.Organization, authForm.Username, password, c.GetAcceptLanguage(), enableCaptcha, isSigninViaLdap, isPasswordWithLdapEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg != "" {
|
if err != nil {
|
||||||
resp = &Response{Status: "error", Msg: msg}
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
|
var application *object.Application
|
||||||
|
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -416,7 +462,8 @@ func (c *ApiController) Login() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
organization, err := object.GetOrganizationByUser(user)
|
var organization *object.Organization
|
||||||
|
organization, err = object.GetOrganizationByUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
}
|
}
|
||||||
@ -461,12 +508,15 @@ func (c *ApiController) Login() {
|
|||||||
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
organization, err := object.GetOrganization(util.GetId("admin", application.Organization))
|
|
||||||
|
var organization *object.Organization
|
||||||
|
organization, err = object.GetOrganization(util.GetId("admin", application.Organization))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(c.T(err.Error()))
|
c.ResponseError(c.T(err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := object.GetProvider(util.GetId("admin", authForm.Provider))
|
var provider *object.Provider
|
||||||
|
provider, err = object.GetProvider(util.GetId("admin", authForm.Provider))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -477,11 +527,10 @@ func (c *ApiController) Login() {
|
|||||||
c.ResponseError(fmt.Sprintf(c.T("auth: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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo := &idp.UserInfo{}
|
userInfo := &idp.UserInfo{}
|
||||||
if provider.Category == "SAML" {
|
if provider.Category == "SAML" {
|
||||||
// SAML
|
// SAML
|
||||||
userInfo.Id, err = object.ParseSamlResponse(authForm.SamlResponse, provider, c.Ctx.Request.Host)
|
userInfo, err = object.ParseSamlResponse(authForm.SamlResponse, provider, c.Ctx.Request.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -489,7 +538,12 @@ func (c *ApiController) Login() {
|
|||||||
} else if provider.Category == "OAuth" || provider.Category == "Web3" {
|
} else if provider.Category == "OAuth" || provider.Category == "Web3" {
|
||||||
// OAuth
|
// OAuth
|
||||||
idpInfo := object.FromProviderToIdpInfo(c.Ctx, provider)
|
idpInfo := object.FromProviderToIdpInfo(c.Ctx, provider)
|
||||||
idProvider := idp.GetIdProvider(idpInfo, authForm.RedirectUri)
|
var idProvider idp.IdProvider
|
||||||
|
idProvider, err = idp.GetIdProvider(idpInfo, authForm.RedirectUri)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
if idProvider == nil {
|
if idProvider == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("storage:The provider type: %s is not supported"), provider.Type))
|
c.ResponseError(fmt.Sprintf(c.T("storage:The provider type: %s is not supported"), provider.Type))
|
||||||
return
|
return
|
||||||
@ -503,7 +557,8 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/golang/oauth2/issues/123#issuecomment-103715338
|
// https://github.com/golang/oauth2/issues/123#issuecomment-103715338
|
||||||
token, err := idProvider.GetToken(authForm.Code)
|
var token *oauth2.Token
|
||||||
|
token, err = idProvider.GetToken(authForm.Code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -524,7 +579,8 @@ func (c *ApiController) Login() {
|
|||||||
if authForm.Method == "signup" {
|
if authForm.Method == "signup" {
|
||||||
user := &object.User{}
|
user := &object.User{}
|
||||||
if provider.Category == "SAML" {
|
if provider.Category == "SAML" {
|
||||||
user, err = object.GetUser(util.GetId(application.Organization, userInfo.Id))
|
// The userInfo.Id is the NameID in SAML response, it could be name / email / phone
|
||||||
|
user, err = object.GetUserByFields(application.Organization, userInfo.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -543,7 +599,12 @@ func (c *ApiController) Login() {
|
|||||||
if user.IsForbidden {
|
if user.IsForbidden {
|
||||||
c.ResponseError(c.T("check:The user is forbidden to sign in, please contact the administrator"))
|
c.ResponseError(c.T("check:The user is forbidden to sign in, please contact the administrator"))
|
||||||
}
|
}
|
||||||
|
// sync info from 3rd-party if possible
|
||||||
|
_, err = object.SetUserOAuthProperties(organization, user, provider.Type, userInfo)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
resp = c.HandleLoggedIn(application, user, &authForm)
|
resp = c.HandleLoggedIn(application, user, &authForm)
|
||||||
|
|
||||||
record := object.NewRecord(c.Ctx)
|
record := object.NewRecord(c.Ctx)
|
||||||
@ -584,14 +645,16 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle username conflicts
|
// Handle username conflicts
|
||||||
tmpUser, err := object.GetUser(util.GetId(application.Organization, userInfo.Username))
|
var tmpUser *object.User
|
||||||
|
tmpUser, err = object.GetUser(util.GetId(application.Organization, userInfo.Username))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if tmpUser != nil {
|
if tmpUser != nil {
|
||||||
uid, err := uuid.NewRandom()
|
var uid uuid.UUID
|
||||||
|
uid, err = uuid.NewRandom()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -602,14 +665,16 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
properties := map[string]string{}
|
properties := map[string]string{}
|
||||||
count, err := object.GetUserCount(application.Organization, "", "", "")
|
var count int64
|
||||||
|
count, err = object.GetUserCount(application.Organization, "", "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
properties["no"] = strconv.Itoa(int(count + 2))
|
properties["no"] = strconv.Itoa(int(count + 2))
|
||||||
initScore, err := organization.GetInitScore()
|
var initScore int
|
||||||
|
initScore, err = organization.GetInitScore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
||||||
return
|
return
|
||||||
@ -641,7 +706,8 @@ func (c *ApiController) Login() {
|
|||||||
Properties: properties,
|
Properties: properties,
|
||||||
}
|
}
|
||||||
|
|
||||||
affected, err := object.AddUser(user)
|
var affected bool
|
||||||
|
affected, err = object.AddUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -651,10 +717,19 @@ func (c *ApiController) Login() {
|
|||||||
c.ResponseError(fmt.Sprintf(c.T("auth: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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if providerItem.SignupGroup != "" {
|
||||||
|
user.Groups = []string{providerItem.SignupGroup}
|
||||||
|
_, err = object.UpdateUser(user.GetId(), user, []string{"groups"}, false)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sync info from 3rd-party if possible
|
// sync info from 3rd-party if possible
|
||||||
_, err := object.SetUserOAuthProperties(organization, user, provider.Type, userInfo)
|
_, err = object.SetUserOAuthProperties(organization, user, provider.Type, userInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -679,6 +754,7 @@ func (c *ApiController) Login() {
|
|||||||
record2.User = user.Name
|
record2.User = user.Name
|
||||||
util.SafeGoroutine(func() { object.AddRecord(record2) })
|
util.SafeGoroutine(func() { object.AddRecord(record2) })
|
||||||
} else if provider.Category == "SAML" {
|
} else if provider.Category == "SAML" {
|
||||||
|
// TODO: since we get the user info from SAML response, we can try to create the user
|
||||||
resp = &Response{Status: "error", Msg: fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(application.Organization, userInfo.Id))}
|
resp = &Response{Status: "error", Msg: fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(application.Organization, userInfo.Id))}
|
||||||
}
|
}
|
||||||
// resp = &Response{Status: "ok", Msg: "", Data: res}
|
// resp = &Response{Status: "ok", Msg: "", Data: res}
|
||||||
@ -689,7 +765,8 @@ func (c *ApiController) Login() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
oldUser, err := object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
|
var oldUser *object.User
|
||||||
|
oldUser, err = object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -700,7 +777,8 @@ func (c *ApiController) Login() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := object.GetUser(userId)
|
var user *object.User
|
||||||
|
user, err = object.GetUser(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -713,7 +791,8 @@ func (c *ApiController) Login() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isLinked, err := object.LinkUserAccount(user, provider.Type, userInfo.Id)
|
var isLinked bool
|
||||||
|
isLinked, err = object.LinkUserAccount(user, provider.Type, userInfo.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -726,7 +805,8 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if c.getMfaUserSession() != "" {
|
} else if c.getMfaUserSession() != "" {
|
||||||
user, err := object.GetUser(c.getMfaUserSession())
|
var user *object.User
|
||||||
|
user, err = object.GetUser(c.getMfaUserSession())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -759,7 +839,8 @@ func (c *ApiController) Login() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
|
var application *object.Application
|
||||||
|
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -780,7 +861,8 @@ func (c *ApiController) Login() {
|
|||||||
} else {
|
} else {
|
||||||
if c.GetSessionUsername() != "" {
|
if c.GetSessionUsername() != "" {
|
||||||
// user already signed in to Casdoor, so let the user click the avatar button to do the quick sign-in
|
// user already signed in to Casdoor, so let the user click the avatar button to do the quick sign-in
|
||||||
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
|
var application *object.Application
|
||||||
|
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -834,9 +916,10 @@ func (c *ApiController) HandleSamlLogin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandleOfficialAccountEvent ...
|
// HandleOfficialAccountEvent ...
|
||||||
// @Tag HandleOfficialAccountEvent API
|
// @Tag System API
|
||||||
// @Title HandleOfficialAccountEvent
|
// @Title HandleOfficialAccountEvent
|
||||||
// @router /api/webhook [POST]
|
// @router /webhook [POST]
|
||||||
|
// @Success 200 {object} object.Userinfo The Response object
|
||||||
func (c *ApiController) HandleOfficialAccountEvent() {
|
func (c *ApiController) HandleOfficialAccountEvent() {
|
||||||
respBytes, err := ioutil.ReadAll(c.Ctx.Request.Body)
|
respBytes, err := ioutil.ReadAll(c.Ctx.Request.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -864,9 +947,10 @@ func (c *ApiController) HandleOfficialAccountEvent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetWebhookEventType ...
|
// GetWebhookEventType ...
|
||||||
// @Tag GetWebhookEventType API
|
// @Tag System API
|
||||||
// @Title GetWebhookEventType
|
// @Title GetWebhookEventType
|
||||||
// @router /api/get-webhook-event [GET]
|
// @router /get-webhook-event [GET]
|
||||||
|
// @Success 200 {object} object.Userinfo The Response object
|
||||||
func (c *ApiController) GetWebhookEventType() {
|
func (c *ApiController) GetWebhookEventType() {
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
defer lock.Unlock()
|
defer lock.Unlock()
|
||||||
@ -886,20 +970,30 @@ func (c *ApiController) GetWebhookEventType() {
|
|||||||
// @Description Get Login Error Counts
|
// @Description Get Login Error Counts
|
||||||
// @Param id query string true "The id ( owner/name ) of user"
|
// @Param id query string true "The id ( owner/name ) of user"
|
||||||
// @Success 200 {object} controllers.Response The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /api/get-captcha-status [get]
|
// @router /get-captcha-status [get]
|
||||||
func (c *ApiController) GetCaptchaStatus() {
|
func (c *ApiController) GetCaptchaStatus() {
|
||||||
organization := c.Input().Get("organization")
|
organization := c.Input().Get("organization")
|
||||||
userId := c.Input().Get("user_id")
|
userId := c.Input().Get("userId")
|
||||||
user, err := object.GetUserByFields(organization, userId)
|
user, err := object.GetUserByFields(organization, userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var captchaEnabled bool
|
captchaEnabled := false
|
||||||
if user != nil && user.SigninWrongTimes >= object.SigninWrongTimesLimit {
|
if user != nil {
|
||||||
captchaEnabled = true
|
var failedSigninLimit int
|
||||||
|
failedSigninLimit, _, err = object.GetFailedSigninConfigByUser(user)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.SigninWrongTimes >= failedSigninLimit {
|
||||||
|
captchaEnabled = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(captchaEnabled)
|
c.ResponseOk(captchaEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,7 +1001,8 @@ func (c *ApiController) GetCaptchaStatus() {
|
|||||||
// @Title Callback
|
// @Title Callback
|
||||||
// @Tag Callback API
|
// @Tag Callback API
|
||||||
// @Description Get Login Error Counts
|
// @Description Get Login Error Counts
|
||||||
// @router /api/Callback [post]
|
// @router /Callback [post]
|
||||||
|
// @Success 200 {object} object.Userinfo The Response object
|
||||||
func (c *ApiController) Callback() {
|
func (c *ApiController) Callback() {
|
||||||
code := c.GetString("code")
|
code := c.GetString("code")
|
||||||
state := c.GetString("state")
|
state := c.GetString("state")
|
||||||
|
@ -16,6 +16,7 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
@ -23,12 +24,13 @@ import (
|
|||||||
|
|
||||||
// Enforce
|
// Enforce
|
||||||
// @Title Enforce
|
// @Title Enforce
|
||||||
// @Tag Enforce API
|
// @Tag Enforcer API
|
||||||
// @Description Call Casbin Enforce API
|
// @Description Call Casbin Enforce API
|
||||||
// @Param body body object.CasbinRequest true "Casbin request"
|
// @Param body body []string true "Casbin request"
|
||||||
// @Param permissionId query string false "permission id"
|
// @Param permissionId query string false "permission id"
|
||||||
// @Param modelId query string false "model id"
|
// @Param modelId query string false "model id"
|
||||||
// @Param resourceId query string false "resource id"
|
// @Param resourceId query string false "resource id"
|
||||||
|
// @Param owner query string false "owner"
|
||||||
// @Success 200 {object} controllers.Response The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /enforce [post]
|
// @router /enforce [post]
|
||||||
func (c *ApiController) Enforce() {
|
func (c *ApiController) Enforce() {
|
||||||
@ -36,8 +38,14 @@ func (c *ApiController) Enforce() {
|
|||||||
modelId := c.Input().Get("modelId")
|
modelId := c.Input().Get("modelId")
|
||||||
resourceId := c.Input().Get("resourceId")
|
resourceId := c.Input().Get("resourceId")
|
||||||
enforcerId := c.Input().Get("enforcerId")
|
enforcerId := c.Input().Get("enforcerId")
|
||||||
|
owner := c.Input().Get("owner")
|
||||||
|
|
||||||
var request object.CasbinRequest
|
if len(c.Ctx.Input.RequestBody) == 0 {
|
||||||
|
c.ResponseError("The request body should not be empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var request []string
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &request)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
@ -51,13 +59,22 @@ func (c *ApiController) Enforce() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := enforcer.Enforce(request...)
|
res := []bool{}
|
||||||
|
keyRes := []string{}
|
||||||
|
|
||||||
|
// type transformation
|
||||||
|
interfaceRequest := util.StringToInterfaceArray(request)
|
||||||
|
|
||||||
|
enforceResult, err := enforcer.Enforce(interfaceRequest...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(res)
|
res = append(res, enforceResult)
|
||||||
|
keyRes = append(keyRes, enforcer.GetModelAndAdapter())
|
||||||
|
|
||||||
|
c.ResponseOk(res, keyRes)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,22 +84,24 @@ func (c *ApiController) Enforce() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res := []bool{}
|
|
||||||
|
|
||||||
if permission == nil {
|
if permission == nil {
|
||||||
res = append(res, false)
|
c.ResponseError(fmt.Sprintf("permission: %s doesn't exist", permissionId))
|
||||||
} else {
|
return
|
||||||
enforceResult, err := object.Enforce(permission, &request)
|
|
||||||
if err != nil {
|
|
||||||
c.ResponseError(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
res = append(res, enforceResult)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(res)
|
res := []bool{}
|
||||||
|
keyRes := []string{}
|
||||||
|
|
||||||
|
enforceResult, err := object.Enforce(permission, request)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res = append(res, enforceResult)
|
||||||
|
keyRes = append(keyRes, permission.GetModelAndAdapter())
|
||||||
|
|
||||||
|
c.ResponseOk(res, keyRes)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,48 +119,53 @@ func (c *ApiController) Enforce() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else if owner != "" {
|
||||||
|
permissions, err = object.GetPermissions(owner)
|
||||||
} else {
|
} else {
|
||||||
c.ResponseError(c.T("general:Missing parameter"))
|
c.ResponseError(c.T("general:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res := []bool{}
|
res := []bool{}
|
||||||
|
keyRes := []string{}
|
||||||
listPermissionIdMap := object.GroupPermissionsByModelAdapter(permissions)
|
listPermissionIdMap := object.GroupPermissionsByModelAdapter(permissions)
|
||||||
for _, permissionIds := range listPermissionIdMap {
|
for key, permissionIds := range listPermissionIdMap {
|
||||||
firstPermission, err := object.GetPermission(permissionIds[0])
|
firstPermission, err := object.GetPermission(permissionIds[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
enforceResult, err := object.Enforce(firstPermission, &request, permissionIds...)
|
enforceResult, err := object.Enforce(firstPermission, request, permissionIds...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res = append(res, enforceResult)
|
res = append(res, enforceResult)
|
||||||
|
keyRes = append(keyRes, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(res)
|
c.ResponseOk(res, keyRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BatchEnforce
|
// BatchEnforce
|
||||||
// @Title BatchEnforce
|
// @Title BatchEnforce
|
||||||
// @Tag Enforce API
|
// @Tag Enforcer API
|
||||||
// @Description Call Casbin BatchEnforce API
|
// @Description Call Casbin BatchEnforce API
|
||||||
// @Param body body object.CasbinRequest true "array of casbin requests"
|
// @Param body body []string true "array of casbin requests"
|
||||||
// @Param permissionId query string false "permission id"
|
// @Param permissionId query string false "permission id"
|
||||||
// @Param modelId query string false "model id"
|
// @Param modelId query string false "model id"
|
||||||
|
// @Param owner query string false "owner"
|
||||||
// @Success 200 {object} controllers.Response The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /batch-enforce [post]
|
// @router /batch-enforce [post]
|
||||||
func (c *ApiController) BatchEnforce() {
|
func (c *ApiController) BatchEnforce() {
|
||||||
permissionId := c.Input().Get("permissionId")
|
permissionId := c.Input().Get("permissionId")
|
||||||
modelId := c.Input().Get("modelId")
|
modelId := c.Input().Get("modelId")
|
||||||
enforcerId := c.Input().Get("enforcerId")
|
enforcerId := c.Input().Get("enforcerId")
|
||||||
|
owner := c.Input().Get("owner")
|
||||||
|
|
||||||
var requests []object.CasbinRequest
|
var requests [][]string
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &requests)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &requests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
@ -155,13 +179,22 @@ func (c *ApiController) BatchEnforce() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := enforcer.BatchEnforce(requests)
|
res := [][]bool{}
|
||||||
|
keyRes := []string{}
|
||||||
|
|
||||||
|
// type transformation
|
||||||
|
interfaceRequests := util.StringToInterfaceArray2d(requests)
|
||||||
|
|
||||||
|
enforceResult, err := enforcer.BatchEnforce(interfaceRequests)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(res)
|
res = append(res, enforceResult)
|
||||||
|
keyRes = append(keyRes, enforcer.GetModelAndAdapter())
|
||||||
|
|
||||||
|
c.ResponseOk(res, keyRes)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,28 +204,24 @@ func (c *ApiController) BatchEnforce() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res := [][]bool{}
|
|
||||||
|
|
||||||
if permission == nil {
|
if permission == nil {
|
||||||
l := len(requests)
|
c.ResponseError(fmt.Sprintf("permission: %s doesn't exist", permissionId))
|
||||||
resRequest := make([]bool, l)
|
return
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
resRequest[i] = false
|
|
||||||
}
|
|
||||||
|
|
||||||
res = append(res, resRequest)
|
|
||||||
} else {
|
|
||||||
enforceResult, err := object.BatchEnforce(permission, &requests)
|
|
||||||
if err != nil {
|
|
||||||
c.ResponseError(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
res = append(res, enforceResult)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(res)
|
res := [][]bool{}
|
||||||
|
keyRes := []string{}
|
||||||
|
|
||||||
|
enforceResult, err := object.BatchEnforce(permission, requests)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res = append(res, enforceResult)
|
||||||
|
keyRes = append(keyRes, permission.GetModelAndAdapter())
|
||||||
|
|
||||||
|
c.ResponseOk(res, keyRes)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,13 +233,15 @@ func (c *ApiController) BatchEnforce() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else if owner != "" {
|
||||||
|
permissions, err = object.GetPermissions(owner)
|
||||||
} else {
|
} else {
|
||||||
c.ResponseError(c.T("general:Missing parameter"))
|
c.ResponseError(c.T("general:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res := [][]bool{}
|
res := [][]bool{}
|
||||||
|
keyRes := []string{}
|
||||||
listPermissionIdMap := object.GroupPermissionsByModelAdapter(permissions)
|
listPermissionIdMap := object.GroupPermissionsByModelAdapter(permissions)
|
||||||
for _, permissionIds := range listPermissionIdMap {
|
for _, permissionIds := range listPermissionIdMap {
|
||||||
firstPermission, err := object.GetPermission(permissionIds[0])
|
firstPermission, err := object.GetPermission(permissionIds[0])
|
||||||
@ -219,44 +250,72 @@ func (c *ApiController) BatchEnforce() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
enforceResult, err := object.BatchEnforce(firstPermission, &requests, permissionIds...)
|
enforceResult, err := object.BatchEnforce(firstPermission, requests, permissionIds...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res = append(res, enforceResult)
|
res = append(res, enforceResult)
|
||||||
|
keyRes = append(keyRes, firstPermission.GetModelAndAdapter())
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(res)
|
c.ResponseOk(res, keyRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) GetAllObjects() {
|
func (c *ApiController) GetAllObjects() {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.Input().Get("userId")
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("general:Please login first"))
|
userId = c.GetSessionUsername()
|
||||||
|
if userId == "" {
|
||||||
|
c.ResponseError(c.T("general:Please login first"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
objects, err := object.GetAllObjects(userId)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(object.GetAllObjects(userId))
|
c.ResponseOk(objects)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) GetAllActions() {
|
func (c *ApiController) GetAllActions() {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.Input().Get("userId")
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("general:Please login first"))
|
userId = c.GetSessionUsername()
|
||||||
|
if userId == "" {
|
||||||
|
c.ResponseError(c.T("general:Please login first"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actions, err := object.GetAllActions(userId)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(object.GetAllActions(userId))
|
c.ResponseOk(actions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) GetAllRoles() {
|
func (c *ApiController) GetAllRoles() {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.Input().Get("userId")
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("general:Please login first"))
|
userId = c.GetSessionUsername()
|
||||||
|
if userId == "" {
|
||||||
|
c.ResponseError(c.T("general:Please login first"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
roles, err := object.GetAllRoles(userId)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(object.GetAllRoles(userId))
|
c.ResponseOk(roles)
|
||||||
}
|
}
|
||||||
|
@ -39,13 +39,13 @@ func (c *ApiController) GetCerts() {
|
|||||||
sortOrder := c.Input().Get("sortOrder")
|
sortOrder := c.Input().Get("sortOrder")
|
||||||
|
|
||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
maskedCerts, err := object.GetMaskedCerts(object.GetCerts(owner))
|
certs, err := object.GetMaskedCerts(object.GetCerts(owner))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(maskedCerts)
|
c.ResponseOk(certs)
|
||||||
} else {
|
} else {
|
||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
count, err := object.GetCertCount(owner, field, value)
|
count, err := object.GetCertCount(owner, field, value)
|
||||||
@ -65,13 +65,13 @@ func (c *ApiController) GetCerts() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetGlobleCerts
|
// GetGlobalCerts
|
||||||
// @Title GetGlobleCerts
|
// @Title GetGlobalCerts
|
||||||
// @Tag Cert API
|
// @Tag Cert API
|
||||||
// @Description get globle certs
|
// @Description get globle certs
|
||||||
// @Success 200 {array} object.Cert The Response object
|
// @Success 200 {array} object.Cert The Response object
|
||||||
// @router /get-globle-certs [get]
|
// @router /get-global-certs [get]
|
||||||
func (c *ApiController) GetGlobleCerts() {
|
func (c *ApiController) GetGlobalCerts() {
|
||||||
limit := c.Input().Get("pageSize")
|
limit := c.Input().Get("pageSize")
|
||||||
page := c.Input().Get("p")
|
page := c.Input().Get("p")
|
||||||
field := c.Input().Get("field")
|
field := c.Input().Get("field")
|
||||||
@ -80,13 +80,13 @@ func (c *ApiController) GetGlobleCerts() {
|
|||||||
sortOrder := c.Input().Get("sortOrder")
|
sortOrder := c.Input().Get("sortOrder")
|
||||||
|
|
||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
maskedCerts, err := object.GetMaskedCerts(object.GetGlobleCerts())
|
certs, err := object.GetMaskedCerts(object.GetGlobalCerts())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(maskedCerts)
|
c.ResponseOk(certs)
|
||||||
} else {
|
} else {
|
||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
count, err := object.GetGlobalCertsCount(field, value)
|
count, err := object.GetGlobalCertsCount(field, value)
|
||||||
|
@ -71,7 +71,7 @@ func (c *ApiController) GetEnforcers() {
|
|||||||
// @Tag Enforcer API
|
// @Tag Enforcer API
|
||||||
// @Description get enforcer
|
// @Description get enforcer
|
||||||
// @Param id query string true "The id ( owner/name ) of enforcer"
|
// @Param id query string true "The id ( owner/name ) of enforcer"
|
||||||
// @Success 200 {object} object
|
// @Success 200 {object} object.Enforcer
|
||||||
// @router /get-enforcer [get]
|
// @router /get-enforcer [get]
|
||||||
func (c *ApiController) GetEnforcer() {
|
func (c *ApiController) GetEnforcer() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
@ -99,7 +99,7 @@ func (c *ApiController) GetEnforcer() {
|
|||||||
// @Description update enforcer
|
// @Description update enforcer
|
||||||
// @Param id query string true "The id ( owner/name ) of enforcer"
|
// @Param id query string true "The id ( owner/name ) of enforcer"
|
||||||
// @Param enforcer body object true "The enforcer object"
|
// @Param enforcer body object true "The enforcer object"
|
||||||
// @Success 200 {object} object
|
// @Success 200 {object} object.Enforcer
|
||||||
// @router /update-enforcer [post]
|
// @router /update-enforcer [post]
|
||||||
func (c *ApiController) UpdateEnforcer() {
|
func (c *ApiController) UpdateEnforcer() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
@ -120,7 +120,7 @@ func (c *ApiController) UpdateEnforcer() {
|
|||||||
// @Tag Enforcer API
|
// @Tag Enforcer API
|
||||||
// @Description add enforcer
|
// @Description add enforcer
|
||||||
// @Param enforcer body object true "The enforcer object"
|
// @Param enforcer body object true "The enforcer object"
|
||||||
// @Success 200 {object} object
|
// @Success 200 {object} object.Enforcer
|
||||||
// @router /add-enforcer [post]
|
// @router /add-enforcer [post]
|
||||||
func (c *ApiController) AddEnforcer() {
|
func (c *ApiController) AddEnforcer() {
|
||||||
enforcer := object.Enforcer{}
|
enforcer := object.Enforcer{}
|
||||||
@ -138,8 +138,8 @@ func (c *ApiController) AddEnforcer() {
|
|||||||
// @Title DeleteEnforcer
|
// @Title DeleteEnforcer
|
||||||
// @Tag Enforcer API
|
// @Tag Enforcer API
|
||||||
// @Description delete enforcer
|
// @Description delete enforcer
|
||||||
// @Param body body object.Enforce true "The enforcer object"
|
// @Param body body object.Enforcer true "The enforcer object"
|
||||||
// @Success 200 {object} object
|
// @Success 200 {object} object.Enforcer
|
||||||
// @router /delete-enforcer [post]
|
// @router /delete-enforcer [post]
|
||||||
func (c *ApiController) DeleteEnforcer() {
|
func (c *ApiController) DeleteEnforcer() {
|
||||||
var enforcer object.Enforcer
|
var enforcer object.Enforcer
|
||||||
@ -191,7 +191,7 @@ func (c *ApiController) UpdatePolicy() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
affected, err := object.UpdatePolicy(id, util.CasbinToSlice(policies[0]), util.CasbinToSlice(policies[1]))
|
affected, err := object.UpdatePolicy(id, policies[0].Ptype, util.CasbinToSlice(policies[0]), util.CasbinToSlice(policies[1]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -210,7 +210,7 @@ func (c *ApiController) AddPolicy() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
affected, err := object.AddPolicy(id, util.CasbinToSlice(policy))
|
affected, err := object.AddPolicy(id, policy.Ptype, util.CasbinToSlice(policy))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -229,7 +229,7 @@ func (c *ApiController) RemovePolicy() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
affected, err := object.RemovePolicy(id, util.CasbinToSlice(policy))
|
affected, err := object.RemovePolicy(id, policy.Ptype, util.CasbinToSlice(policy))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
|
@ -18,7 +18,7 @@ import "github.com/casdoor/casdoor/object"
|
|||||||
|
|
||||||
// GetDashboard
|
// GetDashboard
|
||||||
// @Title GetDashboard
|
// @Title GetDashboard
|
||||||
// @Tag GetDashboard API
|
// @Tag System API
|
||||||
// @Description get information of dashboard
|
// @Description get information of dashboard
|
||||||
// @Success 200 {object} controllers.Response The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /get-dashboard [get]
|
// @router /get-dashboard [get]
|
||||||
|
164
controllers/invitation.go
Normal file
164
controllers/invitation.go
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
// Copyright 2023 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"
|
||||||
|
"github.com/casdoor/casdoor/object"
|
||||||
|
"github.com/casdoor/casdoor/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetInvitations
|
||||||
|
// @Title GetInvitations
|
||||||
|
// @Tag Invitation API
|
||||||
|
// @Description get invitations
|
||||||
|
// @Param owner query string true "The owner of invitations"
|
||||||
|
// @Success 200 {array} object.Invitation The Response object
|
||||||
|
// @router /get-invitations [get]
|
||||||
|
func (c *ApiController) GetInvitations() {
|
||||||
|
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 == "" {
|
||||||
|
invitations, err := object.GetInvitations(owner)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ResponseOk(invitations)
|
||||||
|
} else {
|
||||||
|
limit := util.ParseInt(limit)
|
||||||
|
count, err := object.GetInvitationCount(owner, field, value)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||||
|
invitations, err := object.GetPaginationInvitations(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ResponseOk(invitations, paginator.Nums())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInvitation
|
||||||
|
// @Title GetInvitation
|
||||||
|
// @Tag Invitation API
|
||||||
|
// @Description get invitation
|
||||||
|
// @Param id query string true "The id ( owner/name ) of the invitation"
|
||||||
|
// @Success 200 {object} object.Invitation The Response object
|
||||||
|
// @router /get-invitation [get]
|
||||||
|
func (c *ApiController) GetInvitation() {
|
||||||
|
id := c.Input().Get("id")
|
||||||
|
|
||||||
|
invitation, err := object.GetInvitation(id)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ResponseOk(invitation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateInvitation
|
||||||
|
// @Title UpdateInvitation
|
||||||
|
// @Tag Invitation API
|
||||||
|
// @Description update invitation
|
||||||
|
// @Param id query string true "The id ( owner/name ) of the invitation"
|
||||||
|
// @Param body body object.Invitation true "The details of the invitation"
|
||||||
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
|
// @router /update-invitation [post]
|
||||||
|
func (c *ApiController) UpdateInvitation() {
|
||||||
|
id := c.Input().Get("id")
|
||||||
|
|
||||||
|
var invitation object.Invitation
|
||||||
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &invitation)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = wrapActionResponse(object.UpdateInvitation(id, &invitation))
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddInvitation
|
||||||
|
// @Title AddInvitation
|
||||||
|
// @Tag Invitation API
|
||||||
|
// @Description add invitation
|
||||||
|
// @Param body body object.Invitation true "The details of the invitation"
|
||||||
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
|
// @router /add-invitation [post]
|
||||||
|
func (c *ApiController) AddInvitation() {
|
||||||
|
var invitation object.Invitation
|
||||||
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &invitation)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = wrapActionResponse(object.AddInvitation(&invitation))
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteInvitation
|
||||||
|
// @Title DeleteInvitation
|
||||||
|
// @Tag Invitation API
|
||||||
|
// @Description delete invitation
|
||||||
|
// @Param body body object.Invitation true "The details of the invitation"
|
||||||
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
|
// @router /delete-invitation [post]
|
||||||
|
func (c *ApiController) DeleteInvitation() {
|
||||||
|
var invitation object.Invitation
|
||||||
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &invitation)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = wrapActionResponse(object.DeleteInvitation(&invitation))
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyInvitation
|
||||||
|
// @Title VerifyInvitation
|
||||||
|
// @Tag Invitation API
|
||||||
|
// @Description verify invitation
|
||||||
|
// @Param id query string true "The id ( owner/name ) of the invitation"
|
||||||
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
|
// @router /verify-invitation [get]
|
||||||
|
func (c *ApiController) VerifyInvitation() {
|
||||||
|
id := c.Input().Get("id")
|
||||||
|
|
||||||
|
payment, attachInfo, err := object.VerifyInvitation(id)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ResponseOk(payment, attachInfo)
|
||||||
|
}
|
@ -42,7 +42,7 @@ type LdapSyncResp struct {
|
|||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Description get ldap users
|
// @Description get ldap users
|
||||||
// Param id string true "id"
|
// Param id string true "id"
|
||||||
// @Success 200 {object} LdapResp The Response object
|
// @Success 200 {object} controllers.LdapResp The Response object
|
||||||
// @router /get-ldap-users [get]
|
// @router /get-ldap-users [get]
|
||||||
func (c *ApiController) GetLdapUsers() {
|
func (c *ApiController) GetLdapUsers() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
@ -59,6 +59,7 @@ func (c *ApiController) GetLdapUsers() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
//groupsMap, err := conn.GetLdapGroups(ldapServer.BaseDn)
|
//groupsMap, err := conn.GetLdapGroups(ldapServer.BaseDn)
|
||||||
//if err != nil {
|
//if err != nil {
|
||||||
@ -249,7 +250,7 @@ func (c *ApiController) DeleteLdap() {
|
|||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Description sync ldap users
|
// @Description sync ldap users
|
||||||
// @Param id query string true "id"
|
// @Param id query string true "id"
|
||||||
// @Success 200 {object} LdapSyncResp The Response object
|
// @Success 200 {object} controllers.LdapSyncResp The Response object
|
||||||
// @router /sync-ldap-users [post]
|
// @router /sync-ldap-users [post]
|
||||||
func (c *ApiController) SyncLdapUsers() {
|
func (c *ApiController) SyncLdapUsers() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
|
@ -26,8 +26,10 @@ type LinkForm struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unlink ...
|
// Unlink ...
|
||||||
// @router /unlink [post]
|
|
||||||
// @Tag Login API
|
// @Tag Login API
|
||||||
|
// @Title Unlink
|
||||||
|
// @router /unlink [post]
|
||||||
|
// @Success 200 {object} object.Userinfo The Response object
|
||||||
func (c *ApiController) Unlink() {
|
func (c *ApiController) Unlink() {
|
||||||
user, ok := c.RequireSignedInUser()
|
user, ok := c.RequireSignedInUser()
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -73,7 +73,7 @@ func (c *ApiController) MfaSetupInitiate() {
|
|||||||
// @Description setup verify totp
|
// @Description setup verify totp
|
||||||
// @param secret form string true "MFA secret"
|
// @param secret form string true "MFA secret"
|
||||||
// @param passcode form string true "MFA passcode"
|
// @param passcode form string true "MFA passcode"
|
||||||
// @Success 200 {object} Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /mfa/setup/verify [post]
|
// @router /mfa/setup/verify [post]
|
||||||
func (c *ApiController) MfaSetupVerify() {
|
func (c *ApiController) MfaSetupVerify() {
|
||||||
mfaType := c.Ctx.Request.Form.Get("mfaType")
|
mfaType := c.Ctx.Request.Form.Get("mfaType")
|
||||||
@ -104,7 +104,7 @@ func (c *ApiController) MfaSetupVerify() {
|
|||||||
// @param owner form string true "owner of user"
|
// @param owner form string true "owner of user"
|
||||||
// @param name form string true "name of user"
|
// @param name form string true "name of user"
|
||||||
// @param type form string true "MFA auth type"
|
// @param type form string true "MFA auth type"
|
||||||
// @Success 200 {object} Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /mfa/setup/enable [post]
|
// @router /mfa/setup/enable [post]
|
||||||
func (c *ApiController) MfaSetupEnable() {
|
func (c *ApiController) MfaSetupEnable() {
|
||||||
owner := c.Ctx.Request.Form.Get("owner")
|
owner := c.Ctx.Request.Form.Get("owner")
|
||||||
@ -143,7 +143,7 @@ func (c *ApiController) MfaSetupEnable() {
|
|||||||
// @Description: Delete MFA
|
// @Description: Delete MFA
|
||||||
// @param owner form string true "owner of user"
|
// @param owner form string true "owner of user"
|
||||||
// @param name form string true "name of user"
|
// @param name form string true "name of user"
|
||||||
// @Success 200 {object} Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /delete-mfa/ [post]
|
// @router /delete-mfa/ [post]
|
||||||
func (c *ApiController) DeleteMfa() {
|
func (c *ApiController) DeleteMfa() {
|
||||||
owner := c.Ctx.Request.Form.Get("owner")
|
owner := c.Ctx.Request.Form.Get("owner")
|
||||||
@ -176,7 +176,7 @@ func (c *ApiController) DeleteMfa() {
|
|||||||
// @param owner form string true "owner of user"
|
// @param owner form string true "owner of user"
|
||||||
// @param name form string true "name of user"
|
// @param name form string true "name of user"
|
||||||
// @param id form string true "id of user's MFA props"
|
// @param id form string true "id of user's MFA props"
|
||||||
// @Success 200 {object} Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /set-preferred-mfa [post]
|
// @router /set-preferred-mfa [post]
|
||||||
func (c *ApiController) SetPreferredMfa() {
|
func (c *ApiController) SetPreferredMfa() {
|
||||||
mfaType := c.Ctx.Request.Form.Get("mfaType")
|
mfaType := c.Ctx.Request.Form.Get("mfaType")
|
||||||
|
@ -41,13 +41,12 @@ func (c *ApiController) GetOrganizations() {
|
|||||||
|
|
||||||
isGlobalAdmin := c.IsGlobalAdmin()
|
isGlobalAdmin := c.IsGlobalAdmin()
|
||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
var maskedOrganizations []*object.Organization
|
var organizations []*object.Organization
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if isGlobalAdmin {
|
if isGlobalAdmin {
|
||||||
maskedOrganizations, err = object.GetMaskedOrganizations(object.GetOrganizations(owner))
|
organizations, err = object.GetMaskedOrganizations(object.GetOrganizations(owner))
|
||||||
} else {
|
} else {
|
||||||
maskedOrganizations, err = object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner))
|
organizations, err = object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -55,15 +54,15 @@ func (c *ApiController) GetOrganizations() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(maskedOrganizations)
|
c.ResponseOk(organizations)
|
||||||
} else {
|
} else {
|
||||||
if !isGlobalAdmin {
|
if !isGlobalAdmin {
|
||||||
maskedOrganizations, err := object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner))
|
organizations, err := object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.ResponseOk(maskedOrganizations)
|
c.ResponseOk(organizations)
|
||||||
} else {
|
} else {
|
||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
count, err := object.GetOrganizationCount(owner, field, value)
|
count, err := object.GetOrganizationCount(owner, field, value)
|
||||||
@ -93,13 +92,13 @@ func (c *ApiController) GetOrganizations() {
|
|||||||
// @router /get-organization [get]
|
// @router /get-organization [get]
|
||||||
func (c *ApiController) GetOrganization() {
|
func (c *ApiController) GetOrganization() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
maskedOrganization, err := object.GetMaskedOrganization(object.GetOrganization(id))
|
organization, err := object.GetMaskedOrganization(object.GetOrganization(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(maskedOrganization)
|
c.ResponseOk(organization)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateOrganization ...
|
// UpdateOrganization ...
|
||||||
@ -178,7 +177,7 @@ func (c *ApiController) DeleteOrganization() {
|
|||||||
// @Tag Organization API
|
// @Tag Organization API
|
||||||
// @Description get default application
|
// @Description get default application
|
||||||
// @Param id query string true "organization id"
|
// @Param id query string true "organization id"
|
||||||
// @Success 200 {object} Response The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /get-default-application [get]
|
// @router /get-default-application [get]
|
||||||
func (c *ApiController) GetDefaultApplication() {
|
func (c *ApiController) GetDefaultApplication() {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
@ -190,8 +189,8 @@ func (c *ApiController) GetDefaultApplication() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
maskedApplication := object.GetMaskedApplication(application, userId)
|
application = object.GetMaskedApplication(application, userId)
|
||||||
c.ResponseOk(maskedApplication)
|
c.ResponseOk(application)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOrganizationNames ...
|
// GetOrganizationNames ...
|
||||||
|
@ -163,6 +163,8 @@ func (c *ApiController) BuyProduct() {
|
|||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
host := c.Ctx.Request.Host
|
host := c.Ctx.Request.Host
|
||||||
providerName := c.Input().Get("providerName")
|
providerName := c.Input().Get("providerName")
|
||||||
|
paymentEnv := c.Input().Get("paymentEnv")
|
||||||
|
|
||||||
// buy `pricingName/planName` for `paidUserName`
|
// buy `pricingName/planName` for `paidUserName`
|
||||||
pricingName := c.Input().Get("pricingName")
|
pricingName := c.Input().Get("pricingName")
|
||||||
planName := c.Input().Get("planName")
|
planName := c.Input().Get("planName")
|
||||||
@ -187,11 +189,11 @@ func (c *ApiController) BuyProduct() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
payment, err := object.BuyProduct(id, user, providerName, pricingName, planName, host)
|
payment, attachInfo, err := object.BuyProduct(id, user, providerName, pricingName, planName, host, paymentEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(payment)
|
c.ResponseOk(payment, attachInfo)
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
|
|
||||||
// GetPrometheusInfo
|
// GetPrometheusInfo
|
||||||
// @Title GetPrometheusInfo
|
// @Title GetPrometheusInfo
|
||||||
// @Tag Prometheus API
|
// @Tag System API
|
||||||
// @Description get Prometheus Info
|
// @Description get Prometheus Info
|
||||||
// @Success 200 {object} object.PrometheusInfo The Response object
|
// @Success 200 {object} object.PrometheusInfo The Response object
|
||||||
// @router /get-prometheus-info [get]
|
// @router /get-prometheus-info [get]
|
||||||
|
@ -272,6 +272,11 @@ func (c *ApiController) UploadResource() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if username == "Built-in-Untracked" {
|
||||||
|
c.ResponseOk(fileUrl, objectKey)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if createdTime == "" {
|
if createdTime == "" {
|
||||||
createdTime = util.GetCurrentTime()
|
createdTime = util.GetCurrentTime()
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,13 @@ func (c *ApiController) GetSamlMeta() {
|
|||||||
c.ResponseError(fmt.Sprintf(c.T("saml:Application %s not found"), paramApp))
|
c.ResponseError(fmt.Sprintf(c.T("saml:Application %s not found"), paramApp))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
metadata, _ := object.GetSamlMeta(application, host)
|
|
||||||
|
metadata, err := object.GetSamlMeta(application, host)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.Data["xml"] = metadata
|
c.Data["xml"] = metadata
|
||||||
c.ServeXML()
|
c.ServeXML()
|
||||||
}
|
}
|
||||||
|
27
controllers/scim.go
Normal file
27
controllers/scim.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2023 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 (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/scim"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *RootController) HandleScim() {
|
||||||
|
path := c.Ctx.Request.URL.Path
|
||||||
|
c.Ctx.Request.URL.Path = strings.TrimPrefix(path, "/scim")
|
||||||
|
scim.Server.ServeHTTP(c.Ctx.ResponseWriter, c.Ctx.Request)
|
||||||
|
}
|
@ -51,9 +51,14 @@ type NotificationForm struct {
|
|||||||
// @Param clientId query string true "The clientId of the application"
|
// @Param clientId query string true "The clientId of the application"
|
||||||
// @Param clientSecret query string true "The clientSecret of the application"
|
// @Param clientSecret query string true "The clientSecret of the application"
|
||||||
// @Param from body controllers.EmailForm true "Details of the email request"
|
// @Param from body controllers.EmailForm true "Details of the email request"
|
||||||
// @Success 200 {object} Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /api/send-email [post]
|
// @router /send-email [post]
|
||||||
func (c *ApiController) SendEmail() {
|
func (c *ApiController) SendEmail() {
|
||||||
|
userId, ok := c.RequireSignedIn()
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var emailForm EmailForm
|
var emailForm EmailForm
|
||||||
|
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &emailForm)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &emailForm)
|
||||||
@ -108,8 +113,22 @@ func (c *ApiController) SendEmail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
code := "123456"
|
code := "123456"
|
||||||
|
|
||||||
// "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes."
|
// "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes."
|
||||||
content := fmt.Sprintf(emailForm.Content, code)
|
content := strings.Replace(provider.Content, "%s", code, 1)
|
||||||
|
if !strings.HasPrefix(userId, "app/") {
|
||||||
|
var user *object.User
|
||||||
|
user, err = object.GetUser(userId)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if user != nil {
|
||||||
|
content = strings.Replace(content, "%{user.friendlyName}", user.GetFriendlyName(), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, receiver := range emailForm.Receivers {
|
for _, receiver := range emailForm.Receivers {
|
||||||
err = object.SendEmail(provider, emailForm.Title, content, receiver, emailForm.Sender)
|
err = object.SendEmail(provider, emailForm.Title, content, receiver, emailForm.Sender)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -128,8 +147,8 @@ func (c *ApiController) SendEmail() {
|
|||||||
// @Param clientId query string true "The clientId of the application"
|
// @Param clientId query string true "The clientId of the application"
|
||||||
// @Param clientSecret query string true "The clientSecret of the application"
|
// @Param clientSecret query string true "The clientSecret of the application"
|
||||||
// @Param from body controllers.SmsForm true "Details of the sms request"
|
// @Param from body controllers.SmsForm true "Details of the sms request"
|
||||||
// @Success 200 {object} Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /api/send-sms [post]
|
// @router /send-sms [post]
|
||||||
func (c *ApiController) SendSms() {
|
func (c *ApiController) SendSms() {
|
||||||
provider, err := c.GetProviderFromContext("SMS")
|
provider, err := c.GetProviderFromContext("SMS")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -166,8 +185,8 @@ func (c *ApiController) SendSms() {
|
|||||||
// @Tag Service API
|
// @Tag Service API
|
||||||
// @Description This API is not for Casdoor frontend to call, it is for Casdoor SDKs.
|
// @Description This API is not for Casdoor frontend to call, it is for Casdoor SDKs.
|
||||||
// @Param from body controllers.NotificationForm true "Details of the notification request"
|
// @Param from body controllers.NotificationForm true "Details of the notification request"
|
||||||
// @Success 200 {object} Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /api/send-notification [post]
|
// @router /send-notification [post]
|
||||||
func (c *ApiController) SendNotification() {
|
func (c *ApiController) SendNotification() {
|
||||||
provider, err := c.GetProviderFromContext("Notification")
|
provider, err := c.GetProviderFromContext("Notification")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -40,13 +40,13 @@ func (c *ApiController) GetSyncers() {
|
|||||||
organization := c.Input().Get("organization")
|
organization := c.Input().Get("organization")
|
||||||
|
|
||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
organizationSyncers, err := object.GetOrganizationSyncers(owner, organization)
|
syncers, err := object.GetMaskedSyncers(object.GetOrganizationSyncers(owner, organization))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(organizationSyncers)
|
c.ResponseOk(syncers)
|
||||||
} else {
|
} else {
|
||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
count, err := object.GetSyncerCount(owner, organization, field, value)
|
count, err := object.GetSyncerCount(owner, organization, field, value)
|
||||||
@ -56,7 +56,7 @@ func (c *ApiController) GetSyncers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||||
syncers, err := object.GetPaginationSyncers(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
syncers, err := object.GetMaskedSyncers(object.GetPaginationSyncers(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@ -76,7 +76,7 @@ func (c *ApiController) GetSyncers() {
|
|||||||
func (c *ApiController) GetSyncer() {
|
func (c *ApiController) GetSyncer() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
|
|
||||||
syncer, err := object.GetSyncer(id)
|
syncer, err := object.GetMaskedSyncer(object.GetSyncer(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
|
@ -156,12 +156,11 @@ func (c *ApiController) DeleteToken() {
|
|||||||
// @Success 200 {object} object.TokenWrapper The Response object
|
// @Success 200 {object} object.TokenWrapper The Response object
|
||||||
// @Success 400 {object} object.TokenError The Response object
|
// @Success 400 {object} object.TokenError The Response object
|
||||||
// @Success 401 {object} object.TokenError The Response object
|
// @Success 401 {object} object.TokenError The Response object
|
||||||
// @router api/login/oauth/access_token [post]
|
// @router /login/oauth/access_token [post]
|
||||||
func (c *ApiController) GetOAuthToken() {
|
func (c *ApiController) GetOAuthToken() {
|
||||||
grantType := c.Input().Get("grant_type")
|
|
||||||
refreshToken := c.Input().Get("refresh_token")
|
|
||||||
clientId := c.Input().Get("client_id")
|
clientId := c.Input().Get("client_id")
|
||||||
clientSecret := c.Input().Get("client_secret")
|
clientSecret := c.Input().Get("client_secret")
|
||||||
|
grantType := c.Input().Get("grant_type")
|
||||||
code := c.Input().Get("code")
|
code := c.Input().Get("code")
|
||||||
verifier := c.Input().Get("code_verifier")
|
verifier := c.Input().Get("code_verifier")
|
||||||
scope := c.Input().Get("scope")
|
scope := c.Input().Get("scope")
|
||||||
@ -169,35 +168,61 @@ func (c *ApiController) GetOAuthToken() {
|
|||||||
password := c.Input().Get("password")
|
password := c.Input().Get("password")
|
||||||
tag := c.Input().Get("tag")
|
tag := c.Input().Get("tag")
|
||||||
avatar := c.Input().Get("avatar")
|
avatar := c.Input().Get("avatar")
|
||||||
|
refreshToken := c.Input().Get("refresh_token")
|
||||||
|
|
||||||
if clientId == "" && clientSecret == "" {
|
if clientId == "" && clientSecret == "" {
|
||||||
clientId, clientSecret, _ = c.Ctx.Request.BasicAuth()
|
clientId, clientSecret, _ = c.Ctx.Request.BasicAuth()
|
||||||
}
|
}
|
||||||
if clientId == "" {
|
|
||||||
// If clientID is empty, try to read data from RequestBody
|
if len(c.Ctx.Input.RequestBody) != 0 {
|
||||||
|
// If clientId is empty, try to read data from RequestBody
|
||||||
var tokenRequest TokenRequest
|
var tokenRequest TokenRequest
|
||||||
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &tokenRequest); err == nil {
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &tokenRequest)
|
||||||
clientId = tokenRequest.ClientId
|
if err == nil {
|
||||||
clientSecret = tokenRequest.ClientSecret
|
if clientId == "" {
|
||||||
grantType = tokenRequest.GrantType
|
clientId = tokenRequest.ClientId
|
||||||
refreshToken = tokenRequest.RefreshToken
|
}
|
||||||
code = tokenRequest.Code
|
if clientSecret == "" {
|
||||||
verifier = tokenRequest.Verifier
|
clientSecret = tokenRequest.ClientSecret
|
||||||
scope = tokenRequest.Scope
|
}
|
||||||
username = tokenRequest.Username
|
if grantType == "" {
|
||||||
password = tokenRequest.Password
|
grantType = tokenRequest.GrantType
|
||||||
tag = tokenRequest.Tag
|
}
|
||||||
avatar = tokenRequest.Avatar
|
if code == "" {
|
||||||
|
code = tokenRequest.Code
|
||||||
|
}
|
||||||
|
if verifier == "" {
|
||||||
|
verifier = tokenRequest.Verifier
|
||||||
|
}
|
||||||
|
if scope == "" {
|
||||||
|
scope = tokenRequest.Scope
|
||||||
|
}
|
||||||
|
if username == "" {
|
||||||
|
username = tokenRequest.Username
|
||||||
|
}
|
||||||
|
if password == "" {
|
||||||
|
password = tokenRequest.Password
|
||||||
|
}
|
||||||
|
if tag == "" {
|
||||||
|
tag = tokenRequest.Tag
|
||||||
|
}
|
||||||
|
if avatar == "" {
|
||||||
|
avatar = tokenRequest.Avatar
|
||||||
|
}
|
||||||
|
if refreshToken == "" {
|
||||||
|
refreshToken = tokenRequest.RefreshToken
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
host := c.Ctx.Request.Host
|
host := c.Ctx.Request.Host
|
||||||
oAuthtoken, err := object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
|
token, err := object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = oAuthtoken
|
c.Data["json"] = token
|
||||||
c.SetTokenErrorHttpStatus()
|
c.SetTokenErrorHttpStatus()
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
@ -248,6 +273,7 @@ func (c *ApiController) RefreshToken() {
|
|||||||
|
|
||||||
// IntrospectToken
|
// IntrospectToken
|
||||||
// @Title IntrospectToken
|
// @Title IntrospectToken
|
||||||
|
// @Tag Login API
|
||||||
// @Description The introspection endpoint is an OAuth 2.0 endpoint that takes a
|
// @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
|
// parameter representing an OAuth 2.0 token and returns a JSON document
|
||||||
// representing the meta information surrounding the
|
// representing the meta information surrounding the
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
type TokenRequest struct {
|
type TokenRequest struct {
|
||||||
GrantType string `json:"grant_type"`
|
|
||||||
Code string `json:"code"`
|
|
||||||
ClientId string `json:"client_id"`
|
ClientId string `json:"client_id"`
|
||||||
ClientSecret string `json:"client_secret"`
|
ClientSecret string `json:"client_secret"`
|
||||||
|
GrantType string `json:"grant_type"`
|
||||||
|
Code string `json:"code"`
|
||||||
Verifier string `json:"code_verifier"`
|
Verifier string `json:"code_verifier"`
|
||||||
Scope string `json:"scope"`
|
Scope string `json:"scope"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
|
@ -39,13 +39,13 @@ func (c *ApiController) GetGlobalUsers() {
|
|||||||
sortOrder := c.Input().Get("sortOrder")
|
sortOrder := c.Input().Get("sortOrder")
|
||||||
|
|
||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
maskedUsers, err := object.GetMaskedUsers(object.GetGlobalUsers())
|
users, err := object.GetMaskedUsers(object.GetGlobalUsers())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(maskedUsers)
|
c.ResponseOk(users)
|
||||||
} else {
|
} else {
|
||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
count, err := object.GetGlobalUserCount(field, value)
|
count, err := object.GetGlobalUserCount(field, value)
|
||||||
@ -90,22 +90,22 @@ func (c *ApiController) GetUsers() {
|
|||||||
|
|
||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
if groupName != "" {
|
if groupName != "" {
|
||||||
maskedUsers, err := object.GetMaskedUsers(object.GetGroupUsers(util.GetId(owner, groupName)))
|
users, err := object.GetMaskedUsers(object.GetGroupUsers(util.GetId(owner, groupName)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.ResponseOk(maskedUsers)
|
c.ResponseOk(users)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
maskedUsers, err := object.GetMaskedUsers(object.GetUsers(owner))
|
users, err := object.GetMaskedUsers(object.GetUsers(owner))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(maskedUsers)
|
c.ResponseOk(users)
|
||||||
} else {
|
} else {
|
||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
count, err := object.GetUserCount(owner, field, value, groupName)
|
count, err := object.GetUserCount(owner, field, value, groupName)
|
||||||
@ -160,42 +160,61 @@ func (c *ApiController) GetUser() {
|
|||||||
id = util.GetId(userFromUserId.Owner, userFromUserId.Name)
|
id = util.GetId(userFromUserId.Owner, userFromUserId.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if owner == "" {
|
var user *object.User
|
||||||
owner = util.GetOwnerFromId(id)
|
if id == "" && owner == "" {
|
||||||
}
|
switch {
|
||||||
|
case email != "":
|
||||||
|
user, err = object.GetUserByEmailOnly(email)
|
||||||
|
case phone != "":
|
||||||
|
user, err = object.GetUserByPhoneOnly(phone)
|
||||||
|
case userId != "":
|
||||||
|
user, err = object.GetUserByUserIdOnly(userId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if owner == "" {
|
||||||
|
owner = util.GetOwnerFromId(id)
|
||||||
|
}
|
||||||
|
|
||||||
organization, err := object.GetOrganization(util.GetId("admin", owner))
|
switch {
|
||||||
if err != nil {
|
case email != "":
|
||||||
c.ResponseError(err.Error())
|
user, err = object.GetUserByEmail(owner, email)
|
||||||
return
|
case phone != "":
|
||||||
}
|
user, err = object.GetUserByPhone(owner, phone)
|
||||||
|
case userId != "":
|
||||||
if !organization.IsProfilePublic {
|
user = userFromUserId
|
||||||
requestUserId := c.GetSessionUsername()
|
default:
|
||||||
hasPermission, err := object.CheckUserPermission(requestUserId, id, false, c.GetAcceptLanguage())
|
user, err = object.GetUser(id)
|
||||||
if !hasPermission {
|
|
||||||
c.ResponseError(err.Error())
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var user *object.User
|
|
||||||
switch {
|
|
||||||
case email != "":
|
|
||||||
user, err = object.GetUserByEmail(owner, email)
|
|
||||||
case phone != "":
|
|
||||||
user, err = object.GetUserByPhone(owner, phone)
|
|
||||||
case userId != "":
|
|
||||||
user = userFromUserId
|
|
||||||
default:
|
|
||||||
user, err = object.GetUser(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if user != nil {
|
||||||
|
var organization *object.Organization
|
||||||
|
organization, err = object.GetOrganizationByUser(user)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if organization == nil {
|
||||||
|
c.ResponseError(fmt.Sprintf("the organization: %s is not found", owner))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !organization.IsProfilePublic {
|
||||||
|
requestUserId := c.GetSessionUsername()
|
||||||
|
var hasPermission bool
|
||||||
|
hasPermission, err = object.CheckUserPermission(requestUserId, user.GetId(), false, c.GetAcceptLanguage())
|
||||||
|
if !hasPermission {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if user != nil {
|
if user != nil {
|
||||||
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
|
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
|
||||||
}
|
}
|
||||||
@ -207,13 +226,13 @@ func (c *ApiController) GetUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isAdminOrSelf := c.IsAdminOrSelf(user)
|
isAdminOrSelf := c.IsAdminOrSelf(user)
|
||||||
maskedUser, err := object.GetMaskedUser(user, isAdminOrSelf)
|
user, err = object.GetMaskedUser(user, isAdminOrSelf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(maskedUser)
|
c.ResponseOk(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUser
|
// UpdateUser
|
||||||
@ -460,16 +479,16 @@ func (c *ApiController) SetPassword() {
|
|||||||
isAdmin := c.IsAdmin()
|
isAdmin := c.IsAdmin()
|
||||||
if isAdmin {
|
if isAdmin {
|
||||||
if oldPassword != "" {
|
if oldPassword != "" {
|
||||||
msg := object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
|
err = object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
|
||||||
if msg != "" {
|
if err != nil {
|
||||||
c.ResponseError(msg)
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if code == "" {
|
||||||
msg := object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
|
err = object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
|
||||||
if msg != "" {
|
if err != nil {
|
||||||
c.ResponseError(msg)
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -494,6 +513,7 @@ func (c *ApiController) SetPassword() {
|
|||||||
// @Title CheckUserPassword
|
// @Title CheckUserPassword
|
||||||
// @router /check-user-password [post]
|
// @router /check-user-password [post]
|
||||||
// @Tag User API
|
// @Tag User API
|
||||||
|
// @Success 200 {object} object.Userinfo The Response object
|
||||||
func (c *ApiController) CheckUserPassword() {
|
func (c *ApiController) CheckUserPassword() {
|
||||||
var user object.User
|
var user object.User
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &user)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &user)
|
||||||
@ -502,11 +522,11 @@ func (c *ApiController) CheckUserPassword() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, msg := object.CheckUserPassword(user.Owner, user.Name, user.Password, c.GetAcceptLanguage())
|
_, err = object.CheckUserPassword(user.Owner, user.Name, user.Password, c.GetAcceptLanguage())
|
||||||
if msg == "" {
|
if err != nil {
|
||||||
c.ResponseOk()
|
c.ResponseError(err.Error())
|
||||||
} else {
|
} else {
|
||||||
c.ResponseError(msg)
|
c.ResponseOk()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,13 +544,13 @@ func (c *ApiController) GetSortedUsers() {
|
|||||||
sorter := c.Input().Get("sorter")
|
sorter := c.Input().Get("sorter")
|
||||||
limit := util.ParseInt(c.Input().Get("limit"))
|
limit := util.ParseInt(c.Input().Get("limit"))
|
||||||
|
|
||||||
maskedUsers, err := object.GetMaskedUsers(object.GetSortedUsers(owner, sorter, limit))
|
users, err := object.GetMaskedUsers(object.GetSortedUsers(owner, sorter, limit))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(maskedUsers)
|
c.ResponseOk(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserCount
|
// GetUserCount
|
||||||
@ -560,11 +580,12 @@ func (c *ApiController) GetUserCount() {
|
|||||||
c.ResponseOk(count)
|
c.ResponseOk(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddUserkeys
|
// AddUserKeys
|
||||||
// @Title AddUserkeys
|
// @Title AddUserKeys
|
||||||
// @router /add-user-keys [post]
|
// @router /add-user-keys [post]
|
||||||
// @Tag User API
|
// @Tag User API
|
||||||
func (c *ApiController) AddUserkeys() {
|
// @Success 200 {object} object.Userinfo The Response object
|
||||||
|
func (c *ApiController) AddUserKeys() {
|
||||||
var user object.User
|
var user object.User
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &user)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -573,7 +594,7 @@ func (c *ApiController) AddUserkeys() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isAdmin := c.IsAdmin()
|
isAdmin := c.IsAdmin()
|
||||||
affected, err := object.AddUserkeys(&user, isAdmin)
|
affected, err := object.AddUserKeys(&user, isAdmin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
|
@ -96,6 +96,13 @@ func (c *ApiController) RequireSignedInUser() (*object.User, bool) {
|
|||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(userId, "app/") {
|
||||||
|
tmpUserId := c.Input().Get("userId")
|
||||||
|
if tmpUserId != "" {
|
||||||
|
userId = tmpUserId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
user, err := object.GetUser(userId)
|
user, err := object.GetUser(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
|
@ -39,6 +39,7 @@ const (
|
|||||||
// @Title SendVerificationCode
|
// @Title SendVerificationCode
|
||||||
// @Tag Verification API
|
// @Tag Verification API
|
||||||
// @router /send-verification-code [post]
|
// @router /send-verification-code [post]
|
||||||
|
// @Success 200 {object} object.Userinfo The Response object
|
||||||
func (c *ApiController) SendVerificationCode() {
|
func (c *ApiController) SendVerificationCode() {
|
||||||
var vform form.VerificationForm
|
var vform form.VerificationForm
|
||||||
err := c.ParseForm(&vform)
|
err := c.ParseForm(&vform)
|
||||||
@ -53,17 +54,34 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if vform.CaptchaType != "none" {
|
provider, err := object.GetCaptchaProviderByApplication(vform.ApplicationId, "false", c.GetAcceptLanguage())
|
||||||
if captchaProvider := captcha.GetCaptchaProvider(vform.CaptchaType); captchaProvider == nil {
|
if err != nil {
|
||||||
c.ResponseError(c.T("general:don't support captchaProvider: ") + vform.CaptchaType)
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
} else if isHuman, err := captchaProvider.VerifyCaptcha(vform.CaptchaToken, vform.ClientSecret); err != nil {
|
}
|
||||||
c.ResponseError(err.Error())
|
|
||||||
return
|
if provider != nil {
|
||||||
} else if !isHuman {
|
if vform.CaptchaType != provider.Type {
|
||||||
c.ResponseError(c.T("verification:Turing test failed."))
|
c.ResponseError(c.T("verification:Turing test failed."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if provider.Type != "Default" {
|
||||||
|
vform.ClientSecret = provider.ClientSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
if vform.CaptchaType != "none" {
|
||||||
|
if captchaProvider := captcha.GetCaptchaProvider(vform.CaptchaType); captchaProvider == nil {
|
||||||
|
c.ResponseError(c.T("general:don't support captchaProvider: ") + vform.CaptchaType)
|
||||||
|
return
|
||||||
|
} else if isHuman, err := captchaProvider.VerifyCaptcha(vform.CaptchaToken, vform.ClientSecret); err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
} else if !isHuman {
|
||||||
|
c.ResponseError(c.T("verification:Turing test failed."))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
application, err := object.GetApplication(vform.ApplicationId)
|
application, err := object.GetApplication(vform.ApplicationId)
|
||||||
@ -91,6 +109,15 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if user == nil || user.IsDeleted {
|
||||||
|
c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.IsForbidden {
|
||||||
|
c.ResponseError(c.T("check:The user is forbidden to sign in, please contact the administrator"))
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mfaUserSession != "", means method is MfaAuthVerification
|
// mfaUserSession != "", means method is MfaAuthVerification
|
||||||
@ -142,6 +169,10 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if provider == nil {
|
||||||
|
c.ResponseError(fmt.Sprintf("please add an Email provider to the \"Providers\" list for the application: %s", application.Name))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, remoteAddr, vform.Dest)
|
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, remoteAddr, vform.Dest)
|
||||||
case object.VerifyTypePhone:
|
case object.VerifyTypePhone:
|
||||||
@ -184,6 +215,10 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if provider == nil {
|
||||||
|
c.ResponseError(fmt.Sprintf("please add a SMS provider to the \"Providers\" list for the application: %s", application.Name))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if phone, ok := util.GetE164Number(vform.Dest, vform.CountryCode); !ok {
|
if phone, ok := util.GetE164Number(vform.Dest, vform.CountryCode); !ok {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("verification:Phone number is invalid in your region %s"), vform.CountryCode))
|
c.ResponseError(fmt.Sprintf(c.T("verification:Phone number is invalid in your region %s"), vform.CountryCode))
|
||||||
@ -204,6 +239,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
// @Title VerifyCaptcha
|
// @Title VerifyCaptcha
|
||||||
// @Tag Verification API
|
// @Tag Verification API
|
||||||
// @router /verify-captcha [post]
|
// @router /verify-captcha [post]
|
||||||
|
// @Success 200 {object} object.Userinfo The Response object
|
||||||
func (c *ApiController) VerifyCaptcha() {
|
func (c *ApiController) VerifyCaptcha() {
|
||||||
var vform form.VerificationForm
|
var vform form.VerificationForm
|
||||||
err := c.ParseForm(&vform)
|
err := c.ParseForm(&vform)
|
||||||
@ -217,6 +253,16 @@ func (c *ApiController) VerifyCaptcha() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
captchaProvider, err := object.GetCaptchaProviderByOwnerName(vform.ApplicationId, c.GetAcceptLanguage())
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if captchaProvider.Type != "Default" {
|
||||||
|
vform.ClientSecret = captchaProvider.ClientSecret
|
||||||
|
}
|
||||||
|
|
||||||
provider := captcha.GetCaptchaProvider(vform.CaptchaType)
|
provider := captcha.GetCaptchaProvider(vform.CaptchaType)
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
c.ResponseError(c.T("verification:Invalid captcha provider."))
|
c.ResponseError(c.T("verification:Invalid captcha provider."))
|
||||||
@ -235,7 +281,8 @@ func (c *ApiController) VerifyCaptcha() {
|
|||||||
// ResetEmailOrPhone ...
|
// ResetEmailOrPhone ...
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Title ResetEmailOrPhone
|
// @Title ResetEmailOrPhone
|
||||||
// @router /api/reset-email-or-phone [post]
|
// @router /reset-email-or-phone [post]
|
||||||
|
// @Success 200 {object} object.Userinfo The Response object
|
||||||
func (c *ApiController) ResetEmailOrPhone() {
|
func (c *ApiController) ResetEmailOrPhone() {
|
||||||
user, ok := c.RequireSignedInUser()
|
user, ok := c.RequireSignedInUser()
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -329,7 +376,8 @@ func (c *ApiController) ResetEmailOrPhone() {
|
|||||||
// VerifyCode
|
// VerifyCode
|
||||||
// @Tag Verification API
|
// @Tag Verification API
|
||||||
// @Title VerifyCode
|
// @Title VerifyCode
|
||||||
// @router /api/verify-code [post]
|
// @router /verify-code [post]
|
||||||
|
// @Success 200 {object} object.Userinfo The Response object
|
||||||
func (c *ApiController) VerifyCode() {
|
func (c *ApiController) VerifyCode() {
|
||||||
var authForm form.AuthForm
|
var authForm form.AuthForm
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &authForm)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &authForm)
|
||||||
|
@ -146,7 +146,7 @@ func (c *ApiController) WebAuthnSigninBegin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WebAuthnSigninFinish
|
// WebAuthnSigninFinish
|
||||||
// @Title WebAuthnSigninBegin
|
// @Title WebAuthnSigninFinish
|
||||||
// @Tag Login API
|
// @Tag Login API
|
||||||
// @Description WebAuthn Login Flow 2nd stage
|
// @Description WebAuthn Login Flow 2nd stage
|
||||||
// @Param body body protocol.CredentialAssertionResponse true "authenticator assertion Response"
|
// @Param body body protocol.CredentialAssertionResponse true "authenticator assertion Response"
|
||||||
@ -154,6 +154,7 @@ func (c *ApiController) WebAuthnSigninBegin() {
|
|||||||
// @router /webauthn/signin/finish [post]
|
// @router /webauthn/signin/finish [post]
|
||||||
func (c *ApiController) WebAuthnSigninFinish() {
|
func (c *ApiController) WebAuthnSigninFinish() {
|
||||||
responseType := c.Input().Get("responseType")
|
responseType := c.Input().Get("responseType")
|
||||||
|
clientId := c.Input().Get("clientId")
|
||||||
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
@ -182,7 +183,13 @@ func (c *ApiController) WebAuthnSigninFinish() {
|
|||||||
c.SetSessionUsername(userId)
|
c.SetSessionUsername(userId)
|
||||||
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
|
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
|
||||||
|
|
||||||
application, err := object.GetApplicationByUser(user)
|
var application *object.Application
|
||||||
|
|
||||||
|
if clientId != "" && (responseType == ResponseTypeCode) {
|
||||||
|
application, err = object.GetApplicationByClientId(clientId)
|
||||||
|
} else {
|
||||||
|
application, err = object.GetApplicationByUser(user)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
|
82
email/custom_http.go
Normal file
82
email/custom_http.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// Copyright 2023 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 email
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/proxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HttpEmailProvider struct {
|
||||||
|
endpoint string
|
||||||
|
method string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHttpEmailProvider(endpoint string, method string) *HttpEmailProvider {
|
||||||
|
client := &HttpEmailProvider{
|
||||||
|
endpoint: endpoint,
|
||||||
|
method: method,
|
||||||
|
}
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *HttpEmailProvider) Send(fromAddress string, fromName string, toAddress string, subject string, content string) error {
|
||||||
|
var req *http.Request
|
||||||
|
var err error
|
||||||
|
if c.method == "POST" {
|
||||||
|
formValues := url.Values{}
|
||||||
|
formValues.Set("fromName", fromName)
|
||||||
|
formValues.Set("toAddress", toAddress)
|
||||||
|
formValues.Set("subject", subject)
|
||||||
|
formValues.Set("content", content)
|
||||||
|
req, err = http.NewRequest(c.method, c.endpoint, strings.NewReader(formValues.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
} else if c.method == "GET" {
|
||||||
|
req, err = http.NewRequest(c.method, c.endpoint, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
q := req.URL.Query()
|
||||||
|
q.Add("fromName", fromName)
|
||||||
|
q.Add("toAddress", toAddress)
|
||||||
|
q.Add("subject", subject)
|
||||||
|
q.Add("content", content)
|
||||||
|
req.URL.RawQuery = q.Encode()
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("HttpEmailProvider's Send() error, unsupported method: %s", c.method)
|
||||||
|
}
|
||||||
|
|
||||||
|
httpClient := proxy.DefaultHttpClient
|
||||||
|
resp, err := httpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("HttpEmailProvider's Send() error, custom HTTP Email request failed with status: %s", resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
@ -18,9 +18,11 @@ type EmailProvider interface {
|
|||||||
Send(fromAddress string, fromName, toAddress string, subject string, content string) error
|
Send(fromAddress string, fromName, toAddress string, subject string, content string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetEmailProvider(typ string, clientId string, clientSecret string, host string, port int, disableSsl bool) EmailProvider {
|
func GetEmailProvider(typ string, clientId string, clientSecret string, host string, port int, disableSsl bool, endpoint string, method string) EmailProvider {
|
||||||
if typ == "Azure ACS" {
|
if typ == "Azure ACS" {
|
||||||
return NewAzureACSEmailProvider(clientSecret, host)
|
return NewAzureACSEmailProvider(clientSecret, host)
|
||||||
|
} else if typ == "Custom HTTP Email" {
|
||||||
|
return NewHttpEmailProvider(endpoint, method)
|
||||||
} else {
|
} else {
|
||||||
return NewSmtpEmailProvider(clientId, clientSecret, host, port, typ, disableSsl)
|
return NewSmtpEmailProvider(clientId, clientSecret, host, port, typ, disableSsl)
|
||||||
}
|
}
|
||||||
|
15
form/auth.go
15
form/auth.go
@ -14,8 +14,11 @@
|
|||||||
|
|
||||||
package form
|
package form
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
type AuthForm struct {
|
type AuthForm struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
SigninMethod string `json:"signinMethod"`
|
||||||
|
|
||||||
Organization string `json:"organization"`
|
Organization string `json:"organization"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
@ -59,3 +62,13 @@ type AuthForm struct {
|
|||||||
Plan string `json:"plan"`
|
Plan string `json:"plan"`
|
||||||
Pricing string `json:"pricing"`
|
Pricing string `json:"pricing"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAuthFormFieldValue(form *AuthForm, fieldName string) (bool, string) {
|
||||||
|
val := reflect.ValueOf(*form)
|
||||||
|
fieldValue := val.FieldByName(fieldName)
|
||||||
|
|
||||||
|
if fieldValue.IsValid() && fieldValue.Kind() == reflect.String {
|
||||||
|
return true, fieldValue.String()
|
||||||
|
}
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
33
go.mod
33
go.mod
@ -4,44 +4,43 @@ go 1.16
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Masterminds/squirrel v1.5.3
|
github.com/Masterminds/squirrel v1.5.3
|
||||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b
|
|
||||||
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
|
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
|
||||||
github.com/aws/aws-sdk-go v1.45.5
|
github.com/aws/aws-sdk-go v1.45.5
|
||||||
github.com/beego/beego v1.12.12
|
github.com/beego/beego v1.12.12
|
||||||
github.com/beevik/etree v1.1.0
|
github.com/beevik/etree v1.1.0
|
||||||
github.com/casbin/casbin v1.9.1 // indirect
|
|
||||||
github.com/casbin/casbin/v2 v2.77.2
|
github.com/casbin/casbin/v2 v2.77.2
|
||||||
github.com/casdoor/go-sms-sender v0.14.0
|
github.com/casdoor/go-sms-sender v0.19.0
|
||||||
github.com/casdoor/gomail/v2 v2.0.1
|
github.com/casdoor/gomail/v2 v2.0.1
|
||||||
github.com/casdoor/notify v0.43.0
|
github.com/casdoor/notify v0.45.0
|
||||||
github.com/casdoor/oss v1.3.0
|
github.com/casdoor/oss v1.5.0
|
||||||
github.com/casdoor/xorm-adapter/v3 v3.0.4
|
github.com/casdoor/xorm-adapter/v3 v3.1.0
|
||||||
github.com/casvisor/casvisor-go-sdk v1.0.3
|
github.com/casvisor/casvisor-go-sdk v1.0.3
|
||||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
||||||
github.com/denisenkom/go-mssqldb v0.9.0
|
github.com/denisenkom/go-mssqldb v0.9.0
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect
|
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect
|
||||||
|
github.com/elimity-com/scim v0.0.0-20230426070224-941a5eac92f3
|
||||||
github.com/fogleman/gg v1.3.0
|
github.com/fogleman/gg v1.3.0
|
||||||
github.com/forestmgy/ldapserver v1.1.0
|
github.com/forestmgy/ldapserver v1.1.0
|
||||||
|
github.com/go-asn1-ber/asn1-ber v1.5.5
|
||||||
github.com/go-git/go-git/v5 v5.6.0
|
github.com/go-git/go-git/v5 v5.6.0
|
||||||
github.com/go-ldap/ldap/v3 v3.3.0
|
github.com/go-ldap/ldap/v3 v3.4.6
|
||||||
github.com/go-mysql-org/go-mysql v1.7.0
|
github.com/go-mysql-org/go-mysql v1.7.0
|
||||||
github.com/go-pay/gopay v1.5.72
|
github.com/go-pay/gopay v1.5.72
|
||||||
github.com/go-sql-driver/mysql v1.6.0
|
github.com/go-sql-driver/mysql v1.6.0
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
|
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
|
||||||
github.com/go-webauthn/webauthn v0.6.0
|
github.com/go-webauthn/webauthn v0.6.0
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0
|
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||||
github.com/google/uuid v1.3.1
|
github.com/google/uuid v1.4.0
|
||||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/lestrrat-go/jwx v1.2.21
|
github.com/lestrrat-go/jwx v1.2.21
|
||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
|
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
|
||||||
github.com/markbates/goth v1.75.2
|
github.com/markbates/goth v1.78.0
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
|
||||||
github.com/nyaruka/phonenumbers v1.1.5
|
github.com/nyaruka/phonenumbers v1.1.5
|
||||||
github.com/pquerna/otp v1.4.0
|
github.com/pquerna/otp v1.4.0
|
||||||
github.com/prometheus/client_golang v1.11.1
|
github.com/prometheus/client_golang v1.11.1
|
||||||
github.com/prometheus/client_model v0.3.0
|
github.com/prometheus/client_model v0.4.0
|
||||||
github.com/qiangmzsx/string-adapter/v2 v2.1.0
|
github.com/qiangmzsx/string-adapter/v2 v2.1.0
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/russellhaering/gosaml2 v0.9.0
|
github.com/russellhaering/gosaml2 v0.9.0
|
||||||
@ -60,13 +59,13 @@ require (
|
|||||||
github.com/xorm-io/core v0.7.4
|
github.com/xorm-io/core v0.7.4
|
||||||
github.com/xorm-io/xorm v1.1.6
|
github.com/xorm-io/xorm v1.1.6
|
||||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||||
golang.org/x/crypto v0.12.0
|
golang.org/x/crypto v0.14.0
|
||||||
golang.org/x/net v0.14.0
|
golang.org/x/net v0.17.0
|
||||||
golang.org/x/oauth2 v0.11.0
|
golang.org/x/oauth2 v0.13.0
|
||||||
google.golang.org/api v0.138.0
|
google.golang.org/api v0.150.0
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0
|
gopkg.in/square/go-jose.v2 v2.6.0
|
||||||
layeh.com/radius v0.0.0-20221205141417-e7fbddd11d68 // indirect
|
layeh.com/radius v0.0.0-20221205141417-e7fbddd11d68
|
||||||
maunium.net/go/mautrix v0.16.0
|
maunium.net/go/mautrix v0.16.0
|
||||||
modernc.org/sqlite v1.18.2
|
modernc.org/sqlite v1.18.2
|
||||||
)
|
)
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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": "Das Konto für den Anbieter %s und Benutzernamen %s (%s) existiert nicht und es ist nicht erlaubt, ein neues Konto anzumelden. Bitte wenden Sie sich an Ihren 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": "Das Konto für den Anbieter %s und Benutzernamen %s (%s) existiert nicht und es ist nicht erlaubt, ein neues Konto anzumelden. Bitte wenden Sie sich an Ihren IT-Support",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Das Konto für den Anbieter %s und Benutzernamen %s (%s) ist bereits mit einem anderen Konto verknüpft: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Das Konto für den Anbieter %s und Benutzernamen %s (%s) ist bereits mit einem anderen Konto verknüpft: %s (%s)",
|
||||||
"The application: %s does not exist": "Die Anwendung: %s existiert nicht",
|
"The application: %s does not exist": "Die Anwendung: %s existiert nicht",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "Die Anmeldeart \"Anmeldung mit Passwort\" ist für die Anwendung nicht aktiviert",
|
"The login method: login with password is not enabled for the application": "Die Anmeldeart \"Anmeldung mit Passwort\" ist für die Anwendung nicht aktiviert",
|
||||||
"The provider: %s is not enabled for the application": "Der Anbieter: %s ist nicht für die Anwendung aktiviert",
|
"The provider: %s is not enabled for the application": "Der Anbieter: %s ist nicht für die Anwendung aktiviert",
|
||||||
"Unauthorized operation": "Nicht autorisierte Operation",
|
"Unauthorized operation": "Nicht autorisierte Operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unbekannter Authentifizierungstyp (nicht Passwort oder Anbieter), Formular = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unbekannter Authentifizierungstyp (nicht Passwort oder Anbieter), Formular = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s und %s stimmen nicht überein"
|
"Service %s and %s do not match": "Service %s und %s stimmen nicht überein"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "E-Mail ist ungültig",
|
"Email is invalid": "E-Mail ist ungültig",
|
||||||
"Empty username.": "Leerer Benutzername.",
|
"Empty username.": "Leerer Benutzername.",
|
||||||
"FirstName cannot be blank": "Vorname darf nicht leer sein",
|
"FirstName cannot be blank": "Vorname darf nicht leer sein",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "Ldap Benutzername oder Passwort falsch",
|
"LDAP user name or password incorrect": "Ldap Benutzername oder Passwort falsch",
|
||||||
"LastName cannot be blank": "Nachname darf nicht leer sein",
|
"LastName cannot be blank": "Nachname darf nicht leer sein",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Mehrere Konten mit derselben uid, bitte überprüfen Sie Ihren LDAP-Server",
|
"Multiple accounts with same uid, please check your ldap server": "Mehrere Konten mit derselben uid, bitte überprüfen Sie Ihren LDAP-Server",
|
||||||
"Organization does not exist": "Organisation existiert nicht",
|
"Organization does not exist": "Organisation existiert nicht",
|
||||||
"Password must have at least 6 characters": "Das Passwort muss mindestens 6 Zeichen enthalten",
|
|
||||||
"Phone already exists": "Telefon existiert bereits",
|
"Phone already exists": "Telefon existiert bereits",
|
||||||
"Phone cannot be empty": "Das Telefon darf nicht leer sein",
|
"Phone cannot be empty": "Das Telefon darf nicht leer sein",
|
||||||
"Phone number is invalid": "Die Telefonnummer ist ungültig",
|
"Phone number is invalid": "Die Telefonnummer ist ungültig",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Sitzung abgelaufen, bitte erneut anmelden",
|
"Session outdated, please login again": "Sitzung abgelaufen, bitte erneut anmelden",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "Dem Benutzer ist der Zugang verboten, bitte kontaktieren Sie den Administrator",
|
"The user is forbidden to sign in, please contact the administrator": "Dem Benutzer ist der Zugang verboten, bitte kontaktieren Sie den Administrator",
|
||||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.": "Der Benutzername darf nur alphanumerische Zeichen, Unterstriche oder Bindestriche enthalten, keine aufeinanderfolgenden Bindestriche oder Unterstriche haben und darf nicht mit einem Bindestrich oder Unterstrich beginnen oder enden.",
|
"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.": "Der Benutzername darf nur alphanumerische Zeichen, Unterstriche oder Bindestriche enthalten, keine aufeinanderfolgenden Bindestriche oder Unterstriche haben und darf nicht mit einem Bindestrich oder Unterstrich beginnen oder enden.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Benutzername existiert bereits",
|
"Username already exists": "Benutzername existiert bereits",
|
||||||
"Username cannot be an email address": "Benutzername kann keine E-Mail-Adresse sein",
|
"Username cannot be an email address": "Benutzername kann keine E-Mail-Adresse sein",
|
||||||
"Username cannot contain white spaces": "Benutzername darf keine Leerzeichen enthalten",
|
"Username cannot contain white spaces": "Benutzername darf keine Leerzeichen enthalten",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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": "La cuenta para el proveedor: %s y el nombre de usuario: %s (%s) no existe y no se permite registrarse como una nueva cuenta, por favor contacte a su soporte de TI",
|
"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": "La cuenta para el proveedor: %s y el nombre de usuario: %s (%s) no existe y no se permite registrarse como una nueva cuenta, por favor contacte a su soporte de TI",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "La cuenta para proveedor: %s y nombre de usuario: %s (%s) ya está vinculada a otra cuenta: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "La cuenta para proveedor: %s y nombre de usuario: %s (%s) ya está vinculada a otra cuenta: %s (%s)",
|
||||||
"The application: %s does not exist": "La aplicación: %s no existe",
|
"The application: %s does not exist": "La aplicación: %s no existe",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "El método de inicio de sesión: inicio de sesión con contraseña no está habilitado para la aplicación",
|
"The login method: login with password is not enabled for the application": "El método de inicio de sesión: inicio de sesión con contraseña no está habilitado para la aplicación",
|
||||||
"The provider: %s is not enabled for the application": "El proveedor: %s no está habilitado para la aplicación",
|
"The provider: %s is not enabled for the application": "El proveedor: %s no está habilitado para la aplicación",
|
||||||
"Unauthorized operation": "Operación no autorizada",
|
"Unauthorized operation": "Operación no autorizada",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Tipo de autenticación desconocido (no es contraseña o proveedor), formulario = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Tipo de autenticación desconocido (no es contraseña o proveedor), formulario = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Los servicios %s y %s no coinciden"
|
"Service %s and %s do not match": "Los servicios %s y %s no coinciden"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "El correo electrónico no es válido",
|
"Email is invalid": "El correo electrónico no es válido",
|
||||||
"Empty username.": "Nombre de usuario vacío.",
|
"Empty username.": "Nombre de usuario vacío.",
|
||||||
"FirstName cannot be blank": "El nombre no puede estar en blanco",
|
"FirstName cannot be blank": "El nombre no puede estar en blanco",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "Nombre de usuario o contraseña de Ldap incorrectos",
|
"LDAP user name or password incorrect": "Nombre de usuario o contraseña de Ldap incorrectos",
|
||||||
"LastName cannot be blank": "El apellido no puede estar en blanco",
|
"LastName cannot be blank": "El apellido no puede estar en blanco",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Cuentas múltiples con el mismo uid, por favor revise su servidor ldap",
|
"Multiple accounts with same uid, please check your ldap server": "Cuentas múltiples con el mismo uid, por favor revise su servidor ldap",
|
||||||
"Organization does not exist": "La organización no existe",
|
"Organization does not exist": "La organización no existe",
|
||||||
"Password must have at least 6 characters": "La contraseña debe tener al menos 6 caracteres",
|
|
||||||
"Phone already exists": "El teléfono ya existe",
|
"Phone already exists": "El teléfono ya existe",
|
||||||
"Phone cannot be empty": "Teléfono no puede estar vacío",
|
"Phone cannot be empty": "Teléfono no puede estar vacío",
|
||||||
"Phone number is invalid": "El número de teléfono no es válido",
|
"Phone number is invalid": "El número de teléfono no es válido",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Sesión expirada, por favor vuelva a iniciar sesión",
|
"Session outdated, please login again": "Sesión expirada, por favor vuelva a iniciar sesión",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "El usuario no está autorizado a iniciar sesión, por favor contacte al administrador",
|
"The user is forbidden to sign in, please contact the administrator": "El usuario no está autorizado a iniciar sesión, por favor contacte al administrador",
|
||||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.": "El nombre de usuario solo puede contener caracteres alfanuméricos, guiones bajos o guiones, no puede tener guiones o subrayados consecutivos, y no puede comenzar ni terminar con un guión o subrayado.",
|
"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.": "El nombre de usuario solo puede contener caracteres alfanuméricos, guiones bajos o guiones, no puede tener guiones o subrayados consecutivos, y no puede comenzar ni terminar con un guión o subrayado.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "El nombre de usuario ya existe",
|
"Username already exists": "El nombre de usuario ya existe",
|
||||||
"Username cannot be an email address": "Nombre de usuario no puede ser una dirección de correo electrónico",
|
"Username cannot be an email address": "Nombre de usuario no puede ser una dirección de correo electrónico",
|
||||||
"Username cannot contain white spaces": "Nombre de usuario no puede contener espacios en blanco",
|
"Username cannot contain white spaces": "Nombre de usuario no puede contener espacios en blanco",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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": "Le compte pour le fournisseur : %s et le nom d'utilisateur : %s (%s) n'existe pas et n'est pas autorisé à s'inscrire comme nouveau compte, veuillez contacter votre support informatique",
|
"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": "Le compte pour le fournisseur : %s et le nom d'utilisateur : %s (%s) n'existe pas et n'est pas autorisé à s'inscrire comme nouveau compte, veuillez contacter votre support informatique",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Le compte du fournisseur : %s et le nom d'utilisateur : %s (%s) sont déjà liés à un autre compte : %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Le compte du fournisseur : %s et le nom d'utilisateur : %s (%s) sont déjà liés à un autre compte : %s (%s)",
|
||||||
"The application: %s does not exist": "L'application : %s n'existe pas",
|
"The application: %s does not exist": "L'application : %s n'existe pas",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "La méthode de connexion : connexion avec mot de passe n'est pas activée pour l'application",
|
"The login method: login with password is not enabled for the application": "La méthode de connexion : connexion avec mot de passe n'est pas activée pour l'application",
|
||||||
"The provider: %s is not enabled for the application": "Le fournisseur :%s n'est pas activé pour l'application",
|
"The provider: %s is not enabled for the application": "Le fournisseur :%s n'est pas activé pour l'application",
|
||||||
"Unauthorized operation": "Opération non autorisée",
|
"Unauthorized operation": "Opération non autorisée",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Type d'authentification inconnu (pas de mot de passe ou de fournisseur), formulaire = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Type d'authentification inconnu (pas de mot de passe ou de fournisseur), formulaire = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "Le tag de l’utilisateur %s n’est pas répertorié dans les tags de l’application",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Les services %s et %s ne correspondent pas"
|
"Service %s and %s do not match": "Les services %s et %s ne correspondent pas"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "L'adresse e-mail est invalide",
|
"Email is invalid": "L'adresse e-mail est invalide",
|
||||||
"Empty username.": "Nom d'utilisateur vide.",
|
"Empty username.": "Nom d'utilisateur vide.",
|
||||||
"FirstName cannot be blank": "Le prénom ne peut pas être laissé vide",
|
"FirstName cannot be blank": "Le prénom ne peut pas être laissé vide",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "Nom d'utilisateur ou mot de passe LDAP incorrect",
|
"LDAP user name or password incorrect": "Nom d'utilisateur ou mot de passe LDAP incorrect",
|
||||||
"LastName cannot be blank": "Le nom de famille ne peut pas être vide",
|
"LastName cannot be blank": "Le nom de famille ne peut pas être vide",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Plusieurs comptes avec le même identifiant d'utilisateur, veuillez vérifier votre serveur LDAP",
|
"Multiple accounts with same uid, please check your ldap server": "Plusieurs comptes avec le même identifiant d'utilisateur, veuillez vérifier votre serveur LDAP",
|
||||||
"Organization does not exist": "L'organisation n'existe pas",
|
"Organization does not exist": "L'organisation n'existe pas",
|
||||||
"Password must have at least 6 characters": "Le mot de passe doit comporter au moins 6 caractères",
|
|
||||||
"Phone already exists": "Le téléphone existe déjà",
|
"Phone already exists": "Le téléphone existe déjà",
|
||||||
"Phone cannot be empty": "Le téléphone ne peut pas être vide",
|
"Phone cannot be empty": "Le téléphone ne peut pas être vide",
|
||||||
"Phone number is invalid": "Le numéro de téléphone est invalide",
|
"Phone number is invalid": "Le numéro de téléphone est invalide",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session expirée, veuillez vous connecter à nouveau",
|
"Session outdated, please login again": "Session expirée, veuillez vous connecter à nouveau",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "L'utilisateur est interdit de se connecter, veuillez contacter l'administrateur",
|
"The user is forbidden to sign in, please contact the administrator": "L'utilisateur est interdit de se connecter, veuillez contacter l'administrateur",
|
||||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "L'utilisateur %s n'existe pas sur le serveur LDAP",
|
||||||
"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.": "Le nom d'utilisateur ne peut contenir que des caractères alphanumériques, des traits soulignés ou des tirets, ne peut pas avoir de tirets ou de traits soulignés consécutifs et ne peut pas commencer ou se terminer par un tiret ou un trait souligné.",
|
"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.": "Le nom d'utilisateur ne peut contenir que des caractères alphanumériques, des traits soulignés ou des tirets, ne peut pas avoir de tirets ou de traits soulignés consécutifs et ne peut pas commencer ou se terminer par un tiret ou un trait souligné.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Nom d'utilisateur existe déjà",
|
"Username already exists": "Nom d'utilisateur existe déjà",
|
||||||
"Username cannot be an email address": "Nom d'utilisateur ne peut pas être une adresse e-mail",
|
"Username cannot be an email address": "Nom d'utilisateur ne peut pas être une adresse e-mail",
|
||||||
"Username cannot contain white spaces": "Nom d'utilisateur ne peut pas contenir d'espaces blancs",
|
"Username cannot contain white spaces": "Nom d'utilisateur ne peut pas contenir d'espaces blancs",
|
||||||
@ -53,7 +65,7 @@
|
|||||||
"Username must have at least 2 characters": "Le nom d'utilisateur doit comporter au moins 2 caractères",
|
"Username must have at least 2 characters": "Le nom d'utilisateur doit comporter au moins 2 caractères",
|
||||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "Vous avez entré le mauvais mot de passe ou code plusieurs fois, veuillez attendre %d minutes et réessayer",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "Vous avez entré le mauvais mot de passe ou code plusieurs fois, veuillez attendre %d minutes et réessayer",
|
||||||
"Your region is not allow to signup by phone": "Votre région n'est pas autorisée à s'inscrire par téléphone",
|
"Your region is not allow to signup by phone": "Votre région n'est pas autorisée à s'inscrire par téléphone",
|
||||||
"password or code is incorrect": "password or code is incorrect",
|
"password or code is incorrect": "mot de passe ou code invalide",
|
||||||
"password or code is incorrect, you have %d remaining chances": "Le mot de passe ou le code est incorrect, il vous reste %d chances",
|
"password or code is incorrect, you have %d remaining chances": "Le mot de passe ou le code est incorrect, il vous reste %d chances",
|
||||||
"unsupported password type: %s": "Type de mot de passe non pris en charge : %s"
|
"unsupported password type: %s": "Type de mot de passe non pris en charge : %s"
|
||||||
},
|
},
|
||||||
@ -61,8 +73,8 @@
|
|||||||
"Missing parameter": "Paramètre manquant",
|
"Missing parameter": "Paramètre manquant",
|
||||||
"Please login first": "Veuillez d'abord vous connecter",
|
"Please login first": "Veuillez d'abord vous connecter",
|
||||||
"The user: %s doesn't exist": "L'utilisateur : %s n'existe pas",
|
"The user: %s doesn't exist": "L'utilisateur : %s n'existe pas",
|
||||||
"don't support captchaProvider: ": "Ne pas prendre en charge la captchaProvider",
|
"don't support captchaProvider: ": "ne prend pas en charge captchaProvider: ",
|
||||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
"this operation is not allowed in demo mode": "cette opération n’est pas autorisée en mode démo"
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Le serveur LDAP existe"
|
"Ldap server exist": "Le serveur LDAP existe"
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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": "Akun untuk penyedia: %s dan nama pengguna: %s (%s) tidak ada dan tidak diizinkan untuk mendaftar sebagai akun baru, silakan hubungi dukungan IT Anda",
|
"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": "Akun untuk penyedia: %s dan nama pengguna: %s (%s) tidak ada dan tidak diizinkan untuk mendaftar sebagai akun baru, silakan hubungi dukungan IT Anda",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Akun untuk provider: %s dan username: %s (%s) sudah terhubung dengan akun lain: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Akun untuk provider: %s dan username: %s (%s) sudah terhubung dengan akun lain: %s (%s)",
|
||||||
"The application: %s does not exist": "Aplikasi: %s tidak ada",
|
"The application: %s does not exist": "Aplikasi: %s tidak ada",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "Metode login: login dengan kata sandi tidak diaktifkan untuk aplikasi tersebut",
|
"The login method: login with password is not enabled for the application": "Metode login: login dengan kata sandi tidak diaktifkan untuk aplikasi tersebut",
|
||||||
"The provider: %s is not enabled for the application": "Penyedia: %s tidak diaktifkan untuk aplikasi ini",
|
"The provider: %s is not enabled for the application": "Penyedia: %s tidak diaktifkan untuk aplikasi ini",
|
||||||
"Unauthorized operation": "Operasi tidak sah",
|
"Unauthorized operation": "Operasi tidak sah",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Jenis otentikasi tidak diketahui (bukan kata sandi atau pemberi), formulir = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Jenis otentikasi tidak diketahui (bukan kata sandi atau pemberi), formulir = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Layanan %s dan %s tidak cocok"
|
"Service %s and %s do not match": "Layanan %s dan %s tidak cocok"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Email tidak valid",
|
"Email is invalid": "Email tidak valid",
|
||||||
"Empty username.": "Nama pengguna kosong.",
|
"Empty username.": "Nama pengguna kosong.",
|
||||||
"FirstName cannot be blank": "Nama depan tidak boleh kosong",
|
"FirstName cannot be blank": "Nama depan tidak boleh kosong",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "Nama pengguna atau kata sandi Ldap salah",
|
"LDAP user name or password incorrect": "Nama pengguna atau kata sandi Ldap salah",
|
||||||
"LastName cannot be blank": "Nama belakang tidak boleh kosong",
|
"LastName cannot be blank": "Nama belakang tidak boleh kosong",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Beberapa akun dengan uid yang sama, harap periksa server ldap Anda",
|
"Multiple accounts with same uid, please check your ldap server": "Beberapa akun dengan uid yang sama, harap periksa server ldap Anda",
|
||||||
"Organization does not exist": "Organisasi tidak ada",
|
"Organization does not exist": "Organisasi tidak ada",
|
||||||
"Password must have at least 6 characters": "Kata sandi harus memiliki minimal 6 karakter",
|
|
||||||
"Phone already exists": "Telepon sudah ada",
|
"Phone already exists": "Telepon sudah ada",
|
||||||
"Phone cannot be empty": "Telepon tidak boleh kosong",
|
"Phone cannot be empty": "Telepon tidak boleh kosong",
|
||||||
"Phone number is invalid": "Nomor telepon tidak valid",
|
"Phone number is invalid": "Nomor telepon tidak valid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Sesi kedaluwarsa, silakan masuk lagi",
|
"Session outdated, please login again": "Sesi kedaluwarsa, silakan masuk lagi",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "Pengguna dilarang masuk, silakan hubungi administrator",
|
"The user is forbidden to sign in, please contact the administrator": "Pengguna dilarang masuk, silakan hubungi administrator",
|
||||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.": "Nama pengguna hanya bisa menggunakan karakter alfanumerik, garis bawah atau tanda hubung, tidak boleh memiliki dua tanda hubung atau garis bawah berurutan, dan tidak boleh diawali atau diakhiri dengan tanda hubung atau garis bawah.",
|
"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.": "Nama pengguna hanya bisa menggunakan karakter alfanumerik, garis bawah atau tanda hubung, tidak boleh memiliki dua tanda hubung atau garis bawah berurutan, dan tidak boleh diawali atau diakhiri dengan tanda hubung atau garis bawah.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Nama pengguna sudah ada",
|
"Username already exists": "Nama pengguna sudah ada",
|
||||||
"Username cannot be an email address": "Username tidak bisa menjadi alamat email",
|
"Username cannot be an email address": "Username tidak bisa menjadi alamat email",
|
||||||
"Username cannot contain white spaces": "Username tidak boleh mengandung spasi",
|
"Username cannot contain white spaces": "Username tidak boleh mengandung spasi",
|
||||||
|
@ -15,23 +15,19 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
},
|
},
|
||||||
"chat": {
|
|
||||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
|
||||||
"The chat: %s is not found": "The chat: %s is not found",
|
|
||||||
"The message is invalid": "The message is invalid",
|
|
||||||
"The message: %s is not found": "The message: %s is not found",
|
|
||||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
|
||||||
"The provider: %s is not found": "The provider: %s is not found"
|
|
||||||
},
|
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
@ -41,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "アプリケーション: %sは存在しません",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "ログイン方法:パスワードでのログインはアプリケーションで有効になっていません",
|
"The login method: login with password is not enabled for the application": "ログイン方法:パスワードでのログインはアプリケーションで有効になっていません",
|
||||||
"The provider: %s is not enabled for the application": "プロバイダー:%sはアプリケーションでは有効化されていません",
|
"The provider: %s is not enabled for the application": "プロバイダー:%sはアプリケーションでは有効化されていません",
|
||||||
"Unauthorized operation": "不正操作",
|
"Unauthorized operation": "不正操作",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "不明な認証タイプ(パスワードまたはプロバイダーではない)フォーム=%s",
|
"Unknown authentication type (not password or provider), form = %s": "不明な認証タイプ(パスワードまたはプロバイダーではない)フォーム=%s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "サービス%sと%sは一致しません"
|
"Service %s and %s do not match": "サービス%sと%sは一致しません"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "電子メールは無効です",
|
"Email is invalid": "電子メールは無効です",
|
||||||
"Empty username.": "空のユーザー名。",
|
"Empty username.": "空のユーザー名。",
|
||||||
"FirstName cannot be blank": "ファーストネームは空白にできません",
|
"FirstName cannot be blank": "ファーストネームは空白にできません",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "Ldapのユーザー名またはパスワードが間違っています",
|
"LDAP user name or password incorrect": "Ldapのユーザー名またはパスワードが間違っています",
|
||||||
"LastName cannot be blank": "姓は空白にできません",
|
"LastName cannot be blank": "姓は空白にできません",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "同じuidを持つ複数のアカウントがあります。あなたのLDAPサーバーを確認してください",
|
"Multiple accounts with same uid, please check your ldap server": "同じuidを持つ複数のアカウントがあります。あなたのLDAPサーバーを確認してください",
|
||||||
"Organization does not exist": "組織は存在しません",
|
"Organization does not exist": "組織は存在しません",
|
||||||
"Password must have at least 6 characters": "パスワードは少なくとも6つの文字が必要です",
|
|
||||||
"Phone already exists": "電話はすでに存在しています",
|
"Phone already exists": "電話はすでに存在しています",
|
||||||
"Phone cannot be empty": "電話は空っぽにできません",
|
"Phone cannot be empty": "電話は空っぽにできません",
|
||||||
"Phone number is invalid": "電話番号が無効です",
|
"Phone number is invalid": "電話番号が無効です",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "セッションが期限切れになりました。再度ログインしてください",
|
"Session outdated, please login again": "セッションが期限切れになりました。再度ログインしてください",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.": "ユーザー名には英数字、アンダースコア、ハイフンしか含めることができません。連続したハイフンまたはアンダースコアは不可であり、ハイフンまたはアンダースコアで始まるまたは終わることもできません。",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"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": "ユーザ名にはスペースを含めることはできません",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "해당 애플리케이션(%s)이 존재하지 않습니다",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "어플리케이션에서는 암호를 사용한 로그인 방법이 활성화되어 있지 않습니다",
|
"The login method: login with password is not enabled for the application": "어플리케이션에서는 암호를 사용한 로그인 방법이 활성화되어 있지 않습니다",
|
||||||
"The provider: %s is not enabled for the application": "제공자 %s은(는) 응용 프로그램에서 활성화되어 있지 않습니다",
|
"The provider: %s is not enabled for the application": "제공자 %s은(는) 응용 프로그램에서 활성화되어 있지 않습니다",
|
||||||
"Unauthorized operation": "무단 조작",
|
"Unauthorized operation": "무단 조작",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "알 수 없는 인증 유형(암호 또는 공급자가 아님), 폼 = %s",
|
"Unknown authentication type (not password or provider), form = %s": "알 수 없는 인증 유형(암호 또는 공급자가 아님), 폼 = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "서비스 %s와 %s는 일치하지 않습니다"
|
"Service %s and %s do not match": "서비스 %s와 %s는 일치하지 않습니다"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "이메일이 유효하지 않습니다",
|
"Email is invalid": "이메일이 유효하지 않습니다",
|
||||||
"Empty username.": "빈 사용자 이름.",
|
"Empty username.": "빈 사용자 이름.",
|
||||||
"FirstName cannot be blank": "이름은 공백일 수 없습니다",
|
"FirstName cannot be blank": "이름은 공백일 수 없습니다",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP 사용자 이름 또는 암호가 잘못되었습니다",
|
"LDAP user name or password incorrect": "LDAP 사용자 이름 또는 암호가 잘못되었습니다",
|
||||||
"LastName cannot be blank": "성은 비어 있을 수 없습니다",
|
"LastName cannot be blank": "성은 비어 있을 수 없습니다",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "동일한 UID를 가진 여러 계정이 있습니다. LDAP 서버를 확인해주세요",
|
"Multiple accounts with same uid, please check your ldap server": "동일한 UID를 가진 여러 계정이 있습니다. LDAP 서버를 확인해주세요",
|
||||||
"Organization does not exist": "조직은 존재하지 않습니다",
|
"Organization does not exist": "조직은 존재하지 않습니다",
|
||||||
"Password must have at least 6 characters": "암호는 적어도 6자 이상이어야 합니다",
|
|
||||||
"Phone already exists": "전화기는 이미 존재합니다",
|
"Phone already exists": "전화기는 이미 존재합니다",
|
||||||
"Phone cannot be empty": "전화는 비워 둘 수 없습니다",
|
"Phone cannot be empty": "전화는 비워 둘 수 없습니다",
|
||||||
"Phone number is invalid": "전화번호가 유효하지 않습니다",
|
"Phone number is invalid": "전화번호가 유효하지 않습니다",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "세션이 만료되었습니다. 다시 로그인해주세요",
|
"Session outdated, please login again": "세션이 만료되었습니다. 다시 로그인해주세요",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.": "사용자 이름은 알파벳, 숫자, 밑줄 또는 하이픈만 포함할 수 있으며, 연속된 하이픈 또는 밑줄을 가질 수 없으며, 하이픈 또는 밑줄로 시작하거나 끝날 수 없습니다.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"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": "사용자 이름에는 공백이 포함될 수 없습니다",
|
||||||
|
@ -15,23 +15,19 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
},
|
},
|
||||||
"chat": {
|
|
||||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
|
||||||
"The chat: %s is not found": "The chat: %s is not found",
|
|
||||||
"The message is invalid": "The message is invalid",
|
|
||||||
"The message: %s is not found": "The message: %s is not found",
|
|
||||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
|
||||||
"The provider: %s is not found": "The provider: %s is not found"
|
|
||||||
},
|
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
@ -41,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -1,25 +1,29 @@
|
|||||||
{
|
{
|
||||||
"account": {
|
"account": {
|
||||||
"Failed to add user": "Failed to add user",
|
"Failed to add user": "Falha ao adicionar usuário",
|
||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
"Get init score failed, error: %w": "Obter pontuação inicial falhou, erro: %w",
|
||||||
"Please sign out first": "Please sign out first",
|
"Please sign out first": "Por favor, saia da sessão primeiro",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "O aplicativo não permite a criação de uma nova conta"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"Challenge method should be S256": "Método de desafio deve ser S256",
|
||||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
"Failed to create user, user information is invalid: %s": "Falha ao criar usuário, informação do usuário inválida: %s",
|
||||||
"Failed to login in: %s": "Failed to login in: %s",
|
"Failed to login in: %s": "Falha ao entrar em: %s",
|
||||||
"Invalid token": "Invalid token",
|
"Invalid token": "Token inválido",
|
||||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
"State expected: %s, but got: %s": "Estado esperado: %s, mas recebeu: %s",
|
||||||
"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 via %%s, please use another way to sign up": "A conta para o provedor: %s e nome de usuário: %s (%s) não existe e não é permitido inscrever-se como uma nova conta via %%s, por favor, use outra forma de se inscrever",
|
||||||
"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) does not exist and is not allowed to sign up as new account, please contact your IT support": "A conta para o provedor: %s e nome de usuário: %s (%s) não existe e não é permitido inscrever-se como uma nova conta entre em contato com seu suporte de TI",
|
||||||
"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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
@ -33,27 +37,35 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
"Username cannot start with a digit": "O nome de usuário não pode começar com um dígito",
|
||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"Username is too long (maximum is 39 characters).": "Nome de usuário é muito longo (máximo é 39 caracteres).",
|
||||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
"Username must have at least 2 characters": "Nome de usuário deve ter pelo menos 2 caracteres",
|
||||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||||
"password or code is incorrect": "password or code is incorrect",
|
"password or code is incorrect": "senha ou código incorreto",
|
||||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||||
"unsupported password type: %s": "unsupported password type: %s"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
@ -77,15 +89,15 @@
|
|||||||
},
|
},
|
||||||
"organization": {
|
"organization": {
|
||||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||||
"The %s is immutable.": "The %s is immutable.",
|
"The %s is immutable.": "O %s é imutável.",
|
||||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
"Unknown modify rule %s.": "Regra de modificação %s desconhecida."
|
||||||
},
|
},
|
||||||
"provider": {
|
"provider": {
|
||||||
"Invalid application id": "Invalid application id",
|
"Invalid application id": "Id do aplicativo inválido",
|
||||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
"the provider: %s does not exist": "o provedor: %s não existe"
|
||||||
},
|
},
|
||||||
"resource": {
|
"resource": {
|
||||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
"User is nil for tag: avatar": "Usuário é nulo para tag: avatar",
|
||||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||||
},
|
},
|
||||||
"saml": {
|
"saml": {
|
||||||
@ -104,19 +116,19 @@
|
|||||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
"Empty clientId or clientSecret": "ClientId ou clientSecret vazio",
|
||||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
"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 application or wrong clientSecret": "Aplicativo inválido ou clientSecret errado",
|
||||||
"Invalid client_id": "Invalid client_id",
|
"Invalid client_id": "client_id inválido",
|
||||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "URI de redirecionamento: %s não existe na lista de URI de redirecionamento permitida",
|
||||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
"Token not found, invalid accessToken": "Token não encontrado, token de acesso inválido"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"Display name cannot be empty": "Display name cannot be empty",
|
"Display name cannot be empty": "Nome de exibição não pode ser vazio",
|
||||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||||
},
|
},
|
||||||
"user_upload": {
|
"user_upload": {
|
||||||
"Failed to import users": "Failed to import users"
|
"Failed to import users": "Falha ao importar usuários"
|
||||||
},
|
},
|
||||||
"util": {
|
"util": {
|
||||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"The application does not allow to sign up new account": "Приложение не позволяет зарегистрироваться новому аккаунту"
|
"The application does not allow to sign up new account": "Приложение не позволяет зарегистрироваться новому аккаунту"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"Challenge method should be S256": "Метод испытаний должен быть S256",
|
"Challenge method should be S256": "Метод проверки должен быть S256",
|
||||||
"Failed to create user, user information is invalid: %s": "Не удалось создать пользователя, информация о пользователе недействительна: %s",
|
"Failed to create user, user information is invalid: %s": "Не удалось создать пользователя, информация о пользователе недействительна: %s",
|
||||||
"Failed to login in: %s": "Не удалось войти в систему: %s",
|
"Failed to login in: %s": "Не удалось войти в систему: %s",
|
||||||
"Invalid token": "Недействительный токен",
|
"Invalid token": "Недействительный токен",
|
||||||
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "Приложение: %s не существует",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "Метод входа: вход с паролем не включен для приложения",
|
"The login method: login with password is not enabled for the application": "Метод входа: вход с паролем не включен для приложения",
|
||||||
"The provider: %s is not enabled for the application": "Провайдер: %s не включен для приложения",
|
"The provider: %s is not enabled for the application": "Провайдер: %s не включен для приложения",
|
||||||
"Unauthorized operation": "Несанкционированная операция",
|
"Unauthorized operation": "Несанкционированная операция",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Неизвестный тип аутентификации (не пароль и не провайдер), форма = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Неизвестный тип аутентификации (не пароль и не провайдер), форма = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "Тег пользователя: %s не указан в тэгах приложения",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Сервисы %s и %s не совпадают"
|
"Service %s and %s do not match": "Сервисы %s и %s не совпадают"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Адрес электронной почты недействительный",
|
"Email is invalid": "Адрес электронной почты недействительный",
|
||||||
"Empty username.": "Пустое имя пользователя.",
|
"Empty username.": "Пустое имя пользователя.",
|
||||||
"FirstName cannot be blank": "Имя не может быть пустым",
|
"FirstName cannot be blank": "Имя не может быть пустым",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "Неправильное имя пользователя или пароль Ldap",
|
"LDAP user name or password incorrect": "Неправильное имя пользователя или пароль Ldap",
|
||||||
"LastName cannot be blank": "Фамилия не может быть пустой",
|
"LastName cannot be blank": "Фамилия не может быть пустой",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Множественные учетные записи с тем же UID. Пожалуйста, проверьте свой сервер LDAP",
|
"Multiple accounts with same uid, please check your ldap server": "Множественные учетные записи с тем же UID. Пожалуйста, проверьте свой сервер LDAP",
|
||||||
"Organization does not exist": "Организация не существует",
|
"Organization does not exist": "Организация не существует",
|
||||||
"Password must have at least 6 characters": "Пароль должен содержать не менее 6 символов",
|
|
||||||
"Phone already exists": "Телефон уже существует",
|
"Phone already exists": "Телефон уже существует",
|
||||||
"Phone cannot be empty": "Телефон не может быть пустым",
|
"Phone cannot be empty": "Телефон не может быть пустым",
|
||||||
"Phone number is invalid": "Номер телефона является недействительным",
|
"Phone number is invalid": "Номер телефона является недействительным",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Сессия устарела, пожалуйста, войдите снова",
|
"Session outdated, please login again": "Сессия устарела, пожалуйста, войдите снова",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "Пользователь %s не существует на LDAP сервере",
|
||||||
"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.": "Имя пользователя может состоять только из буквенно-цифровых символов, нижних подчеркиваний или дефисов, не может содержать последовательные дефисы или подчеркивания, а также не может начинаться или заканчиваться на дефис или подчеркивание.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"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": "Имя пользователя не может содержать пробелы",
|
||||||
@ -53,7 +65,7 @@
|
|||||||
"Username must have at least 2 characters": "Имя пользователя должно содержать не менее 2 символов",
|
"Username must have at least 2 characters": "Имя пользователя должно содержать не менее 2 символов",
|
||||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "Вы ввели неправильный пароль или код слишком много раз, пожалуйста, подождите %d минут и попробуйте снова",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "Вы ввели неправильный пароль или код слишком много раз, пожалуйста, подождите %d минут и попробуйте снова",
|
||||||
"Your region is not allow to signup by phone": "Ваш регион не разрешает регистрацию по телефону",
|
"Your region is not allow to signup by phone": "Ваш регион не разрешает регистрацию по телефону",
|
||||||
"password or code is incorrect": "password or code is incorrect",
|
"password or code is incorrect": "неправильный пароль или код",
|
||||||
"password or code is incorrect, you have %d remaining chances": "Неправильный пароль или код, у вас осталось %d попыток",
|
"password or code is incorrect, you have %d remaining chances": "Неправильный пароль или код, у вас осталось %d попыток",
|
||||||
"unsupported password type: %s": "неподдерживаемый тип пароля: %s"
|
"unsupported password type: %s": "неподдерживаемый тип пароля: %s"
|
||||||
},
|
},
|
||||||
@ -61,8 +73,8 @@
|
|||||||
"Missing parameter": "Отсутствующий параметр",
|
"Missing parameter": "Отсутствующий параметр",
|
||||||
"Please login first": "Пожалуйста, сначала войдите в систему",
|
"Please login first": "Пожалуйста, сначала войдите в систему",
|
||||||
"The user: %s doesn't exist": "Пользователь %s не существует",
|
"The user: %s doesn't exist": "Пользователь %s не существует",
|
||||||
"don't support captchaProvider: ": "не поддерживайте captchaProvider:",
|
"don't support captchaProvider: ": "неподдерживаемый captchaProvider: ",
|
||||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
"this operation is not allowed in demo mode": "эта операция не разрешена в демо-режиме"
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "LDAP-сервер существует"
|
"Ldap server exist": "LDAP-сервер существует"
|
||||||
@ -101,7 +113,7 @@
|
|||||||
},
|
},
|
||||||
"storage": {
|
"storage": {
|
||||||
"The objectKey: %s is not allowed": "Объект «objectKey: %s» не разрешен",
|
"The objectKey: %s is not allowed": "Объект «objectKey: %s» не разрешен",
|
||||||
"The provider type: %s is not supported": "Тип поставщика: %s не поддерживается"
|
"The provider type: %s is not supported": "Тип провайдера: %s не поддерживается"
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"Empty clientId or clientSecret": "Пустой идентификатор клиента или секрет клиента",
|
"Empty clientId or clientSecret": "Пустой идентификатор клиента или секрет клиента",
|
||||||
@ -120,7 +132,7 @@
|
|||||||
},
|
},
|
||||||
"util": {
|
"util": {
|
||||||
"No application is found for userId: %s": "Не найдено заявки для пользователя с идентификатором: %s",
|
"No application is found for userId: %s": "Не найдено заявки для пользователя с идентификатором: %s",
|
||||||
"No provider for category: %s is found for application: %s": "Нет поставщика для категории: %s для приложения: %s",
|
"No provider for category: %s is found for application: %s": "Нет провайдера для категории: %s для приложения: %s",
|
||||||
"The provider: %s is not found": "Поставщик: %s не найден"
|
"The provider: %s is not found": "Поставщик: %s не найден"
|
||||||
},
|
},
|
||||||
"verification": {
|
"verification": {
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -15,23 +15,19 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
},
|
},
|
||||||
"chat": {
|
|
||||||
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
|
|
||||||
"The chat: %s is not found": "The chat: %s is not found",
|
|
||||||
"The message is invalid": "The message is invalid",
|
|
||||||
"The message: %s is not found": "The message: %s is not found",
|
|
||||||
"The provider: %s is invalid": "The provider: %s is invalid",
|
|
||||||
"The provider: %s is not found": "The provider: %s is not found"
|
|
||||||
},
|
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
@ -41,27 +37,35 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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": "Telefon numarası zaten mevcut",
|
||||||
"Phone already exists": "Phone already exists",
|
"Phone cannot be empty": "Telefon numarası boş olamaz",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone number is invalid": "Telefon numarası geçersiz",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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",
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username already exists": "Kullanıcı adı zaten var",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot be an email address": "Kullanıcı adı bir e-mail adresi olamaz",
|
||||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
"Username cannot contain white spaces": "Kullanıcı adı boşluk karakteri içeremez",
|
||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"Username cannot start with a digit": "Kullanıcı adı rakamla başlayamaz",
|
||||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
"Username is too long (maximum is 39 characters).": "Kullanıcı adı çok uzun (en fazla 39 karakter olmalı).",
|
||||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
"Username must have at least 2 characters": "Kullanıcı adı en az iki karakterden oluşmalı",
|
||||||
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "Çok fazla hatalı şifre denemesi yaptınız. %d dakika kadar bekleyip yeniden giriş yapmayı deneyebilirsiniz.",
|
||||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||||
"password or code is incorrect": "password or code is incorrect",
|
"password or code is incorrect": "şifre veya kod hatalı",
|
||||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||||
"unsupported password type: %s": "unsupported password type: %s"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
@ -120,8 +124,8 @@
|
|||||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"Display name cannot be empty": "Display name cannot be empty",
|
"Display name cannot be empty": "Görünen ad boş olamaz",
|
||||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
"New password cannot contain blank space.": "Yeni şifreniz boşluk karakteri içeremez."
|
||||||
},
|
},
|
||||||
"user_upload": {
|
"user_upload": {
|
||||||
"Failed to import users": "Failed to import users"
|
"Failed to import users": "Failed to import users"
|
||||||
@ -134,7 +138,7 @@
|
|||||||
"verification": {
|
"verification": {
|
||||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
"Phone number is invalid in your region %s": "Telefon numaranızın bulunduğu bölgeye hizmet veremiyoruz",
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"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.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Empty username.": "Empty username.",
|
"Empty username.": "Empty username.",
|
||||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||||
"LastName cannot be blank": "LastName cannot be blank",
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
"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",
|
"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 already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.",
|
"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.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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": "Tài khoản cho nhà cung cấp: %s và tên người dùng: %s (%s) không tồn tại và không được phép đăng ký như một tài khoản mới, vui lòng liên hệ với bộ phận hỗ trợ công nghệ thông tin của bạn",
|
"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": "Tài khoản cho nhà cung cấp: %s và tên người dùng: %s (%s) không tồn tại và không được phép đăng ký như một tài khoản mới, vui lòng liên hệ với bộ phận hỗ trợ công nghệ thông tin của bạn",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Tài khoản cho nhà cung cấp: %s và tên người dùng: %s (%s) đã được liên kết với tài khoản khác: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Tài khoản cho nhà cung cấp: %s và tên người dùng: %s (%s) đã được liên kết với tài khoản khác: %s (%s)",
|
||||||
"The application: %s does not exist": "Ứng dụng: %s không tồn tại",
|
"The application: %s does not exist": "Ứng dụng: %s không tồn tại",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
||||||
|
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
||||||
"The login method: login with password is not enabled for the application": "Phương thức đăng nhập: đăng nhập bằng mật khẩu không được kích hoạt cho ứng dụng",
|
"The login method: login with password is not enabled for the application": "Phương thức đăng nhập: đăng nhập bằng mật khẩu không được kích hoạt cho ứng dụng",
|
||||||
"The provider: %s is not enabled for the application": "Nhà cung cấp: %s không được kích hoạt cho ứng dụng",
|
"The provider: %s is not enabled for the application": "Nhà cung cấp: %s không được kích hoạt cho ứng dụng",
|
||||||
"Unauthorized operation": "Hoạt động không được ủy quyền",
|
"Unauthorized operation": "Hoạt động không được ủy quyền",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Loại xác thực không xác định (không phải mật khẩu hoặc nhà cung cấp), biểu mẫu = %s",
|
"Unknown authentication type (not password or provider), form = %s": "Loại xác thực không xác định (không phải mật khẩu hoặc nhà cung cấp), biểu mẫu = %s",
|
||||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Dịch sang tiếng Việt: Dịch vụ %s và %s không khớp"
|
"Service %s and %s do not match": "Dịch sang tiếng Việt: Dịch vụ %s và %s không khớp"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "Địa chỉ email không hợp lệ",
|
"Email is invalid": "Địa chỉ email không hợp lệ",
|
||||||
"Empty username.": "Tên đăng nhập trống.",
|
"Empty username.": "Tên đăng nhập trống.",
|
||||||
"FirstName cannot be blank": "Tên không được để trống",
|
"FirstName cannot be blank": "Tên không được để trống",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "Invitation code exhausted",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "Invitation code suspended",
|
||||||
"LDAP user name or password incorrect": "Tên người dùng hoặc mật khẩu Ldap không chính xác",
|
"LDAP user name or password incorrect": "Tên người dùng hoặc mật khẩu Ldap không chính xác",
|
||||||
"LastName cannot be blank": "Họ không thể để trống",
|
"LastName cannot be blank": "Họ không thể để trống",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "Nhiều tài khoản với cùng một uid, vui lòng kiểm tra máy chủ ldap của bạn",
|
"Multiple accounts with same uid, please check your ldap server": "Nhiều tài khoản với cùng một uid, vui lòng kiểm tra máy chủ ldap của bạn",
|
||||||
"Organization does not exist": "Tổ chức không tồn tại",
|
"Organization does not exist": "Tổ chức không tồn tại",
|
||||||
"Password must have at least 6 characters": "Mật khẩu phải ít nhất 6 ký tự",
|
|
||||||
"Phone already exists": "Điện thoại đã tồn tại",
|
"Phone already exists": "Điện thoại đã tồn tại",
|
||||||
"Phone cannot be empty": "Điện thoại không thể để trống",
|
"Phone cannot be empty": "Điện thoại không thể để trống",
|
||||||
"Phone number is invalid": "Số điện thoại không hợp lệ",
|
"Phone number is invalid": "Số điện thoại không hợp lệ",
|
||||||
|
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
||||||
|
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
||||||
"Session outdated, please login again": "Phiên làm việc hết hạn, vui lòng đăng nhập lại",
|
"Session outdated, please login again": "Phiên làm việc hết hạn, vui lòng đăng nhập lại",
|
||||||
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "Người dùng bị cấm đăng nhập, vui lòng liên hệ với quản trị viên",
|
"The user is forbidden to sign in, please contact the administrator": "Người dùng bị cấm đăng nhập, vui lòng liên hệ với quản trị viên",
|
||||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||||
"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.": "Tên người dùng chỉ có thể chứa các ký tự chữ và số, gạch dưới hoặc gạch ngang, không được có hai ký tự gạch dưới hoặc gạch ngang liền kề và không được bắt đầu hoặc kết thúc bằng dấu gạch dưới hoặc gạch ngang.",
|
"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.": "Tên người dùng chỉ có thể chứa các ký tự chữ và số, gạch dưới hoặc gạch ngang, không được có hai ký tự gạch dưới hoặc gạch ngang liền kề và không được bắt đầu hoặc kết thúc bằng dấu gạch dưới hoặc gạch ngang.",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
||||||
"Username already exists": "Tên đăng nhập đã tồn tại",
|
"Username already exists": "Tên đăng nhập đã tồn tại",
|
||||||
"Username cannot be an email address": "Tên người dùng không thể là địa chỉ email",
|
"Username cannot be an email address": "Tên người dùng không thể là địa chỉ email",
|
||||||
"Username cannot contain white spaces": "Tên người dùng không thể chứa khoảng trắng",
|
"Username cannot contain white spaces": "Tên người dùng không thể chứa khoảng trắng",
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
"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) 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 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 application: %s does not exist": "应用%s不存在",
|
||||||
|
"The login method: login with LDAP is not enabled for the application": "该应用禁止采用LDAP登录方式",
|
||||||
|
"The login method: login with SMS is not enabled for the application": "该应用禁止采用短信登录方式",
|
||||||
|
"The login method: login with email is not enabled for the application": "该应用禁止采用邮箱登录方式",
|
||||||
"The login method: login with password is not enabled for the application": "该应用禁止采用密码登录方式",
|
"The login method: login with password is not enabled for the application": "该应用禁止采用密码登录方式",
|
||||||
"The provider: %s is not enabled for the application": "该应用的提供商: %s未被启用",
|
"The provider: %s is not enabled for the application": "该应用的提供商: %s未被启用",
|
||||||
"Unauthorized operation": "未授权的操作",
|
"Unauthorized operation": "未授权的操作",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "未知的认证类型(非密码或第三方提供商):%s",
|
"Unknown authentication type (not password or provider), form = %s": "未知的认证类型(非密码或第三方提供商):%s",
|
||||||
"User's tag: %s is not listed in the application's tags": "用户的标签: %s不在该应用的标签列表中"
|
"User's tag: %s is not listed in the application's tags": "用户的标签: %s不在该应用的标签列表中",
|
||||||
|
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "服务%s与%s不匹配"
|
"Service %s and %s do not match": "服务%s与%s不匹配"
|
||||||
@ -33,18 +37,26 @@
|
|||||||
"Email is invalid": "无效邮箱",
|
"Email is invalid": "无效邮箱",
|
||||||
"Empty username.": "用户名不可为空",
|
"Empty username.": "用户名不可为空",
|
||||||
"FirstName cannot be blank": "名不可以为空",
|
"FirstName cannot be blank": "名不可以为空",
|
||||||
|
"Invitation code cannot be blank": "Invitation code cannot be blank",
|
||||||
|
"Invitation code exhausted": "邀请码使用次数已耗尽",
|
||||||
|
"Invitation code is invalid": "Invitation code is invalid",
|
||||||
|
"Invitation code suspended": "邀请码已被禁止使用",
|
||||||
"LDAP user name or password incorrect": "LDAP密码错误",
|
"LDAP user name or password incorrect": "LDAP密码错误",
|
||||||
"LastName cannot be blank": "姓不可以为空",
|
"LastName cannot be blank": "姓不可以为空",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "多个帐户具有相同的uid,请检查您的 LDAP 服务器",
|
"Multiple accounts with same uid, please check your ldap server": "多个帐户具有相同的uid,请检查您的 LDAP 服务器",
|
||||||
"Organization does not exist": "组织不存在",
|
"Organization does not exist": "组织不存在",
|
||||||
"Password must have at least 6 characters": "新密码至少为6位",
|
|
||||||
"Phone already exists": "该手机号已存在",
|
"Phone already exists": "该手机号已存在",
|
||||||
"Phone cannot be empty": "手机号不可为空",
|
"Phone cannot be empty": "手机号不可为空",
|
||||||
"Phone number is invalid": "无效手机号",
|
"Phone number is invalid": "无效手机号",
|
||||||
|
"Please register using the email corresponding to the invitation code": "请使用邀请码关联的邮箱注册",
|
||||||
|
"Please register using the phone corresponding to the invitation code": "请使用邀请码关联的手机号注册",
|
||||||
|
"Please register using the username corresponding to the invitation code": "请使用邀请码关联的用户名注册",
|
||||||
"Session outdated, please login again": "会话已过期,请重新登录",
|
"Session outdated, please login again": "会话已过期,请重新登录",
|
||||||
|
"The invitation code has already been used": "邀请码已被使用",
|
||||||
"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 in LDAP server": "The user: %s doesn't exist in LDAP server",
|
"The user: %s doesn't exist in LDAP server": "用户: %s 在LDAP服务器中未找到",
|
||||||
"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.": "用户名只能包含字母数字字符、下划线或连字符,不能有连续的连字符或下划线,也不能以连字符或下划线开头或结尾",
|
||||||
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "值\\\"%s\\\"在注册字段\\\"%s\\\"中与应用\\\"%s\\\"的注册项正则表达式不匹配",
|
||||||
"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": "用户名禁止包含空格",
|
||||||
@ -62,7 +74,7 @@
|
|||||||
"Please login first": "请先登录",
|
"Please login first": "请先登录",
|
||||||
"The user: %s doesn't exist": "用户: %s不存在",
|
"The user: %s doesn't exist": "用户: %s不存在",
|
||||||
"don't support captchaProvider: ": "不支持验证码提供商: ",
|
"don't support captchaProvider: ": "不支持验证码提供商: ",
|
||||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
"this operation is not allowed in demo mode": "demo模式下不允许该操作"
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "LDAP服务器已存在"
|
"Ldap server exist": "LDAP服务器已存在"
|
||||||
|
26
idp/adfs.go
26
idp/adfs.go
@ -19,7 +19,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
@ -84,11 +83,14 @@ func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
payload.Set("code", code)
|
payload.Set("code", code)
|
||||||
payload.Set("grant_type", "authorization_code")
|
payload.Set("grant_type", "authorization_code")
|
||||||
payload.Set("client_id", idp.Config.ClientID)
|
payload.Set("client_id", idp.Config.ClientID)
|
||||||
|
payload.Set("client_secret", idp.Config.ClientSecret)
|
||||||
payload.Set("redirect_uri", idp.Config.RedirectURL)
|
payload.Set("redirect_uri", idp.Config.RedirectURL)
|
||||||
|
|
||||||
resp, err := idp.Client.PostForm(idp.Config.Endpoint.TokenURL, payload)
|
resp, err := idp.Client.PostForm(idp.Config.Endpoint.TokenURL, payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := io.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -97,10 +99,10 @@ func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
pToken := &AdfsToken{}
|
pToken := &AdfsToken{}
|
||||||
err = json.Unmarshal(data, pToken)
|
err = json.Unmarshal(data, pToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("fail to unmarshal token response: %s", err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
if pToken.ErrMsg != "" {
|
if pToken.ErrMsg != "" {
|
||||||
return nil, fmt.Errorf("pToken.Errmsg = %s", pToken.ErrMsg)
|
return nil, fmt.Errorf(pToken.ErrMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
token := &oauth2.Token{
|
token := &oauth2.Token{
|
||||||
@ -118,11 +120,25 @@ func (idp *AdfsIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
keyset, err := jwk.ParseKey(body)
|
var respKeys struct {
|
||||||
|
Keys []interface{} `json:"keys"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(body, &respKeys); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
respKey, err := json.Marshal(&(respKeys.Keys[0]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keyset, err := jwk.ParseKey(respKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
tokenSrc := []byte(token.AccessToken)
|
tokenSrc := []byte(token.AccessToken)
|
||||||
publicKey, _ := keyset.PublicKey()
|
publicKey, _ := keyset.PublicKey()
|
||||||
idToken, _ := jwt.Parse(tokenSrc, jwt.WithVerify(jwa.RS256, publicKey))
|
idToken, _ := jwt.Parse(tokenSrc, jwt.WithVerify(jwa.RS256, publicKey))
|
||||||
|
126
idp/azuread_b2c.go
Normal file
126
idp/azuread_b2c.go
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
// Copyright 2023 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 idp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AzureADB2CProvider struct {
|
||||||
|
Client *http.Client
|
||||||
|
Config *oauth2.Config
|
||||||
|
Tenant string
|
||||||
|
UserFlow string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAzureAdB2cProvider(clientId, clientSecret, redirectUrl, tenant string, userFlow string) *AzureADB2CProvider {
|
||||||
|
return &AzureADB2CProvider{
|
||||||
|
Config: &oauth2.Config{
|
||||||
|
ClientID: clientId,
|
||||||
|
ClientSecret: clientSecret,
|
||||||
|
RedirectURL: redirectUrl,
|
||||||
|
Endpoint: oauth2.Endpoint{
|
||||||
|
AuthURL: fmt.Sprintf("https://%s.b2clogin.com/%s.onmicrosoft.com/%s/oauth2/v2.0/authorize", tenant, tenant, userFlow),
|
||||||
|
TokenURL: fmt.Sprintf("https://%s.b2clogin.com/%s.onmicrosoft.com/%s/oauth2/v2.0/token", tenant, tenant, userFlow),
|
||||||
|
},
|
||||||
|
Scopes: []string{"openid", "email"},
|
||||||
|
},
|
||||||
|
Tenant: tenant,
|
||||||
|
UserFlow: userFlow,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AzureADB2CProvider) SetHttpClient(client *http.Client) {
|
||||||
|
p.Client = client
|
||||||
|
}
|
||||||
|
|
||||||
|
type AzureadB2cToken struct {
|
||||||
|
IdToken string `json:"id_token"`
|
||||||
|
TokenType string `json:"token_type"`
|
||||||
|
NotBefore int `json:"not_before"`
|
||||||
|
IdTokenExpiresIn int `json:"id_token_expires_in"`
|
||||||
|
ProfileInfo string `json:"profile_info"`
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AzureADB2CProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||||
|
payload := url.Values{}
|
||||||
|
payload.Set("code", code)
|
||||||
|
payload.Set("grant_type", "authorization_code")
|
||||||
|
payload.Set("client_id", p.Config.ClientID)
|
||||||
|
payload.Set("client_secret", p.Config.ClientSecret)
|
||||||
|
payload.Set("redirect_uri", p.Config.RedirectURL)
|
||||||
|
|
||||||
|
resp, err := p.Client.PostForm(p.Config.Endpoint.TokenURL, payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pToken := &AzureadB2cToken{}
|
||||||
|
err = json.Unmarshal(data, pToken)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
token := &oauth2.Token{
|
||||||
|
AccessToken: pToken.IdToken,
|
||||||
|
Expiry: time.Unix(time.Now().Unix()+int64(pToken.IdTokenExpiresIn), 0),
|
||||||
|
}
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *AzureADB2CProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||||
|
userInfoEndpoint := fmt.Sprintf("https://%s.b2clogin.com/%s.onmicrosoft.com/%s/openid/v2.0/userinfo", p.Tenant, p.Tenant, p.UserFlow)
|
||||||
|
req, err := http.NewRequest("GET", userInfoEndpoint, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Add("Authorization", "Bearer "+token.AccessToken)
|
||||||
|
|
||||||
|
resp, err := p.Client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("error fetching user info: status code %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyBytes, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var userInfo UserInfo
|
||||||
|
err = json.Unmarshal(bodyBytes, &userInfo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &userInfo, nil
|
||||||
|
}
|
24
idp/goth.go
24
idp/goth.go
@ -89,7 +89,7 @@ type GothIdProvider struct {
|
|||||||
Session goth.Session
|
Session goth.Session
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGothIdProvider(providerType string, clientId string, clientSecret string, redirectUrl string, hostUrl string) *GothIdProvider {
|
func NewGothIdProvider(providerType string, clientId string, clientSecret string, clientId2 string, clientSecret2 string, redirectUrl string, hostUrl string) (*GothIdProvider, error) {
|
||||||
var idp GothIdProvider
|
var idp GothIdProvider
|
||||||
switch providerType {
|
switch providerType {
|
||||||
case "Amazon":
|
case "Amazon":
|
||||||
@ -101,8 +101,24 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
|
|||||||
if !strings.Contains(redirectUrl, "/api/callback") {
|
if !strings.Contains(redirectUrl, "/api/callback") {
|
||||||
redirectUrl = strings.Replace(redirectUrl, "/callback", "/api/callback", 1)
|
redirectUrl = strings.Replace(redirectUrl, "/callback", "/api/callback", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iat := time.Now().Unix()
|
||||||
|
exp := iat + 60*60
|
||||||
|
sp := apple.SecretParams{
|
||||||
|
ClientId: clientId,
|
||||||
|
TeamId: clientSecret,
|
||||||
|
KeyId: clientId2,
|
||||||
|
PKCS8PrivateKey: clientSecret2,
|
||||||
|
Iat: int(iat),
|
||||||
|
Exp: int(exp),
|
||||||
|
}
|
||||||
|
secret, err := apple.MakeSecret(sp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
idp = GothIdProvider{
|
idp = GothIdProvider{
|
||||||
Provider: apple.New(clientId, clientSecret, redirectUrl, nil),
|
Provider: apple.New(clientId, *secret, redirectUrl, nil),
|
||||||
Session: &apple.Session{},
|
Session: &apple.Session{},
|
||||||
}
|
}
|
||||||
case "AzureAD":
|
case "AzureAD":
|
||||||
@ -386,10 +402,10 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
|
|||||||
Session: &zoom.Session{},
|
Session: &zoom.Session{},
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil, fmt.Errorf("OAuth Goth provider type: %s is not supported", providerType)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &idp
|
return &idp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHttpClient
|
// SetHttpClient
|
||||||
|
30
idp/lark.go
30
idp/lark.go
@ -16,6 +16,7 @@ package idp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
@ -82,13 +83,22 @@ func (idp *LarkIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
AppID string `json:"app_id"`
|
AppID string `json:"app_id"`
|
||||||
AppSecret string `json:"app_secret"`
|
AppSecret string `json:"app_secret"`
|
||||||
}{idp.Config.ClientID, idp.Config.ClientSecret}
|
}{idp.Config.ClientID, idp.Config.ClientSecret}
|
||||||
|
|
||||||
data, err := idp.postWithBody(params, idp.Config.Endpoint.TokenURL)
|
data, err := idp.postWithBody(params, idp.Config.Endpoint.TokenURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
appToken := &LarkAccessToken{}
|
appToken := &LarkAccessToken{}
|
||||||
if err = json.Unmarshal(data, appToken); err != nil || appToken.Code != 0 {
|
err = json.Unmarshal(data, appToken)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if appToken.Code != 0 {
|
||||||
|
return nil, fmt.Errorf("GetToken() error, appToken.Code: %d, appToken.Msg: %s", appToken.Code, appToken.Msg)
|
||||||
|
}
|
||||||
|
|
||||||
t := &oauth2.Token{
|
t := &oauth2.Token{
|
||||||
AccessToken: appToken.TenantAccessToken,
|
AccessToken: appToken.TenantAccessToken,
|
||||||
TokenType: "Bearer",
|
TokenType: "Bearer",
|
||||||
@ -98,7 +108,6 @@ func (idp *LarkIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
raw := make(map[string]interface{})
|
raw := make(map[string]interface{})
|
||||||
raw["code"] = code
|
raw["code"] = code
|
||||||
t = t.WithExtra(raw)
|
t = t.WithExtra(raw)
|
||||||
|
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,11 +168,17 @@ func (idp *LarkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
GrantType string `json:"grant_type"`
|
GrantType string `json:"grant_type"`
|
||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
}{"authorization_code", token.Extra("code").(string)}
|
}{"authorization_code", token.Extra("code").(string)}
|
||||||
data, _ := json.Marshal(body)
|
|
||||||
|
data, err := json.Marshal(body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", "https://open.feishu.cn/open-apis/authen/v1/access_token", strings.NewReader(string(data)))
|
req, err := http.NewRequest("POST", "https://open.feishu.cn/open-apis/authen/v1/access_token", strings.NewReader(string(data)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
req.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
||||||
req.Header.Set("Authorization", "Bearer "+token.AccessToken)
|
req.Header.Set("Authorization", "Bearer "+token.AccessToken)
|
||||||
|
|
||||||
@ -171,6 +186,7 @@ func (idp *LarkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
data, err = io.ReadAll(resp.Body)
|
data, err = io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -178,7 +194,8 @@ func (idp *LarkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var larkUserInfo LarkUserInfo
|
var larkUserInfo LarkUserInfo
|
||||||
if err = json.Unmarshal(data, &larkUserInfo); err != nil {
|
err = json.Unmarshal(data, &larkUserInfo)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +206,6 @@ func (idp *LarkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
Email: larkUserInfo.Data.Email,
|
Email: larkUserInfo.Data.Email,
|
||||||
AvatarUrl: larkUserInfo.Data.AvatarUrl,
|
AvatarUrl: larkUserInfo.Data.AvatarUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &userInfo, nil
|
return &userInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,21 +214,23 @@ func (idp *LarkIdProvider) postWithBody(body interface{}, url string) ([]byte, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
r := strings.NewReader(string(bs))
|
r := strings.NewReader(string(bs))
|
||||||
resp, err := idp.Client.Post(url, "application/json;charset=UTF-8", r)
|
resp, err := idp.Client.Post(url, "application/json;charset=UTF-8", r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := io.ReadAll(resp.Body)
|
data, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func(Body io.ReadCloser) {
|
defer func(Body io.ReadCloser) {
|
||||||
err := Body.Close()
|
err := Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}(resp.Body)
|
}(resp.Body)
|
||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
package idp
|
package idp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -30,16 +31,19 @@ type UserInfo struct {
|
|||||||
Phone string
|
Phone string
|
||||||
CountryCode string
|
CountryCode string
|
||||||
AvatarUrl string
|
AvatarUrl string
|
||||||
|
Extra map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProviderInfo struct {
|
type ProviderInfo struct {
|
||||||
Type string
|
Type string
|
||||||
SubType string
|
SubType string
|
||||||
ClientId string
|
ClientId string
|
||||||
ClientSecret string
|
ClientSecret string
|
||||||
AppId string
|
ClientId2 string
|
||||||
HostUrl string
|
ClientSecret2 string
|
||||||
RedirectUrl string
|
AppId string
|
||||||
|
HostUrl string
|
||||||
|
RedirectUrl string
|
||||||
|
|
||||||
TokenURL string
|
TokenURL string
|
||||||
AuthURL string
|
AuthURL string
|
||||||
@ -53,71 +57,75 @@ type IdProvider interface {
|
|||||||
GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetIdProvider(idpInfo *ProviderInfo, redirectUrl string) IdProvider {
|
func GetIdProvider(idpInfo *ProviderInfo, redirectUrl string) (IdProvider, error) {
|
||||||
switch idpInfo.Type {
|
switch idpInfo.Type {
|
||||||
case "GitHub":
|
case "GitHub":
|
||||||
return NewGithubIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewGithubIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "Google":
|
case "Google":
|
||||||
return NewGoogleIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewGoogleIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "QQ":
|
case "QQ":
|
||||||
return NewQqIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewQqIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "WeChat":
|
case "WeChat":
|
||||||
return NewWeChatIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewWeChatIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "Facebook":
|
case "Facebook":
|
||||||
return NewFacebookIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewFacebookIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "DingTalk":
|
case "DingTalk":
|
||||||
return NewDingTalkIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewDingTalkIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "Weibo":
|
case "Weibo":
|
||||||
return NewWeiBoIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewWeiBoIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "Gitee":
|
case "Gitee":
|
||||||
return NewGiteeIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewGiteeIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "LinkedIn":
|
case "LinkedIn":
|
||||||
return NewLinkedInIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewLinkedInIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "WeCom":
|
case "WeCom":
|
||||||
if idpInfo.SubType == "Internal" {
|
if idpInfo.SubType == "Internal" {
|
||||||
return NewWeComInternalIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewWeComInternalIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
} else if idpInfo.SubType == "Third-party" {
|
} else if idpInfo.SubType == "Third-party" {
|
||||||
return NewWeComIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewWeComIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil, fmt.Errorf("WeCom provider subType: %s is not supported", idpInfo.SubType)
|
||||||
}
|
}
|
||||||
case "Lark":
|
case "Lark":
|
||||||
return NewLarkIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewLarkIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "GitLab":
|
case "GitLab":
|
||||||
return NewGitlabIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewGitlabIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "Adfs":
|
case "ADFS":
|
||||||
return NewAdfsIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl)
|
return NewAdfsIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl), nil
|
||||||
|
case "AzureADB2C":
|
||||||
|
return NewAzureAdB2cProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl, idpInfo.AppId), nil
|
||||||
case "Baidu":
|
case "Baidu":
|
||||||
return NewBaiduIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewBaiduIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "Alipay":
|
case "Alipay":
|
||||||
return NewAlipayIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewAlipayIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "Custom":
|
case "Custom":
|
||||||
return NewCustomIdProvider(idpInfo, redirectUrl)
|
return NewCustomIdProvider(idpInfo, redirectUrl), nil
|
||||||
case "Infoflow":
|
case "Infoflow":
|
||||||
if idpInfo.SubType == "Internal" {
|
if idpInfo.SubType == "Internal" {
|
||||||
return NewInfoflowInternalIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, idpInfo.AppId, redirectUrl)
|
return NewInfoflowInternalIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, idpInfo.AppId, redirectUrl), nil
|
||||||
} else if idpInfo.SubType == "Third-party" {
|
} else if idpInfo.SubType == "Third-party" {
|
||||||
return NewInfoflowIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, idpInfo.AppId, redirectUrl)
|
return NewInfoflowIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, idpInfo.AppId, redirectUrl), nil
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil, fmt.Errorf("Infoflow provider subType: %s is not supported", idpInfo.SubType)
|
||||||
}
|
}
|
||||||
case "Casdoor":
|
case "Casdoor":
|
||||||
return NewCasdoorIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl)
|
return NewCasdoorIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl), nil
|
||||||
case "Okta":
|
case "Okta":
|
||||||
return NewOktaIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl)
|
return NewOktaIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl), nil
|
||||||
case "Douyin":
|
case "Douyin":
|
||||||
return NewDouyinIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewDouyinIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "Bilibili":
|
case "Bilibili":
|
||||||
return NewBilibiliIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
return NewBilibiliIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
case "MetaMask":
|
case "MetaMask":
|
||||||
return NewMetaMaskIdProvider()
|
return NewMetaMaskIdProvider(), nil
|
||||||
case "Web3Onboard":
|
case "Web3Onboard":
|
||||||
return NewWeb3OnboardIdProvider()
|
return NewWeb3OnboardIdProvider(), nil
|
||||||
|
case "Twitter":
|
||||||
|
return NewTwitterIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||||
default:
|
default:
|
||||||
if isGothSupport(idpInfo.Type) {
|
if isGothSupport(idpInfo.Type) {
|
||||||
return NewGothIdProvider(idpInfo.Type, idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl)
|
return NewGothIdProvider(idpInfo.Type, idpInfo.ClientId, idpInfo.ClientSecret, idpInfo.ClientId2, idpInfo.ClientSecret2, redirectUrl, idpInfo.HostUrl)
|
||||||
}
|
}
|
||||||
return nil
|
return nil, fmt.Errorf("OAuth provider type: %s is not supported", idpInfo.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +173,6 @@ var gothList = []string{
|
|||||||
"TikTok",
|
"TikTok",
|
||||||
"Tumblr",
|
"Tumblr",
|
||||||
"Twitch",
|
"Twitch",
|
||||||
"Twitter",
|
|
||||||
"Typetalk",
|
"Typetalk",
|
||||||
"Uber",
|
"Uber",
|
||||||
"VK",
|
"VK",
|
||||||
|
190
idp/twitter.go
Normal file
190
idp/twitter.go
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
// Copyright 2021 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 idp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TwitterIdProvider struct {
|
||||||
|
Client *http.Client
|
||||||
|
Config *oauth2.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTwitterIdProvider(clientId string, clientSecret string, redirectUrl string) *TwitterIdProvider {
|
||||||
|
idp := &TwitterIdProvider{}
|
||||||
|
|
||||||
|
config := idp.getConfig(clientId, clientSecret, redirectUrl)
|
||||||
|
idp.Config = config
|
||||||
|
|
||||||
|
return idp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (idp *TwitterIdProvider) SetHttpClient(client *http.Client) {
|
||||||
|
idp.Client = client
|
||||||
|
}
|
||||||
|
|
||||||
|
// getConfig return a point of Config, which describes a typical 3-legged OAuth2 flow
|
||||||
|
func (idp *TwitterIdProvider) getConfig(clientId string, clientSecret string, redirectUrl string) *oauth2.Config {
|
||||||
|
endpoint := oauth2.Endpoint{
|
||||||
|
TokenURL: "https://api.twitter.com/2/oauth2/token",
|
||||||
|
}
|
||||||
|
|
||||||
|
config := &oauth2.Config{
|
||||||
|
Scopes: []string{"users.read", "tweet.read"},
|
||||||
|
Endpoint: endpoint,
|
||||||
|
ClientID: clientId,
|
||||||
|
ClientSecret: clientSecret,
|
||||||
|
RedirectURL: redirectUrl,
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
type TwitterAccessToken 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
type TwitterCheckToken struct {
|
||||||
|
Data TwitterUserInfo `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TwitterCheckTokenData
|
||||||
|
// Get more detail via: https://developers.Twitter.com/docs/Twitter-login/guides/advanced/manual-flow#checktoken
|
||||||
|
type TwitterCheckTokenData struct {
|
||||||
|
UserId string `json:"user_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetToken use code get access_token (*operation of getting code ought to be done in front)
|
||||||
|
// get more detail via: https://developers.Twitter.com/docs/Twitter-login/guides/advanced/manual-flow#confirm
|
||||||
|
func (idp *TwitterIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||||
|
params := url.Values{}
|
||||||
|
// params.Add("client_id", idp.Config.ClientID)
|
||||||
|
params.Add("redirect_uri", idp.Config.RedirectURL)
|
||||||
|
params.Add("code_verifier", "casdoor-verifier")
|
||||||
|
params.Add("code", code)
|
||||||
|
params.Add("grant_type", "authorization_code")
|
||||||
|
req, err := http.NewRequest("POST", "https://api.twitter.com/2/oauth2/token", strings.NewReader(params.Encode()))
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
e := base64.StdEncoding.EncodeToString([]byte(idp.Config.ClientID + ":" + idp.Config.ClientSecret))
|
||||||
|
req.Header.Add("Authorization", "Basic "+e)
|
||||||
|
accessTokenResp, err := idp.GetUrlResp(req)
|
||||||
|
var TwitterAccessToken TwitterAccessToken
|
||||||
|
if err = json.Unmarshal([]byte(accessTokenResp), &TwitterAccessToken); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
token := oauth2.Token{
|
||||||
|
AccessToken: TwitterAccessToken.AccessToken,
|
||||||
|
TokenType: TwitterAccessToken.TokenType,
|
||||||
|
Expiry: time.Time{},
|
||||||
|
}
|
||||||
|
|
||||||
|
return &token, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//{
|
||||||
|
// "id": "123456789",
|
||||||
|
// "name": "Example Name",
|
||||||
|
// "name_format": "{first} {last}",
|
||||||
|
// "picture": {
|
||||||
|
// "data": {
|
||||||
|
// "height": 50,
|
||||||
|
// "is_silhouette": false,
|
||||||
|
// "url": "https://example.com",
|
||||||
|
// "width": 50
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "email": "test@example.com"
|
||||||
|
//}
|
||||||
|
|
||||||
|
type TwitterUserInfo struct {
|
||||||
|
Id string `json:"id"` // The app user's App-Scoped User ID. This ID is unique to the app and cannot be used by other apps.
|
||||||
|
Name string `json:"name"` // The person's full name.
|
||||||
|
UserName string `json:"username"` // The person's name formatted to correctly handle Chinese, Japanese, or Korean ordering.
|
||||||
|
Picture struct { // The person's profile picture.
|
||||||
|
Data struct { // This struct is different as https://developers.Twitter.com/docs/graph-api/reference/user/picture/
|
||||||
|
Height int `json:"height"`
|
||||||
|
IsSilhouette bool `json:"is_silhouette"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
Width int `json:"width"`
|
||||||
|
} `json:"data"`
|
||||||
|
} `json:"picture"`
|
||||||
|
Email string `json:"email"` // The User's primary email address listed on their profile. This field will not be returned if no valid email address is available.
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserInfo use TwitterAccessToken gotten before return TwitterUserInfo
|
||||||
|
// get more detail via: https://developers.Twitter.com/docs/graph-api/reference/user
|
||||||
|
func (idp *TwitterIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||||
|
var TwitterUserInfo TwitterUserInfo
|
||||||
|
// accessToken := token.AccessToken
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", "https://api.twitter.com/2/users/me", nil)
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
req.Header.Add("Authorization", "Bearer "+token.AccessToken)
|
||||||
|
// req.URL.Query().Set("user.fields", "profile_image_url")
|
||||||
|
// userIdUrl := fmt.Sprintf("https://graph.Twitter.com/me?access_token=%s", accessToken)
|
||||||
|
userIdResp, err := idp.GetUrlResp(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
empTwitterCheckToken := &TwitterCheckToken{}
|
||||||
|
if err = json.Unmarshal([]byte(userIdResp), &empTwitterCheckToken); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
TwitterUserInfo = empTwitterCheckToken.Data
|
||||||
|
|
||||||
|
userInfo := UserInfo{
|
||||||
|
Id: TwitterUserInfo.Id,
|
||||||
|
Username: TwitterUserInfo.UserName,
|
||||||
|
DisplayName: TwitterUserInfo.Name,
|
||||||
|
Email: TwitterUserInfo.Email,
|
||||||
|
AvatarUrl: TwitterUserInfo.Picture.Data.Url,
|
||||||
|
}
|
||||||
|
return &userInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (idp *TwitterIdProvider) GetUrlResp(url *http.Request) (string, error) {
|
||||||
|
resp, err := idp.Client.Do(url)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func(Body io.ReadCloser) {
|
||||||
|
err := Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}(resp.Body)
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
_, err = buf.ReadFrom(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
@ -186,15 +186,24 @@ func (idp *WeChatIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
id = wechatUserInfo.Openid
|
id = wechatUserInfo.Openid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extra := make(map[string]string)
|
||||||
|
extra["wechat_unionid"] = wechatUserInfo.Openid
|
||||||
|
// For WeChat, different appId corresponds to different openId
|
||||||
|
extra[BuildWechatOpenIdKey(idp.Config.ClientID)] = wechatUserInfo.Openid
|
||||||
userInfo := UserInfo{
|
userInfo := UserInfo{
|
||||||
Id: id,
|
Id: id,
|
||||||
Username: wechatUserInfo.Nickname,
|
Username: wechatUserInfo.Nickname,
|
||||||
DisplayName: wechatUserInfo.Nickname,
|
DisplayName: wechatUserInfo.Nickname,
|
||||||
AvatarUrl: wechatUserInfo.Headimgurl,
|
AvatarUrl: wechatUserInfo.Headimgurl,
|
||||||
|
Extra: extra,
|
||||||
}
|
}
|
||||||
return &userInfo, nil
|
return &userInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BuildWechatOpenIdKey(appId string) string {
|
||||||
|
return fmt.Sprintf("wechat_openid_%s", appId)
|
||||||
|
}
|
||||||
|
|
||||||
func GetWechatOfficialAccountAccessToken(clientId string, clientSecret string) (string, error) {
|
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)
|
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)
|
request, err := http.NewRequest("GET", accessTokenUrl, nil)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
"tags": [],
|
"tags": [],
|
||||||
"languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "it", "ms", "tr","ar", "he", "nl", "pl", "fi", "sv", "uk", "kk", "fa"],
|
"languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "it", "ms", "tr","ar", "he", "nl", "pl", "fi", "sv", "uk", "kk", "fa"],
|
||||||
"masterPassword": "",
|
"masterPassword": "",
|
||||||
|
"defaultPassword": "",
|
||||||
"initScore": 2000,
|
"initScore": 2000,
|
||||||
"enableSoftDeletion": false,
|
"enableSoftDeletion": false,
|
||||||
"isProfilePublic": true,
|
"isProfilePublic": true,
|
||||||
@ -44,6 +45,23 @@
|
|||||||
"alertType": "None"
|
"alertType": "None"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"signinMethods": [
|
||||||
|
{
|
||||||
|
"name": "Password",
|
||||||
|
"displayName": "Password",
|
||||||
|
"rule": "All",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Verification code",
|
||||||
|
"displayName": "Verification code",
|
||||||
|
"rule": "All",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "WebAuthn",
|
||||||
|
"displayName": "WebAuthn",
|
||||||
|
"rule": "None",
|
||||||
|
},
|
||||||
|
],
|
||||||
"signupItems": [
|
"signupItems": [
|
||||||
{
|
{
|
||||||
"name": "ID",
|
"name": "ID",
|
||||||
@ -103,7 +121,9 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"redirectUris": [""],
|
"redirectUris": [""],
|
||||||
"expireInHours": 168
|
"expireInHours": 168,
|
||||||
|
"failedSigninLimit": 5,
|
||||||
|
"failedSigninFrozenTime": 15
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"users": [
|
"users": [
|
||||||
@ -176,9 +196,7 @@
|
|||||||
],
|
],
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"actions": [
|
"actions": [],
|
||||||
""
|
|
||||||
],
|
|
||||||
"displayName": "",
|
"displayName": "",
|
||||||
"effect": "",
|
"effect": "",
|
||||||
"isEnabled": true,
|
"isEnabled": true,
|
||||||
@ -186,15 +204,9 @@
|
|||||||
"name": "",
|
"name": "",
|
||||||
"owner": "",
|
"owner": "",
|
||||||
"resourceType": "",
|
"resourceType": "",
|
||||||
"resources": [
|
"resources": [],
|
||||||
""
|
"roles": [],
|
||||||
],
|
"users": []
|
||||||
"roles": [
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"users": [
|
|
||||||
""
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"payments": [
|
"payments": [
|
||||||
@ -236,9 +248,7 @@
|
|||||||
"name": "",
|
"name": "",
|
||||||
"owner": "",
|
"owner": "",
|
||||||
"price": 0,
|
"price": 0,
|
||||||
"providers": [
|
"providers": [],
|
||||||
""
|
|
||||||
],
|
|
||||||
"quantity": 0,
|
"quantity": 0,
|
||||||
"returnUrl": "",
|
"returnUrl": "",
|
||||||
"sold": 0,
|
"sold": 0,
|
||||||
@ -268,12 +278,8 @@
|
|||||||
"isEnabled": true,
|
"isEnabled": true,
|
||||||
"name": "",
|
"name": "",
|
||||||
"owner": "",
|
"owner": "",
|
||||||
"roles": [
|
"roles": [],
|
||||||
""
|
"users": []
|
||||||
],
|
|
||||||
"users": [
|
|
||||||
""
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"syncers": [
|
"syncers": [
|
||||||
@ -284,7 +290,7 @@
|
|||||||
"databaseType": "",
|
"databaseType": "",
|
||||||
"errorText": "",
|
"errorText": "",
|
||||||
"host": "",
|
"host": "",
|
||||||
"isEnabled": true,
|
"isEnabled": false,
|
||||||
"name": "",
|
"name": "",
|
||||||
"organization": "",
|
"organization": "",
|
||||||
"owner": "",
|
"owner": "",
|
||||||
@ -298,9 +304,7 @@
|
|||||||
"isHashed": true,
|
"isHashed": true,
|
||||||
"name": "",
|
"name": "",
|
||||||
"type": "",
|
"type": "",
|
||||||
"values": [
|
"values": []
|
||||||
""
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tablePrimaryKey": "",
|
"tablePrimaryKey": "",
|
||||||
@ -330,9 +334,7 @@
|
|||||||
"webhooks": [
|
"webhooks": [
|
||||||
{
|
{
|
||||||
"contentType": "",
|
"contentType": "",
|
||||||
"events": [
|
"events": [],
|
||||||
""
|
|
||||||
],
|
|
||||||
"headers": [
|
"headers": [
|
||||||
{
|
{
|
||||||
"name": "",
|
"name": "",
|
||||||
|
@ -16,6 +16,7 @@ package ldap
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/fnv"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
@ -25,6 +26,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func StartLdapServer() {
|
func StartLdapServer() {
|
||||||
|
ldapServerPort := conf.GetConfigString("ldapServerPort")
|
||||||
|
if ldapServerPort == "" || ldapServerPort == "0" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
server := ldap.NewServer()
|
server := ldap.NewServer()
|
||||||
routes := ldap.NewRouteMux()
|
routes := ldap.NewRouteMux()
|
||||||
|
|
||||||
@ -32,7 +38,7 @@ func StartLdapServer() {
|
|||||||
routes.Search(handleSearch).Label(" SEARCH****")
|
routes.Search(handleSearch).Label(" SEARCH****")
|
||||||
|
|
||||||
server.Handle(routes)
|
server.Handle(routes)
|
||||||
err := server.ListenAndServe("0.0.0.0:" + conf.GetConfigString("ldapServerPort"))
|
err := server.ListenAndServe("0.0.0.0:" + ldapServerPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("StartLdapServer() failed, err = %s", err.Error())
|
log.Printf("StartLdapServer() failed, err = %s", err.Error())
|
||||||
}
|
}
|
||||||
@ -44,20 +50,20 @@ func handleBind(w ldap.ResponseWriter, m *ldap.Message) {
|
|||||||
|
|
||||||
if r.AuthenticationChoice() == "simple" {
|
if r.AuthenticationChoice() == "simple" {
|
||||||
bindUsername, bindOrg, err := getNameAndOrgFromDN(string(r.Name()))
|
bindUsername, bindOrg, err := getNameAndOrgFromDN(string(r.Name()))
|
||||||
if err != "" {
|
if err != nil {
|
||||||
log.Printf("Bind failed ,ErrMsg=%s", err)
|
log.Printf("getNameAndOrgFromDN() error: %s", err.Error())
|
||||||
res.SetResultCode(ldap.LDAPResultInvalidDNSyntax)
|
res.SetResultCode(ldap.LDAPResultInvalidDNSyntax)
|
||||||
res.SetDiagnosticMessage("bind failed ErrMsg: " + err)
|
res.SetDiagnosticMessage(fmt.Sprintf("getNameAndOrgFromDN() error: %s", err.Error()))
|
||||||
w.Write(res)
|
w.Write(res)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bindPassword := string(r.AuthenticationSimple())
|
bindPassword := string(r.AuthenticationSimple())
|
||||||
bindUser, err := object.CheckUserPassword(bindOrg, bindUsername, bindPassword, "en")
|
bindUser, err := object.CheckUserPassword(bindOrg, bindUsername, bindPassword, "en")
|
||||||
if err != "" {
|
if err != nil {
|
||||||
log.Printf("Bind failed User=%s, Pass=%#v, ErrMsg=%s", string(r.Name()), r.Authentication(), err)
|
log.Printf("Bind failed User=%s, Pass=%#v, ErrMsg=%s", string(r.Name()), r.Authentication(), err)
|
||||||
res.SetResultCode(ldap.LDAPResultInvalidCredentials)
|
res.SetResultCode(ldap.LDAPResultInvalidCredentials)
|
||||||
res.SetDiagnosticMessage("invalid credentials ErrMsg: " + err)
|
res.SetDiagnosticMessage("invalid credentials ErrMsg: " + err.Error())
|
||||||
w.Write(res)
|
w.Write(res)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -73,7 +79,7 @@ func handleBind(w ldap.ResponseWriter, m *ldap.Message) {
|
|||||||
m.Client.OrgName = bindOrg
|
m.Client.OrgName = bindOrg
|
||||||
} else {
|
} else {
|
||||||
res.SetResultCode(ldap.LDAPResultAuthMethodNotSupported)
|
res.SetResultCode(ldap.LDAPResultAuthMethodNotSupported)
|
||||||
res.SetDiagnosticMessage("Authentication method not supported,Please use Simple Authentication")
|
res.SetDiagnosticMessage("Authentication method not supported, please use Simple Authentication")
|
||||||
}
|
}
|
||||||
w.Write(res)
|
w.Write(res)
|
||||||
}
|
}
|
||||||
@ -108,10 +114,22 @@ func handleSearch(w ldap.ResponseWriter, m *ldap.Message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
dn := fmt.Sprintf("cn=%s,%s", user.Name, string(r.BaseObject()))
|
dn := fmt.Sprintf("uid=%s,cn=%s,%s", user.Id, user.Name, string(r.BaseObject()))
|
||||||
e := ldap.NewSearchResultEntry(dn)
|
e := ldap.NewSearchResultEntry(dn)
|
||||||
|
uidNumberStr := fmt.Sprintf("%v", hash(user.Name))
|
||||||
for _, attr := range r.Attributes() {
|
e.AddAttribute("uidNumber", message.AttributeValue(uidNumberStr))
|
||||||
|
e.AddAttribute("gidNumber", message.AttributeValue(uidNumberStr))
|
||||||
|
e.AddAttribute("homeDirectory", message.AttributeValue("/home/"+user.Name))
|
||||||
|
e.AddAttribute("cn", message.AttributeValue(user.Name))
|
||||||
|
e.AddAttribute("uid", message.AttributeValue(user.Id))
|
||||||
|
attrs := r.Attributes()
|
||||||
|
for _, attr := range attrs {
|
||||||
|
if string(attr) == "*" {
|
||||||
|
attrs = AdditionalLdapAttributes
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, attr := range attrs {
|
||||||
e.AddAttribute(message.AttributeDescription(attr), getAttribute(string(attr), user))
|
e.AddAttribute(message.AttributeDescription(attr), getAttribute(string(attr), user))
|
||||||
if string(attr) == "cn" {
|
if string(attr) == "cn" {
|
||||||
e.AddAttribute(message.AttributeDescription(attr), getAttribute("title", user))
|
e.AddAttribute(message.AttributeDescription(attr), getAttribute("title", user))
|
||||||
@ -122,3 +140,9 @@ func handleSearch(w ldap.ResponseWriter, m *ldap.Message) {
|
|||||||
}
|
}
|
||||||
w.Write(res)
|
w.Write(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hash(s string) uint32 {
|
||||||
|
h := fnv.New32a()
|
||||||
|
h.Write([]byte(s))
|
||||||
|
return h.Sum32()
|
||||||
|
}
|
||||||
|
200
ldap/util.go
200
ldap/util.go
@ -24,9 +24,73 @@ import (
|
|||||||
"github.com/lor00x/goldap/message"
|
"github.com/lor00x/goldap/message"
|
||||||
|
|
||||||
ldap "github.com/forestmgy/ldapserver"
|
ldap "github.com/forestmgy/ldapserver"
|
||||||
|
|
||||||
|
"github.com/xorm-io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getNameAndOrgFromDN(DN string) (string, string, string) {
|
type AttributeMapper func(user *object.User) message.AttributeValue
|
||||||
|
|
||||||
|
type FieldRelation struct {
|
||||||
|
userField string
|
||||||
|
notSearchable bool
|
||||||
|
hideOnStarOp bool
|
||||||
|
fieldMapper AttributeMapper
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rel FieldRelation) GetField() (string, error) {
|
||||||
|
if rel.notSearchable {
|
||||||
|
return "", fmt.Errorf("attribute %s not supported", rel.userField)
|
||||||
|
}
|
||||||
|
return rel.userField, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rel FieldRelation) GetAttributeValue(user *object.User) message.AttributeValue {
|
||||||
|
return rel.fieldMapper(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ldapAttributesMapping = map[string]FieldRelation{
|
||||||
|
"cn": {userField: "name", hideOnStarOp: true, fieldMapper: func(user *object.User) message.AttributeValue {
|
||||||
|
return message.AttributeValue(user.Name)
|
||||||
|
}},
|
||||||
|
"uid": {userField: "name", hideOnStarOp: true, fieldMapper: func(user *object.User) message.AttributeValue {
|
||||||
|
return message.AttributeValue(user.Name)
|
||||||
|
}},
|
||||||
|
"displayname": {userField: "displayName", fieldMapper: func(user *object.User) message.AttributeValue {
|
||||||
|
return message.AttributeValue(user.DisplayName)
|
||||||
|
}},
|
||||||
|
"email": {userField: "email", fieldMapper: func(user *object.User) message.AttributeValue {
|
||||||
|
return message.AttributeValue(user.Email)
|
||||||
|
}},
|
||||||
|
"mail": {userField: "email", fieldMapper: func(user *object.User) message.AttributeValue {
|
||||||
|
return message.AttributeValue(user.Email)
|
||||||
|
}},
|
||||||
|
"mobile": {userField: "phone", fieldMapper: func(user *object.User) message.AttributeValue {
|
||||||
|
return message.AttributeValue(user.Phone)
|
||||||
|
}},
|
||||||
|
"title": {userField: "tag", fieldMapper: func(user *object.User) message.AttributeValue {
|
||||||
|
return message.AttributeValue(user.Tag)
|
||||||
|
}},
|
||||||
|
"userPassword": {
|
||||||
|
userField: "userPassword",
|
||||||
|
notSearchable: true,
|
||||||
|
fieldMapper: func(user *object.User) message.AttributeValue {
|
||||||
|
return message.AttributeValue(getUserPasswordWithType(user))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var AdditionalLdapAttributes []message.LDAPString
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
for k, v := range ldapAttributesMapping {
|
||||||
|
if v.hideOnStarOp {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
AdditionalLdapAttributes = append(AdditionalLdapAttributes, message.LDAPString(k))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNameAndOrgFromDN(DN string) (string, string, error) {
|
||||||
DNFields := strings.Split(DN, ",")
|
DNFields := strings.Split(DN, ",")
|
||||||
params := make(map[string]string, len(DNFields))
|
params := make(map[string]string, len(DNFields))
|
||||||
for _, field := range DNFields {
|
for _, field := range DNFields {
|
||||||
@ -37,12 +101,12 @@ func getNameAndOrgFromDN(DN string) (string, string, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if params["cn"] == "" {
|
if params["cn"] == "" {
|
||||||
return "", "", "please use Admin Name format like cn=xxx,ou=xxx,dc=example,dc=com"
|
return "", "", fmt.Errorf("please use Admin Name format like cn=xxx,ou=xxx,dc=example,dc=com")
|
||||||
}
|
}
|
||||||
if params["ou"] == "" {
|
if params["ou"] == "" {
|
||||||
return params["cn"], object.CasdoorOrganization, ""
|
return params["cn"], object.CasdoorOrganization, nil
|
||||||
}
|
}
|
||||||
return params["cn"], params["ou"], ""
|
return params["cn"], params["ou"], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNameAndOrgFromFilter(baseDN, filter string) (string, string, int) {
|
func getNameAndOrgFromFilter(baseDN, filter string) (string, string, int) {
|
||||||
@ -50,7 +114,11 @@ func getNameAndOrgFromFilter(baseDN, filter string) (string, string, int) {
|
|||||||
return "", "", ldap.LDAPResultInvalidDNSyntax
|
return "", "", ldap.LDAPResultInvalidDNSyntax
|
||||||
}
|
}
|
||||||
|
|
||||||
name, org, _ := getNameAndOrgFromDN(fmt.Sprintf("cn=%s,", getUsername(filter)) + baseDN)
|
name, org, err := getNameAndOrgFromDN(fmt.Sprintf("cn=%s,", getUsername(filter)) + baseDN)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
return name, org, ldap.LDAPResultSuccess
|
return name, org, ldap.LDAPResultSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +151,92 @@ func stringInSlice(value string, list []string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildUserFilterCondition(filter interface{}) (builder.Cond, error) {
|
||||||
|
switch f := filter.(type) {
|
||||||
|
case message.FilterAnd:
|
||||||
|
conditions := make([]builder.Cond, len(f))
|
||||||
|
for i, v := range f {
|
||||||
|
cond, err := buildUserFilterCondition(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conditions[i] = cond
|
||||||
|
}
|
||||||
|
return builder.And(conditions...), nil
|
||||||
|
case message.FilterOr:
|
||||||
|
conditions := make([]builder.Cond, len(f))
|
||||||
|
for i, v := range f {
|
||||||
|
cond, err := buildUserFilterCondition(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conditions[i] = cond
|
||||||
|
}
|
||||||
|
return builder.Or(conditions...), nil
|
||||||
|
case message.FilterNot:
|
||||||
|
cond, err := buildUserFilterCondition(f.Filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return builder.Not{cond}, nil
|
||||||
|
case message.FilterEqualityMatch:
|
||||||
|
field, err := getUserFieldFromAttribute(string(f.AttributeDesc()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return builder.Eq{field: string(f.AssertionValue())}, nil
|
||||||
|
case message.FilterPresent:
|
||||||
|
field, err := getUserFieldFromAttribute(string(f))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return builder.NotNull{field}, nil
|
||||||
|
case message.FilterGreaterOrEqual:
|
||||||
|
field, err := getUserFieldFromAttribute(string(f.AttributeDesc()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return builder.Gte{field: string(f.AssertionValue())}, nil
|
||||||
|
case message.FilterLessOrEqual:
|
||||||
|
field, err := getUserFieldFromAttribute(string(f.AttributeDesc()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return builder.Lte{field: string(f.AssertionValue())}, nil
|
||||||
|
case message.FilterSubstrings:
|
||||||
|
field, err := getUserFieldFromAttribute(string(f.Type_()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var expr string
|
||||||
|
for _, substring := range f.Substrings() {
|
||||||
|
switch s := substring.(type) {
|
||||||
|
case message.SubstringInitial:
|
||||||
|
expr += string(s) + "%"
|
||||||
|
continue
|
||||||
|
case message.SubstringAny:
|
||||||
|
expr += string(s) + "%"
|
||||||
|
continue
|
||||||
|
case message.SubstringFinal:
|
||||||
|
expr += string(s)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.Expr(field+" LIKE ?", expr), nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("LDAP filter operation %#v not supported", f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildSafeCondition(filter interface{}) builder.Cond {
|
||||||
|
condition, err := buildUserFilterCondition(filter)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("err = %v", err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return condition
|
||||||
|
}
|
||||||
|
|
||||||
func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int) {
|
func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int) {
|
||||||
var err error
|
var err error
|
||||||
r := m.GetSearchRequest()
|
r := m.GetSearchRequest()
|
||||||
@ -94,15 +248,14 @@ func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int)
|
|||||||
|
|
||||||
if name == "*" && m.Client.IsOrgAdmin { // get all users from organization 'org'
|
if name == "*" && m.Client.IsOrgAdmin { // get all users from organization 'org'
|
||||||
if m.Client.IsGlobalAdmin && org == "*" {
|
if m.Client.IsGlobalAdmin && org == "*" {
|
||||||
|
filteredUsers, err = object.GetGlobalUsersWithFilter(buildSafeCondition(r.Filter()))
|
||||||
filteredUsers, err = object.GetGlobalUsers()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return filteredUsers, ldap.LDAPResultSuccess
|
return filteredUsers, ldap.LDAPResultSuccess
|
||||||
}
|
}
|
||||||
if m.Client.IsGlobalAdmin || org == m.Client.OrgName {
|
if m.Client.IsGlobalAdmin || org == m.Client.OrgName {
|
||||||
filteredUsers, err = object.GetUsers(org)
|
filteredUsers, err = object.GetUsersWithFilter(org, buildSafeCondition(r.Filter()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -144,7 +297,7 @@ func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int)
|
|||||||
return nil, ldap.LDAPResultNoSuchObject
|
return nil, ldap.LDAPResultNoSuchObject
|
||||||
}
|
}
|
||||||
|
|
||||||
users, err := object.GetUsersByTag(org, name)
|
users, err := object.GetUsersByTagWithFilter(org, name, buildSafeCondition(r.Filter()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -178,24 +331,17 @@ func getUserPasswordWithType(user *object.User) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getAttribute(attributeName string, user *object.User) message.AttributeValue {
|
func getAttribute(attributeName string, user *object.User) message.AttributeValue {
|
||||||
switch attributeName {
|
v, ok := ldapAttributesMapping[attributeName]
|
||||||
case "cn":
|
if !ok {
|
||||||
return message.AttributeValue(user.Name)
|
|
||||||
case "uid":
|
|
||||||
return message.AttributeValue(user.Name)
|
|
||||||
case "displayname":
|
|
||||||
return message.AttributeValue(user.DisplayName)
|
|
||||||
case "email":
|
|
||||||
return message.AttributeValue(user.Email)
|
|
||||||
case "mail":
|
|
||||||
return message.AttributeValue(user.Email)
|
|
||||||
case "mobile":
|
|
||||||
return message.AttributeValue(user.Phone)
|
|
||||||
case "title":
|
|
||||||
return message.AttributeValue(user.Tag)
|
|
||||||
case "userPassword":
|
|
||||||
return message.AttributeValue(getUserPasswordWithType(user))
|
|
||||||
default:
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
return v.GetAttributeValue(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUserFieldFromAttribute(attributeName string) (string, error) {
|
||||||
|
v, ok := ldapAttributesMapping[attributeName]
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("attribute %s not supported", attributeName)
|
||||||
|
}
|
||||||
|
return v.GetField()
|
||||||
}
|
}
|
||||||
|
87
ldap/util_test.go
Normal file
87
ldap/util_test.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package ldap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
ber "github.com/go-asn1-ber/asn1-ber"
|
||||||
|
goldap "github.com/go-ldap/ldap/v3"
|
||||||
|
"github.com/lor00x/goldap/message"
|
||||||
|
"github.com/xorm-io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
func args(exp ...interface{}) []interface{} {
|
||||||
|
return exp
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLdapFilterAsQuery(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
description string
|
||||||
|
input string
|
||||||
|
expectedExpr string
|
||||||
|
expectedArgs []interface{}
|
||||||
|
}{
|
||||||
|
{"Should be SQL for FilterAnd", "(&(mail=2)(email=1))", "email=? AND email=?", args("2", "1")},
|
||||||
|
{"Should be SQL for FilterOr", "(|(mail=2)(email=1))", "email=? OR email=?", args("2", "1")},
|
||||||
|
{"Should be SQL for FilterNot", "(!(mail=2))", "NOT email=?", args("2")},
|
||||||
|
{"Should be SQL for FilterEqualityMatch", "(mail=2)", "email=?", args("2")},
|
||||||
|
{"Should be SQL for FilterPresent", "(mail=*)", "email IS NOT NULL", nil},
|
||||||
|
{"Should be SQL for FilterGreaterOrEqual", "(mail>=admin)", "email>=?", args("admin")},
|
||||||
|
{"Should be SQL for FilterLessOrEqual", "(mail<=admin)", "email<=?", args("admin")},
|
||||||
|
{"Should be SQL for FilterSubstrings", "(mail=admin*ex*c*m)", "email LIKE ?", args("admin%ex%c%m")},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, scenery := range scenarios {
|
||||||
|
t.Run(scenery.description, func(t *testing.T) {
|
||||||
|
searchRequest, err := buildLdapSearchRequest(scenery.input)
|
||||||
|
if err != nil {
|
||||||
|
assert.FailNow(t, "Unable to create searchRequest", err)
|
||||||
|
}
|
||||||
|
m, err := message.ReadLDAPMessage(message.NewBytes(0, searchRequest.Bytes()))
|
||||||
|
if err != nil {
|
||||||
|
assert.FailNow(t, "Unable to create searchRequest", err)
|
||||||
|
}
|
||||||
|
req := m.ProtocolOp().(message.SearchRequest)
|
||||||
|
|
||||||
|
cond, err := buildUserFilterCondition(req.Filter())
|
||||||
|
if err != nil {
|
||||||
|
assert.FailNow(t, "Unable to build condition", err)
|
||||||
|
}
|
||||||
|
expr, args, err := builder.ToSQL(cond)
|
||||||
|
if err != nil {
|
||||||
|
assert.FailNow(t, "Unable to build sql", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, scenery.expectedExpr, expr)
|
||||||
|
assert.Equal(t, scenery.expectedArgs, args)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildLdapSearchRequest(filter string) (*ber.Packet, error) {
|
||||||
|
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
||||||
|
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 1, "MessageID"))
|
||||||
|
|
||||||
|
pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, goldap.ApplicationSearchRequest, nil, "Search Request")
|
||||||
|
pkt.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "Base DN"))
|
||||||
|
pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, 0, "Scope"))
|
||||||
|
pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, 0, "Deref Aliases"))
|
||||||
|
pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 0, "Size Limit"))
|
||||||
|
pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 0, "Time Limit"))
|
||||||
|
pkt.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, false, "Types Only"))
|
||||||
|
// compile and encode filter
|
||||||
|
filterPacket, err := goldap.CompileFilter(filter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pkt.AppendChild(filterPacket)
|
||||||
|
// encode attributes
|
||||||
|
attributesPacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes")
|
||||||
|
attributesPacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "*", "Attribute"))
|
||||||
|
pkt.AppendChild(attributesPacket)
|
||||||
|
|
||||||
|
packet.AppendChild(pkt)
|
||||||
|
|
||||||
|
return packet, nil
|
||||||
|
}
|
1
main.go
1
main.go
@ -34,7 +34,6 @@ func main() {
|
|||||||
object.InitFlag()
|
object.InitFlag()
|
||||||
object.InitAdapter()
|
object.InitAdapter()
|
||||||
object.CreateTables()
|
object.CreateTables()
|
||||||
object.DoMigration()
|
|
||||||
|
|
||||||
object.InitDb()
|
object.InitDb()
|
||||||
object.InitFromFile()
|
object.InitFromFile()
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
# Patterns to ignore when building packages.
|
|
||||||
# This supports shell glob matching, relative path matching, and
|
|
||||||
# negation (prefixed with !). Only one pattern per line.
|
|
||||||
.DS_Store
|
|
||||||
# Common VCS dirs
|
|
||||||
.git/
|
|
||||||
.gitignore
|
|
||||||
.bzr/
|
|
||||||
.bzrignore
|
|
||||||
.hg/
|
|
||||||
.hgignore
|
|
||||||
.svn/
|
|
||||||
# Common backup files
|
|
||||||
*.swp
|
|
||||||
*.bak
|
|
||||||
*.tmp
|
|
||||||
*.orig
|
|
||||||
*~
|
|
||||||
# Various IDEs
|
|
||||||
.project
|
|
||||||
.idea/
|
|
||||||
*.tmproj
|
|
||||||
.vscode/
|
|
@ -1,24 +0,0 @@
|
|||||||
apiVersion: v2
|
|
||||||
name: casdoor
|
|
||||||
description: A Helm chart for Kubernetes
|
|
||||||
|
|
||||||
# A chart can be either an 'application' or a 'library' chart.
|
|
||||||
#
|
|
||||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
|
||||||
# to be deployed.
|
|
||||||
#
|
|
||||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
|
||||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
|
||||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
|
||||||
type: application
|
|
||||||
|
|
||||||
# This is the chart version. This version number should be incremented each time you make changes
|
|
||||||
# to the chart and its templates, including the app version.
|
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
|
||||||
version: 0.1.0
|
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
|
||||||
# incremented each time you make changes to the application. Versions are not expected to
|
|
||||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
|
||||||
# It is recommended to use it with quotes.
|
|
||||||
appVersion: "1.16.0"
|
|
@ -1,22 +0,0 @@
|
|||||||
1. Get the application URL by running these commands:
|
|
||||||
{{- if .Values.ingress.enabled }}
|
|
||||||
{{- range $host := .Values.ingress.hosts }}
|
|
||||||
{{- range .paths }}
|
|
||||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- else if contains "NodePort" .Values.service.type }}
|
|
||||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "casdoor.fullname" . }})
|
|
||||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
|
||||||
echo http://$NODE_IP:$NODE_PORT
|
|
||||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
|
||||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
|
||||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "casdoor.fullname" . }}'
|
|
||||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "casdoor.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
|
||||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
|
||||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
|
||||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "casdoor.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
|
||||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
|
||||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
|
||||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
|
||||||
{{- end }}
|
|
@ -1,62 +0,0 @@
|
|||||||
{{/*
|
|
||||||
Expand the name of the chart.
|
|
||||||
*/}}
|
|
||||||
{{- define "casdoor.name" -}}
|
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create a default fully qualified app name.
|
|
||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
|
||||||
If release name contains chart name it will be used as a full name.
|
|
||||||
*/}}
|
|
||||||
{{- define "casdoor.fullname" -}}
|
|
||||||
{{- if .Values.fullnameOverride }}
|
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
|
||||||
{{- if contains $name .Release.Name }}
|
|
||||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create chart name and version as used by the chart label.
|
|
||||||
*/}}
|
|
||||||
{{- define "casdoor.chart" -}}
|
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Common labels
|
|
||||||
*/}}
|
|
||||||
{{- define "casdoor.labels" -}}
|
|
||||||
helm.sh/chart: {{ include "casdoor.chart" . }}
|
|
||||||
{{ include "casdoor.selectorLabels" . }}
|
|
||||||
{{- if .Chart.AppVersion }}
|
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
|
||||||
{{- end }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Selector labels
|
|
||||||
*/}}
|
|
||||||
{{- define "casdoor.selectorLabels" -}}
|
|
||||||
app.kubernetes.io/name: {{ include "casdoor.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create the name of the service account to use
|
|
||||||
*/}}
|
|
||||||
{{- define "casdoor.serviceAccountName" -}}
|
|
||||||
{{- if .Values.serviceAccount.create }}
|
|
||||||
{{- default (include "casdoor.fullname" .) .Values.serviceAccount.name }}
|
|
||||||
{{- else }}
|
|
||||||
{{- default "default" .Values.serviceAccount.name }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
@ -1,8 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: {{ printf "%s-config" (include "casdoor.fullname" .) }}
|
|
||||||
labels:
|
|
||||||
{{- include "casdoor.labels" . | nindent 4 }}
|
|
||||||
data:
|
|
||||||
app.conf: {{ tpl .Values.config . | toYaml | nindent 4 }}
|
|
@ -1,83 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{ include "casdoor.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "casdoor.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
{{- if not .Values.autoscaling.enabled }}
|
|
||||||
replicas: {{ .Values.replicaCount }}
|
|
||||||
{{- end }}
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
{{- include "casdoor.selectorLabels" . | nindent 6 }}
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
checksum/config: {{ tpl .Values.config . | toYaml | sha256sum }}
|
|
||||||
{{- with .Values.podAnnotations }}
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
labels:
|
|
||||||
{{- include "casdoor.selectorLabels" . | nindent 8 }}
|
|
||||||
spec:
|
|
||||||
{{- with .Values.imagePullSecrets }}
|
|
||||||
imagePullSecrets:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
serviceAccountName: {{ include "casdoor.serviceAccountName" . }}
|
|
||||||
securityContext:
|
|
||||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
|
||||||
containers:
|
|
||||||
- name: {{ .Chart.Name }}
|
|
||||||
securityContext:
|
|
||||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
|
||||||
image: "{{ .Values.image.repository }}/{{ .Values.image.name }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
||||||
# command: ["sleep", "100000000"]
|
|
||||||
env:
|
|
||||||
- name: RUNNING_IN_DOCKER
|
|
||||||
value: "true"
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: {{ .Values.service.port }}
|
|
||||||
protocol: TCP
|
|
||||||
{{ if .Values.probe.liveness.enabled }}
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /
|
|
||||||
port: http
|
|
||||||
{{ end }}
|
|
||||||
{{ if .Values.probe.readiness.enabled }}
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /
|
|
||||||
port: http
|
|
||||||
{{ end }}
|
|
||||||
resources:
|
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
|
||||||
volumeMounts:
|
|
||||||
- name: config-volume
|
|
||||||
mountPath: /conf
|
|
||||||
volumes:
|
|
||||||
- name: config-volume
|
|
||||||
projected:
|
|
||||||
defaultMode: 420
|
|
||||||
sources:
|
|
||||||
- configMap:
|
|
||||||
items:
|
|
||||||
- key: app.conf
|
|
||||||
path: app.conf
|
|
||||||
name: {{ printf "%s-config" (include "casdoor.fullname" .) }}
|
|
||||||
{{- with .Values.nodeSelector }}
|
|
||||||
nodeSelector:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.affinity }}
|
|
||||||
affinity:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.tolerations }}
|
|
||||||
tolerations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
@ -1,28 +0,0 @@
|
|||||||
{{- if .Values.autoscaling.enabled }}
|
|
||||||
apiVersion: autoscaling/v2beta1
|
|
||||||
kind: HorizontalPodAutoscaler
|
|
||||||
metadata:
|
|
||||||
name: {{ include "casdoor.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "casdoor.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
scaleTargetRef:
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
name: {{ include "casdoor.fullname" . }}
|
|
||||||
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
|
||||||
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
|
||||||
metrics:
|
|
||||||
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
|
||||||
- type: Resource
|
|
||||||
resource:
|
|
||||||
name: cpu
|
|
||||||
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
|
||||||
- type: Resource
|
|
||||||
resource:
|
|
||||||
name: memory
|
|
||||||
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
@ -1,61 +0,0 @@
|
|||||||
{{- if .Values.ingress.enabled -}}
|
|
||||||
{{- $fullName := include "casdoor.fullname" . -}}
|
|
||||||
{{- $svcPort := .Values.service.port -}}
|
|
||||||
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
|
||||||
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
|
|
||||||
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
|
||||||
apiVersion: networking.k8s.io/v1beta1
|
|
||||||
{{- else -}}
|
|
||||||
apiVersion: extensions/v1beta1
|
|
||||||
{{- end }}
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: {{ $fullName }}
|
|
||||||
labels:
|
|
||||||
{{- include "casdoor.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.ingress.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
|
||||||
ingressClassName: {{ .Values.ingress.className }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.ingress.tls }}
|
|
||||||
tls:
|
|
||||||
{{- range .Values.ingress.tls }}
|
|
||||||
- hosts:
|
|
||||||
{{- range .hosts }}
|
|
||||||
- {{ . | quote }}
|
|
||||||
{{- end }}
|
|
||||||
secretName: {{ .secretName }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
rules:
|
|
||||||
{{- range .Values.ingress.hosts }}
|
|
||||||
- host: {{ .host | quote }}
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
{{- range .paths }}
|
|
||||||
- path: {{ .path }}
|
|
||||||
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
|
|
||||||
pathType: {{ .pathType }}
|
|
||||||
{{- end }}
|
|
||||||
backend:
|
|
||||||
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
|
||||||
service:
|
|
||||||
name: {{ $fullName }}
|
|
||||||
port:
|
|
||||||
number: {{ $svcPort }}
|
|
||||||
{{- else }}
|
|
||||||
serviceName: {{ $fullName }}
|
|
||||||
servicePort: {{ $svcPort }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
@ -1,15 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: {{ include "casdoor.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "casdoor.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
type: {{ .Values.service.type }}
|
|
||||||
ports:
|
|
||||||
- port: {{ .Values.service.port }}
|
|
||||||
targetPort: http
|
|
||||||
protocol: TCP
|
|
||||||
name: http
|
|
||||||
selector:
|
|
||||||
{{- include "casdoor.selectorLabels" . | nindent 4 }}
|
|
@ -1,12 +0,0 @@
|
|||||||
{{- if .Values.serviceAccount.create -}}
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: {{ include "casdoor.serviceAccountName" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "casdoor.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.serviceAccount.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
@ -1,15 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: "{{ include "casdoor.fullname" . }}-test-connection"
|
|
||||||
labels:
|
|
||||||
{{- include "casdoor.labels" . | nindent 4 }}
|
|
||||||
annotations:
|
|
||||||
"helm.sh/hook": test
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: wget
|
|
||||||
image: busybox
|
|
||||||
command: ['wget']
|
|
||||||
args: ['{{ include "casdoor.fullname" . }}:{{ .Values.service.port }}']
|
|
||||||
restartPolicy: Never
|
|
@ -1,109 +0,0 @@
|
|||||||
# Default values for casdoor.
|
|
||||||
# This is a YAML-formatted file.
|
|
||||||
# Declare variables to be passed into your templates.
|
|
||||||
|
|
||||||
replicaCount: 1
|
|
||||||
|
|
||||||
image:
|
|
||||||
repository: casbin
|
|
||||||
name: casdoor
|
|
||||||
pullPolicy: IfNotPresent
|
|
||||||
# Overrides the image tag whose default is the chart appVersion.
|
|
||||||
tag: ""
|
|
||||||
|
|
||||||
# ref: https://casdoor.org/docs/basic/server-installation#via-ini-file
|
|
||||||
config: |
|
|
||||||
appname = casdoor
|
|
||||||
httpport = {{ .Values.service.port }}
|
|
||||||
runmode = dev
|
|
||||||
SessionOn = true
|
|
||||||
copyrequestbody = true
|
|
||||||
driverName = sqlite
|
|
||||||
dataSourceName = "file:ent?mode=memory&cache=shared&_fk=1"
|
|
||||||
dbName = casdoor
|
|
||||||
redisEndpoint =
|
|
||||||
defaultStorageProvider =
|
|
||||||
isCloudIntranet = false
|
|
||||||
authState = "casdoor"
|
|
||||||
socks5Proxy = ""
|
|
||||||
verificationCodeTimeout = 10
|
|
||||||
initScore = 2000
|
|
||||||
logPostOnly = true
|
|
||||||
origin = "https://door.casbin.com"
|
|
||||||
|
|
||||||
imagePullSecrets: []
|
|
||||||
nameOverride: ""
|
|
||||||
fullnameOverride: ""
|
|
||||||
|
|
||||||
serviceAccount:
|
|
||||||
# Specifies whether a service account should be created
|
|
||||||
create: true
|
|
||||||
# Annotations to add to the service account
|
|
||||||
annotations: {}
|
|
||||||
# The name of the service account to use.
|
|
||||||
# If not set and create is true, a name is generated using the fullname template
|
|
||||||
name: ""
|
|
||||||
|
|
||||||
podAnnotations: {}
|
|
||||||
|
|
||||||
podSecurityContext: {}
|
|
||||||
# fsGroup: 2000
|
|
||||||
|
|
||||||
securityContext: {}
|
|
||||||
# capabilities:
|
|
||||||
# drop:
|
|
||||||
# - ALL
|
|
||||||
# readOnlyRootFilesystem: true
|
|
||||||
# runAsNonRoot: true
|
|
||||||
# runAsUser: 1000
|
|
||||||
|
|
||||||
probe:
|
|
||||||
readiness:
|
|
||||||
enabled: true
|
|
||||||
liveness:
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
service:
|
|
||||||
type: ClusterIP
|
|
||||||
port: 8000
|
|
||||||
|
|
||||||
ingress:
|
|
||||||
enabled: false
|
|
||||||
className: ""
|
|
||||||
annotations: {}
|
|
||||||
# kubernetes.io/ingress.class: nginx
|
|
||||||
# kubernetes.io/tls-acme: "true"
|
|
||||||
hosts:
|
|
||||||
- host: chart-example.local
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: ImplementationSpecific
|
|
||||||
tls: []
|
|
||||||
# - secretName: chart-example-tls
|
|
||||||
# hosts:
|
|
||||||
# - chart-example.local
|
|
||||||
|
|
||||||
resources: {}
|
|
||||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
|
||||||
# choice for the user. This also increases chances charts run on environments with little
|
|
||||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
|
||||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
|
||||||
# limits:
|
|
||||||
# cpu: 100m
|
|
||||||
# memory: 128Mi
|
|
||||||
# requests:
|
|
||||||
# cpu: 100m
|
|
||||||
# memory: 128Mi
|
|
||||||
|
|
||||||
autoscaling:
|
|
||||||
enabled: false
|
|
||||||
minReplicas: 1
|
|
||||||
maxReplicas: 100
|
|
||||||
targetCPUUtilizationPercentage: 80
|
|
||||||
# targetMemoryUtilizationPercentage: 80
|
|
||||||
|
|
||||||
nodeSelector: {}
|
|
||||||
|
|
||||||
tolerations: []
|
|
||||||
|
|
||||||
affinity: {}
|
|
@ -15,10 +15,11 @@
|
|||||||
package notification
|
package notification
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/proxy"
|
"github.com/casdoor/casdoor/proxy"
|
||||||
)
|
)
|
||||||
@ -39,26 +40,29 @@ func NewCustomHttpProvider(endpoint string, method string, paramName string) (*H
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *HttpNotificationClient) Send(ctx context.Context, subject string, content string) error {
|
func (c *HttpNotificationClient) Send(ctx context.Context, subject string, content string) error {
|
||||||
|
var req *http.Request
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
httpClient := proxy.DefaultHttpClient
|
|
||||||
|
|
||||||
req, err := http.NewRequest(c.method, c.endpoint, bytes.NewBufferString(content))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.method == "POST" {
|
if c.method == "POST" {
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
formValues := url.Values{}
|
||||||
req.PostForm = map[string][]string{
|
formValues.Set(c.paramName, content)
|
||||||
c.paramName: {content},
|
req, err = http.NewRequest(c.method, c.endpoint, strings.NewReader(formValues.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
} else if c.method == "GET" {
|
} else if c.method == "GET" {
|
||||||
|
req, err = http.NewRequest(c.method, c.endpoint, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
q := req.URL.Query()
|
q := req.URL.Query()
|
||||||
q.Add(c.paramName, content)
|
q.Add(c.paramName, content)
|
||||||
req.URL.RawQuery = q.Encode()
|
req.URL.RawQuery = q.Encode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
httpClient := proxy.DefaultHttpClient
|
||||||
resp, err := httpClient.Do(req)
|
resp, err := httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -66,7 +70,7 @@ func (c *HttpNotificationClient) Send(ctx context.Context, subject string, conte
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return fmt.Errorf("SendMessage() error, custom HTTP Notification request failed with status: %s", resp.Status)
|
return fmt.Errorf("HttpNotificationClient's SendMessage() error, custom HTTP Notification request failed with status: %s", resp.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -30,15 +30,15 @@ type Adapter struct {
|
|||||||
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||||
|
|
||||||
Type string `xorm:"varchar(100)" json:"type"`
|
Table string `xorm:"varchar(100)" json:"table"`
|
||||||
DatabaseType string `xorm:"varchar(100)" json:"databaseType"`
|
UseSameDb bool `json:"useSameDb"`
|
||||||
Host string `xorm:"varchar(100)" json:"host"`
|
Type string `xorm:"varchar(100)" json:"type"`
|
||||||
Port int `json:"port"`
|
DatabaseType string `xorm:"varchar(100)" json:"databaseType"`
|
||||||
User string `xorm:"varchar(100)" json:"user"`
|
Host string `xorm:"varchar(100)" json:"host"`
|
||||||
Password string `xorm:"varchar(100)" json:"password"`
|
Port int `json:"port"`
|
||||||
Database string `xorm:"varchar(100)" json:"database"`
|
User string `xorm:"varchar(100)" json:"user"`
|
||||||
Table string `xorm:"varchar(100)" json:"table"`
|
Password string `xorm:"varchar(100)" json:"password"`
|
||||||
TableNamePrefix string `xorm:"varchar(100)" json:"tableNamePrefix"`
|
Database string `xorm:"varchar(100)" json:"database"`
|
||||||
|
|
||||||
*xormadapter.Adapter `xorm:"-" json:"-"`
|
*xormadapter.Adapter `xorm:"-" json:"-"`
|
||||||
}
|
}
|
||||||
@ -139,63 +139,69 @@ func (adapter *Adapter) GetId() string {
|
|||||||
return fmt.Sprintf("%s/%s", adapter.Owner, adapter.Name)
|
return fmt.Sprintf("%s/%s", adapter.Owner, adapter.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adapter *Adapter) getTable() string {
|
|
||||||
if adapter.DatabaseType == "mssql" {
|
|
||||||
return fmt.Sprintf("[%s]", adapter.Table)
|
|
||||||
} else {
|
|
||||||
return adapter.Table
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (adapter *Adapter) InitAdapter() error {
|
func (adapter *Adapter) InitAdapter() error {
|
||||||
if adapter.Adapter == nil {
|
if adapter.Adapter != nil {
|
||||||
var dataSourceName string
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if adapter.isBuiltIn() {
|
var driverName string
|
||||||
dataSourceName = conf.GetConfigString("dataSourceName")
|
var dataSourceName string
|
||||||
if adapter.DatabaseType == "mysql" {
|
if adapter.UseSameDb || adapter.isBuiltIn() {
|
||||||
dataSourceName = dataSourceName + adapter.Database
|
driverName = conf.GetConfigString("driverName")
|
||||||
}
|
dataSourceName = conf.GetConfigString("dataSourceName")
|
||||||
} else {
|
if conf.GetConfigString("driverName") == "mysql" {
|
||||||
switch adapter.DatabaseType {
|
dataSourceName = dataSourceName + conf.GetConfigString("dbName")
|
||||||
case "mssql":
|
|
||||||
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", adapter.User,
|
|
||||||
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
|
|
||||||
case "mysql":
|
|
||||||
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", adapter.User,
|
|
||||||
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
|
|
||||||
case "postgres":
|
|
||||||
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s", adapter.User,
|
|
||||||
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
|
|
||||||
case "CockroachDB":
|
|
||||||
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s serial_normalization=virtual_sequence",
|
|
||||||
adapter.User, adapter.Password, adapter.Host, adapter.Port, adapter.Database)
|
|
||||||
case "sqlite3":
|
|
||||||
dataSourceName = fmt.Sprintf("file:%s", adapter.Host)
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unsupported database type: %s", adapter.DatabaseType)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
if !isCloudIntranet {
|
driverName = adapter.DatabaseType
|
||||||
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
|
switch driverName {
|
||||||
}
|
case "mssql":
|
||||||
|
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", adapter.User,
|
||||||
var err error
|
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
|
||||||
engine, err := xorm.NewEngine(adapter.DatabaseType, dataSourceName)
|
case "mysql":
|
||||||
|
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", adapter.User,
|
||||||
if adapter.isBuiltIn() && adapter.DatabaseType == "postgres" {
|
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
|
||||||
schema := util.GetValueFromDataSourceName("search_path", dataSourceName)
|
case "postgres":
|
||||||
if schema != "" {
|
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s", adapter.User,
|
||||||
engine.SetSchema(schema)
|
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
|
||||||
}
|
case "CockroachDB":
|
||||||
}
|
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s serial_normalization=virtual_sequence",
|
||||||
|
adapter.User, adapter.Password, adapter.Host, adapter.Port, adapter.Database)
|
||||||
adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(engine, adapter.getTable(), adapter.TableNamePrefix)
|
case "sqlite3":
|
||||||
if err != nil {
|
dataSourceName = fmt.Sprintf("file:%s", adapter.Host)
|
||||||
return err
|
default:
|
||||||
|
return fmt.Errorf("unsupported database type: %s", adapter.DatabaseType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !isCloudIntranet {
|
||||||
|
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
|
||||||
|
}
|
||||||
|
|
||||||
|
engine, err := xorm.NewEngine(driverName, dataSourceName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adapter.UseSameDb || adapter.isBuiltIn()) && driverName == "postgres" {
|
||||||
|
schema := util.GetValueFromDataSourceName("search_path", dataSourceName)
|
||||||
|
if schema != "" {
|
||||||
|
engine.SetSchema(schema)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tableName string
|
||||||
|
if driverName == "mssql" {
|
||||||
|
tableName = fmt.Sprintf("[%s]", adapter.Table)
|
||||||
|
} else {
|
||||||
|
tableName = adapter.Table
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(engine, tableName, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,12 +24,27 @@ import (
|
|||||||
"github.com/xorm-io/core"
|
"github.com/xorm-io/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type SigninMethod struct {
|
||||||
|
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||||
|
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||||
|
Rule string `json:"rule"`
|
||||||
|
}
|
||||||
|
|
||||||
type SignupItem struct {
|
type SignupItem struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Visible bool `json:"visible"`
|
Visible bool `json:"visible"`
|
||||||
Required bool `json:"required"`
|
Required bool `json:"required"`
|
||||||
Prompted bool `json:"prompted"`
|
Prompted bool `json:"prompted"`
|
||||||
Rule string `json:"rule"`
|
Label string `json:"label"`
|
||||||
|
Placeholder string `json:"placeholder"`
|
||||||
|
Regex string `json:"regex"`
|
||||||
|
Rule string `json:"rule"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SamlItem struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
NameFormat string `json:"nameFormat"`
|
||||||
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Application struct {
|
type Application struct {
|
||||||
@ -49,22 +64,25 @@ type Application struct {
|
|||||||
EnableAutoSignin bool `json:"enableAutoSignin"`
|
EnableAutoSignin bool `json:"enableAutoSignin"`
|
||||||
EnableCodeSignin bool `json:"enableCodeSignin"`
|
EnableCodeSignin bool `json:"enableCodeSignin"`
|
||||||
EnableSamlCompress bool `json:"enableSamlCompress"`
|
EnableSamlCompress bool `json:"enableSamlCompress"`
|
||||||
|
EnableSamlC14n10 bool `json:"enableSamlC14n10"`
|
||||||
EnableWebAuthn bool `json:"enableWebAuthn"`
|
EnableWebAuthn bool `json:"enableWebAuthn"`
|
||||||
EnableLinkWithEmail bool `json:"enableLinkWithEmail"`
|
EnableLinkWithEmail bool `json:"enableLinkWithEmail"`
|
||||||
OrgChoiceMode string `json:"orgChoiceMode"`
|
OrgChoiceMode string `json:"orgChoiceMode"`
|
||||||
SamlReplyUrl string `xorm:"varchar(100)" json:"samlReplyUrl"`
|
SamlReplyUrl string `xorm:"varchar(100)" json:"samlReplyUrl"`
|
||||||
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
|
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
|
||||||
SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
|
SigninMethods []*SigninMethod `xorm:"varchar(2000)" json:"signinMethods"`
|
||||||
|
SignupItems []*SignupItem `xorm:"varchar(2000)" json:"signupItems"`
|
||||||
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`
|
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`
|
||||||
OrganizationObj *Organization `xorm:"-" json:"organizationObj"`
|
OrganizationObj *Organization `xorm:"-" json:"organizationObj"`
|
||||||
CertPublicKey string `xorm:"-" json:"certPublicKey"`
|
CertPublicKey string `xorm:"-" json:"certPublicKey"`
|
||||||
Tags []string `xorm:"mediumtext" json:"tags"`
|
Tags []string `xorm:"mediumtext" json:"tags"`
|
||||||
InvitationCodes []string `xorm:"varchar(200)" json:"invitationCodes"`
|
SamlAttributes []*SamlItem `xorm:"varchar(1000)" json:"samlAttributes"`
|
||||||
|
|
||||||
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
||||||
ClientSecret string `xorm:"varchar(100)" json:"clientSecret"`
|
ClientSecret string `xorm:"varchar(100)" json:"clientSecret"`
|
||||||
RedirectUris []string `xorm:"varchar(1000)" json:"redirectUris"`
|
RedirectUris []string `xorm:"varchar(1000)" json:"redirectUris"`
|
||||||
TokenFormat string `xorm:"varchar(100)" json:"tokenFormat"`
|
TokenFormat string `xorm:"varchar(100)" json:"tokenFormat"`
|
||||||
|
TokenFields []string `xorm:"varchar(1000)" json:"tokenFields"`
|
||||||
ExpireInHours int `json:"expireInHours"`
|
ExpireInHours int `json:"expireInHours"`
|
||||||
RefreshExpireInHours int `json:"refreshExpireInHours"`
|
RefreshExpireInHours int `json:"refreshExpireInHours"`
|
||||||
SignupUrl string `xorm:"varchar(200)" json:"signupUrl"`
|
SignupUrl string `xorm:"varchar(200)" json:"signupUrl"`
|
||||||
@ -80,6 +98,9 @@ type Application struct {
|
|||||||
FormOffset int `json:"formOffset"`
|
FormOffset int `json:"formOffset"`
|
||||||
FormSideHtml string `xorm:"mediumtext" json:"formSideHtml"`
|
FormSideHtml string `xorm:"mediumtext" json:"formSideHtml"`
|
||||||
FormBackgroundUrl string `xorm:"varchar(200)" json:"formBackgroundUrl"`
|
FormBackgroundUrl string `xorm:"varchar(200)" json:"formBackgroundUrl"`
|
||||||
|
|
||||||
|
FailedSigninLimit int `json:"failedSigninLimit"`
|
||||||
|
FailedSigninFrozenTime int `json:"failedSigninFrozenTime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetApplicationCount(owner, field, value string) (int64, error) {
|
func GetApplicationCount(owner, field, value string) (int64, error) {
|
||||||
@ -178,6 +199,30 @@ func extendApplicationWithOrg(application *Application) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func extendApplicationWithSigninMethods(application *Application) (err error) {
|
||||||
|
if len(application.SigninMethods) == 0 {
|
||||||
|
if application.EnablePassword {
|
||||||
|
signinMethod := &SigninMethod{Name: "Password", DisplayName: "Password", Rule: "All"}
|
||||||
|
application.SigninMethods = append(application.SigninMethods, signinMethod)
|
||||||
|
}
|
||||||
|
if application.EnableCodeSignin {
|
||||||
|
signinMethod := &SigninMethod{Name: "Verification code", DisplayName: "Verification code", Rule: "All"}
|
||||||
|
application.SigninMethods = append(application.SigninMethods, signinMethod)
|
||||||
|
}
|
||||||
|
if application.EnableWebAuthn {
|
||||||
|
signinMethod := &SigninMethod{Name: "WebAuthn", DisplayName: "WebAuthn", Rule: "None"}
|
||||||
|
application.SigninMethods = append(application.SigninMethods, signinMethod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(application.SigninMethods) == 0 {
|
||||||
|
signinMethod := &SigninMethod{Name: "Password", DisplayName: "Password", Rule: "All"}
|
||||||
|
application.SigninMethods = append(application.SigninMethods, signinMethod)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func getApplication(owner string, name string) (*Application, error) {
|
func getApplication(owner string, name string) (*Application, error) {
|
||||||
if owner == "" || name == "" {
|
if owner == "" || name == "" {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -200,6 +245,11 @@ func getApplication(owner string, name string) (*Application, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = extendApplicationWithSigninMethods(&application)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &application, nil
|
return &application, nil
|
||||||
} else {
|
} else {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -224,6 +274,11 @@ func GetApplicationByOrganizationName(organization string) (*Application, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = extendApplicationWithSigninMethods(&application)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &application, nil
|
return &application, nil
|
||||||
} else {
|
} else {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -271,6 +326,11 @@ func GetApplicationByClientId(clientId string) (*Application, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = extendApplicationWithSigninMethods(&application)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &application, nil
|
return &application, nil
|
||||||
} else {
|
} else {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -287,6 +347,17 @@ func GetMaskedApplication(application *Application, userId string) *Application
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if application.TokenFields == nil {
|
||||||
|
application.TokenFields = []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if application.FailedSigninLimit == 0 {
|
||||||
|
application.FailedSigninLimit = DefaultFailedSigninLimit
|
||||||
|
}
|
||||||
|
if application.FailedSigninFrozenTime == 0 {
|
||||||
|
application.FailedSigninFrozenTime = DefaultFailedSigninFrozenTime
|
||||||
|
}
|
||||||
|
|
||||||
if userId != "" {
|
if userId != "" {
|
||||||
if isUserIdGlobalAdmin(userId) {
|
if isUserIdGlobalAdmin(userId) {
|
||||||
return application
|
return application
|
||||||
@ -306,6 +377,12 @@ func GetMaskedApplication(application *Application, userId string) *Application
|
|||||||
if application.OrganizationObj.MasterPassword != "" {
|
if application.OrganizationObj.MasterPassword != "" {
|
||||||
application.OrganizationObj.MasterPassword = "***"
|
application.OrganizationObj.MasterPassword = "***"
|
||||||
}
|
}
|
||||||
|
if application.OrganizationObj.DefaultPassword != "" {
|
||||||
|
application.OrganizationObj.DefaultPassword = "***"
|
||||||
|
}
|
||||||
|
if application.OrganizationObj.MasterVerificationCode != "" {
|
||||||
|
application.OrganizationObj.MasterVerificationCode = "***"
|
||||||
|
}
|
||||||
if application.OrganizationObj.PasswordType != "" {
|
if application.OrganizationObj.PasswordType != "" {
|
||||||
application.OrganizationObj.PasswordType = "***"
|
application.OrganizationObj.PasswordType = "***"
|
||||||
}
|
}
|
||||||
@ -314,10 +391,6 @@ func GetMaskedApplication(application *Application, userId string) *Application
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.InvitationCodes != nil {
|
|
||||||
application.InvitationCodes = []string{"***"}
|
|
||||||
}
|
|
||||||
|
|
||||||
return application
|
return application
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,6 +405,34 @@ func GetMaskedApplications(applications []*Application, userId string) []*Applic
|
|||||||
return applications
|
return applications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAllowedApplications(applications []*Application, userId string) ([]*Application, error) {
|
||||||
|
if userId == "" || isUserIdGlobalAdmin(userId) {
|
||||||
|
return applications, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := GetUser(userId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if user != nil && user.IsAdmin {
|
||||||
|
return applications, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res := []*Application{}
|
||||||
|
for _, application := range applications {
|
||||||
|
var allowed bool
|
||||||
|
allowed, err = CheckLoginPermission(userId, application)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if allowed {
|
||||||
|
res = append(res, application)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
func UpdateApplication(id string, application *Application) (bool, error) {
|
func UpdateApplication(id string, application *Application) (bool, error) {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
oldApplication, err := getApplication(owner, name)
|
oldApplication, err := getApplication(owner, name)
|
||||||
@ -428,7 +529,7 @@ func (application *Application) GetId() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (application *Application) IsRedirectUriValid(redirectUri string) bool {
|
func (application *Application) IsRedirectUriValid(redirectUri string) bool {
|
||||||
redirectUris := append([]string{"http://localhost:"}, application.RedirectUris...)
|
redirectUris := append([]string{"http://localhost:", "https://localhost:", "http://127.0.0.1:", "http://casdoor-app"}, application.RedirectUris...)
|
||||||
for _, targetUri := range redirectUris {
|
for _, targetUri := range redirectUris {
|
||||||
targetUriRegex := regexp.MustCompile(targetUri)
|
targetUriRegex := regexp.MustCompile(targetUri)
|
||||||
if targetUriRegex.MatchString(redirectUri) || strings.Contains(redirectUri, targetUri) {
|
if targetUriRegex.MatchString(redirectUri) || strings.Contains(redirectUri, targetUri) {
|
||||||
@ -438,6 +539,69 @@ func (application *Application) IsRedirectUriValid(redirectUri string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (application *Application) IsPasswordEnabled() bool {
|
||||||
|
if len(application.SigninMethods) == 0 {
|
||||||
|
return application.EnablePassword
|
||||||
|
} else {
|
||||||
|
for _, signinMethod := range application.SigninMethods {
|
||||||
|
if signinMethod.Name == "Password" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (application *Application) IsPasswordWithLdapEnabled() bool {
|
||||||
|
if len(application.SigninMethods) == 0 {
|
||||||
|
return application.EnablePassword
|
||||||
|
} else {
|
||||||
|
for _, signinMethod := range application.SigninMethods {
|
||||||
|
if signinMethod.Name == "Password" && signinMethod.Rule == "All" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (application *Application) IsCodeSigninViaEmailEnabled() bool {
|
||||||
|
if len(application.SigninMethods) == 0 {
|
||||||
|
return application.EnableCodeSignin
|
||||||
|
} else {
|
||||||
|
for _, signinMethod := range application.SigninMethods {
|
||||||
|
if signinMethod.Name == "Verification code" && signinMethod.Rule != "Phone only" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (application *Application) IsCodeSigninViaSmsEnabled() bool {
|
||||||
|
if len(application.SigninMethods) == 0 {
|
||||||
|
return application.EnableCodeSignin
|
||||||
|
} else {
|
||||||
|
for _, signinMethod := range application.SigninMethods {
|
||||||
|
if signinMethod.Name == "Verification code" && signinMethod.Rule != "Email only" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (application *Application) IsLdapEnabled() bool {
|
||||||
|
if len(application.SigninMethods) > 0 {
|
||||||
|
for _, signinMethod := range application.SigninMethods {
|
||||||
|
if signinMethod.Name == "LDAP" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func IsOriginAllowed(origin string) (bool, error) {
|
func IsOriginAllowed(origin string) (bool, error) {
|
||||||
applications, err := GetApplications("")
|
applications, err := GetApplications("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -532,7 +696,7 @@ func applicationChangeTrigger(oldName string, newName string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
permissions[i].Resources = permissionResoureces
|
permissions[i].Resources = permissionResoureces
|
||||||
_, err = session.Where("name=?", permissions[i].Name).Update(permissions[i])
|
_, err = session.Where("owner=?", permissions[i].Owner).Where("name=?", permissions[i].Name).Update(permissions[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ func GetGlobalCertsCount(field, value string) (int64, error) {
|
|||||||
return session.Count(&Cert{})
|
return session.Count(&Cert{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetGlobleCerts() ([]*Cert, error) {
|
func GetGlobalCerts() ([]*Cert, error) {
|
||||||
certs := []*Cert{}
|
certs := []*Cert{}
|
||||||
err := ormer.Engine.Desc("created_time").Find(&certs)
|
err := ormer.Engine.Desc("created_time").Find(&certs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -163,6 +163,12 @@ func UpdateCert(id string, cert *Cert) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := cert.populateContent()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(cert)
|
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@ -172,10 +178,9 @@ func UpdateCert(id string, cert *Cert) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AddCert(cert *Cert) (bool, error) {
|
func AddCert(cert *Cert) (bool, error) {
|
||||||
if cert.Certificate == "" || cert.PrivateKey == "" {
|
err := cert.populateContent()
|
||||||
certificate, privateKey := generateRsaKeys(cert.BitSize, cert.ExpireInYears, cert.Name, cert.Owner)
|
if err != nil {
|
||||||
cert.Certificate = certificate
|
return false, err
|
||||||
cert.PrivateKey = privateKey
|
|
||||||
}
|
}
|
||||||
|
|
||||||
affected, err := ormer.Engine.Insert(cert)
|
affected, err := ormer.Engine.Insert(cert)
|
||||||
@ -199,6 +204,20 @@ func (p *Cert) GetId() string {
|
|||||||
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
|
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Cert) populateContent() error {
|
||||||
|
if p.Certificate == "" || p.PrivateKey == "" {
|
||||||
|
certificate, privateKey, err := generateRsaKeys(p.BitSize, p.ExpireInYears, p.Name, p.Owner)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Certificate = certificate
|
||||||
|
p.PrivateKey = privateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getCertByApplication(application *Application) (*Cert, error) {
|
func getCertByApplication(application *Application) (*Cert, error) {
|
||||||
if application.Cert != "" {
|
if application.Cert != "" {
|
||||||
return getCertByName(application.Cert)
|
return getCertByName(application.Cert)
|
||||||
|
260
object/check.go
260
object/check.go
@ -16,6 +16,7 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
@ -28,93 +29,93 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SigninWrongTimesLimit = 5
|
DefaultFailedSigninLimit = 5
|
||||||
LastSignWrongTimeDuration = time.Minute * 15
|
DefaultFailedSigninFrozenTime = 15
|
||||||
)
|
)
|
||||||
|
|
||||||
func CheckUserSignup(application *Application, organization *Organization, form *form.AuthForm, lang string) string {
|
func CheckUserSignup(application *Application, organization *Organization, authForm *form.AuthForm, lang string) string {
|
||||||
if organization == nil {
|
if organization == nil {
|
||||||
return i18n.Translate(lang, "check:Organization does not exist")
|
return i18n.Translate(lang, "check:Organization does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.IsSignupItemVisible("Username") {
|
if application.IsSignupItemVisible("Username") {
|
||||||
if len(form.Username) <= 1 {
|
if len(authForm.Username) <= 1 {
|
||||||
return i18n.Translate(lang, "check:Username must have at least 2 characters")
|
return i18n.Translate(lang, "check:Username must have at least 2 characters")
|
||||||
}
|
}
|
||||||
if unicode.IsDigit(rune(form.Username[0])) {
|
if unicode.IsDigit(rune(authForm.Username[0])) {
|
||||||
return i18n.Translate(lang, "check:Username cannot start with a digit")
|
return i18n.Translate(lang, "check:Username cannot start with a digit")
|
||||||
}
|
}
|
||||||
if util.IsEmailValid(form.Username) {
|
if util.IsEmailValid(authForm.Username) {
|
||||||
return i18n.Translate(lang, "check:Username cannot be an email address")
|
return i18n.Translate(lang, "check:Username cannot be an email address")
|
||||||
}
|
}
|
||||||
if util.ReWhiteSpace.MatchString(form.Username) {
|
if util.ReWhiteSpace.MatchString(authForm.Username) {
|
||||||
return i18n.Translate(lang, "check:Username cannot contain white spaces")
|
return i18n.Translate(lang, "check:Username cannot contain white spaces")
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg := CheckUsername(form.Username, lang); msg != "" {
|
if msg := CheckUsername(authForm.Username, lang); msg != "" {
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
if HasUserByField(organization.Name, "name", form.Username) {
|
if HasUserByField(organization.Name, "name", authForm.Username) {
|
||||||
return i18n.Translate(lang, "check:Username already exists")
|
return i18n.Translate(lang, "check:Username already exists")
|
||||||
}
|
}
|
||||||
if HasUserByField(organization.Name, "email", form.Email) {
|
if HasUserByField(organization.Name, "email", authForm.Email) {
|
||||||
return i18n.Translate(lang, "check:Email already exists")
|
return i18n.Translate(lang, "check:Email already exists")
|
||||||
}
|
}
|
||||||
if HasUserByField(organization.Name, "phone", form.Phone) {
|
if HasUserByField(organization.Name, "phone", authForm.Phone) {
|
||||||
return i18n.Translate(lang, "check:Phone already exists")
|
return i18n.Translate(lang, "check:Phone already exists")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.IsSignupItemVisible("Password") {
|
if application.IsSignupItemVisible("Password") {
|
||||||
msg := CheckPasswordComplexityByOrg(organization, form.Password)
|
msg := CheckPasswordComplexityByOrg(organization, authForm.Password)
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.IsSignupItemVisible("Email") {
|
if application.IsSignupItemVisible("Email") {
|
||||||
if form.Email == "" {
|
if authForm.Email == "" {
|
||||||
if application.IsSignupItemRequired("Email") {
|
if application.IsSignupItemRequired("Email") {
|
||||||
return i18n.Translate(lang, "check:Email cannot be empty")
|
return i18n.Translate(lang, "check:Email cannot be empty")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if HasUserByField(organization.Name, "email", form.Email) {
|
if HasUserByField(organization.Name, "email", authForm.Email) {
|
||||||
return i18n.Translate(lang, "check:Email already exists")
|
return i18n.Translate(lang, "check:Email already exists")
|
||||||
} else if !util.IsEmailValid(form.Email) {
|
} else if !util.IsEmailValid(authForm.Email) {
|
||||||
return i18n.Translate(lang, "check:Email is invalid")
|
return i18n.Translate(lang, "check:Email is invalid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.IsSignupItemVisible("Phone") {
|
if application.IsSignupItemVisible("Phone") {
|
||||||
if form.Phone == "" {
|
if authForm.Phone == "" {
|
||||||
if application.IsSignupItemRequired("Phone") {
|
if application.IsSignupItemRequired("Phone") {
|
||||||
return i18n.Translate(lang, "check:Phone cannot be empty")
|
return i18n.Translate(lang, "check:Phone cannot be empty")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if HasUserByField(organization.Name, "phone", form.Phone) {
|
if HasUserByField(organization.Name, "phone", authForm.Phone) {
|
||||||
return i18n.Translate(lang, "check:Phone already exists")
|
return i18n.Translate(lang, "check:Phone already exists")
|
||||||
} else if !util.IsPhoneAllowInRegin(form.CountryCode, organization.CountryCodes) {
|
} else if !util.IsPhoneAllowInRegin(authForm.CountryCode, organization.CountryCodes) {
|
||||||
return i18n.Translate(lang, "check:Your region is not allow to signup by phone")
|
return i18n.Translate(lang, "check:Your region is not allow to signup by phone")
|
||||||
} else if !util.IsPhoneValid(form.Phone, form.CountryCode) {
|
} else if !util.IsPhoneValid(authForm.Phone, authForm.CountryCode) {
|
||||||
return i18n.Translate(lang, "check:Phone number is invalid")
|
return i18n.Translate(lang, "check:Phone number is invalid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.IsSignupItemVisible("Display name") {
|
if application.IsSignupItemVisible("Display name") {
|
||||||
if application.GetSignupItemRule("Display name") == "First, last" && (form.FirstName != "" || form.LastName != "") {
|
if application.GetSignupItemRule("Display name") == "First, last" && (authForm.FirstName != "" || authForm.LastName != "") {
|
||||||
if form.FirstName == "" {
|
if authForm.FirstName == "" {
|
||||||
return i18n.Translate(lang, "check:FirstName cannot be blank")
|
return i18n.Translate(lang, "check:FirstName cannot be blank")
|
||||||
} else if form.LastName == "" {
|
} else if authForm.LastName == "" {
|
||||||
return i18n.Translate(lang, "check:LastName cannot be blank")
|
return i18n.Translate(lang, "check:LastName cannot be blank")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if form.Name == "" {
|
if authForm.Name == "" {
|
||||||
return i18n.Translate(lang, "check:DisplayName cannot be blank")
|
return i18n.Translate(lang, "check:DisplayName cannot be blank")
|
||||||
} else if application.GetSignupItemRule("Display name") == "Real name" {
|
} else if application.GetSignupItemRule("Display name") == "Real name" {
|
||||||
if !isValidRealName(form.Name) {
|
if !isValidRealName(authForm.Name) {
|
||||||
return i18n.Translate(lang, "check:DisplayName is not valid real name")
|
return i18n.Translate(lang, "check:DisplayName is not valid real name")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,65 +123,113 @@ func CheckUserSignup(application *Application, organization *Organization, form
|
|||||||
}
|
}
|
||||||
|
|
||||||
if application.IsSignupItemVisible("Affiliation") {
|
if application.IsSignupItemVisible("Affiliation") {
|
||||||
if form.Affiliation == "" {
|
if authForm.Affiliation == "" {
|
||||||
return i18n.Translate(lang, "check:Affiliation cannot be blank")
|
return i18n.Translate(lang, "check:Affiliation cannot be blank")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(application.InvitationCodes) > 0 {
|
for _, signupItem := range application.SignupItems {
|
||||||
if form.InvitationCode == "" {
|
if signupItem.Regex == "" {
|
||||||
if application.IsSignupItemRequired("Invitation code") {
|
continue
|
||||||
return i18n.Translate(lang, "check:Invitation code cannot be blank")
|
}
|
||||||
}
|
|
||||||
} else {
|
isString, value := form.GetAuthFormFieldValue(authForm, signupItem.Name)
|
||||||
if !util.InSlice(application.InvitationCodes, form.InvitationCode) {
|
if !isString {
|
||||||
return i18n.Translate(lang, "check:Invitation code is invalid")
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regexSignupItem, err := regexp.Compile(signupItem.Regex)
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
matched := regexSignupItem.MatchString(value)
|
||||||
|
if !matched {
|
||||||
|
return fmt.Sprintf(i18n.Translate(lang, "check:The value \"%s\" for signup field \"%s\" doesn't match the signup item regex of the application \"%s\""), value, signupItem.Name, application.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkSigninErrorTimes(user *User, lang string) string {
|
func CheckInvitationCode(application *Application, organization *Organization, authForm *form.AuthForm, lang string) (*Invitation, string) {
|
||||||
if user.SigninWrongTimes >= SigninWrongTimesLimit {
|
if authForm.InvitationCode == "" {
|
||||||
|
if application.IsSignupItemRequired("Invitation code") {
|
||||||
|
return nil, i18n.Translate(lang, "check:Invitation code cannot be blank")
|
||||||
|
} else {
|
||||||
|
return nil, ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
invitations, err := GetInvitations(organization.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err.Error()
|
||||||
|
}
|
||||||
|
errMsg := ""
|
||||||
|
for _, invitation := range invitations {
|
||||||
|
if invitation.Application != application.Name && invitation.Application != "All" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if isValid, msg := invitation.IsInvitationCodeValid(application, authForm.InvitationCode, authForm.Username, authForm.Email, authForm.Phone, lang); isValid {
|
||||||
|
return invitation, msg
|
||||||
|
} else if msg != "" && errMsg == "" {
|
||||||
|
errMsg = msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if errMsg != "" {
|
||||||
|
return nil, errMsg
|
||||||
|
} else {
|
||||||
|
return nil, i18n.Translate(lang, "check:Invitation code is invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkSigninErrorTimes(user *User, lang string) error {
|
||||||
|
failedSigninLimit, failedSigninFrozenTime, err := GetFailedSigninConfigByUser(user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.SigninWrongTimes >= failedSigninLimit {
|
||||||
lastSignWrongTime, _ := time.Parse(time.RFC3339, user.LastSigninWrongTime)
|
lastSignWrongTime, _ := time.Parse(time.RFC3339, user.LastSigninWrongTime)
|
||||||
passedTime := time.Now().UTC().Sub(lastSignWrongTime)
|
passedTime := time.Now().UTC().Sub(lastSignWrongTime)
|
||||||
minutes := int(LastSignWrongTimeDuration.Minutes() - passedTime.Minutes())
|
minutes := failedSigninFrozenTime - int(passedTime.Minutes())
|
||||||
|
|
||||||
// deny the login if the error times is greater than the limit and the last login time is less than the duration
|
// deny the login if the error times is greater than the limit and the last login time is less than the duration
|
||||||
if minutes > 0 {
|
if minutes > 0 {
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "check:You have entered the wrong password or code too many times, please wait for %d minutes and try again"), minutes)
|
return fmt.Errorf(i18n.Translate(lang, "check:You have entered the wrong password or code too many times, please wait for %d minutes and try again"), minutes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the error times
|
// reset the error times
|
||||||
user.SigninWrongTimes = 0
|
user.SigninWrongTimes = 0
|
||||||
|
|
||||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times"}, false)
|
_, err := UpdateUser(user.GetId(), user, []string{"signin_wrong_times"}, false)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckPassword(user *User, password string, lang string, options ...bool) string {
|
func CheckPassword(user *User, password string, lang string, options ...bool) error {
|
||||||
enableCaptcha := false
|
enableCaptcha := false
|
||||||
if len(options) > 0 {
|
if len(options) > 0 {
|
||||||
enableCaptcha = options[0]
|
enableCaptcha = options[0]
|
||||||
}
|
}
|
||||||
// check the login error times
|
// check the login error times
|
||||||
if !enableCaptcha {
|
if !enableCaptcha {
|
||||||
if msg := checkSigninErrorTimes(user, lang); msg != "" {
|
err := checkSigninErrorTimes(user, lang)
|
||||||
return msg
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
organization, err := GetOrganizationByUser(user)
|
organization, err := GetOrganizationByUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if organization == nil {
|
if organization == nil {
|
||||||
return i18n.Translate(lang, "check:Organization does not exist")
|
return fmt.Errorf(i18n.Translate(lang, "check:Organization does not exist"))
|
||||||
}
|
}
|
||||||
|
|
||||||
passwordType := user.PasswordType
|
passwordType := user.PasswordType
|
||||||
@ -191,19 +240,17 @@ func CheckPassword(user *User, password string, lang string, options ...bool) st
|
|||||||
if credManager != nil {
|
if credManager != nil {
|
||||||
if organization.MasterPassword != "" {
|
if organization.MasterPassword != "" {
|
||||||
if credManager.IsPasswordCorrect(password, organization.MasterPassword, "", organization.PasswordSalt) {
|
if credManager.IsPasswordCorrect(password, organization.MasterPassword, "", organization.PasswordSalt) {
|
||||||
resetUserSigninErrorTimes(user)
|
return resetUserSigninErrorTimes(user)
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if credManager.IsPasswordCorrect(password, user.Password, user.PasswordSalt, organization.PasswordSalt) {
|
if credManager.IsPasswordCorrect(password, user.Password, user.PasswordSalt, organization.PasswordSalt) {
|
||||||
resetUserSigninErrorTimes(user)
|
return resetUserSigninErrorTimes(user)
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return recordSigninErrorInfo(user, lang, enableCaptcha)
|
return recordSigninErrorInfo(user, lang, enableCaptcha)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "check:unsupported password type: %s"), organization.PasswordType)
|
return fmt.Errorf(i18n.Translate(lang, "check:unsupported password type: %s"), organization.PasswordType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,10 +264,10 @@ func CheckPasswordComplexity(user *User, password string) string {
|
|||||||
return CheckPasswordComplexityByOrg(organization, password)
|
return CheckPasswordComplexityByOrg(organization, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkLdapUserPassword(user *User, password string, lang string) string {
|
func checkLdapUserPassword(user *User, password string, lang string) error {
|
||||||
ldaps, err := GetLdaps(user.Owner)
|
ldaps, err := GetLdaps(user.Owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err.Error()
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ldapLoginSuccess := false
|
ldapLoginSuccess := false
|
||||||
@ -237,65 +284,96 @@ func checkLdapUserPassword(user *User, password string, lang string) string {
|
|||||||
|
|
||||||
searchResult, err := conn.Conn.Search(searchReq)
|
searchResult, err := conn.Conn.Search(searchReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err.Error()
|
conn.Close()
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(searchResult.Entries) == 0 {
|
if len(searchResult.Entries) == 0 {
|
||||||
|
conn.Close()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(searchResult.Entries) > 1 {
|
if len(searchResult.Entries) > 1 {
|
||||||
return i18n.Translate(lang, "check:Multiple accounts with same uid, please check your ldap server")
|
conn.Close()
|
||||||
|
return fmt.Errorf(i18n.Translate(lang, "check:Multiple accounts with same uid, please check your ldap server"))
|
||||||
}
|
}
|
||||||
|
|
||||||
hit = true
|
hit = true
|
||||||
dn := searchResult.Entries[0].DN
|
dn := searchResult.Entries[0].DN
|
||||||
if err := conn.Conn.Bind(dn, password); err == nil {
|
if err = conn.Conn.Bind(dn, password); err == nil {
|
||||||
ldapLoginSuccess = true
|
ldapLoginSuccess = true
|
||||||
|
conn.Close()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ldapLoginSuccess {
|
if !ldapLoginSuccess {
|
||||||
if !hit {
|
if !hit {
|
||||||
return "user not exist"
|
return fmt.Errorf("user not exist")
|
||||||
}
|
}
|
||||||
return i18n.Translate(lang, "check:LDAP user name or password incorrect")
|
return fmt.Errorf(i18n.Translate(lang, "check:LDAP user name or password incorrect"))
|
||||||
}
|
}
|
||||||
return ""
|
return resetUserSigninErrorTimes(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckUserPassword(organization string, username string, password string, lang string, options ...bool) (*User, string) {
|
func CheckUserPassword(organization string, username string, password string, lang string, options ...bool) (*User, error) {
|
||||||
enableCaptcha := false
|
enableCaptcha := false
|
||||||
|
isSigninViaLdap := false
|
||||||
|
isPasswordWithLdapEnabled := false
|
||||||
if len(options) > 0 {
|
if len(options) > 0 {
|
||||||
enableCaptcha = options[0]
|
enableCaptcha = options[0]
|
||||||
|
isSigninViaLdap = options[1]
|
||||||
|
isPasswordWithLdapEnabled = options[2]
|
||||||
}
|
}
|
||||||
user, err := GetUserByFields(organization, username)
|
user, err := GetUserByFields(organization, username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if user == nil || user.IsDeleted {
|
if user == nil || user.IsDeleted {
|
||||||
return nil, fmt.Sprintf(i18n.Translate(lang, "general:The user: %s doesn't exist"), util.GetId(organization, username))
|
return nil, fmt.Errorf(i18n.Translate(lang, "general:The user: %s doesn't exist"), util.GetId(organization, username))
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.IsForbidden {
|
if user.IsForbidden {
|
||||||
return nil, i18n.Translate(lang, "check:The user is forbidden to sign in, please contact the administrator")
|
return nil, fmt.Errorf(i18n.Translate(lang, "check:The user is forbidden to sign in, please contact the administrator"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if isSigninViaLdap {
|
||||||
|
if user.Ldap == "" {
|
||||||
|
return nil, fmt.Errorf(i18n.Translate(lang, "check:The user: %s doesn't exist in LDAP server"), username)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Ldap != "" {
|
if user.Ldap != "" {
|
||||||
// ONLY for ldap users
|
if !isSigninViaLdap && !isPasswordWithLdapEnabled {
|
||||||
if msg := checkLdapUserPassword(user, password, lang); msg != "" {
|
return nil, fmt.Errorf(i18n.Translate(lang, "check:password or code is incorrect"))
|
||||||
if msg == "user not exist" {
|
}
|
||||||
return nil, fmt.Sprintf(i18n.Translate(lang, "check:The user: %s doesn't exist in LDAP server"), username)
|
|
||||||
|
// check the login error times
|
||||||
|
if !enableCaptcha {
|
||||||
|
err = checkSigninErrorTimes(user, lang)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return nil, msg
|
}
|
||||||
|
|
||||||
|
// only for LDAP users
|
||||||
|
err = checkLdapUserPassword(user, password, lang)
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "user not exist" {
|
||||||
|
return nil, fmt.Errorf(i18n.Translate(lang, "check:The user: %s doesn't exist in LDAP server"), username)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, recordSigninErrorInfo(user, lang, enableCaptcha)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if msg := CheckPassword(user, password, lang, enableCaptcha); msg != "" {
|
err = CheckPassword(user, password, lang, enableCaptcha)
|
||||||
return nil, msg
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return user, ""
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckUserPermission(requestUserId, userId string, strict bool, lang string) (bool, error) {
|
func CheckUserPermission(requestUserId, userId string, strict bool, lang string) (bool, error) {
|
||||||
@ -308,7 +386,7 @@ func CheckUserPermission(requestUserId, userId string, strict bool, lang string)
|
|||||||
if userId != "" {
|
if userId != "" {
|
||||||
targetUser, err := GetUser(userId)
|
targetUser, err := GetUser(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if targetUser == nil {
|
if targetUser == nil {
|
||||||
@ -351,8 +429,8 @@ func CheckUserPermission(requestUserId, userId string, strict bool, lang string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CheckLoginPermission(userId string, application *Application) (bool, error) {
|
func CheckLoginPermission(userId string, application *Application) (bool, error) {
|
||||||
var err error
|
owner, _ := util.GetOwnerAndNameFromId(userId)
|
||||||
if userId == "built-in/admin" {
|
if owner == "built-in" {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,18 +439,28 @@ func CheckLoginPermission(userId string, application *Application) (bool, error)
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allowPermissionCount := 0
|
||||||
|
denyPermissionCount := 0
|
||||||
allowCount := 0
|
allowCount := 0
|
||||||
denyCount := 0
|
denyCount := 0
|
||||||
for _, permission := range permissions {
|
for _, permission := range permissions {
|
||||||
if !permission.IsEnabled || permission.ResourceType != "Application" || !permission.isResourceHit(application.Name) {
|
if !permission.IsEnabled || permission.State != "Approved" || permission.ResourceType != "Application" || !permission.isResourceHit(application.Name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if permission.isUserHit(userId) {
|
if !permission.isUserHit(userId) && !permission.isRoleHit(userId) {
|
||||||
allowCount += 1
|
if permission.Effect == "Allow" {
|
||||||
|
allowPermissionCount += 1
|
||||||
|
} else {
|
||||||
|
denyPermissionCount += 1
|
||||||
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
enforcer := getPermissionEnforcer(permission)
|
enforcer, err := getPermissionEnforcer(permission)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
var isAllowed bool
|
var isAllowed bool
|
||||||
isAllowed, err = enforcer.Enforce(userId, application.Name, "Read")
|
isAllowed, err = enforcer.Enforce(userId, application.Name, "Read")
|
||||||
@ -391,8 +479,18 @@ func CheckLoginPermission(userId string, application *Application) (bool, error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deny-override, if one deny is found, then deny
|
||||||
if denyCount > 0 {
|
if denyCount > 0 {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
} else if allowCount > 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// For no-allow and no-deny condition
|
||||||
|
// If only allow permissions exist, we suppose it's Deny-by-default, aka no-allow means deny
|
||||||
|
// Otherwise, it's Allow-by-default, aka no-deny means allow
|
||||||
|
if allowPermissionCount > 0 && denyPermissionCount == 0 {
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
@ -451,7 +549,13 @@ func CheckToEnableCaptcha(application *Application, organization, username strin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
return user != nil && user.SigninWrongTimes >= SigninWrongTimesLimit, nil
|
|
||||||
|
failedSigninLimit := application.FailedSigninLimit
|
||||||
|
if failedSigninLimit == 0 {
|
||||||
|
failedSigninLimit = DefaultFailedSigninLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
return user != nil && user.SigninWrongTimes >= failedSigninLimit, nil
|
||||||
}
|
}
|
||||||
return providerItem.Rule == "Always", nil
|
return providerItem.Rule == "Always", nil
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ var (
|
|||||||
regexLowerCase = regexp.MustCompile(`[a-z]`)
|
regexLowerCase = regexp.MustCompile(`[a-z]`)
|
||||||
regexUpperCase = regexp.MustCompile(`[A-Z]`)
|
regexUpperCase = regexp.MustCompile(`[A-Z]`)
|
||||||
regexDigit = regexp.MustCompile(`\d`)
|
regexDigit = regexp.MustCompile(`\d`)
|
||||||
regexSpecial = regexp.MustCompile(`[!@#$%^&*]`)
|
regexSpecial = regexp.MustCompile("[!-/:-@[-`{-~]")
|
||||||
)
|
)
|
||||||
|
|
||||||
func isValidOption_AtLeast6(password string) string {
|
func isValidOption_AtLeast6(password string) string {
|
||||||
|
@ -36,38 +36,70 @@ func isValidRealName(s string) bool {
|
|||||||
return reRealName.MatchString(s)
|
return reRealName.MatchString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func resetUserSigninErrorTimes(user *User) {
|
func resetUserSigninErrorTimes(user *User) error {
|
||||||
// if the password is correct and wrong times is not zero, reset the error times
|
// if the password is correct and wrong times is not zero, reset the error times
|
||||||
if user.SigninWrongTimes == 0 {
|
if user.SigninWrongTimes == 0 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
user.SigninWrongTimes = 0
|
user.SigninWrongTimes = 0
|
||||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, false)
|
_, err := UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, false)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func recordSigninErrorInfo(user *User, lang string, options ...bool) string {
|
func GetFailedSigninConfigByUser(user *User) (int, int, error) {
|
||||||
|
application, err := GetApplicationByUser(user)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
failedSigninLimit := application.FailedSigninLimit
|
||||||
|
if failedSigninLimit == 0 {
|
||||||
|
failedSigninLimit = DefaultFailedSigninLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
failedSigninFrozenTime := application.FailedSigninFrozenTime
|
||||||
|
if failedSigninFrozenTime == 0 {
|
||||||
|
failedSigninFrozenTime = DefaultFailedSigninFrozenTime
|
||||||
|
}
|
||||||
|
|
||||||
|
return failedSigninLimit, failedSigninFrozenTime, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func recordSigninErrorInfo(user *User, lang string, options ...bool) error {
|
||||||
enableCaptcha := false
|
enableCaptcha := false
|
||||||
if len(options) > 0 {
|
if len(options) > 0 {
|
||||||
enableCaptcha = options[0]
|
enableCaptcha = options[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
failedSigninLimit, failedSigninFrozenTime, errSignin := GetFailedSigninConfigByUser(user)
|
||||||
|
if errSignin != nil {
|
||||||
|
return errSignin
|
||||||
|
}
|
||||||
|
|
||||||
// increase failed login count
|
// increase failed login count
|
||||||
if user.SigninWrongTimes < SigninWrongTimesLimit {
|
if user.SigninWrongTimes < failedSigninLimit {
|
||||||
user.SigninWrongTimes++
|
user.SigninWrongTimes++
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.SigninWrongTimes >= SigninWrongTimesLimit {
|
if user.SigninWrongTimes >= failedSigninLimit {
|
||||||
// record the latest failed login time
|
// record the latest failed login time
|
||||||
user.LastSigninWrongTime = time.Now().UTC().Format(time.RFC3339)
|
user.LastSigninWrongTime = time.Now().UTC().Format(time.RFC3339)
|
||||||
}
|
}
|
||||||
|
|
||||||
// update user
|
// update user
|
||||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, false)
|
_, err := UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, false)
|
||||||
leftChances := SigninWrongTimesLimit - user.SigninWrongTimes
|
if err != nil {
|
||||||
if leftChances == 0 && enableCaptcha {
|
return err
|
||||||
return fmt.Sprint(i18n.Translate(lang, "check:password or code is incorrect"))
|
|
||||||
} else if leftChances >= 0 {
|
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "check:password or code is incorrect, you have %d remaining chances"), leftChances)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leftChances := failedSigninLimit - user.SigninWrongTimes
|
||||||
|
if leftChances == 0 && enableCaptcha {
|
||||||
|
return fmt.Errorf(i18n.Translate(lang, "check:password or code is incorrect"))
|
||||||
|
} else if leftChances >= 0 {
|
||||||
|
return fmt.Errorf(i18n.Translate(lang, "check:password or code is incorrect, you have %d remaining chances"), leftChances)
|
||||||
|
}
|
||||||
|
|
||||||
// don't show the chance error message if the user has no chance left
|
// don't show the chance error message if the user has no chance left
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "check:You have entered the wrong password or code too many times, please wait for %d minutes and try again"), int(LastSignWrongTimeDuration.Minutes()))
|
return fmt.Errorf(i18n.Translate(lang, "check:You have entered the wrong password or code too many times, please wait for %d minutes and try again"), failedSigninFrozenTime)
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ func getDialer(provider *Provider) *gomail.Dialer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SendEmail(provider *Provider, title string, content string, dest string, sender string) error {
|
func SendEmail(provider *Provider, title string, content string, dest string, sender string) error {
|
||||||
emailProvider := email.GetEmailProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, provider.Port, provider.DisableSsl)
|
emailProvider := email.GetEmailProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, provider.Port, provider.DisableSsl, provider.Endpoint, provider.Method)
|
||||||
|
|
||||||
fromAddress := provider.ClientId2
|
fromAddress := provider.ClientId2
|
||||||
if fromAddress == "" {
|
if fromAddress == "" {
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/casbin/casbin/v2"
|
"github.com/casbin/casbin/v2"
|
||||||
"github.com/casbin/casbin/v2/config"
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||||
"github.com/xorm-io/core"
|
"github.com/xorm-io/core"
|
||||||
@ -126,6 +125,10 @@ func (enforcer *Enforcer) GetId() string {
|
|||||||
return fmt.Sprintf("%s/%s", enforcer.Owner, enforcer.Name)
|
return fmt.Sprintf("%s/%s", enforcer.Owner, enforcer.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (enforcer *Enforcer) GetModelAndAdapter() string {
|
||||||
|
return util.GetId(enforcer.Model, enforcer.Adapter)
|
||||||
|
}
|
||||||
|
|
||||||
func (enforcer *Enforcer) InitEnforcer() error {
|
func (enforcer *Enforcer) InitEnforcer() error {
|
||||||
if enforcer.Enforcer != nil {
|
if enforcer.Enforcer != nil {
|
||||||
return nil
|
return nil
|
||||||
@ -191,39 +194,55 @@ func GetPolicies(id string) ([]*xormadapter.CasbinRule, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
policies := util.MatrixToCasbinRules("p", enforcer.GetPolicy())
|
pRules := enforcer.GetPolicy()
|
||||||
|
res := util.MatrixToCasbinRules("p", pRules)
|
||||||
|
|
||||||
if enforcer.GetModel()["g"] != nil {
|
if enforcer.GetModel()["g"] != nil {
|
||||||
policies = append(policies, util.MatrixToCasbinRules("g", enforcer.GetGroupingPolicy())...)
|
gRules := enforcer.GetGroupingPolicy()
|
||||||
|
res2 := util.MatrixToCasbinRules("g", gRules)
|
||||||
|
res = append(res, res2...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return policies, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdatePolicy(id string, oldPolicy, newPolicy []string) (bool, error) {
|
func UpdatePolicy(id string, ptype string, oldPolicy []string, newPolicy []string) (bool, error) {
|
||||||
enforcer, err := GetInitializedEnforcer(id)
|
enforcer, err := GetInitializedEnforcer(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return enforcer.UpdatePolicy(oldPolicy, newPolicy)
|
if ptype == "p" {
|
||||||
|
return enforcer.UpdatePolicy(oldPolicy, newPolicy)
|
||||||
|
} else {
|
||||||
|
return enforcer.UpdateGroupingPolicy(oldPolicy, newPolicy)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddPolicy(id string, policy []string) (bool, error) {
|
func AddPolicy(id string, ptype string, policy []string) (bool, error) {
|
||||||
enforcer, err := GetInitializedEnforcer(id)
|
enforcer, err := GetInitializedEnforcer(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return enforcer.AddPolicy(policy)
|
if ptype == "p" {
|
||||||
|
return enforcer.AddPolicy(policy)
|
||||||
|
} else {
|
||||||
|
return enforcer.AddGroupingPolicy(policy)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemovePolicy(id string, policy []string) (bool, error) {
|
func RemovePolicy(id string, ptype string, policy []string) (bool, error) {
|
||||||
enforcer, err := GetInitializedEnforcer(id)
|
enforcer, err := GetInitializedEnforcer(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return enforcer.RemovePolicy(policy)
|
if ptype == "p" {
|
||||||
|
return enforcer.RemovePolicy(policy)
|
||||||
|
} else {
|
||||||
|
return enforcer.RemoveGroupingPolicy(policy)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (enforcer *Enforcer) LoadModelCfg() error {
|
func (enforcer *Enforcer) LoadModelCfg() error {
|
||||||
@ -231,23 +250,17 @@ func (enforcer *Enforcer) LoadModelCfg() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
model, err := GetModel(enforcer.Model)
|
model, err := GetModelEx(enforcer.Model)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if model == nil {
|
} else if model == nil {
|
||||||
return fmt.Errorf("the model: %s for enforcer: %s is not found", enforcer.Model, enforcer.GetId())
|
return fmt.Errorf("the model: %s for enforcer: %s is not found", enforcer.Model, enforcer.GetId())
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := config.NewConfigFromText(model.ModelText)
|
enforcer.ModelCfg, err = getModelCfg(model)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
enforcer.ModelCfg = make(map[string]string)
|
|
||||||
enforcer.ModelCfg["p"] = cfg.String("policy_definition::p")
|
|
||||||
if cfg.String("role_definition::g") != "" {
|
|
||||||
enforcer.ModelCfg["g"] = cfg.String("role_definition::g")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"github.com/xorm-io/builder"
|
"github.com/xorm-io/builder"
|
||||||
"github.com/xorm-io/core"
|
"github.com/xorm-io/core"
|
||||||
@ -224,7 +225,8 @@ func GetGroupUserCount(groupId string, field, value string) (int64, error) {
|
|||||||
if field == "" && value == "" {
|
if field == "" && value == "" {
|
||||||
return int64(len(names)), nil
|
return int64(len(names)), nil
|
||||||
} else {
|
} else {
|
||||||
return ormer.Engine.Table("user").
|
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||||
|
return ormer.Engine.Table(tableNamePrefix+"user").
|
||||||
Where("owner = ?", owner).In("name", names).
|
Where("owner = ?", owner).In("name", names).
|
||||||
And(fmt.Sprintf("user.%s like ?", util.CamelToSnakeCase(field)), "%"+value+"%").
|
And(fmt.Sprintf("user.%s like ?", util.CamelToSnakeCase(field)), "%"+value+"%").
|
||||||
Count()
|
Count()
|
||||||
@ -239,7 +241,9 @@ func GetPaginationGroupUsers(groupId string, offset, limit int, field, value, so
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
session := ormer.Engine.Table("user").
|
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||||
|
prefixedUserTable := tableNamePrefix + "user"
|
||||||
|
session := ormer.Engine.Table(prefixedUserTable).
|
||||||
Where("owner = ?", owner).In("name", names)
|
Where("owner = ?", owner).In("name", names)
|
||||||
|
|
||||||
if offset != -1 && limit != -1 {
|
if offset != -1 && limit != -1 {
|
||||||
@ -247,16 +251,19 @@ func GetPaginationGroupUsers(groupId string, offset, limit int, field, value, so
|
|||||||
}
|
}
|
||||||
|
|
||||||
if field != "" && value != "" {
|
if field != "" && value != "" {
|
||||||
session = session.And(fmt.Sprintf("user.%s like ?", util.CamelToSnakeCase(field)), "%"+value+"%")
|
session = session.And(fmt.Sprintf("%s.%s like ?", prefixedUserTable, util.CamelToSnakeCase(field)), "%"+value+"%")
|
||||||
}
|
}
|
||||||
|
|
||||||
if sortField == "" || sortOrder == "" {
|
if sortField == "" || sortOrder == "" {
|
||||||
sortField = "created_time"
|
sortField = "created_time"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
orderQuery := fmt.Sprintf("%s.%s", prefixedUserTable, util.SnakeString(sortField))
|
||||||
|
|
||||||
if sortOrder == "ascend" {
|
if sortOrder == "ascend" {
|
||||||
session = session.Asc(fmt.Sprintf("user.%s", util.SnakeString(sortField)))
|
session = session.Asc(orderQuery)
|
||||||
} else {
|
} else {
|
||||||
session = session.Desc(fmt.Sprintf("user.%s", util.SnakeString(sortField)))
|
session = session.Desc(orderQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = session.Find(&users)
|
err = session.Find(&users)
|
||||||
@ -271,7 +278,9 @@ func GetGroupUsers(groupId string) ([]*User, error) {
|
|||||||
users := []*User{}
|
users := []*User{}
|
||||||
owner, _ := util.GetOwnerAndNameFromId(groupId)
|
owner, _ := util.GetOwnerAndNameFromId(groupId)
|
||||||
names, err := userEnforcer.GetUserNamesByGroupName(groupId)
|
names, err := userEnforcer.GetUserNamesByGroupName(groupId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
err = ormer.Engine.Where("owner = ?", owner).In("name", names).Find(&users)
|
err = ormer.Engine.Where("owner = ?", owner).In("name", names).Find(&users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -303,6 +312,9 @@ func GroupChangeTrigger(oldName, newName string) error {
|
|||||||
|
|
||||||
groups := []*Group{}
|
groups := []*Group{}
|
||||||
err = session.Where("parent_id = ?", oldName).Find(&groups)
|
err = session.Where("parent_id = ?", oldName).Find(&groups)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
for _, group := range groups {
|
for _, group := range groups {
|
||||||
group.ParentId = newName
|
group.ParentId = newName
|
||||||
_, err := session.ID(core.PK{group.Owner, group.Name}).Cols("parent_id").Update(group)
|
_, err := session.ID(core.PK{group.Owner, group.Name}).Cols("parent_id").Update(group)
|
||||||
|
@ -178,7 +178,12 @@ func initBuiltInApplication() {
|
|||||||
EnablePassword: true,
|
EnablePassword: true,
|
||||||
EnableSignUp: true,
|
EnableSignUp: true,
|
||||||
Providers: []*ProviderItem{
|
Providers: []*ProviderItem{
|
||||||
{Name: "provider_captcha_default", CanSignUp: false, CanSignIn: false, CanUnlink: false, Prompted: false, AlertType: "None", Rule: "None", Provider: nil},
|
{Name: "provider_captcha_default", CanSignUp: false, CanSignIn: false, CanUnlink: false, Prompted: false, SignupGroup: "", Rule: "None", Provider: nil},
|
||||||
|
},
|
||||||
|
SigninMethods: []*SigninMethod{
|
||||||
|
{Name: "Password", DisplayName: "Password", Rule: "All"},
|
||||||
|
{Name: "Verification code", DisplayName: "Verification code", Rule: "All"},
|
||||||
|
{Name: "WebAuthn", DisplayName: "WebAuthn", Rule: "None"},
|
||||||
},
|
},
|
||||||
SignupItems: []*SignupItem{
|
SignupItems: []*SignupItem{
|
||||||
{Name: "ID", Visible: false, Required: true, Prompted: false, Rule: "Random"},
|
{Name: "ID", Visible: false, Required: true, Prompted: false, Rule: "Random"},
|
||||||
@ -192,6 +197,7 @@ func initBuiltInApplication() {
|
|||||||
},
|
},
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
RedirectUris: []string{},
|
RedirectUris: []string{},
|
||||||
|
TokenFields: []string{},
|
||||||
ExpireInHours: 168,
|
ExpireInHours: 168,
|
||||||
FormOffset: 2,
|
FormOffset: 2,
|
||||||
}
|
}
|
||||||
@ -396,15 +402,22 @@ func initBuiltInPermission() {
|
|||||||
Name: "permission-built-in",
|
Name: "permission-built-in",
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
DisplayName: "Built-in Permission",
|
DisplayName: "Built-in Permission",
|
||||||
|
Description: "Built-in Permission",
|
||||||
Users: []string{"built-in/*"},
|
Users: []string{"built-in/*"},
|
||||||
|
Groups: []string{},
|
||||||
Roles: []string{},
|
Roles: []string{},
|
||||||
Domains: []string{},
|
Domains: []string{},
|
||||||
Model: "model-built-in",
|
Model: "model-built-in",
|
||||||
|
Adapter: "",
|
||||||
ResourceType: "Application",
|
ResourceType: "Application",
|
||||||
Resources: []string{"app-built-in"},
|
Resources: []string{"app-built-in"},
|
||||||
Actions: []string{"Read", "Write", "Admin"},
|
Actions: []string{"Read", "Write", "Admin"},
|
||||||
Effect: "Allow",
|
Effect: "Allow",
|
||||||
IsEnabled: true,
|
IsEnabled: true,
|
||||||
|
Submitter: "admin",
|
||||||
|
Approver: "admin",
|
||||||
|
ApproveTime: util.GetCurrentTime(),
|
||||||
|
State: "Approved",
|
||||||
}
|
}
|
||||||
_, err = AddPermission(permission)
|
_, err = AddPermission(permission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -423,14 +436,11 @@ func initBuiltInUserAdapter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
adapter = &Adapter{
|
adapter = &Adapter{
|
||||||
Owner: "built-in",
|
Owner: "built-in",
|
||||||
Name: "user-adapter-built-in",
|
Name: "user-adapter-built-in",
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
Type: "Database",
|
Table: "casbin_user_rule",
|
||||||
DatabaseType: conf.GetConfigString("driverName"),
|
UseSameDb: true,
|
||||||
TableNamePrefix: conf.GetConfigString("tableNamePrefix"),
|
|
||||||
Database: conf.GetConfigString("dbName"),
|
|
||||||
Table: "casbin_user_rule",
|
|
||||||
}
|
}
|
||||||
_, err = AddAdapter(adapter)
|
_, err = AddAdapter(adapter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -449,14 +459,11 @@ func initBuiltInApiAdapter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
adapter = &Adapter{
|
adapter = &Adapter{
|
||||||
Owner: "built-in",
|
Owner: "built-in",
|
||||||
Name: "api-adapter-built-in",
|
Name: "api-adapter-built-in",
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
Type: "Database",
|
Table: "casbin_api_rule",
|
||||||
DatabaseType: conf.GetConfigString("driverName"),
|
UseSameDb: true,
|
||||||
TableNamePrefix: conf.GetConfigString("tableNamePrefix"),
|
|
||||||
Database: conf.GetConfigString("dbName"),
|
|
||||||
Table: "casbin_api_rule",
|
|
||||||
}
|
}
|
||||||
_, err = AddAdapter(adapter)
|
_, err = AddAdapter(adapter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -136,17 +136,23 @@ func readInitDataFromFile(filePath string) (*InitData, error) {
|
|||||||
if application.Providers == nil {
|
if application.Providers == nil {
|
||||||
application.Providers = []*ProviderItem{}
|
application.Providers = []*ProviderItem{}
|
||||||
}
|
}
|
||||||
|
if application.SigninMethods == nil {
|
||||||
|
application.SigninMethods = []*SigninMethod{}
|
||||||
|
}
|
||||||
if application.SignupItems == nil {
|
if application.SignupItems == nil {
|
||||||
application.SignupItems = []*SignupItem{}
|
application.SignupItems = []*SignupItem{}
|
||||||
}
|
}
|
||||||
if application.GrantTypes == nil {
|
if application.GrantTypes == nil {
|
||||||
application.GrantTypes = []string{}
|
application.GrantTypes = []string{}
|
||||||
}
|
}
|
||||||
|
if application.Tags == nil {
|
||||||
|
application.Tags = []string{}
|
||||||
|
}
|
||||||
if application.RedirectUris == nil {
|
if application.RedirectUris == nil {
|
||||||
application.RedirectUris = []string{}
|
application.RedirectUris = []string{}
|
||||||
}
|
}
|
||||||
if application.Tags == nil {
|
if application.TokenFields == nil {
|
||||||
application.Tags = []string{}
|
application.TokenFields = []string{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, permission := range data.Permissions {
|
for _, permission := range data.Permissions {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user