Compare commits

..

2 Commits

Author SHA1 Message Date
b195b19a8c Update MfaVerifyForm.js 2023-05-21 00:43:21 +08:00
57e4a66156 Revert "feat: fix UI in IE11 (#1871)"
This reverts commit 319031da28.
2023-05-21 00:40:37 +08:00
458 changed files with 16101 additions and 57406 deletions

View File

@ -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: 18 node-version: 16
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: 18 node-version: 16
cache: 'yarn' cache: 'yarn'
cache-dependency-path: ./web/yarn.lock cache-dependency-path: ./web/yarn.lock
- run: yarn install - run: yarn install
@ -110,7 +110,7 @@ jobs:
with: with:
start: yarn start start: yarn start
wait-on: 'http://localhost:7001' wait-on: 'http://localhost:7001'
wait-on-timeout: 210 wait-on-timeout: 180
working-directory: ./web working-directory: ./web
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
@ -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 == 'casbin/casdoor' && github.event_name == 'push' if: github.repository == 'casdoor/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: 18 node-version: 16
- name: Fetch Previous version - name: Fetch Previous version
id: get-previous-tag id: get-previous-tag
@ -167,8 +167,10 @@ 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
@ -182,57 +184,27 @@ 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 == 'casbin/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true' if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
with: 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 == 'casbin/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true' if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
with: with:
context: . context: .
target: STANDARD target: STANDARD
platforms: linux/amd64 platforms: linux/amd64,linux/arm64
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 == 'casbin/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true' if: github.repository == 'casdoor/casdoor' && github.event_name == 'push' && steps.should_push.outputs.push=='true'
with: with:
context: . context: .
target: ALLINONE target: ALLINONE
platforms: linux/amd64 platforms: linux/amd64,linux/arm64
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 Normal file
View File

@ -0,0 +1,61 @@
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: ./

View File

@ -7,7 +7,7 @@ on:
jobs: jobs:
synchronize-with-crowdin: synchronize-with-crowdin:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'casbin/casdoor' && github.event_name == 'push' if: github.repository == 'casdoor/casdoor' && github.event_name == 'push'
steps: steps:
- name: Checkout - name: Checkout

6
.gitignore vendored
View File

@ -18,7 +18,7 @@ bin/
.idea/ .idea/
*.iml *.iml
.vscode/settings.json .vscode/
tmp/ tmp/
tmpFiles/ tmpFiles/
@ -30,7 +30,3 @@ commentsRouter*.go
# ignore build result # ignore build result
casdoor casdoor
server
# include helm-chart
!manifests/casdoor

15
.vscode/launch.json vendored
View File

@ -1,15 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}",
"cwd": "${workspaceFolder}",
"debugAdapter": "dlv-dap",
"args": ["--createDatabase=true"]
}
]
}

View File

@ -1,10 +1,11 @@
FROM node:18.19.0 AS FRONT FROM node:16.18.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.20.12 AS BACK FROM golang:1.19.9 AS BACK
WORKDIR /go/src/casdoor WORKDIR /go/src/casdoor
COPY . . COPY . .
RUN ./build.sh RUN ./build.sh
@ -13,6 +14,9 @@ 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
@ -27,7 +31,7 @@ RUN adduser -D $USER -u 1000 \
USER 1000 USER 1000
WORKDIR / WORKDIR /
COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/server ./server COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/server_${BUILDX_ARCH} ./server
COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/swagger ./swagger COPY --from=BACK --chown=$USER:$USER /go/src/casdoor/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
@ -46,17 +50,21 @@ 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 ./server COPY --from=BACK /go/src/casdoor/server_${BUILDX_ARCH} ./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
COPY --from=BACK /go/src/casdoor/version_info.txt ./go/src/casdoor/version_info.txt COPY --from=BACK /go/src/casdoor/version_info.txt ./go/src/casdoor/version_info.txt
COPY --from=FRONT /web/build ./web/build COPY --from=FRONT /web/build ./web/build
RUN mkdir tempFiles
ENTRYPOINT ["/bin/bash"] ENTRYPOINT ["/bin/bash"]
CMD ["/docker-entrypoint.sh"] CMD ["/docker-entrypoint.sh"]

View File

@ -86,9 +86,6 @@ 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

View File

@ -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">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> <h3 align="center">A UI-first centralized authentication / Single-Sign-On (SSO) platform based on OAuth 2.0 / OIDC.</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">
@ -11,7 +11,7 @@
<img alt="GitHub Workflow Status (branch)" src="https://github.com/casdoor/casdoor/workflows/Build/badge.svg?style=flat-square"> <img alt="GitHub Workflow Status (branch)" src="https://github.com/casdoor/casdoor/workflows/Build/badge.svg?style=flat-square">
</a> </a>
<a href="https://github.com/casdoor/casdoor/releases/latest"> <a href="https://github.com/casdoor/casdoor/releases/latest">
<img alt="GitHub Release" src="https://img.shields.io/github/v/release/casdoor/casdoor.svg"> <img alt="GitHub Release" src="https://img.shields.io/github/v/release/casbin/casdoor.svg">
</a> </a>
<a href="https://hub.docker.com/repository/docker/casbin/casdoor"> <a href="https://hub.docker.com/repository/docker/casbin/casdoor">
<img alt="Docker Image Version (latest semver)" src="https://img.shields.io/badge/Docker%20Hub-latest-brightgreen"> <img alt="Docker Image Version (latest semver)" src="https://img.shields.io/badge/Docker%20Hub-latest-brightgreen">
@ -23,39 +23,25 @@
<img alt="Go Report Card" src="https://goreportcard.com/badge/github.com/casdoor/casdoor?style=flat-square"> <img alt="Go Report Card" src="https://goreportcard.com/badge/github.com/casdoor/casdoor?style=flat-square">
</a> </a>
<a href="https://github.com/casdoor/casdoor/blob/master/LICENSE"> <a href="https://github.com/casdoor/casdoor/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/casdoor/casdoor?style=flat-square" alt="license"> <img src="https://img.shields.io/github/license/casbin/casdoor?style=flat-square" alt="license">
</a> </a>
<a href="https://github.com/casdoor/casdoor/issues"> <a href="https://github.com/casdoor/casdoor/issues">
<img alt="GitHub issues" src="https://img.shields.io/github/issues/casdoor/casdoor?style=flat-square"> <img alt="GitHub issues" src="https://img.shields.io/github/issues/casbin/casdoor?style=flat-square">
</a> </a>
<a href="#"> <a href="#">
<img alt="GitHub stars" src="https://img.shields.io/github/stars/casdoor/casdoor?style=flat-square"> <img alt="GitHub stars" src="https://img.shields.io/github/stars/casbin/casdoor?style=flat-square">
</a> </a>
<a href="https://github.com/casdoor/casdoor/network"> <a href="https://github.com/casdoor/casdoor/network">
<img alt="GitHub forks" src="https://img.shields.io/github/forks/casdoor/casdoor?style=flat-square"> <img alt="GitHub forks" src="https://img.shields.io/github/forks/casbin/casdoor?style=flat-square">
</a> </a>
<a href="https://crowdin.com/project/casdoor-site"> <a href="https://crowdin.com/project/casdoor-site">
<img alt="Crowdin" src="https://badges.crowdin.net/casdoor-site/localized.svg"> <img alt="Crowdin" src="https://badges.crowdin.net/casdoor-site/localized.svg">
</a> </a>
<a href="https://discord.gg/5rPsrAzK7S"> <a href="https://gitter.im/casbin/casdoor">
<img alt="Discord" src="https://img.shields.io/discord/1022748306096537660?style=flat-square&logo=discord&label=discord&color=5865F2"> <img alt="Gitter" src="https://badges.gitter.im/casbin/casdoor.svg">
</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)
@ -69,7 +55,6 @@ 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?
@ -86,7 +71,7 @@ https://casdoor.org/docs/category/integrations
## How to contact? ## How to contact?
- Discord: https://discord.gg/5rPsrAzK7S - Gitter: https://gitter.im/casbin/casdoor
- Forum: https://forum.casbin.com - Forum: https://forum.casbin.com
- Contact: https://tawk.to/chat/623352fea34c2456412b8c51/1fuc7od6e - Contact: https://tawk.to/chat/623352fea34c2456412b8c51/1fuc7od6e

141
ai/ai.go Normal file
View File

@ -0,0 +1,141 @@
// 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 ai
import (
"context"
"fmt"
"io"
"net/http"
"strings"
"time"
"github.com/sashabaranov/go-openai"
)
func queryAnswer(authToken string, question string, timeout int) (string, error) {
// fmt.Printf("Question: %s\n", question)
client := getProxyClientFromToken(authToken)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(2+timeout*2)*time.Second)
defer cancel()
resp, err := client.CreateChatCompletion(
ctx,
openai.ChatCompletionRequest{
Model: openai.GPT3Dot5Turbo,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: question,
},
},
},
)
if err != nil {
return "", err
}
res := resp.Choices[0].Message.Content
res = strings.Trim(res, "\n")
// fmt.Printf("Answer: %s\n\n", res)
return res, nil
}
func QueryAnswerSafe(authToken string, question string) string {
var res string
var err error
for i := 0; i < 10; i++ {
res, err = queryAnswer(authToken, question, i)
if err != nil {
if i > 0 {
fmt.Printf("\tFailed (%d): %s\n", i+1, err.Error())
}
} else {
break
}
}
if err != nil {
panic(err)
}
return res
}
func QueryAnswerStream(authToken string, question string, writer io.Writer, builder *strings.Builder) error {
client := getProxyClientFromToken(authToken)
ctx := context.Background()
flusher, ok := writer.(http.Flusher)
if !ok {
return fmt.Errorf("writer does not implement http.Flusher")
}
// https://platform.openai.com/tokenizer
// https://github.com/pkoukk/tiktoken-go#available-encodings
promptTokens, err := getTokenSize(openai.GPT3TextDavinci003, question)
if err != nil {
return err
}
// https://platform.openai.com/docs/models/gpt-3-5
maxTokens := 4097 - promptTokens
respStream, err := client.CreateCompletionStream(
ctx,
openai.CompletionRequest{
Model: openai.GPT3TextDavinci003,
Prompt: question,
MaxTokens: maxTokens,
Stream: true,
},
)
if err != nil {
return err
}
defer respStream.Close()
isLeadingReturn := true
for {
completion, streamErr := respStream.Recv()
if streamErr != nil {
if streamErr == io.EOF {
break
}
return streamErr
}
data := completion.Choices[0].Text
if isLeadingReturn && len(data) != 0 {
if strings.Count(data, "\n") == len(data) {
continue
} else {
isLeadingReturn = false
}
}
fmt.Printf("%s", data)
// Write the streamed data as Server-Sent Events
if _, err = fmt.Fprintf(writer, "data: %s\n\n", data); err != nil {
return err
}
flusher.Flush()
// Append the response to the strings.Builder
builder.WriteString(data)
}
return nil
}

View File

@ -12,22 +12,31 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package storage //go:build !skipCi
// +build !skipCi
package ai
import ( import (
"github.com/casdoor/oss" "testing"
"github.com/casdoor/oss/googlecloud"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/proxy"
"github.com/sashabaranov/go-openai"
) )
func NewGoogleCloudStorageProvider(clientSecret string, bucket string, endpoint string) oss.StorageInterface { func TestRun(t *testing.T) {
sp, err := googlecloud.New(&googlecloud.Config{ object.InitConfig()
ServiceAccountJson: clientSecret, proxy.InitHttpClient()
Bucket: bucket,
Endpoint: endpoint, text, err := queryAnswer("", "hi", 5)
})
if err != nil { if err != nil {
panic(err) panic(err)
} }
return sp println(text)
}
func TestToken(t *testing.T) {
println(getTokenSize(openai.GPT3TextDavinci003, ""))
} }

View File

@ -12,16 +12,17 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package controllers package ai
import ( import (
"strings" "github.com/casdoor/casdoor/proxy"
"github.com/sashabaranov/go-openai"
"github.com/casdoor/casdoor/scim"
) )
func (c *RootController) HandleScim() { func getProxyClientFromToken(authToken string) *openai.Client {
path := c.Ctx.Request.URL.Path config := openai.DefaultConfig(authToken)
c.Ctx.Request.URL.Path = strings.TrimPrefix(path, "/scim") config.HTTPClient = proxy.ProxyHttpClient
scim.Server.ServeHTTP(c.Ctx.ResponseWriter, c.Ctx.Request)
c := openai.NewClientWithConfig(config)
return c
} }

View File

@ -12,18 +12,17 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//go:build !skipCi package ai
// +build !skipCi
package object import "github.com/pkoukk/tiktoken-go"
import "testing" func getTokenSize(model string, prompt string) (int, error) {
tkm, err := tiktoken.EncodingForModel(model)
func TestDumpToFile(t *testing.T) {
InitConfig()
err := DumpToFile("./init_data_dump.json")
if err != nil { if err != nil {
panic(err) return 0, err
} }
token := tkm.Encode(prompt, nil, nil)
res := len(token)
return res, nil
} }

View File

@ -18,21 +18,60 @@ import (
"strings" "strings"
"github.com/casbin/casbin/v2" "github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
"github.com/casdoor/casdoor/conf" "github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
xormadapter "github.com/casdoor/xorm-adapter/v3"
stringadapter "github.com/qiangmzsx/string-adapter/v2" stringadapter "github.com/qiangmzsx/string-adapter/v2"
) )
var Enforcer *casbin.Enforcer var Enforcer *casbin.Enforcer
func InitApi() { func InitAuthz() {
e, err := object.GetInitializedEnforcer(util.GetId("built-in", "api-enforcer-built-in")) var err error
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
driverName := conf.GetConfigString("driverName")
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
a, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, "casbin_rule", tableNamePrefix, true)
if err != nil {
panic(err)
}
modelText := `
[request_definition]
r = subOwner, subName, method, urlPath, objOwner, objName
[policy_definition]
p = subOwner, subName, method, urlPath, objOwner, objName
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = (r.subOwner == p.subOwner || p.subOwner == "*") && \
(r.subName == p.subName || p.subName == "*" || r.subName != "anonymous" && p.subName == "!anonymous") && \
(r.method == p.method || p.method == "*") && \
(r.urlPath == p.urlPath || p.urlPath == "*") && \
(r.objOwner == p.objOwner || p.objOwner == "*") && \
(r.objName == p.objName || p.objName == "*") || \
(r.subOwner == r.objOwner && r.subName == r.objName)
`
m, err := model.NewModelFromString(modelText)
if err != nil {
panic(err)
}
Enforcer, err = casbin.NewEnforcer(m, a)
if err != nil { if err != nil {
panic(err) panic(err)
} }
Enforcer = e.Enforcer
Enforcer.ClearPolicy() Enforcer.ClearPolicy()
// if len(Enforcer.GetPolicy()) == 0 { // if len(Enforcer.GetPolicy()) == 0 {
@ -46,13 +85,11 @@ p, *, *, POST, /api/login, *, *
p, *, *, GET, /api/get-app-login, *, * p, *, *, GET, /api/get-app-login, *, *
p, *, *, POST, /api/logout, *, * p, *, *, POST, /api/logout, *, *
p, *, *, GET, /api/logout, *, * p, *, *, GET, /api/logout, *, *
p, *, *, POST, /api/callback, *, *
p, *, *, GET, /api/get-account, *, * p, *, *, GET, /api/get-account, *, *
p, *, *, GET, /api/userinfo, *, * p, *, *, GET, /api/userinfo, *, *
p, *, *, GET, /api/user, *, * p, *, *, GET, /api/user, *, *
p, *, *, GET, /api/health, *, * p, *, *, GET, /api/health, *, *
p, *, *, *, /api/webhook, *, * p, *, *, POST, /api/webhook, *, *
p, *, *, GET, /api/get-qrcode, *, *
p, *, *, GET, /api/get-webhook-event, *, * p, *, *, GET, /api/get-webhook-event, *, *
p, *, *, GET, /api/get-captcha-status, *, * p, *, *, GET, /api/get-captcha-status, *, *
p, *, *, *, /api/login/oauth, *, * p, *, *, *, /api/login/oauth, *, *
@ -81,28 +118,20 @@ p, *, *, *, /.well-known/jwks, *, *
p, *, *, GET, /api/get-saml-login, *, * 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, *, *, *, /api/saml/redirect, *, *
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, *, *
p, *, *, GET, /api/get-prometheus-info, *, * p, *, *, GET, /api/get-prometheus-info, *, *
p, *, *, *, /api/metrics, *, * p, *, *, *, /api/metrics, *, *
p, *, *, GET, /api/get-subscriptions, *, *
p, *, *, GET, /api/get-pricing, *, * p, *, *, GET, /api/get-pricing, *, *
p, *, *, GET, /api/get-plan, *, * p, *, *, GET, /api/get-plan, *, *
p, *, *, GET, /api/get-subscription, *, *
p, *, *, GET, /api/get-provider, *, *
p, *, *, GET, /api/get-organization-names, *, *
p, *, *, GET, /api/get-all-objects, *, *
p, *, *, GET, /api/get-all-actions, *, *
p, *, *, GET, /api/get-all-roles, *, *
p, *, *, GET, /api/get-invitation-info, *, *
` `
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)
} }
@ -124,25 +153,11 @@ func IsAllowed(subOwner string, subName string, method string, urlPath string, o
} }
} }
user, err := object.GetUser(util.GetId(subOwner, subName)) user := object.GetUser(util.GetId(subOwner, subName))
if err != nil { if user != nil && user.IsAdmin && (subOwner == objOwner || (objOwner == "admin")) {
panic(err)
}
if subOwner == "app" {
return true return true
} }
if user != nil {
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)
if err != nil { if err != nil {
panic(err) panic(err)
@ -153,11 +168,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/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/") || urlPath == "/api/webhook" || urlPath == "/api/get-qrcode" { 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" {
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 == "app") && !(subOwner == "built-in" && subName == "admin") { if subOwner == objOwner && subName == objName && !(subOwner == "built-in" && subName == "admin") {
return true return true
} }
return false return false

View File

@ -8,4 +8,5 @@ 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 . CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o server_linux_amd64 .
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-w -s" -o server_linux_arm64 .

View File

@ -13,18 +13,11 @@ isCloudIntranet = false
authState = "casdoor" authState = "casdoor"
socks5Proxy = "127.0.0.1:10808" socks5Proxy = "127.0.0.1:10808"
verificationCodeTimeout = 10 verificationCodeTimeout = 10
initScore = 0 initScore = 2000
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
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"}
initDataFile = "./init_data.json"
frontendBaseDir = "../casdoor"

View File

@ -15,6 +15,7 @@
package conf package conf
import ( import (
"encoding/json"
"fmt" "fmt"
"os" "os"
"runtime" "runtime"
@ -24,6 +25,15 @@ import (
"github.com/beego/beego" "github.com/beego/beego"
) )
type Quota struct {
Organization int `json:"organization"`
User int `json:"user"`
Application int `json:"application"`
Provider int `json:"provider"`
}
var quota = &Quota{-1, -1, -1, -1}
func init() { func init() {
// this array contains the beego configuration items that may be modified via env // this array contains the beego configuration items that may be modified via env
presetConfigItems := []string{"httpport", "appname"} presetConfigItems := []string{"httpport", "appname"}
@ -35,6 +45,17 @@ func init() {
} }
} }
} }
initQuota()
}
func initQuota() {
res := beego.AppConfig.String("quota")
if res != "" {
err := json.Unmarshal([]byte(res), quota)
if err != nil {
panic(err)
}
}
} }
func GetConfigString(key string) string { func GetConfigString(key string) string {
@ -46,21 +67,20 @@ func GetConfigString(key string) string {
if res == "" { if res == "" {
if key == "staticBaseUrl" { if key == "staticBaseUrl" {
res = "https://cdn.casbin.org" res = "https://cdn.casbin.org"
} else if key == "logConfig" {
res = fmt.Sprintf("{\"filename\": \"logs/%s.log\", \"maxdays\":99999, \"perm\":\"0770\"}", beego.AppConfig.String("appname"))
} }
} }
return res return res
} }
func GetConfigBool(key string) bool { func GetConfigBool(key string) (bool, error) {
value := GetConfigString(key) value := GetConfigString(key)
if value == "true" { if value == "true" {
return true return true, nil
} else { } else if value == "false" {
return false return false, nil
} }
return false, fmt.Errorf("value %s cannot be converted into bool", value)
} }
func GetConfigInt64(key string) (int64, error) { func GetConfigInt64(key string) (int64, error) {
@ -90,10 +110,10 @@ func GetLanguage(language string) string {
return "en" return "en"
} }
if len(language) != 2 || language == "nu" { if len(language) < 2 {
return "en" return "en"
} else { } else {
return language return language[0:2]
} }
} }
@ -109,6 +129,10 @@ func GetConfigBatchSize() int {
return res return res
} }
func GetConfigQuota() *Quota {
return quota
}
func GetConfigRealDataSourceName(driverName string) string { func GetConfigRealDataSourceName(driverName string) string {
var dataSourceName string var dataSourceName string
if driverName != "mysql" { if driverName != "mysql" {

View File

@ -1,48 +0,0 @@
// 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 conf
import (
"encoding/json"
"github.com/beego/beego"
)
type Quota struct {
Organization int `json:"organization"`
User int `json:"user"`
Application int `json:"application"`
Provider int `json:"provider"`
}
var quota = &Quota{-1, -1, -1, -1}
func init() {
initQuota()
}
func initQuota() {
res := beego.AppConfig.String("quota")
if res != "" {
err := json.Unmarshal([]byte(res), quota)
if err != nil {
panic(err)
}
}
}
func GetConfigQuota() *Quota {
return quota
}

View File

@ -87,7 +87,7 @@ func TestGetConfBool(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
for _, scenery := range scenarios { for _, scenery := range scenarios {
t.Run(scenery.description, func(t *testing.T) { t.Run(scenery.description, func(t *testing.T) {
actual := GetConfigBool(scenery.input) actual, err := GetConfigBool(scenery.input)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, scenery.expected, actual) assert.Equal(t, scenery.expected, actual)
}) })
@ -109,19 +109,3 @@ func TestGetConfigQuota(t *testing.T) {
assert.Equal(t, scenery.expected, quota) assert.Equal(t, scenery.expected, quota)
} }
} }
func TestGetConfigLogs(t *testing.T) {
scenarios := []struct {
description string
expected string
}{
{"Default log config", `{"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}`},
}
err := beego.LoadAppConfig("ini", "app.conf")
assert.Nil(t, err)
for _, scenery := range scenarios {
quota := GetConfigString("logConfig")
assert.Equal(t, scenery.expected, quota)
}
}

View File

@ -18,6 +18,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strconv"
"strings" "strings"
"github.com/casdoor/casdoor/form" "github.com/casdoor/casdoor/form"
@ -56,17 +57,6 @@ 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
@ -88,48 +78,19 @@ func (c *ApiController) Signup() {
return return
} }
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application)) application := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
return
}
if !application.EnableSignUp { if !application.EnableSignUp {
c.ResponseError(c.T("account:The application does not allow to sign up new account")) c.ResponseError(c.T("account:The application does not allow to sign up new account"))
return return
} }
organization, err := object.GetOrganization(util.GetId("admin", authForm.Organization)) organization := object.GetOrganization(util.GetId("admin", authForm.Organization))
if err != nil {
c.ResponseError(c.T(err.Error()))
return
}
if organization == nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The organization: %s does not exist"), authForm.Organization))
return
}
msg := object.CheckUserSignup(application, organization, &authForm, c.GetAcceptLanguage()) msg := object.CheckUserSignup(application, organization, &authForm, c.GetAcceptLanguage())
if msg != "" { if msg != "" {
c.ResponseError(msg) c.ResponseError(msg)
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 {
@ -148,10 +109,16 @@ func (c *ApiController) Signup() {
} }
} }
id, err := object.GenerateIdForNewUser(application) id := util.GenerateId()
if err != nil { if application.GetSignupItemRule("ID") == "Incremental" {
c.ResponseError(err.Error()) lastUser := object.GetLastUser(authForm.Organization)
return
lastIdInt := -1
if lastUser != nil {
lastIdInt = util.ParseInt(lastUser.Id)
}
id = strconv.Itoa(lastIdInt + 1)
} }
username := authForm.Username username := authForm.Username
@ -165,22 +132,12 @@ func (c *ApiController) Signup() {
return return
} }
userType := "normal-user"
if authForm.Plan != "" && authForm.Pricing != "" {
err = object.CheckPricingAndPlan(authForm.Organization, authForm.Pricing, authForm.Plan)
if err != nil {
c.ResponseError(err.Error())
return
}
userType = "paid-user"
}
user := &object.User{ user := &object.User{
Owner: authForm.Organization, Owner: authForm.Organization,
Name: username, Name: username,
CreatedTime: util.GetCurrentTime(), CreatedTime: util.GetCurrentTime(),
Id: id, Id: id,
Type: userType, Type: "normal-user",
Password: authForm.Password, Password: authForm.Password,
DisplayName: authForm.Name, DisplayName: authForm.Name,
Avatar: organization.DefaultAvatar, Avatar: organization.DefaultAvatar,
@ -193,13 +150,12 @@ func (c *ApiController) Signup() {
Region: authForm.Region, Region: authForm.Region,
Score: initScore, Score: initScore,
IsAdmin: false, IsAdmin: false,
IsGlobalAdmin: false,
IsForbidden: false, IsForbidden: false,
IsDeleted: false, IsDeleted: false,
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 {
@ -217,47 +173,25 @@ func (c *ApiController) Signup() {
} }
} }
affected, err := object.AddUser(user) affected := object.AddUser(user)
if err != nil {
c.ResponseError(err.Error())
return
}
if !affected { if !affected {
c.ResponseError(c.T("account:Failed to add user"), util.StructToJson(user)) c.ResponseError(c.T("account:Failed to add user"), util.StructToJson(user))
return return
} }
err = object.AddUserToOriginalDatabase(user) object.AddUserToOriginalDatabase(user)
if err != nil {
c.ResponseError(err.Error())
return
}
if invitation != nil { if application.HasPromptPage() {
invitation.UsedCount += 1
_, err := object.UpdateInvitation(invitation.GetId(), invitation, c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error())
return
}
}
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())
} }
err = object.DisableVerificationCode(authForm.Email) object.DisableVerificationCode(authForm.Email)
if err != nil { object.DisableVerificationCode(checkPhone)
c.ResponseError(err.Error())
return
}
err = object.DisableVerificationCode(checkPhone) isSignupFromPricing := authForm.Plan != "" && authForm.Pricing != ""
if err != nil { if isSignupFromPricing {
c.ResponseError(err.Error()) object.Subscribe(organization.Name, user.Name, authForm.Plan, authForm.Pricing)
return
} }
record := object.NewRecord(c.Ctx) record := object.NewRecord(c.Ctx)
@ -279,7 +213,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 [post] // @router /logout [get,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")
@ -297,11 +231,7 @@ func (c *ApiController) Logout() {
c.ClearUserSession() c.ClearUserSession()
owner, username := util.GetOwnerAndNameFromId(user) owner, username := util.GetOwnerAndNameFromId(user)
_, err := object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID()) object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID())
if err != nil {
c.ResponseError(err.Error())
return
}
util.LogInfo(c.Ctx, "API: [%s] logged out", user) util.LogInfo(c.Ctx, "API: [%s] logged out", user)
@ -313,64 +243,42 @@ func (c *ApiController) Logout() {
c.ResponseOk(user, application.HomepageUrl) c.ResponseOk(user, application.HomepageUrl)
return return
} else { } else {
// "post_logout_redirect_uri" has been made optional, see: https://github.com/casdoor/casdoor/issues/2151 if redirectUri == "" {
// if redirectUri == "" { c.ResponseError(c.T("general:Missing parameter") + ": post_logout_redirect_uri")
// c.ResponseError(c.T("general:Missing parameter") + ": post_logout_redirect_uri") return
// return }
// }
if accessToken == "" { if accessToken == "" {
c.ResponseError(c.T("general:Missing parameter") + ": id_token_hint") c.ResponseError(c.T("general:Missing parameter") + ": id_token_hint")
return return
} }
_, application, token, err := object.ExpireTokenByAccessToken(accessToken) affected, application, token := object.ExpireTokenByAccessToken(accessToken)
if err != nil { if !affected {
c.ResponseError(err.Error())
return
}
if token == nil {
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
} }
if user == "" { if application.IsRedirectUriValid(redirectUri) {
user = util.GetId(token.Organization, token.User) if user == "" {
} user = util.GetId(token.Organization, token.User)
c.ClearUserSession()
// TODO https://github.com/casdoor/casdoor/pull/1494#discussion_r1095675265
owner, username := util.GetOwnerAndNameFromId(user)
_, err = object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID())
if err != nil {
c.ResponseError(err.Error())
return
}
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
if redirectUri == "" {
c.ResponseOk()
return
} else {
if application.IsRedirectUriValid(redirectUri) {
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 {
c.ResponseError(fmt.Sprintf(c.T("token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), redirectUri))
return
} }
c.ClearUserSession()
// TODO https://github.com/casdoor/casdoor/pull/1494#discussion_r1095675265
owner, username := util.GetOwnerAndNameFromId(user)
object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID())
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
c.Ctx.Redirect(http.StatusFound, fmt.Sprintf("%s?state=%s", strings.TrimRight(redirectUri, "/"), state))
} else {
c.ResponseError(fmt.Sprintf(c.T("token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), redirectUri))
return
} }
} }
} }
@ -382,7 +290,6 @@ func (c *ApiController) Logout() {
// @Success 200 {object} controllers.Response The Response object // @Success 200 {object} controllers.Response The Response object
// @router /get-account [get] // @router /get-account [get]
func (c *ApiController) GetAccount() { func (c *ApiController) GetAccount() {
var err error
user, ok := c.RequireSignedInUser() user, ok := c.RequireSignedInUser()
if !ok { if !ok {
return return
@ -390,43 +297,20 @@ func (c *ApiController) GetAccount() {
managedAccounts := c.Input().Get("managedAccounts") managedAccounts := c.Input().Get("managedAccounts")
if managedAccounts == "1" { if managedAccounts == "1" {
user, err = object.ExtendManagedAccountsWithUser(user) user = object.ExtendManagedAccountsWithUser(user)
if err != nil {
c.ResponseError(err.Error())
return
}
} }
err = object.ExtendUserWithRolesAndPermissions(user) object.ExtendUserWithRolesAndPermissions(user)
if err != nil {
c.ResponseError(err.Error())
return
}
if user != nil { user.Permissions = object.GetMaskedPermissions(user.Permissions)
user.Permissions = object.GetMaskedPermissions(user.Permissions) user.Roles = object.GetMaskedRoles(user.Roles)
user.Roles = object.GetMaskedRoles(user.Roles)
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
}
organization, err := object.GetMaskedOrganization(object.GetOrganizationByUser(user))
if err != nil {
c.ResponseError(err.Error())
return
}
isAdminOrSelf := c.IsAdminOrSelf(user)
u, err := object.GetMaskedUser(user, isAdminOrSelf)
if err != nil {
c.ResponseError(err.Error())
return
}
organization := object.GetMaskedOrganization(object.GetOrganizationByUser(user))
resp := Response{ resp := Response{
Status: "ok", Status: "ok",
Sub: user.Id, Sub: user.Id,
Name: user.Name, Name: user.Name,
Data: u, Data: object.GetMaskedUser(user),
Data2: organization, Data2: organization,
} }
c.Data["json"] = resp c.Data["json"] = resp
@ -459,7 +343,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} controllers.LaravelResponse The Response object // @Success 200 {object} 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()
@ -467,6 +351,17 @@ 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,
@ -483,8 +378,7 @@ func (c *ApiController) GetUserinfo2() {
// GetCaptcha ... // GetCaptcha ...
// @Tag Login API // @Tag Login API
// @Title GetCaptcha // @Title GetCaptcha
// @router /get-captcha [get] // @router /api/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")
@ -497,12 +391,7 @@ func (c *ApiController) GetCaptcha() {
if captchaProvider != nil { if captchaProvider != nil {
if captchaProvider.Type == "Default" { if captchaProvider.Type == "Default" {
id, img, err := object.GetCaptcha() id, img := object.GetCaptcha()
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(Captcha{Type: captchaProvider.Type, CaptchaId: id, CaptchaImage: img}) c.ResponseOk(Captcha{Type: captchaProvider.Type, CaptchaId: id, CaptchaImage: img})
return return
} else if captchaProvider.Type != "" { } else if captchaProvider.Type != "" {
@ -510,7 +399,7 @@ func (c *ApiController) GetCaptcha() {
Type: captchaProvider.Type, Type: captchaProvider.Type,
SubType: captchaProvider.SubType, SubType: captchaProvider.SubType,
ClientId: captchaProvider.ClientId, ClientId: captchaProvider.ClientId,
ClientSecret: "***", ClientSecret: captchaProvider.ClientSecret,
ClientId2: captchaProvider.ClientId2, ClientId2: captchaProvider.ClientId2,
ClientSecret2: captchaProvider.ClientSecret2, ClientSecret2: captchaProvider.ClientSecret2,
}) })

View File

@ -1,145 +0,0 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package controllers
import (
"encoding/json"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
// GetAdapters
// @Title GetAdapters
// @Tag Adapter API
// @Description get adapters
// @Param owner query string true "The owner of adapters"
// @Success 200 {array} object.Adapter The Response object
// @router /get-adapters [get]
func (c *ApiController) GetAdapters() {
owner := c.Input().Get("owner")
limit := c.Input().Get("pageSize")
page := c.Input().Get("p")
field := c.Input().Get("field")
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
adapters, err := object.GetAdapters(owner)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(adapters)
} else {
limit := util.ParseInt(limit)
count, err := object.GetAdapterCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
adapters, err := object.GetPaginationAdapters(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(adapters, paginator.Nums())
}
}
// GetAdapter
// @Title GetAdapter
// @Tag Adapter API
// @Description get adapter
// @Param id query string true "The id ( owner/name ) of the adapter"
// @Success 200 {object} object.Adapter The Response object
// @router /get-adapter [get]
func (c *ApiController) GetAdapter() {
id := c.Input().Get("id")
adapter, err := object.GetAdapter(id)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(adapter)
}
// UpdateAdapter
// @Title UpdateAdapter
// @Tag Adapter API
// @Description update adapter
// @Param id query string true "The id ( owner/name ) of the adapter"
// @Param body body object.Adapter true "The details of the adapter"
// @Success 200 {object} controllers.Response The Response object
// @router /update-adapter [post]
func (c *ApiController) UpdateAdapter() {
id := c.Input().Get("id")
var adapter object.Adapter
err := json.Unmarshal(c.Ctx.Input.RequestBody, &adapter)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.UpdateAdapter(id, &adapter))
c.ServeJSON()
}
// AddAdapter
// @Title AddAdapter
// @Tag Adapter API
// @Description add adapter
// @Param body body object.Adapter true "The details of the adapter"
// @Success 200 {object} controllers.Response The Response object
// @router /add-adapter [post]
func (c *ApiController) AddAdapter() {
var adapter object.Adapter
err := json.Unmarshal(c.Ctx.Input.RequestBody, &adapter)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.AddAdapter(&adapter))
c.ServeJSON()
}
// DeleteAdapter
// @Title DeleteAdapter
// @Tag Adapter API
// @Description delete adapter
// @Param body body object.Adapter true "The details of the adapter"
// @Success 200 {object} controllers.Response The Response object
// @router /delete-adapter [post]
func (c *ApiController) DeleteAdapter() {
var adapter object.Adapter
err := json.Unmarshal(c.Ctx.Input.RequestBody, &adapter)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.DeleteAdapter(&adapter))
c.ServeJSON()
}

View File

@ -40,35 +40,21 @@ func (c *ApiController) GetApplications() {
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
organization := c.Input().Get("organization") organization := c.Input().Get("organization")
var err error
if limit == "" || page == "" { if limit == "" || page == "" {
var applications []*object.Application var applications []*object.Application
if organization == "" { if organization == "" {
applications, err = object.GetApplications(owner) applications = object.GetApplications(owner)
} else { } else {
applications, err = object.GetOrganizationApplications(owner, organization) applications = object.GetOrganizationApplications(owner, organization)
} }
if err != nil {
c.ResponseError(err.Error()) c.Data["json"] = object.GetMaskedApplications(applications, userId)
return c.ServeJSON()
}
c.ResponseOk(object.GetMaskedApplications(applications, userId))
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetApplicationCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetApplicationCount(owner, field, value)))
if err != nil { applications := object.GetMaskedApplications(object.GetPaginationApplications(owner, paginator.Offset(), limit, field, value, sortField, sortOrder), userId)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
application, err := object.GetPaginationApplications(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
applications := object.GetMaskedApplications(application, userId)
c.ResponseOk(applications, paginator.Nums()) c.ResponseOk(applications, paginator.Nums())
} }
} }
@ -84,33 +70,8 @@ func (c *ApiController) GetApplication() {
userId := c.GetSessionUsername() userId := c.GetSessionUsername()
id := c.Input().Get("id") id := c.Input().Get("id")
application, err := object.GetApplication(id) c.Data["json"] = object.GetMaskedApplication(object.GetApplication(id), userId)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
if c.Input().Get("withKey") != "" && application != nil && application.Cert != "" {
cert, err := object.GetCert(util.GetId(application.Owner, application.Cert))
if err != nil {
c.ResponseError(err.Error())
return
}
if cert == nil {
cert, err = object.GetCert(util.GetId(application.Organization, application.Cert))
if err != nil {
c.ResponseError(err.Error())
return
}
}
if cert != nil {
application.CertPublicKey = cert.Certificate
}
}
c.ResponseOk(object.GetMaskedApplication(application, userId))
} }
// GetUserApplication // GetUserApplication
@ -123,28 +84,14 @@ func (c *ApiController) GetApplication() {
func (c *ApiController) GetUserApplication() { func (c *ApiController) GetUserApplication() {
userId := c.GetSessionUsername() userId := c.GetSessionUsername()
id := c.Input().Get("id") id := c.Input().Get("id")
user := object.GetUser(id)
user, err := object.GetUser(id)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil { if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), id)) c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), id))
return return
} }
application, err := object.GetApplicationByUser(user) c.Data["json"] = object.GetMaskedApplication(object.GetApplicationByUser(user), userId)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
if application == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The organization: %s should have one application at least"), user.Owner))
return
}
c.ResponseOk(object.GetMaskedApplication(application, userId))
} }
// GetOrganizationApplications // GetOrganizationApplications
@ -171,36 +118,14 @@ func (c *ApiController) GetOrganizationApplications() {
} }
if limit == "" || page == "" { if limit == "" || page == "" {
applications, err := object.GetOrganizationApplications(owner, organization) var applications []*object.Application
if err != nil { applications = object.GetOrganizationApplications(owner, organization)
c.ResponseError(err.Error()) c.Data["json"] = object.GetMaskedApplications(applications, userId)
return c.ServeJSON()
}
applications, err = object.GetAllowedApplications(applications, userId)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(object.GetMaskedApplications(applications, userId))
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetOrganizationApplicationCount(owner, organization, field, value)))
count, err := object.GetOrganizationApplicationCount(owner, organization, field, value) applications := object.GetMaskedApplications(object.GetPaginationOrganizationApplications(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder), userId)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
application, err := object.GetPaginationOrganizationApplications(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
applications := object.GetMaskedApplications(application, userId)
c.ResponseOk(applications, paginator.Nums()) c.ResponseOk(applications, paginator.Nums())
} }
} }
@ -242,13 +167,8 @@ func (c *ApiController) AddApplication() {
return return
} }
count, err := object.GetApplicationCount("", "", "") count := object.GetApplicationCount("", "", "")
if err != nil { if err := checkQuotaForApplication(count); err != nil {
c.ResponseError(err.Error())
return
}
if err := checkQuotaForApplication(int(count)); err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }

View File

@ -19,11 +19,11 @@ import (
"encoding/json" "encoding/json"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"io" "io/ioutil"
"net/http"
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"sync"
"github.com/casdoor/casdoor/captcha" "github.com/casdoor/casdoor/captcha"
"github.com/casdoor/casdoor/conf" "github.com/casdoor/casdoor/conf"
@ -33,7 +33,11 @@ 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 (
wechatScanType string
lock sync.RWMutex
) )
func codeToResponse(code *object.Code) *Response { func codeToResponse(code *object.Code) *Response {
@ -55,7 +59,7 @@ func tokenToResponse(token *object.Token) *Response {
func (c *ApiController) HandleLoggedIn(application *object.Application, user *object.User, form *form.AuthForm) (resp *Response) { func (c *ApiController) HandleLoggedIn(application *object.Application, user *object.User, form *form.AuthForm) (resp *Response) {
userId := user.GetId() userId := user.GetId()
allowed, err := object.CheckLoginPermission(userId, application) allowed, err := object.CheckAccessPermission(userId, application)
if err != nil { if err != nil {
c.ResponseError(err.Error(), nil) c.ResponseError(err.Error(), nil)
return return
@ -65,53 +69,10 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
return return
} }
// check user's tag if form.Password != "" && user.IsMfaEnabled() {
if !user.IsGlobalAdmin() && !user.IsAdmin && len(application.Tags) > 0 { c.setMfaSessionData(&object.MfaSessionData{UserId: userId})
// only users with the tag that is listed in the application tags can login resp = &Response{Status: object.NextMfa, Data: user.GetPreferMfa(true)}
if !util.InSlice(application.Tags, user.Tag) { return
c.ResponseError(fmt.Sprintf(c.T("auth:User's tag: %s is not listed in the application's tags"), user.Tag))
return
}
}
// check whether paid-user have active subscription
if user.Type == "paid-user" {
subscriptions, err := object.GetSubscriptionsByUser(user.Owner, user.Name)
if err != nil {
c.ResponseError(err.Error())
return
}
existActiveSubscription := false
for _, subscription := range subscriptions {
if subscription.State == object.SubStateActive {
existActiveSubscription = true
break
}
}
if !existActiveSubscription {
// check pending subscription
for _, sub := range subscriptions {
if sub.State == object.SubStatePending {
c.ResponseOk("BuyPlanResult", sub)
return
}
}
// paid-user does not have active or pending subscription, find the default pricing of application
pricing, err := object.GetApplicationDefaultPricing(application.Organization, application.Name)
if err != nil {
c.ResponseError(err.Error())
return
}
if pricing == nil {
c.ResponseError(fmt.Sprintf(c.T("auth:paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"), user.Name, application.Name))
return
} else {
// let the paid-user select plan
c.ResponseOk("SelectPlan", pricing)
return
}
}
} }
if form.Type == ResponseTypeLogin { if form.Type == ResponseTypeLogin {
@ -132,12 +93,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
c.ResponseError(c.T("auth:Challenge method should be S256")) c.ResponseError(c.T("auth:Challenge method should be S256"))
return return
} }
code, err := object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, c.Ctx.Request.Host, c.GetAcceptLanguage()) code := object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, c.Ctx.Request.Host, c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error(), nil)
return
}
resp = codeToResponse(code) resp = codeToResponse(code)
if application.EnableSigninSession || application.HasPromptPage() { if application.EnableSigninSession || application.HasPromptPage() {
@ -149,8 +105,7 @@ 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")
nonce := c.Input().Get("nonce") token, _ := object.GetTokenByUser(application, user, scope, c.Ctx.Request.Host)
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
@ -160,11 +115,6 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
return return
} }
resp = &Response{Status: "ok", Msg: "", Data: res, Data2: map[string]string{"redirectUrl": redirectUrl, "method": method}} resp = &Response{Status: "ok", Msg: "", Data: res, Data2: map[string]string{"redirectUrl": redirectUrl, "method": method}}
if application.EnableSigninSession || application.HasPromptPage() {
// The prompt page needs the user to be signed in
c.SetSessionUsername(userId)
}
} else if form.Type == ResponseTypeCas { } else if form.Type == ResponseTypeCas {
// not oauth but CAS SSO protocol // not oauth but CAS SSO protocol
service := c.Input().Get("service") service := c.Input().Get("service")
@ -177,11 +127,11 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
resp.Data = st resp.Data = st
} }
} }
if application.EnableSigninSession || application.HasPromptPage() { if application.EnableSigninSession || application.HasPromptPage() {
// The prompt page needs the user to be signed in // The prompt page needs the user to be signed in
c.SetSessionUsername(userId) c.SetSessionUsername(userId)
} }
} else { } else {
resp = wrapErrorResponse(fmt.Errorf("unknown response type: %s", form.Type)) resp = wrapErrorResponse(fmt.Errorf("unknown response type: %s", form.Type))
} }
@ -192,16 +142,12 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
} }
if resp.Status == "ok" { if resp.Status == "ok" {
_, err = object.AddSession(&object.Session{ object.AddSession(&object.Session{
Owner: user.Owner, Owner: user.Owner,
Name: user.Name, Name: user.Name,
Application: application.Name, Application: application.Name,
SessionId: []string{c.Ctx.Input.CruSession.SessionID()}, SessionId: []string{c.Ctx.Input.CruSession.SessionID()},
}) })
if err != nil {
c.ResponseError(err.Error(), nil)
return
}
} }
return resp return resp
@ -216,7 +162,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} controllers.Response The Response object // @Success 200 {object} 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")
@ -224,36 +170,8 @@ func (c *ApiController) GetApplicationLogin() {
redirectUri := c.Input().Get("redirectUri") redirectUri := c.Input().Get("redirectUri")
scope := c.Input().Get("scope") scope := c.Input().Get("scope")
state := c.Input().Get("state") state := c.Input().Get("state")
id := c.Input().Get("id")
loginType := c.Input().Get("type")
var application *object.Application
var msg string
var err error
if loginType == "code" {
msg, application, err = object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state, c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error())
return
}
} else if loginType == "cas" {
application, err = object.GetApplication(id)
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), id))
return
}
err = object.CheckCasLogin(application, c.GetAcceptLanguage(), redirectUri)
if err != nil {
c.ResponseError(err.Error())
return
}
}
msg, application := object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state, c.GetAcceptLanguage())
application = object.GetMaskedApplication(application, "") application = object.GetMaskedApplication(application, "")
if msg != "" { if msg != "" {
c.ResponseError(msg, application) c.ResponseError(msg, application)
@ -306,7 +224,7 @@ func isProxyProviderType(providerType string) bool {
// @Param code_challenge_method query string false code_challenge_method // @Param code_challenge_method query string false code_challenge_method
// @Param code_challenge query string false code_challenge // @Param code_challenge query string false code_challenge
// @Param form body controllers.AuthForm true "Login information" // @Param form body controllers.AuthForm true "Login information"
// @Success 200 {object} controllers.Response The Response object // @Success 200 {object} Response The Response object
// @router /login [post] // @router /login [post]
func (c *ApiController) Login() { func (c *ApiController) Login() {
resp := &Response{} resp := &Response{}
@ -327,37 +245,15 @@ 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 = object.GetUserByFields(authForm.Organization, authForm.Username); user == nil {
c.ResponseError(err.Error(), nil)
return
} else if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(authForm.Organization, authForm.Username))) c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(authForm.Organization, authForm.Username)))
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)
@ -369,55 +265,27 @@ func (c *ApiController) Login() {
} }
// check result through Email or Phone // check result through Email or Phone
err = object.CheckSigninCode(user, checkDest, authForm.Code, c.GetAcceptLanguage()) checkResult := object.CheckSigninCode(user, checkDest, authForm.Code, c.GetAcceptLanguage())
if err != nil { if len(checkResult) != 0 {
c.ResponseError(fmt.Sprintf("%s - %s", verificationCodeType, err.Error())) c.ResponseError(fmt.Sprintf("%s - %s", verificationCodeType, checkResult))
return return
} }
// disable the verification code // disable the verification code
err = object.DisableVerificationCode(checkDest) object.DisableVerificationCode(checkDest)
if err != nil {
c.ResponseError(err.Error(), nil)
return
}
} else { } else {
var application *object.Application application := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error(), nil)
return
}
if application == nil { if application == nil {
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 authForm.SigninMethod == "Password" && !application.IsPasswordEnabled() { if !application.EnablePassword {
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 = object.CheckToEnableCaptcha(application, authForm.Organization, authForm.Username); enableCaptcha {
c.ResponseError(err.Error()) isHuman, err := captcha.VerifyCaptchaByCaptchaType(authForm.CaptchaType, authForm.CaptchaToken, authForm.ClientSecret)
return
} else if enableCaptcha {
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
@ -430,53 +298,25 @@ func (c *ApiController) Login() {
} }
password := authForm.Password password := authForm.Password
isSigninViaLdap := authForm.SigninMethod == "LDAP" user, msg = object.CheckUserPassword(authForm.Organization, authForm.Username, password, c.GetAcceptLanguage(), enableCaptcha)
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 err != nil { if msg != "" {
c.ResponseError(err.Error()) resp = &Response{Status: "error", Msg: msg}
return
} else { } else {
var application *object.Application application := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil { if application == nil {
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
} }
var organization *object.Organization
organization, err = object.GetOrganizationByUser(user)
if err != nil {
c.ResponseError(err.Error())
}
if object.IsNeedPromptMfa(organization, user) {
// The prompt page needs the user to be signed in
c.SetSessionUsername(user.GetId())
c.ResponseOk(object.RequiredMfa)
return
}
if user.IsMfaEnabled() {
c.setMfaUserSession(user.GetId())
c.ResponseOk(object.NextMfa, user.GetPreferredMfaProps(true))
return
}
resp = c.HandleLoggedIn(application, user, &authForm) resp = c.HandleLoggedIn(application, user, &authForm)
organization := object.GetOrganizationByUser(user)
if user != nil && organization.HasRequiredMfa() && !user.IsMfaEnabled() {
resp.Msg = object.RequiredMfa
}
record := object.NewRecord(c.Ctx) record := object.NewRecord(c.Ctx)
record.Organization = application.Organization record.Organization = application.Organization
record.User = user.Name record.User = user.Name
@ -485,17 +325,9 @@ func (c *ApiController) Login() {
} else if authForm.Provider != "" { } else if authForm.Provider != "" {
var application *object.Application var application *object.Application
if authForm.ClientId != "" { if authForm.ClientId != "" {
application, err = object.GetApplicationByClientId(authForm.ClientId) application = object.GetApplicationByClientId(authForm.ClientId)
if err != nil {
c.ResponseError(err.Error())
return
}
} else { } else {
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application)) application = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error())
return
}
} }
if application == nil { if application == nil {
@ -503,41 +335,33 @@ func (c *ApiController) Login() {
return return
} }
var organization *object.Organization organization := object.GetOrganization(util.GetId("admin", application.Organization))
organization, err = object.GetOrganization(util.GetId("admin", application.Organization)) provider := object.GetProvider(util.GetId("admin", authForm.Provider))
if err != nil {
c.ResponseError(c.T(err.Error()))
}
var provider *object.Provider
provider, err = object.GetProvider(util.GetId("admin", authForm.Provider))
if err != nil {
c.ResponseError(err.Error())
return
}
providerItem := application.GetProviderItem(provider.Name) providerItem := application.GetProviderItem(provider.Name)
if !providerItem.IsProviderVisible() { if !providerItem.IsProviderVisible() {
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, err = object.ParseSamlResponse(authForm.SamlResponse, provider, c.Ctx.Request.Host) userInfo.Id, 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
} }
} else if provider.Category == "OAuth" || provider.Category == "Web3" { } else if provider.Category == "OAuth" {
// OAuth // OAuth
idpInfo := object.FromProviderToIdpInfo(c.Ctx, provider)
var idProvider idp.IdProvider clientId := provider.ClientId
idProvider, err = idp.GetIdProvider(idpInfo, authForm.RedirectUri) clientSecret := provider.ClientSecret
if err != nil { if provider.Type == "WeChat" && strings.Contains(c.Ctx.Request.UserAgent(), "MicroMessenger") {
c.ResponseError(err.Error()) clientId = provider.ClientId2
return clientSecret = provider.ClientSecret2
} }
idProvider := idp.GetIdProvider(provider.Type, provider.SubType, clientId, clientSecret, provider.AppId, authForm.RedirectUri, provider.Domain, provider.CustomAuthUrl, provider.CustomTokenUrl, provider.CustomUserInfoUrl)
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
@ -551,8 +375,7 @@ func (c *ApiController) Login() {
} }
// https://github.com/golang/oauth2/issues/123#issuecomment-103715338 // https://github.com/golang/oauth2/issues/123#issuecomment-103715338
var token *oauth2.Token token, err := idProvider.GetToken(authForm.Code)
token, err = idProvider.GetToken(authForm.Code)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -573,18 +396,9 @@ 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" {
// The userInfo.Id is the NameID in SAML response, it could be name / email / phone user = object.GetUser(util.GetId(application.Organization, userInfo.Id))
user, err = object.GetUserByFields(application.Organization, userInfo.Id) } else if provider.Category == "OAuth" {
if err != nil { user = object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
c.ResponseError(err.Error())
return
}
} else if provider.Category == "OAuth" || provider.Category == "Web3" {
user, err = object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
} }
if user != nil && !user.IsDeleted { if user != nil && !user.IsDeleted {
@ -593,37 +407,24 @@ 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)
record.Organization = application.Organization record.Organization = application.Organization
record.User = user.Name record.User = user.Name
util.SafeGoroutine(func() { object.AddRecord(record) }) util.SafeGoroutine(func() { object.AddRecord(record) })
} else if provider.Category == "OAuth" || provider.Category == "Web3" { } else if provider.Category == "OAuth" {
// Sign up via OAuth // Sign up via OAuth
if application.EnableLinkWithEmail { if application.EnableLinkWithEmail {
if userInfo.Email != "" { if userInfo.Email != "" {
// Find existing user with Email // Find existing user with Email
user, err = object.GetUserByField(application.Organization, "email", userInfo.Email) user = object.GetUserByField(application.Organization, "email", userInfo.Email)
if err != nil {
c.ResponseError(err.Error())
return
}
} }
if user == nil && userInfo.Phone != "" { if user == nil && userInfo.Phone != "" {
// Find existing user with phone number // Find existing user with phone number
user, err = object.GetUserByField(application.Organization, "phone", userInfo.Phone) user = object.GetUserByField(application.Organization, "phone", userInfo.Phone)
if err != nil {
c.ResponseError(err.Error())
return
}
} }
} }
@ -639,16 +440,9 @@ func (c *ApiController) Login() {
} }
// Handle username conflicts // Handle username conflicts
var tmpUser *object.User tmpUser := object.GetUser(util.GetId(application.Organization, userInfo.Username))
tmpUser, err = object.GetUser(util.GetId(application.Organization, userInfo.Username))
if err != nil {
c.ResponseError(err.Error())
return
}
if tmpUser != nil { if tmpUser != nil {
var uid uuid.UUID uid, err := uuid.NewRandom()
uid, err = uuid.NewRandom()
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -659,31 +453,18 @@ func (c *ApiController) Login() {
} }
properties := map[string]string{} properties := map[string]string{}
var count int64 properties["no"] = strconv.Itoa(object.GetUserCount(application.Organization, "", "") + 2)
count, err = object.GetUserCount(application.Organization, "", "", "") initScore, err := organization.GetInitScore()
if err != nil {
c.ResponseError(err.Error())
return
}
properties["no"] = strconv.Itoa(int(count + 2))
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
} }
userId := userInfo.Id
if userId == "" {
userId = util.GenerateId()
}
user = &object.User{ user = &object.User{
Owner: application.Organization, Owner: application.Organization,
Name: userInfo.Username, Name: userInfo.Username,
CreatedTime: util.GetCurrentTime(), CreatedTime: util.GetCurrentTime(),
Id: userId, Id: util.GenerateId(),
Type: "normal-user", Type: "normal-user",
DisplayName: userInfo.DisplayName, DisplayName: userInfo.DisplayName,
Avatar: userInfo.AvatarUrl, Avatar: userInfo.AvatarUrl,
@ -694,46 +475,23 @@ func (c *ApiController) Login() {
Region: userInfo.CountryCode, Region: userInfo.CountryCode,
Score: initScore, Score: initScore,
IsAdmin: false, IsAdmin: false,
IsGlobalAdmin: false,
IsForbidden: false, IsForbidden: false,
IsDeleted: false, IsDeleted: false,
SignupApplication: application.Name, SignupApplication: application.Name,
Properties: properties, Properties: properties,
} }
var affected bool affected := object.AddUser(user)
affected, err = object.AddUser(user)
if err != nil {
c.ResponseError(err.Error())
return
}
if !affected { if !affected {
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) object.SetUserOAuthProperties(organization, user, provider.Type, userInfo)
if err != nil { object.LinkUserAccount(user, provider.Type, userInfo.Id)
c.ResponseError(err.Error())
return
}
_, err = object.LinkUserAccount(user, provider.Type, userInfo.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
resp = c.HandleLoggedIn(application, user, &authForm) resp = c.HandleLoggedIn(application, user, &authForm)
@ -748,7 +506,6 @@ 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}
@ -759,94 +516,51 @@ func (c *ApiController) Login() {
return return
} }
var oldUser *object.User oldUser := object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
oldUser, err = object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
if oldUser != nil { if oldUser != nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)"), provider.Type, userInfo.Username, userInfo.DisplayName, oldUser.Name, oldUser.DisplayName)) c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)"), provider.Type, userInfo.Username, userInfo.DisplayName, oldUser.Name, oldUser.DisplayName))
return return
} }
var user *object.User user := object.GetUser(userId)
user, err = object.GetUser(userId)
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) object.SetUserOAuthProperties(organization, user, provider.Type, userInfo)
if err != nil {
c.ResponseError(err.Error())
return
}
var isLinked bool
isLinked, err = object.LinkUserAccount(user, provider.Type, userInfo.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
isLinked := object.LinkUserAccount(user, provider.Type, userInfo.Id)
if isLinked { if isLinked {
resp = &Response{Status: "ok", Msg: "", Data: isLinked} resp = &Response{Status: "ok", Msg: "", Data: isLinked}
} else { } else {
resp = &Response{Status: "error", Msg: "Failed to link user account", Data: isLinked} resp = &Response{Status: "error", Msg: "Failed to link user account", Data: isLinked}
} }
} }
} else if c.getMfaUserSession() != "" { } else if c.getMfaSessionData() != nil {
var user *object.User mfaSession := c.getMfaSessionData()
user, err = object.GetUser(c.getMfaUserSession()) user := object.GetUser(mfaSession.UserId)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError("expired user session")
return
}
if authForm.Passcode != "" { if authForm.Passcode != "" {
mfaUtil := object.GetMfaUtil(authForm.MfaType, user.GetPreferredMfaProps(false)) MfaUtil := object.GetMfaUtil(authForm.MfaType, user.GetPreferMfa(false))
if mfaUtil == nil { err = MfaUtil.Verify(authForm.Passcode)
c.ResponseError("Invalid multi-factor authentication type")
return
}
err = mfaUtil.Verify(authForm.Passcode)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
} else if authForm.RecoveryCode != "" { }
err = object.MfaRecover(user, authForm.RecoveryCode) if authForm.RecoveryCode != "" {
err = object.RecoverTfs(user, authForm.RecoveryCode)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
} else {
c.ResponseError("missing passcode or recovery code")
return
}
var application *object.Application
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error())
return
} }
application := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if application == nil { if application == nil {
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
} }
resp = c.HandleLoggedIn(application, user, &authForm) resp = c.HandleLoggedIn(application, user, &authForm)
c.setMfaUserSession("")
record := object.NewRecord(c.Ctx) record := object.NewRecord(c.Ctx)
record.Organization = application.Organization record.Organization = application.Organization
@ -855,13 +569,7 @@ 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
var application *object.Application application := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil { if application == nil {
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
@ -906,119 +614,50 @@ func (c *ApiController) HandleSamlLogin() {
samlResponse = url.QueryEscape(samlResponse) samlResponse = url.QueryEscape(samlResponse)
targetUrl := fmt.Sprintf("%s?relayState=%s&samlResponse=%s", targetUrl := fmt.Sprintf("%s?relayState=%s&samlResponse=%s",
slice[4], relayState, samlResponse) slice[4], relayState, samlResponse)
c.Redirect(targetUrl, http.StatusSeeOther) c.Redirect(targetUrl, 303)
} }
// HandleOfficialAccountEvent ... // HandleOfficialAccountEvent ...
// @Tag System API // @Tag HandleOfficialAccountEvent API
// @Title HandleOfficialAccountEvent // @Title HandleOfficialAccountEvent
// @router /webhook [POST] // @router /api/webhook [POST]
// @Success 200 {object} controllers.Response The Response object
func (c *ApiController) HandleOfficialAccountEvent() { func (c *ApiController) HandleOfficialAccountEvent() {
if c.Ctx.Request.Method == "GET" { respBytes, err := ioutil.ReadAll(c.Ctx.Request.Body)
s := c.Ctx.Request.FormValue("echostr")
echostr, _ := strconv.Atoi(s)
c.SetData(echostr)
c.ServeJSON()
return
}
respBytes, err := io.ReadAll(c.Ctx.Request.Body)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return
} }
signature := c.Input().Get("signature")
timestamp := c.Input().Get("timestamp")
nonce := c.Input().Get("nonce")
var data struct { var data struct {
MsgType string `xml:"MsgType"` MsgType string `xml:"MsgType"`
Event string `xml:"Event"` Event string `xml:"Event"`
EventKey string `xml:"EventKey"` EventKey string `xml:"EventKey"`
FromUserName string `xml:"FromUserName"`
Ticket string `xml:"Ticket"`
} }
err = xml.Unmarshal(respBytes, &data) err = xml.Unmarshal(respBytes, &data)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return
} }
if strings.ToUpper(data.Event) != "SCAN" && strings.ToUpper(data.Event) != "SUBSCRIBE" { lock.Lock()
defer lock.Unlock()
if data.EventKey != "" {
wechatScanType = data.Event
c.Ctx.WriteString("") c.Ctx.WriteString("")
return
} }
if data.Ticket == "" {
c.ResponseError(err.Error())
return
}
providerId := data.EventKey
provider, err := object.GetProvider(providerId)
if err != nil {
c.ResponseError(err.Error())
return
}
if data.Ticket == "" {
c.ResponseError("empty ticket")
return
}
if !idp.VerifyWechatSignature(provider.Content, nonce, timestamp, signature) {
c.ResponseError("invalid signature")
return
}
idp.Lock.Lock()
if idp.WechatCacheMap == nil {
idp.WechatCacheMap = make(map[string]idp.WechatCacheMapValue)
}
idp.WechatCacheMap[data.Ticket] = idp.WechatCacheMapValue{
IsScanned: true,
WechatUnionId: data.FromUserName,
}
idp.Lock.Unlock()
c.Ctx.WriteString("")
} }
// GetWebhookEventType ... // GetWebhookEventType ...
// @Tag System API // @Tag GetWebhookEventType API
// @Title GetWebhookEventType // @Title GetWebhookEventType
// @router /get-webhook-event [GET] // @router /api/get-webhook-event [GET]
// @Param ticket query string true "The eventId of QRCode"
// @Success 200 {object} controllers.Response The Response object
func (c *ApiController) GetWebhookEventType() { func (c *ApiController) GetWebhookEventType() {
ticket := c.Input().Get("ticket") lock.Lock()
defer lock.Unlock()
idp.Lock.RLock() resp := &Response{
_, ok := idp.WechatCacheMap[ticket] Status: "ok",
idp.Lock.RUnlock() Msg: "",
if !ok { Data: wechatScanType,
c.ResponseError("ticket not found")
return
} }
c.Data["json"] = resp
c.ResponseOk("SCAN", ticket) wechatScanType = ""
} c.ServeJSON()
// GetQRCode
// @Tag System API
// @Title GetWechatQRCode
// @router /get-qrcode [GET]
// @Param id query string true "The id ( owner/name ) of provider"
// @Success 200 {object} controllers.Response The Response object
func (c *ApiController) GetQRCode() {
providerId := c.Input().Get("id")
provider, err := object.GetProvider(providerId)
if err != nil {
c.ResponseError(err.Error())
return
}
code, ticket, err := idp.GetWechatOfficialAccountQRCode(provider.ClientId2, provider.ClientSecret2, providerId)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(code, ticket)
} }
// GetCaptchaStatus // GetCaptchaStatus
@ -1027,43 +666,14 @@ func (c *ApiController) GetQRCode() {
// @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 /get-captcha-status [get] // @router /api/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("userId") userId := c.Input().Get("user_id")
user, err := object.GetUserByFields(organization, userId) user := object.GetUserByFields(organization, userId)
if err != nil { var captchaEnabled bool
c.ResponseError(err.Error()) if user != nil && user.SigninWrongTimes >= object.SigninWrongTimesLimit {
return captchaEnabled = true
} }
captchaEnabled := false
if user != nil {
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)
} }
// Callback
// @Title Callback
// @Tag Callback API
// @Description Get Login Error Counts
// @router /Callback [post]
// @Success 200 {object} object.Userinfo The Response object
func (c *ApiController) Callback() {
code := c.GetString("code")
state := c.GetString("state")
frontendCallbackUrl := fmt.Sprintf("/callback?code=%s&state=%s", code, state)
c.Ctx.Redirect(http.StatusFound, frontendCallbackUrl)
}

View File

@ -55,22 +55,6 @@ func (c *ApiController) IsAdmin() bool {
return isGlobalAdmin || user.IsAdmin return isGlobalAdmin || user.IsAdmin
} }
func (c *ApiController) IsAdminOrSelf(user2 *object.User) bool {
isGlobalAdmin, user := c.isGlobalAdmin()
if isGlobalAdmin || (user != nil && user.IsAdmin) {
return true
}
if user == nil || user2 == nil {
return false
}
if user.Owner == user2.Owner && user.Name == user2.Name {
return true
}
return false
}
func (c *ApiController) isGlobalAdmin() (bool, *object.User) { func (c *ApiController) isGlobalAdmin() (bool, *object.User) {
username := c.GetSessionUsername() username := c.GetSessionUsername()
if strings.HasPrefix(username, "app/") { if strings.HasPrefix(username, "app/") {
@ -83,21 +67,16 @@ func (c *ApiController) isGlobalAdmin() (bool, *object.User) {
return false, nil return false, nil
} }
return user.IsGlobalAdmin(), user return user.Owner == "built-in" || user.IsGlobalAdmin, user
} }
func (c *ApiController) getCurrentUser() *object.User { func (c *ApiController) getCurrentUser() *object.User {
var user *object.User var user *object.User
var err error
userId := c.GetSessionUsername() userId := c.GetSessionUsername()
if userId == "" { if userId == "" {
user = nil user = nil
} else { } else {
user, err = object.GetUser(userId) user = object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return nil
}
} }
return user return user
} }
@ -127,12 +106,7 @@ func (c *ApiController) GetSessionApplication() *object.Application {
if clientId == nil { if clientId == nil {
return nil return nil
} }
application, err := object.GetApplicationByClientId(clientId.(string)) application := object.GetApplicationByClientId(clientId.(string))
if err != nil {
c.ResponseError(err.Error())
return nil
}
return application return application
} }
@ -194,16 +168,20 @@ func (c *ApiController) SetSessionData(s *SessionData) {
c.SetSession("SessionData", util.StructToJson(s)) c.SetSession("SessionData", util.StructToJson(s))
} }
func (c *ApiController) setMfaUserSession(userId string) { func (c *ApiController) setMfaSessionData(data *object.MfaSessionData) {
c.SetSession(object.MfaSessionUserId, userId) c.SetSession(object.MfaSessionUserId, data.UserId)
} }
func (c *ApiController) getMfaUserSession() string { func (c *ApiController) getMfaSessionData() *object.MfaSessionData {
userId := c.Ctx.Input.CruSession.Get(object.MfaSessionUserId) userId := c.GetSession(object.MfaSessionUserId)
if userId == nil { if userId == nil {
return "" return nil
} }
return userId.(string)
data := &object.MfaSessionData{
UserId: userId.(string),
}
return data
} }
func (c *ApiController) setExpireForSession() { func (c *ApiController) setExpireForSession() {
@ -214,10 +192,8 @@ func (c *ApiController) setExpireForSession() {
}) })
} }
func wrapActionResponse(affected bool, e ...error) *Response { func wrapActionResponse(affected bool) *Response {
if len(e) != 0 && e[0] != nil { if affected {
return &Response{Status: "error", Msg: e[0].Error()}
} else if affected {
return &Response{Status: "ok", Msg: "", Data: "Affected"} return &Response{Status: "ok", Msg: "", Data: "Affected"}
} else { } else {
return &Response{Status: "ok", Msg: "", Data: "Unaffected"} return &Response{Status: "ok", Msg: "", Data: "Unaffected"}

View File

@ -35,11 +35,6 @@ const (
UnauthorizedService string = "UNAUTHORIZED_SERVICE" UnauthorizedService string = "UNAUTHORIZED_SERVICE"
) )
func queryUnescape(service string) string {
s, _ := url.QueryUnescape(service)
return s
}
func (c *RootController) CasValidate() { func (c *RootController) CasValidate() {
ticket := c.Input().Get("ticket") ticket := c.Input().Get("ticket")
service := c.Input().Get("service") service := c.Input().Get("service")
@ -65,25 +60,24 @@ func (c *RootController) CasServiceValidate() {
if !strings.HasPrefix(ticket, "ST") { if !strings.HasPrefix(ticket, "ST") {
c.sendCasAuthenticationResponseErr(InvalidTicket, fmt.Sprintf("Ticket %s not recognized", ticket), format) c.sendCasAuthenticationResponseErr(InvalidTicket, fmt.Sprintf("Ticket %s not recognized", ticket), format)
} }
c.CasP3ProxyValidate() c.CasP3ServiceAndProxyValidate()
} }
func (c *RootController) CasProxyValidate() { func (c *RootController) CasProxyValidate() {
// https://apereo.github.io/cas/6.6.x/protocol/CAS-Protocol-Specification.html#26-proxyvalidate-cas-20
// "/proxyValidate" should accept both service tickets and proxy tickets.
c.CasP3ProxyValidate()
}
func (c *RootController) CasP3ServiceValidate() {
ticket := c.Input().Get("ticket") ticket := c.Input().Get("ticket")
format := c.Input().Get("format") format := c.Input().Get("format")
if !strings.HasPrefix(ticket, "ST") { if !strings.HasPrefix(ticket, "PT") {
c.sendCasAuthenticationResponseErr(InvalidTicket, fmt.Sprintf("Ticket %s not recognized", ticket), format) c.sendCasAuthenticationResponseErr(InvalidTicket, fmt.Sprintf("Ticket %s not recognized", ticket), format)
} }
c.CasP3ProxyValidate() c.CasP3ServiceAndProxyValidate()
} }
func (c *RootController) CasP3ProxyValidate() { func queryUnescape(service string) string {
s, _ := url.QueryUnescape(service)
return s
}
func (c *RootController) CasP3ServiceAndProxyValidate() {
ticket := c.Input().Get("ticket") ticket := c.Input().Get("ticket")
format := c.Input().Get("format") format := c.Input().Get("format")
service := c.Input().Get("service") service := c.Input().Get("service")
@ -121,17 +115,15 @@ func (c *RootController) CasP3ProxyValidate() {
pgtiou := serviceResponse.Success.ProxyGrantingTicket pgtiou := serviceResponse.Success.ProxyGrantingTicket
// todo: check whether it is https // todo: check whether it is https
pgtUrlObj, err := url.Parse(pgtUrl) pgtUrlObj, err := url.Parse(pgtUrl)
if err != nil {
c.sendCasAuthenticationResponseErr(InvalidProxyCallback, err.Error(), format)
return
}
if pgtUrlObj.Scheme != "https" { if pgtUrlObj.Scheme != "https" {
c.sendCasAuthenticationResponseErr(InvalidProxyCallback, "callback is not https", format) c.sendCasAuthenticationResponseErr(InvalidProxyCallback, "callback is not https", format)
return return
} }
// make a request to pgturl passing pgt and pgtiou // make a request to pgturl passing pgt and pgtiou
if err != nil {
c.sendCasAuthenticationResponseErr(InternalError, err.Error(), format)
return
}
param := pgtUrlObj.Query() param := pgtUrlObj.Query()
param.Add("pgtId", pgt) param.Add("pgtId", pgt)
param.Add("pgtIou", pgtiou) param.Add("pgtIou", pgtiou)
@ -271,6 +263,7 @@ func (c *RootController) sendCasAuthenticationResponseErr(code, msg, format stri
Message: msg, Message: msg,
}, },
} }
if format == "json" { if format == "json" {
c.Data["json"] = serviceResponse c.Data["json"] = serviceResponse
c.ServeJSON() c.ServeJSON()

View File

@ -0,0 +1,158 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package controllers
import (
"encoding/json"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
xormadapter "github.com/casdoor/xorm-adapter/v3"
)
func (c *ApiController) GetCasbinAdapters() {
owner := c.Input().Get("owner")
limit := c.Input().Get("pageSize")
page := c.Input().Get("p")
field := c.Input().Get("field")
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
organization := c.Input().Get("organization")
if limit == "" || page == "" {
adapters := object.GetCasbinAdapters(owner, organization)
c.ResponseOk(adapters)
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetCasbinAdapterCount(owner, organization, field, value)))
adapters := object.GetPaginationCasbinAdapters(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseOk(adapters, paginator.Nums())
}
}
func (c *ApiController) GetCasbinAdapter() {
id := c.Input().Get("id")
adapter := object.GetCasbinAdapter(id)
c.ResponseOk(adapter)
}
func (c *ApiController) UpdateCasbinAdapter() {
id := c.Input().Get("id")
var casbinAdapter object.CasbinAdapter
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.UpdateCasbinAdapter(id, &casbinAdapter))
c.ServeJSON()
}
func (c *ApiController) AddCasbinAdapter() {
var casbinAdapter object.CasbinAdapter
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.AddCasbinAdapter(&casbinAdapter))
c.ServeJSON()
}
func (c *ApiController) DeleteCasbinAdapter() {
var casbinAdapter object.CasbinAdapter
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.DeleteCasbinAdapter(&casbinAdapter))
c.ServeJSON()
}
func (c *ApiController) SyncPolicies() {
id := c.Input().Get("id")
adapter := object.GetCasbinAdapter(id)
policies, err := object.SyncPolicies(adapter)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(policies)
}
func (c *ApiController) UpdatePolicy() {
id := c.Input().Get("id")
adapter := object.GetCasbinAdapter(id)
var policies []xormadapter.CasbinRule
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policies)
if err != nil {
c.ResponseError(err.Error())
return
}
affected, err := object.UpdatePolicy(util.CasbinToSlice(policies[0]), util.CasbinToSlice(policies[1]), adapter)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(affected)
c.ServeJSON()
}
func (c *ApiController) AddPolicy() {
id := c.Input().Get("id")
adapter := object.GetCasbinAdapter(id)
var policy xormadapter.CasbinRule
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
if err != nil {
c.ResponseError(err.Error())
return
}
affected, err := object.AddPolicy(util.CasbinToSlice(policy), adapter)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(affected)
c.ServeJSON()
}
func (c *ApiController) RemovePolicy() {
id := c.Input().Get("id")
adapter := object.GetCasbinAdapter(id)
var policy xormadapter.CasbinRule
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
if err != nil {
c.ResponseError(err.Error())
return
}
affected, err := object.RemovePolicy(util.CasbinToSlice(policy), adapter)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(affected)
c.ServeJSON()
}

View File

@ -1,329 +0,0 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package controllers
import (
"encoding/json"
"fmt"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
// Enforce
// @Title Enforce
// @Tag Enforcer API
// @Description Call Casbin Enforce API
// @Param body body []string true "Casbin request"
// @Param permissionId query string false "permission id"
// @Param modelId query string false "model id"
// @Param resourceId query string false "resource id"
// @Param owner query string false "owner"
// @Success 200 {object} controllers.Response The Response object
// @router /enforce [post]
func (c *ApiController) Enforce() {
permissionId := c.Input().Get("permissionId")
modelId := c.Input().Get("modelId")
resourceId := c.Input().Get("resourceId")
enforcerId := c.Input().Get("enforcerId")
owner := c.Input().Get("owner")
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)
if err != nil {
c.ResponseError(err.Error())
return
}
if enforcerId != "" {
enforcer, err := object.GetInitializedEnforcer(enforcerId)
if err != nil {
c.ResponseError(err.Error())
return
}
res := []bool{}
keyRes := []string{}
// type transformation
interfaceRequest := util.StringToInterfaceArray(request)
enforceResult, err := enforcer.Enforce(interfaceRequest...)
if err != nil {
c.ResponseError(err.Error())
return
}
res = append(res, enforceResult)
keyRes = append(keyRes, enforcer.GetModelAndAdapter())
c.ResponseOk(res, keyRes)
return
}
if permissionId != "" {
permission, err := object.GetPermission(permissionId)
if err != nil {
c.ResponseError(err.Error())
return
}
if permission == nil {
c.ResponseError(fmt.Sprintf("permission: %s doesn't exist", permissionId))
return
}
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
}
permissions := []*object.Permission{}
if modelId != "" {
owner, modelName := util.GetOwnerAndNameFromId(modelId)
permissions, err = object.GetPermissionsByModel(owner, modelName)
if err != nil {
c.ResponseError(err.Error())
return
}
} else if resourceId != "" {
permissions, err = object.GetPermissionsByResource(resourceId)
if err != nil {
c.ResponseError(err.Error())
return
}
} else if owner != "" {
permissions, err = object.GetPermissions(owner)
if err != nil {
c.ResponseError(err.Error())
return
}
} else {
c.ResponseError(c.T("general:Missing parameter"))
return
}
res := []bool{}
keyRes := []string{}
listPermissionIdMap := object.GroupPermissionsByModelAdapter(permissions)
for key, permissionIds := range listPermissionIdMap {
firstPermission, err := object.GetPermission(permissionIds[0])
if err != nil {
c.ResponseError(err.Error())
return
}
enforceResult, err := object.Enforce(firstPermission, request, permissionIds...)
if err != nil {
c.ResponseError(err.Error())
return
}
res = append(res, enforceResult)
keyRes = append(keyRes, key)
}
c.ResponseOk(res, keyRes)
}
// BatchEnforce
// @Title BatchEnforce
// @Tag Enforcer API
// @Description Call Casbin BatchEnforce API
// @Param body body []string true "array of casbin requests"
// @Param permissionId query string false "permission id"
// @Param modelId query string false "model id"
// @Param owner query string false "owner"
// @Success 200 {object} controllers.Response The Response object
// @router /batch-enforce [post]
func (c *ApiController) BatchEnforce() {
permissionId := c.Input().Get("permissionId")
modelId := c.Input().Get("modelId")
enforcerId := c.Input().Get("enforcerId")
owner := c.Input().Get("owner")
var requests [][]string
err := json.Unmarshal(c.Ctx.Input.RequestBody, &requests)
if err != nil {
c.ResponseError(err.Error())
return
}
if enforcerId != "" {
enforcer, err := object.GetInitializedEnforcer(enforcerId)
if err != nil {
c.ResponseError(err.Error())
return
}
res := [][]bool{}
keyRes := []string{}
// type transformation
interfaceRequests := util.StringToInterfaceArray2d(requests)
enforceResult, err := enforcer.BatchEnforce(interfaceRequests)
if err != nil {
c.ResponseError(err.Error())
return
}
res = append(res, enforceResult)
keyRes = append(keyRes, enforcer.GetModelAndAdapter())
c.ResponseOk(res, keyRes)
return
}
if permissionId != "" {
permission, err := object.GetPermission(permissionId)
if err != nil {
c.ResponseError(err.Error())
return
}
if permission == nil {
c.ResponseError(fmt.Sprintf("permission: %s doesn't exist", permissionId))
return
}
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
}
permissions := []*object.Permission{}
if modelId != "" {
owner, modelName := util.GetOwnerAndNameFromId(modelId)
permissions, err = object.GetPermissionsByModel(owner, modelName)
if err != nil {
c.ResponseError(err.Error())
return
}
} else if owner != "" {
permissions, err = object.GetPermissions(owner)
if err != nil {
c.ResponseError(err.Error())
return
}
} else {
c.ResponseError(c.T("general:Missing parameter"))
return
}
res := [][]bool{}
keyRes := []string{}
listPermissionIdMap := object.GroupPermissionsByModelAdapter(permissions)
for _, permissionIds := range listPermissionIdMap {
firstPermission, err := object.GetPermission(permissionIds[0])
if err != nil {
c.ResponseError(err.Error())
return
}
enforceResult, err := object.BatchEnforce(firstPermission, requests, permissionIds...)
if err != nil {
c.ResponseError(err.Error())
return
}
res = append(res, enforceResult)
keyRes = append(keyRes, firstPermission.GetModelAndAdapter())
}
c.ResponseOk(res, keyRes)
}
func (c *ApiController) GetAllObjects() {
userId := c.Input().Get("userId")
if userId == "" {
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
}
c.ResponseOk(objects)
}
func (c *ApiController) GetAllActions() {
userId := c.Input().Get("userId")
if userId == "" {
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
}
c.ResponseOk(actions)
}
func (c *ApiController) GetAllRoles() {
userId := c.Input().Get("userId")
if userId == "" {
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
}
c.ResponseOk(roles)
}

View File

@ -37,71 +37,37 @@ func (c *ApiController) GetCerts() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
certs, err := object.GetMaskedCerts(object.GetCerts(owner)) c.Data["json"] = object.GetMaskedCerts(object.GetCerts(owner))
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(certs)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetCertCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetCertCount(owner, field, value)))
if err != nil { certs := object.GetMaskedCerts(object.GetPaginationCerts(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
certs, err := object.GetMaskedCerts(object.GetPaginationCerts(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(certs, paginator.Nums()) c.ResponseOk(certs, paginator.Nums())
} }
} }
// GetGlobalCerts // GetGlobleCerts
// @Title GetGlobalCerts // @Title GetGlobleCerts
// @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-global-certs [get] // @router /get-globle-certs [get]
func (c *ApiController) GetGlobalCerts() { func (c *ApiController) GetGlobleCerts() {
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")
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
certs, err := object.GetMaskedCerts(object.GetGlobalCerts()) c.Data["json"] = object.GetMaskedCerts(object.GetGlobleCerts())
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(certs)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetGlobalCertsCount(field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetGlobalCertsCount(field, value)))
if err != nil { certs := object.GetMaskedCerts(object.GetPaginationGlobalCerts(paginator.Offset(), limit, field, value, sortField, sortOrder))
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
certs, err := object.GetMaskedCerts(object.GetPaginationGlobalCerts(paginator.Offset(), limit, field, value, sortField, sortOrder))
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(certs, paginator.Nums()) c.ResponseOk(certs, paginator.Nums())
} }
} }
@ -115,13 +81,9 @@ func (c *ApiController) GetGlobalCerts() {
// @router /get-cert [get] // @router /get-cert [get]
func (c *ApiController) GetCert() { func (c *ApiController) GetCert() {
id := c.Input().Get("id") id := c.Input().Get("id")
cert, err := object.GetCert(id)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(object.GetMaskedCert(cert)) c.Data["json"] = object.GetMaskedCert(object.GetCert(id))
c.ServeJSON()
} }
// UpdateCert // UpdateCert

124
controllers/chat.go Normal file
View File

@ -0,0 +1,124 @@
// 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"
)
// GetChats
// @Title GetChats
// @Tag Chat API
// @Description get chats
// @Param owner query string true "The owner of chats"
// @Success 200 {array} object.Chat The Response object
// @router /get-chats [get]
func (c *ApiController) GetChats() {
owner := c.Input().Get("owner")
owner = "admin"
limit := c.Input().Get("pageSize")
page := c.Input().Get("p")
field := c.Input().Get("field")
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetMaskedChats(object.GetChats(owner))
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetChatCount(owner, field, value)))
chats := object.GetMaskedChats(object.GetPaginationChats(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
c.ResponseOk(chats, paginator.Nums())
}
}
// GetChat
// @Title GetChat
// @Tag Chat API
// @Description get chat
// @Param id query string true "The id ( owner/name ) of the chat"
// @Success 200 {object} object.Chat The Response object
// @router /get-chat [get]
func (c *ApiController) GetChat() {
id := c.Input().Get("id")
c.Data["json"] = object.GetMaskedChat(object.GetChat(id))
c.ServeJSON()
}
// UpdateChat
// @Title UpdateChat
// @Tag Chat API
// @Description update chat
// @Param id query string true "The id ( owner/name ) of the chat"
// @Param body body object.Chat true "The details of the chat"
// @Success 200 {object} controllers.Response The Response object
// @router /update-chat [post]
func (c *ApiController) UpdateChat() {
id := c.Input().Get("id")
var chat object.Chat
err := json.Unmarshal(c.Ctx.Input.RequestBody, &chat)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.UpdateChat(id, &chat))
c.ServeJSON()
}
// AddChat
// @Title AddChat
// @Tag Chat API
// @Description add chat
// @Param body body object.Chat true "The details of the chat"
// @Success 200 {object} controllers.Response The Response object
// @router /add-chat [post]
func (c *ApiController) AddChat() {
var chat object.Chat
err := json.Unmarshal(c.Ctx.Input.RequestBody, &chat)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.AddChat(&chat))
c.ServeJSON()
}
// DeleteChat
// @Title DeleteChat
// @Tag Chat API
// @Description delete chat
// @Param body body object.Chat true "The details of the chat"
// @Success 200 {object} controllers.Response The Response object
// @router /delete-chat [post]
func (c *ApiController) DeleteChat() {
var chat object.Chat
err := json.Unmarshal(c.Ctx.Input.RequestBody, &chat)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.DeleteChat(&chat))
c.ServeJSON()
}

View File

@ -1,4 +1,4 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved. // Copyright 2022 The Casdoor Authors. All Rights Reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -17,223 +17,101 @@ package controllers
import ( import (
"encoding/json" "encoding/json"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
xormadapter "github.com/casdoor/xorm-adapter/v3"
) )
// GetEnforcers func (c *ApiController) Enforce() {
// @Title GetEnforcers permissionId := c.Input().Get("permissionId")
// @Tag Enforcer API modelId := c.Input().Get("modelId")
// @Description get enforcers resourceId := c.Input().Get("resourceId")
// @Param owner query string true "The owner of enforcers"
// @Success 200 {array} object.Enforcer
// @router /get-enforcers [get]
func (c *ApiController) GetEnforcers() {
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 == "" { var request object.CasbinRequest
enforcers, err := object.GetEnforcers(owner) err := json.Unmarshal(c.Ctx.Input.RequestBody, &request)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.ResponseOk(enforcers) if permissionId != "" {
c.Data["json"] = object.Enforce(permissionId, &request)
c.ServeJSON()
return
}
permissions := make([]*object.Permission, 0)
res := []bool{}
if modelId != "" {
owner, modelName := util.GetOwnerAndNameFromId(modelId)
permissions = object.GetPermissionsByModel(owner, modelName)
} else { } else {
limit := util.ParseInt(limit) permissions = object.GetPermissionsByResource(resourceId)
count, err := object.GetEnforcerCount(owner, field, value) }
if err != nil {
c.ResponseError(err.Error()) for _, permission := range permissions {
return res = append(res, object.Enforce(permission.GetId(), &request))
}
c.Data["json"] = res
c.ServeJSON()
}
func (c *ApiController) BatchEnforce() {
permissionId := c.Input().Get("permissionId")
modelId := c.Input().Get("modelId")
var requests []object.CasbinRequest
err := json.Unmarshal(c.Ctx.Input.RequestBody, &requests)
if err != nil {
c.ResponseError(err.Error())
return
}
if permissionId != "" {
c.Data["json"] = object.BatchEnforce(permissionId, &requests)
c.ServeJSON()
} else {
owner, modelName := util.GetOwnerAndNameFromId(modelId)
permissions := object.GetPermissionsByModel(owner, modelName)
res := [][]bool{}
for _, permission := range permissions {
res = append(res, object.BatchEnforce(permission.GetId(), &requests))
} }
c.Data["json"] = res
paginator := pagination.SetPaginator(c.Ctx, limit, count) c.ServeJSON()
enforcers, err := object.GetPaginationEnforcers(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(enforcers, paginator.Nums())
} }
} }
// GetEnforcer func (c *ApiController) GetAllObjects() {
// @Title GetEnforcer userId := c.GetSessionUsername()
// @Tag Enforcer API if userId == "" {
// @Description get enforcer c.ResponseError(c.T("general:Please login first"))
// @Param id query string true "The id ( owner/name ) of enforcer"
// @Success 200 {object} object.Enforcer
// @router /get-enforcer [get]
func (c *ApiController) GetEnforcer() {
id := c.Input().Get("id")
loadModelCfg := c.Input().Get("loadModelCfg")
enforcer, err := object.GetEnforcer(id)
if err != nil {
c.ResponseError(err.Error())
return return
} }
if loadModelCfg == "true" && enforcer.Model != "" { c.Data["json"] = object.GetAllObjects(userId)
err := enforcer.LoadModelCfg()
if err != nil {
return
}
}
c.ResponseOk(enforcer)
}
// UpdateEnforcer
// @Title UpdateEnforcer
// @Tag Enforcer API
// @Description update enforcer
// @Param id query string true "The id ( owner/name ) of enforcer"
// @Param enforcer body object true "The enforcer object"
// @Success 200 {object} object.Enforcer
// @router /update-enforcer [post]
func (c *ApiController) UpdateEnforcer() {
id := c.Input().Get("id")
enforcer := object.Enforcer{}
err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.UpdateEnforcer(id, &enforcer))
c.ServeJSON() c.ServeJSON()
} }
// AddEnforcer func (c *ApiController) GetAllActions() {
// @Title AddEnforcer userId := c.GetSessionUsername()
// @Tag Enforcer API if userId == "" {
// @Description add enforcer c.ResponseError(c.T("general:Please login first"))
// @Param enforcer body object true "The enforcer object"
// @Success 200 {object} object.Enforcer
// @router /add-enforcer [post]
func (c *ApiController) AddEnforcer() {
enforcer := object.Enforcer{}
err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
if err != nil {
c.ResponseError(err.Error())
return return
} }
c.Data["json"] = wrapActionResponse(object.AddEnforcer(&enforcer)) c.Data["json"] = object.GetAllActions(userId)
c.ServeJSON() c.ServeJSON()
} }
// DeleteEnforcer func (c *ApiController) GetAllRoles() {
// @Title DeleteEnforcer userId := c.GetSessionUsername()
// @Tag Enforcer API if userId == "" {
// @Description delete enforcer c.ResponseError(c.T("general:Please login first"))
// @Param body body object.Enforcer true "The enforcer object"
// @Success 200 {object} object.Enforcer
// @router /delete-enforcer [post]
func (c *ApiController) DeleteEnforcer() {
var enforcer object.Enforcer
err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
if err != nil {
c.ResponseError(err.Error())
return return
} }
c.Data["json"] = wrapActionResponse(object.DeleteEnforcer(&enforcer)) c.Data["json"] = object.GetAllRoles(userId)
c.ServeJSON()
}
func (c *ApiController) GetPolicies() {
id := c.Input().Get("id")
adapterId := c.Input().Get("adapterId")
if adapterId != "" {
adapter, err := object.GetAdapter(adapterId)
if err != nil {
c.ResponseError(err.Error())
return
}
err = adapter.InitAdapter()
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk()
return
}
policies, err := object.GetPolicies(id)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(policies)
}
func (c *ApiController) UpdatePolicy() {
id := c.Input().Get("id")
var policies []xormadapter.CasbinRule
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policies)
if err != nil {
c.ResponseError(err.Error())
return
}
affected, err := object.UpdatePolicy(id, policies[0].Ptype, util.CasbinToSlice(policies[0]), util.CasbinToSlice(policies[1]))
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(affected)
c.ServeJSON()
}
func (c *ApiController) AddPolicy() {
id := c.Input().Get("id")
var policy xormadapter.CasbinRule
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
if err != nil {
c.ResponseError(err.Error())
return
}
affected, err := object.AddPolicy(id, policy.Ptype, util.CasbinToSlice(policy))
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(affected)
c.ServeJSON()
}
func (c *ApiController) RemovePolicy() {
id := c.Input().Get("id")
var policy xormadapter.CasbinRule
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
if err != nil {
c.ResponseError(err.Error())
return
}
affected, err := object.RemovePolicy(id, policy.Ptype, util.CasbinToSlice(policy))
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(affected)
c.ServeJSON() c.ServeJSON()
} }

View File

@ -1,35 +0,0 @@
// 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 "github.com/casdoor/casdoor/object"
// GetDashboard
// @Title GetDashboard
// @Tag System API
// @Description get information of dashboard
// @Success 200 {object} controllers.Response The Response object
// @router /get-dashboard [get]
func (c *ApiController) GetDashboard() {
owner := c.Input().Get("owner")
data, err := object.GetDashboard(owner)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(data)
}

View File

@ -1,148 +0,0 @@
// 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
package controllers
import (
"encoding/json"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
// GetGroups
// @Title GetGroups
// @Tag Group API
// @Description get groups
// @Param owner query string true "The owner of groups"
// @Success 200 {array} object.Group The Response object
// @router /get-groups [get]
func (c *ApiController) GetGroups() {
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")
withTree := c.Input().Get("withTree")
if limit == "" || page == "" {
groups, err := object.GetGroups(owner)
if err != nil {
c.ResponseError(err.Error())
return
} else {
if withTree == "true" {
c.ResponseOk(object.ConvertToTreeData(groups, owner))
return
}
c.ResponseOk(groups)
}
} else {
limit := util.ParseInt(limit)
count, err := object.GetGroupCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
groups, err := object.GetPaginationGroups(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
} else {
c.ResponseOk(groups, paginator.Nums())
}
}
}
// GetGroup
// @Title GetGroup
// @Tag Group API
// @Description get group
// @Param id query string true "The id ( owner/name ) of the group"
// @Success 200 {object} object.Group The Response object
// @router /get-group [get]
func (c *ApiController) GetGroup() {
id := c.Input().Get("id")
group, err := object.GetGroup(id)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(group)
}
// UpdateGroup
// @Title UpdateGroup
// @Tag Group API
// @Description update group
// @Param id query string true "The id ( owner/name ) of the group"
// @Param body body object.Group true "The details of the group"
// @Success 200 {object} controllers.Response The Response object
// @router /update-group [post]
func (c *ApiController) UpdateGroup() {
id := c.Input().Get("id")
var group object.Group
err := json.Unmarshal(c.Ctx.Input.RequestBody, &group)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.UpdateGroup(id, &group))
c.ServeJSON()
}
// AddGroup
// @Title AddGroup
// @Tag Group API
// @Description add group
// @Param body body object.Group true "The details of the group"
// @Success 200 {object} controllers.Response The Response object
// @router /add-group [post]
func (c *ApiController) AddGroup() {
var group object.Group
err := json.Unmarshal(c.Ctx.Input.RequestBody, &group)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.AddGroup(&group))
c.ServeJSON()
}
// DeleteGroup
// @Title DeleteGroup
// @Tag Group API
// @Description delete group
// @Param body body object.Group true "The details of the group"
// @Success 200 {object} controllers.Response The Response object
// @router /delete-group [post]
func (c *ApiController) DeleteGroup() {
var group object.Group
err := json.Unmarshal(c.Ctx.Input.RequestBody, &group)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.DeleteGroup(&group))
c.ServeJSON()
}

View File

@ -1,190 +0,0 @@
// 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)
}
// GetInvitationCodeInfo
// @Title GetInvitationCodeInfo
// @Tag Invitation API
// @Description get invitation code information
// @Param code query string true "Invitation code"
// @Success 200 {object} object.Invitation The Response object
// @router /get-invitation-info [get]
func (c *ApiController) GetInvitationCodeInfo() {
code := c.Input().Get("code")
applicationId := c.Input().Get("applicationId")
application, err := object.GetApplication(applicationId)
if err != nil {
c.ResponseError(err.Error())
return
}
invitation, msg := object.GetInvitationByCode(code, application.Organization, c.GetAcceptLanguage())
if msg != "" {
c.ResponseError(msg)
return
}
c.ResponseOk(object.GetMaskedInvitation(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.GetAcceptLanguage()))
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.GetAcceptLanguage()))
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)
}

View File

@ -38,28 +38,20 @@ type LdapSyncResp struct {
} }
// GetLdapUsers // GetLdapUsers
// @Title GetLdapser
// @Tag Account API // @Tag Account API
// @Description get ldap users // @Title GetLdapser
// Param id string true "id"
// @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")
_, ldapId := util.GetOwnerAndNameFromId(id) _, ldapId := util.GetOwnerAndNameFromId(id)
ldapServer, err := object.GetLdap(ldapId) ldapServer := object.GetLdap(ldapId)
if err != nil {
c.ResponseError(err.Error())
return
}
conn, err := ldapServer.GetLdapConn() conn, err := ldapServer.GetLdapConn()
if err != nil { if err != nil {
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 {
@ -84,11 +76,7 @@ func (c *ApiController) GetLdapUsers() {
for i, user := range users { for i, user := range users {
uuids[i] = user.GetLdapUuid() uuids[i] = user.GetLdapUuid()
} }
existUuids, err := object.GetExistUuids(ldapServer.Owner, uuids) existUuids := object.GetExistUuids(ldapServer.Owner, uuids)
if err != nil {
c.ResponseError(err.Error())
return
}
resp := LdapResp{ resp := LdapResp{
Users: object.AutoAdjustLdapUser(users), Users: object.AutoAdjustLdapUser(users),
@ -98,24 +86,18 @@ func (c *ApiController) GetLdapUsers() {
} }
// GetLdaps // GetLdaps
// @Title GetLdaps
// @Tag Account API // @Tag Account API
// @Description get ldaps // @Title GetLdaps
// @Param owner query string false "owner"
// @Success 200 {array} object.Ldap The Response object
// @router /get-ldaps [get] // @router /get-ldaps [get]
func (c *ApiController) GetLdaps() { func (c *ApiController) GetLdaps() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
c.ResponseOk(object.GetMaskedLdaps(object.GetLdaps(owner))) c.ResponseOk(object.GetLdaps(owner))
} }
// GetLdap // GetLdap
// @Title GetLdap
// @Tag Account API // @Tag Account API
// @Description get ldap // @Title GetLdap
// @Param id query string true "id"
// @Success 200 {object} object.Ldap The Response object
// @router /get-ldap [get] // @router /get-ldap [get]
func (c *ApiController) GetLdap() { func (c *ApiController) GetLdap() {
id := c.Input().Get("id") id := c.Input().Get("id")
@ -126,20 +108,12 @@ func (c *ApiController) GetLdap() {
} }
_, name := util.GetOwnerAndNameFromId(id) _, name := util.GetOwnerAndNameFromId(id)
ldap, err := object.GetLdap(name) c.ResponseOk(object.GetLdap(name))
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(object.GetMaskedLdap(ldap))
} }
// AddLdap // AddLdap
// @Title AddLdap
// @Tag Account API // @Tag Account API
// @Description add ldap // @Title AddLdap
// @Param body body object.Ldap true "The details of the ldap"
// @Success 200 {object} controllers.Response The Response object
// @router /add-ldap [post] // @router /add-ldap [post]
func (c *ApiController) AddLdap() { func (c *ApiController) AddLdap() {
var ldap object.Ldap var ldap object.Ldap
@ -154,23 +128,17 @@ func (c *ApiController) AddLdap() {
return return
} }
if ok, err := object.CheckLdapExist(&ldap); err != nil { if object.CheckLdapExist(&ldap) {
c.ResponseError(err.Error())
return
} else if ok {
c.ResponseError(c.T("ldap:Ldap server exist")) c.ResponseError(c.T("ldap:Ldap server exist"))
return return
} }
resp := wrapActionResponse(object.AddLdap(&ldap)) affected := object.AddLdap(&ldap)
resp := wrapActionResponse(affected)
resp.Data2 = ldap resp.Data2 = ldap
if ldap.AutoSync != 0 { if ldap.AutoSync != 0 {
err = object.GetLdapAutoSynchronizer().StartAutoSync(ldap.Id) object.GetLdapAutoSynchronizer().StartAutoSync(ldap.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
} }
c.Data["json"] = resp c.Data["json"] = resp
@ -178,11 +146,8 @@ func (c *ApiController) AddLdap() {
} }
// UpdateLdap // UpdateLdap
// @Title UpdateLdap
// @Tag Account API // @Tag Account API
// @Description update ldap // @Title UpdateLdap
// @Param body body object.Ldap true "The details of the ldap"
// @Success 200 {object} controllers.Response The Response object
// @router /update-ldap [post] // @router /update-ldap [post]
func (c *ApiController) UpdateLdap() { func (c *ApiController) UpdateLdap() {
var ldap object.Ldap var ldap object.Ldap
@ -192,24 +157,11 @@ func (c *ApiController) UpdateLdap() {
return return
} }
prevLdap, err := object.GetLdap(ldap.Id) prevLdap := object.GetLdap(ldap.Id)
if err != nil { affected := object.UpdateLdap(&ldap)
c.ResponseError(err.Error())
return
}
affected, err := object.UpdateLdap(&ldap)
if err != nil {
c.ResponseError(err.Error())
return
}
if ldap.AutoSync != 0 { if ldap.AutoSync != 0 {
err := object.GetLdapAutoSynchronizer().StartAutoSync(ldap.Id) object.GetLdapAutoSynchronizer().StartAutoSync(ldap.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
} else if ldap.AutoSync == 0 && prevLdap.AutoSync != 0 { } else if ldap.AutoSync == 0 && prevLdap.AutoSync != 0 {
object.GetLdapAutoSynchronizer().StopAutoSync(ldap.Id) object.GetLdapAutoSynchronizer().StopAutoSync(ldap.Id)
} }
@ -219,11 +171,8 @@ func (c *ApiController) UpdateLdap() {
} }
// DeleteLdap // DeleteLdap
// @Title DeleteLdap
// @Tag Account API // @Tag Account API
// @Description delete ldap // @Title DeleteLdap
// @Param body body object.Ldap true "The details of the ldap"
// @Success 200 {object} controllers.Response The Response object
// @router /delete-ldap [post] // @router /delete-ldap [post]
func (c *ApiController) DeleteLdap() { func (c *ApiController) DeleteLdap() {
var ldap object.Ldap var ldap object.Ldap
@ -233,11 +182,7 @@ func (c *ApiController) DeleteLdap() {
return return
} }
affected, err := object.DeleteLdap(&ldap) affected := object.DeleteLdap(&ldap)
if err != nil {
c.ResponseError(err.Error())
return
}
object.GetLdapAutoSynchronizer().StopAutoSync(ldap.Id) object.GetLdapAutoSynchronizer().StopAutoSync(ldap.Id)
@ -246,16 +191,12 @@ func (c *ApiController) DeleteLdap() {
} }
// SyncLdapUsers // SyncLdapUsers
// @Title SyncLdapUsers
// @Tag Account API // @Tag Account API
// @Description sync ldap users // @Title SyncLdapUsers
// @Param id query string true "id"
// @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") owner := c.Input().Get("owner")
ldapId := c.Input().Get("ldapId")
owner, ldapId := util.GetOwnerAndNameFromId(id)
var users []object.LdapUser var users []object.LdapUser
err := json.Unmarshal(c.Ctx.Input.RequestBody, &users) err := json.Unmarshal(c.Ctx.Input.RequestBody, &users)
if err != nil { if err != nil {
@ -263,11 +204,7 @@ func (c *ApiController) SyncLdapUsers() {
return return
} }
err = object.UpdateLdapSyncTime(ldapId) object.UpdateLdapSyncTime(ldapId)
if err != nil {
c.ResponseError(err.Error())
return
}
exist, failed, _ := object.SyncLdapUsers(owner, users, ldapId) exist, failed, _ := object.SyncLdapUsers(owner, users, ldapId)

View File

@ -26,10 +26,8 @@ type LinkForm struct {
} }
// Unlink ... // Unlink ...
// @Tag Login API
// @Title Unlink
// @router /unlink [post] // @router /unlink [post]
// @Success 200 {object} object.Userinfo The Response object // @Tag Login API
func (c *ApiController) Unlink() { func (c *ApiController) Unlink() {
user, ok := c.RequireSignedInUser() user, ok := c.RequireSignedInUser()
if !ok { if !ok {
@ -47,20 +45,15 @@ func (c *ApiController) Unlink() {
// the user will be unlinked from the provider // the user will be unlinked from the provider
unlinkedUser := form.User unlinkedUser := form.User
if user.Id != unlinkedUser.Id && !user.IsGlobalAdmin() { if user.Id != unlinkedUser.Id && !user.IsGlobalAdmin {
// if the user is not the same as the one we are unlinking, we need to make sure the user is the global admin. // if the user is not the same as the one we are unlinking, we need to make sure the user is the global admin.
c.ResponseError(c.T("link:You are not the global admin, you can't unlink other users")) c.ResponseError(c.T("link:You are not the global admin, you can't unlink other users"))
return return
} }
if user.Id == unlinkedUser.Id && !user.IsGlobalAdmin() { if user.Id == unlinkedUser.Id && !user.IsGlobalAdmin {
// if the user is unlinking themselves, should check the provider can be unlinked, if not, we should return an error. // if the user is unlinking themselves, should check the provider can be unlinked, if not, we should return an error.
application, err := object.GetApplicationByUser(user) application := object.GetApplicationByUser(user)
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil { if application == nil {
c.ResponseError(c.T("link:You can't unlink yourself, you are not a member of any application")) c.ResponseError(c.T("link:You can't unlink yourself, you are not a member of any application"))
return return
@ -95,17 +88,8 @@ func (c *ApiController) Unlink() {
return return
} }
_, err = object.ClearUserOAuthProperties(&unlinkedUser, providerType) object.ClearUserOAuthProperties(&unlinkedUser, providerType)
if err != nil {
c.ResponseError(err.Error())
return
}
_, err = object.LinkUserAccount(&unlinkedUser, providerType, "")
if err != nil {
c.ResponseError(err.Error())
return
}
object.LinkUserAccount(&unlinkedUser, providerType, "")
c.ResponseOk() c.ResponseOk()
} }

256
controllers/message.go Normal file
View File

@ -0,0 +1,256 @@
// 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"
"fmt"
"strings"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/ai"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
// GetMessages
// @Title GetMessages
// @Tag Message API
// @Description get messages
// @Param owner query string true "The owner of messages"
// @Success 200 {array} object.Message The Response object
// @router /get-messages [get]
func (c *ApiController) GetMessages() {
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")
chat := c.Input().Get("chat")
organization := c.Input().Get("organization")
if limit == "" || page == "" {
var messages []*object.Message
if chat == "" {
messages = object.GetMessages(owner)
} else {
messages = object.GetChatMessages(chat)
}
c.Data["json"] = object.GetMaskedMessages(messages)
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetMessageCount(owner, organization, field, value)))
messages := object.GetMaskedMessages(object.GetPaginationMessages(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder))
c.ResponseOk(messages, paginator.Nums())
}
}
// GetMessage
// @Title GetMessage
// @Tag Message API
// @Description get message
// @Param id query string true "The id ( owner/name ) of the message"
// @Success 200 {object} object.Message The Response object
// @router /get-message [get]
func (c *ApiController) GetMessage() {
id := c.Input().Get("id")
c.Data["json"] = object.GetMaskedMessage(object.GetMessage(id))
c.ServeJSON()
}
func (c *ApiController) ResponseErrorStream(errorText string) {
event := fmt.Sprintf("event: myerror\ndata: %s\n\n", errorText)
_, err := c.Ctx.ResponseWriter.Write([]byte(event))
if err != nil {
panic(err)
}
}
// GetMessageAnswer
// @Title GetMessageAnswer
// @Tag Message API
// @Description get message answer
// @Param id query string true "The id ( owner/name ) of the message"
// @Success 200 {object} object.Message The Response object
// @router /get-message-answer [get]
func (c *ApiController) GetMessageAnswer() {
id := c.Input().Get("id")
c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
message := object.GetMessage(id)
if message == nil {
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The message: %s is not found"), id))
return
}
if message.Author != "AI" || message.ReplyTo == "" || message.Text != "" {
c.ResponseErrorStream(c.T("chat:The message is invalid"))
return
}
chatId := util.GetId("admin", message.Chat)
chat := object.GetChat(chatId)
if chat == nil || chat.Organization != message.Organization {
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The chat: %s is not found"), chatId))
return
}
if chat.Type != "AI" {
c.ResponseErrorStream(c.T("chat:The chat type must be \"AI\""))
return
}
questionMessage := object.GetMessage(message.ReplyTo)
if questionMessage == nil {
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The message: %s is not found"), id))
return
}
providerId := util.GetId(chat.Owner, chat.User2)
provider := object.GetProvider(providerId)
if provider == nil {
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The provider: %s is not found"), providerId))
return
}
if provider.Category != "AI" || provider.ClientSecret == "" {
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The provider: %s is invalid"), providerId))
return
}
c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
authToken := provider.ClientSecret
question := questionMessage.Text
var stringBuilder strings.Builder
fmt.Printf("Question: [%s]\n", questionMessage.Text)
fmt.Printf("Answer: [")
err := ai.QueryAnswerStream(authToken, question, c.Ctx.ResponseWriter, &stringBuilder)
if err != nil {
c.ResponseErrorStream(err.Error())
return
}
fmt.Printf("]\n")
event := fmt.Sprintf("event: end\ndata: %s\n\n", "end")
_, err = c.Ctx.ResponseWriter.Write([]byte(event))
if err != nil {
panic(err)
}
answer := stringBuilder.String()
message.Text = answer
object.UpdateMessage(message.GetId(), message)
}
// UpdateMessage
// @Title UpdateMessage
// @Tag Message API
// @Description update message
// @Param id query string true "The id ( owner/name ) of the message"
// @Param body body object.Message true "The details of the message"
// @Success 200 {object} controllers.Response The Response object
// @router /update-message [post]
func (c *ApiController) UpdateMessage() {
id := c.Input().Get("id")
var message object.Message
err := json.Unmarshal(c.Ctx.Input.RequestBody, &message)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.UpdateMessage(id, &message))
c.ServeJSON()
}
// AddMessage
// @Title AddMessage
// @Tag Message API
// @Description add message
// @Param body body object.Message true "The details of the message"
// @Success 200 {object} controllers.Response The Response object
// @router /add-message [post]
func (c *ApiController) AddMessage() {
var message object.Message
err := json.Unmarshal(c.Ctx.Input.RequestBody, &message)
if err != nil {
c.ResponseError(err.Error())
return
}
var chat *object.Chat
if message.Chat != "" {
chatId := util.GetId("admin", message.Chat)
chat = object.GetChat(chatId)
if chat == nil || chat.Organization != message.Organization {
c.ResponseError(fmt.Sprintf(c.T("chat:The chat: %s is not found"), chatId))
return
}
}
affected := object.AddMessage(&message)
if affected {
if chat != nil && chat.Type == "AI" {
answerMessage := &object.Message{
Owner: message.Owner,
Name: fmt.Sprintf("message_%s", util.GetRandomName()),
CreatedTime: util.GetCurrentTimeEx(message.CreatedTime),
Organization: message.Organization,
Chat: message.Chat,
ReplyTo: message.GetId(),
Author: "AI",
Text: "",
}
object.AddMessage(answerMessage)
}
}
c.Data["json"] = wrapActionResponse(affected)
c.ServeJSON()
}
// DeleteMessage
// @Title DeleteMessage
// @Tag Message API
// @Description delete message
// @Param body body object.Message true "The details of the message"
// @Success 200 {object} controllers.Response The Response object
// @router /delete-message [post]
func (c *ApiController) DeleteMessage() {
var message object.Message
err := json.Unmarshal(c.Ctx.Input.RequestBody, &message)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.DeleteMessage(&message))
c.ServeJSON()
}

View File

@ -17,16 +17,9 @@ package controllers
import ( import (
"net/http" "net/http"
"github.com/beego/beego"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
"github.com/google/uuid"
)
const (
MfaRecoveryCodesSession = "mfa_recovery_codes"
MfaCountryCodeSession = "mfa_country_code"
MfaDestSession = "mfa_dest"
MfaTotpSecretSession = "mfa_totp_secret"
) )
// MfaSetupInitiate // MfaSetupInitiate
@ -36,12 +29,12 @@ const (
// @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} controllers.Response The Response object // @Success 200 {object} The Response object
// @router /mfa/setup/initiate [post] // @router /mfa/setup/initiate [post]
func (c *ApiController) MfaSetupInitiate() { func (c *ApiController) MfaSetupInitiate() {
owner := c.Ctx.Request.Form.Get("owner") owner := c.Ctx.Request.Form.Get("owner")
name := c.Ctx.Request.Form.Get("name") name := c.Ctx.Request.Form.Get("name")
mfaType := c.Ctx.Request.Form.Get("mfaType") authType := c.Ctx.Request.Form.Get("type")
userId := util.GetId(owner, name) userId := util.GetId(owner, name)
if len(userId) == 0 { if len(userId) == 0 {
@ -49,36 +42,25 @@ func (c *ApiController) MfaSetupInitiate() {
return return
} }
MfaUtil := object.GetMfaUtil(mfaType, nil) MfaUtil := object.GetMfaUtil(authType, nil)
if MfaUtil == nil { if MfaUtil == nil {
c.ResponseError("Invalid auth type") c.ResponseError("Invalid auth type")
} }
user := object.GetUser(userId)
user, err := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil { if user == nil {
c.ResponseError("User doesn't exist") c.ResponseError("User doesn't exist")
return return
} }
mfaProps, err := MfaUtil.Initiate(user.GetId()) issuer := beego.AppConfig.String("appname")
accountName := user.GetId()
mfaProps, err := MfaUtil.Initiate(c.Ctx, issuer, accountName)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
recoveryCode := uuid.NewString()
c.SetSession(MfaRecoveryCodesSession, recoveryCode)
if mfaType == object.TotpType {
c.SetSession(MfaTotpSecretSession, mfaProps.Secret)
}
mfaProps.RecoveryCodes = []string{recoveryCode}
resp := mfaProps resp := mfaProps
c.ResponseOk(resp) c.ResponseOk(resp)
} }
@ -89,49 +71,19 @@ 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} controllers.Response The Response object // @Success 200 {object} 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") authType := c.Ctx.Request.Form.Get("type")
passcode := c.Ctx.Request.Form.Get("passcode") passcode := c.Ctx.Request.Form.Get("passcode")
if mfaType == "" || passcode == "" { if authType == "" || passcode == "" {
c.ResponseError("missing auth type or passcode") c.ResponseError("missing auth type or passcode")
return return
} }
MfaUtil := object.GetMfaUtil(authType, nil)
config := &object.MfaProps{ err := MfaUtil.SetupVerify(c.Ctx, passcode)
MfaType: mfaType,
}
if mfaType == object.TotpType {
secret := c.GetSession(MfaTotpSecretSession)
if secret == nil {
c.ResponseError("totp secret is missing")
return
}
config.Secret = secret.(string)
} else if mfaType == object.EmailType || mfaType == object.SmsType {
dest := c.GetSession(MfaDestSession)
if dest == nil {
c.ResponseError("destination is missing")
return
}
config.Secret = dest.(string)
countryCode := c.GetSession(MfaCountryCodeSession)
if countryCode == nil {
c.ResponseError("country code is missing")
return
}
config.CountryCode = countryCode.(string)
}
mfaUtil := object.GetMfaUtil(mfaType, config)
if mfaUtil == nil {
c.ResponseError("Invalid multi-factor authentication type")
return
}
err := mfaUtil.SetupVerify(passcode)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
} else { } else {
@ -146,76 +98,26 @@ 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} controllers.Response The Response object // @Success 200 {object} 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")
name := c.Ctx.Request.Form.Get("name") name := c.Ctx.Request.Form.Get("name")
mfaType := c.Ctx.Request.Form.Get("mfaType") authType := c.Ctx.Request.Form.Get("type")
user, err := object.GetUser(util.GetId(owner, name))
if err != nil {
c.ResponseError(err.Error())
return
}
user := object.GetUser(util.GetId(owner, name))
if user == nil { if user == nil {
c.ResponseError("User doesn't exist") c.ResponseError("User doesn't exist")
return return
} }
config := &object.MfaProps{ twoFactor := object.GetMfaUtil(authType, nil)
MfaType: mfaType, err := twoFactor.Enable(c.Ctx, user)
}
if mfaType == object.TotpType {
secret := c.GetSession(MfaTotpSecretSession)
if secret == nil {
c.ResponseError("totp secret is missing")
return
}
config.Secret = secret.(string)
} else if mfaType == object.EmailType || mfaType == object.SmsType {
dest := c.GetSession(MfaDestSession)
if dest == nil {
c.ResponseError("destination is missing")
return
}
config.Secret = dest.(string)
countryCode := c.GetSession(MfaCountryCodeSession)
if countryCode == nil {
c.ResponseError("country code is missing")
return
}
config.CountryCode = countryCode.(string)
}
recoveryCodes := c.GetSession(MfaRecoveryCodesSession)
if recoveryCodes == nil {
c.ResponseError("recovery codes is missing")
return
}
config.RecoveryCodes = []string{recoveryCodes.(string)}
mfaUtil := object.GetMfaUtil(mfaType, config)
if mfaUtil == nil {
c.ResponseError("Invalid multi-factor authentication type")
return
}
err = mfaUtil.Enable(user)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.DelSession(MfaRecoveryCodesSession)
if mfaType == object.TotpType {
c.DelSession(MfaTotpSecretSession)
} else {
c.DelSession(MfaCountryCodeSession)
c.DelSession(MfaDestSession)
}
c.ResponseOk(http.StatusText(http.StatusOK)) c.ResponseOk(http.StatusText(http.StatusOK))
} }
@ -225,30 +127,32 @@ 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} controllers.Response The Response object // @param id form string true "id of user's MFA props"
// @Success 200 {object} Response object
// @router /delete-mfa/ [post] // @router /delete-mfa/ [post]
func (c *ApiController) DeleteMfa() { func (c *ApiController) DeleteMfa() {
id := c.Ctx.Request.Form.Get("id")
owner := c.Ctx.Request.Form.Get("owner") owner := c.Ctx.Request.Form.Get("owner")
name := c.Ctx.Request.Form.Get("name") name := c.Ctx.Request.Form.Get("name")
userId := util.GetId(owner, name) userId := util.GetId(owner, name)
user, err := object.GetUser(userId) user := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil { if user == nil {
c.ResponseError("User doesn't exist") c.ResponseError("User doesn't exist")
return return
} }
err = object.DisabledMultiFactorAuth(user) mfaProps := user.MultiFactorAuths[:0]
if err != nil { i := 0
c.ResponseError(err.Error()) for _, mfaProp := range mfaProps {
return if mfaProp.Id != id {
mfaProps[i] = mfaProp
i++
}
} }
user.MultiFactorAuths = mfaProps
c.ResponseOk(object.GetAllMfaProps(user, true)) object.UpdateUser(userId, user, []string{"multi_factor_auths"}, user.IsAdminUser())
c.ResponseOk(user.MultiFactorAuths)
} }
// SetPreferredMfa // SetPreferredMfa
@ -258,28 +162,33 @@ 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} controllers.Response The Response object // @Success 200 {object} 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") id := c.Ctx.Request.Form.Get("id")
owner := c.Ctx.Request.Form.Get("owner") owner := c.Ctx.Request.Form.Get("owner")
name := c.Ctx.Request.Form.Get("name") name := c.Ctx.Request.Form.Get("name")
userId := util.GetId(owner, name) userId := util.GetId(owner, name)
user, err := object.GetUser(userId) user := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil { if user == nil {
c.ResponseError("User doesn't exist") c.ResponseError("User doesn't exist")
return return
} }
err = object.SetPreferredMultiFactorAuth(user, mfaType) mfaProps := user.MultiFactorAuths
if err != nil { for i, mfaProp := range user.MultiFactorAuths {
c.ResponseError(err.Error()) if mfaProp.Id == id {
return mfaProps[i].IsPreferred = true
} else {
mfaProps[i].IsPreferred = false
}
} }
c.ResponseOk(object.GetAllMfaProps(user, true))
object.UpdateUser(userId, user, []string{"multi_factor_auths"}, user.IsAdminUser())
for i, mfaProp := range mfaProps {
mfaProps[i] = object.GetMaskedProps(mfaProp)
}
c.ResponseOk(mfaProps)
} }

View File

@ -37,30 +37,13 @@ func (c *ApiController) GetModels() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
models, err := object.GetModels(owner) c.Data["json"] = object.GetModels(owner)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(models)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetModelCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetModelCount(owner, field, value)))
if err != nil { models := object.GetPaginationModels(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
models, err := object.GetPaginationModels(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(models, paginator.Nums()) c.ResponseOk(models, paginator.Nums())
} }
} }
@ -75,13 +58,8 @@ func (c *ApiController) GetModels() {
func (c *ApiController) GetModel() { func (c *ApiController) GetModel() {
id := c.Input().Get("id") id := c.Input().Get("id")
model, err := object.GetModel(id) c.Data["json"] = object.GetModel(id)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(model)
} }
// UpdateModel // UpdateModel

View File

@ -37,49 +37,14 @@ func (c *ApiController) GetOrganizations() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
organizationName := c.Input().Get("organizationName")
isGlobalAdmin := c.IsGlobalAdmin()
if limit == "" || page == "" { if limit == "" || page == "" {
var organizations []*object.Organization c.Data["json"] = object.GetMaskedOrganizations(object.GetOrganizations(owner))
var err error c.ServeJSON()
if isGlobalAdmin {
organizations, err = object.GetMaskedOrganizations(object.GetOrganizations(owner))
} else {
organizations, err = object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner))
}
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(organizations)
} else { } else {
if !isGlobalAdmin { limit := util.ParseInt(limit)
organizations, err := object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner)) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetOrganizationCount(owner, field, value)))
if err != nil { organizations := object.GetMaskedOrganizations(object.GetPaginationOrganizations(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
c.ResponseError(err.Error()) c.ResponseOk(organizations, paginator.Nums())
return
}
c.ResponseOk(organizations)
} else {
limit := util.ParseInt(limit)
count, err := object.GetOrganizationCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
organizations, err := object.GetMaskedOrganizations(object.GetPaginationOrganizations(owner, organizationName, paginator.Offset(), limit, field, value, sortField, sortOrder))
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(organizations, paginator.Nums())
}
} }
} }
@ -92,13 +57,9 @@ 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")
organization, err := object.GetMaskedOrganization(object.GetOrganization(id))
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(organization) c.Data["json"] = object.GetMaskedOrganization(object.GetOrganization(id))
c.ServeJSON()
} }
// UpdateOrganization ... // UpdateOrganization ...
@ -138,13 +99,8 @@ func (c *ApiController) AddOrganization() {
return return
} }
count, err := object.GetOrganizationCount("", "", "") count := object.GetOrganizationCount("", "", "")
if err != nil { if err := checkQuotaForOrganization(count); err != nil {
c.ResponseError(err.Error())
return
}
if err = checkQuotaForOrganization(int(count)); err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
@ -177,7 +133,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} controllers.Response The Response object // @Success 200 {object} 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()
@ -189,24 +145,6 @@ func (c *ApiController) GetDefaultApplication() {
return return
} }
application = object.GetMaskedApplication(application, userId) maskedApplication := object.GetMaskedApplication(application, userId)
c.ResponseOk(application) c.ResponseOk(maskedApplication)
}
// GetOrganizationNames ...
// @Title GetOrganizationNames
// @Tag Organization API
// @Param owner query string true "owner"
// @Description get all organization name and displayName
// @Success 200 {array} object.Organization The Response object
// @router /get-organization-names [get]
func (c *ApiController) GetOrganizationNames() {
owner := c.Input().Get("owner")
organizationNames, err := object.GetOrganizationsByFields(owner, []string{"name", "display_name"}...)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(organizationNames)
} }

View File

@ -16,6 +16,7 @@ package controllers
import ( import (
"encoding/json" "encoding/json"
"fmt"
"github.com/beego/beego/utils/pagination" "github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
@ -37,30 +38,13 @@ func (c *ApiController) GetPayments() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
payments, err := object.GetPayments(owner) c.Data["json"] = object.GetPayments(owner)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(payments)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetPaymentCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetPaymentCount(owner, field, value)))
if err != nil { payments := object.GetPaginationPayments(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
payments, err := object.GetPaginationPayments(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(payments, paginator.Nums()) c.ResponseOk(payments, paginator.Nums())
} }
} }
@ -76,14 +60,10 @@ func (c *ApiController) GetPayments() {
// @router /get-user-payments [get] // @router /get-user-payments [get]
func (c *ApiController) GetUserPayments() { func (c *ApiController) GetUserPayments() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
organization := c.Input().Get("organization")
user := c.Input().Get("user") user := c.Input().Get("user")
payments, err := object.GetUserPayments(owner, user) payments := object.GetUserPayments(owner, organization, user)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(payments) c.ResponseOk(payments)
} }
@ -97,13 +77,8 @@ func (c *ApiController) GetUserPayments() {
func (c *ApiController) GetPayment() { func (c *ApiController) GetPayment() {
id := c.Input().Get("id") id := c.Input().Get("id")
payment, err := object.GetPayment(id) c.Data["json"] = object.GetPayment(id)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(payment)
} }
// UpdatePayment // UpdatePayment
@ -175,17 +150,22 @@ func (c *ApiController) DeletePayment() {
// @router /notify-payment [post] // @router /notify-payment [post]
func (c *ApiController) NotifyPayment() { func (c *ApiController) NotifyPayment() {
owner := c.Ctx.Input.Param(":owner") owner := c.Ctx.Input.Param(":owner")
providerName := c.Ctx.Input.Param(":provider")
productName := c.Ctx.Input.Param(":product")
paymentName := c.Ctx.Input.Param(":payment") paymentName := c.Ctx.Input.Param(":payment")
body := c.Ctx.Input.RequestBody body := c.Ctx.Input.RequestBody
payment, err := object.NotifyPayment(body, owner, paymentName) ok := object.NotifyPayment(c.Ctx.Request, body, owner, providerName, productName, paymentName)
if err != nil { if ok {
c.ResponseError(err.Error()) _, err := c.Ctx.ResponseWriter.Write([]byte("success"))
return if err != nil {
c.ResponseError(err.Error())
return
}
} else {
panic(fmt.Errorf("NotifyPayment() failed: %v", ok))
} }
c.ResponseOk(payment)
} }
// InvoicePayment // InvoicePayment
@ -198,12 +178,7 @@ func (c *ApiController) NotifyPayment() {
func (c *ApiController) InvoicePayment() { func (c *ApiController) InvoicePayment() {
id := c.Input().Get("id") id := c.Input().Get("id")
payment, err := object.GetPayment(id) payment := object.GetPayment(id)
if err != nil {
c.ResponseError(err.Error())
return
}
invoiceUrl, err := object.InvoicePayment(payment) invoiceUrl, err := object.InvoicePayment(payment)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())

View File

@ -37,30 +37,13 @@ func (c *ApiController) GetPermissions() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
permissions, err := object.GetPermissions(owner) c.Data["json"] = object.GetPermissions(owner)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(permissions)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetPermissionCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetPermissionCount(owner, field, value)))
if err != nil { permissions := object.GetPaginationPermissions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
permissions, err := object.GetPaginationPermissions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(permissions, paginator.Nums()) c.ResponseOk(permissions, paginator.Nums())
} }
} }
@ -77,13 +60,9 @@ func (c *ApiController) GetPermissionsBySubmitter() {
return return
} }
permissions, err := object.GetPermissionsBySubmitter(user.Owner, user.Name) permissions := object.GetPermissionsBySubmitter(user.Owner, user.Name)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(permissions, len(permissions)) c.ResponseOk(permissions, len(permissions))
return
} }
// GetPermissionsByRole // GetPermissionsByRole
@ -95,13 +74,9 @@ func (c *ApiController) GetPermissionsBySubmitter() {
// @router /get-permissions-by-role [get] // @router /get-permissions-by-role [get]
func (c *ApiController) GetPermissionsByRole() { func (c *ApiController) GetPermissionsByRole() {
id := c.Input().Get("id") id := c.Input().Get("id")
permissions, err := object.GetPermissionsByRole(id) permissions := object.GetPermissionsByRole(id)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(permissions, len(permissions)) c.ResponseOk(permissions, len(permissions))
return
} }
// GetPermission // GetPermission
@ -114,13 +89,8 @@ func (c *ApiController) GetPermissionsByRole() {
func (c *ApiController) GetPermission() { func (c *ApiController) GetPermission() {
id := c.Input().Get("id") id := c.Input().Get("id")
permission, err := object.GetPermission(id) c.Data["json"] = object.GetPermission(id)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(permission)
} }
// UpdatePermission // UpdatePermission

View File

@ -1,54 +0,0 @@
// 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 (
"fmt"
"os"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
func (c *ApiController) UploadPermissions() {
userId := c.GetSessionUsername()
owner, user := util.GetOwnerAndNameFromId(userId)
file, header, err := c.Ctx.Request.FormFile("file")
if err != nil {
c.ResponseError(err.Error())
return
}
fileId := fmt.Sprintf("%s_%s_%s", owner, user, util.RemoveExt(header.Filename))
path := util.GetUploadXlsxPath(fileId)
defer os.Remove(path)
err = saveFile(path, &file)
if err != nil {
c.ResponseError(err.Error())
return
}
affected, err := object.UploadPermissions(owner, path)
if err != nil {
c.ResponseError(err.Error())
}
if affected {
c.ResponseOk()
} else {
c.ResponseError(c.T("user_upload:Failed to import users"))
}
}

View File

@ -37,30 +37,13 @@ func (c *ApiController) GetPlans() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
plans, err := object.GetPlans(owner) c.Data["json"] = object.GetPlans(owner)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(plans)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetPlanCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetPlanCount(owner, field, value)))
if err != nil { plan := object.GetPaginatedPlans(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
plan, err := object.GetPaginatedPlans(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(plan, paginator.Nums()) c.ResponseOk(plan, paginator.Nums())
} }
} }
@ -77,25 +60,20 @@ func (c *ApiController) GetPlan() {
id := c.Input().Get("id") id := c.Input().Get("id")
includeOption := c.Input().Get("includeOption") == "true" includeOption := c.Input().Get("includeOption") == "true"
plan, err := object.GetPlan(id) plan := object.GetPlan(id)
if err != nil {
c.ResponseError(err.Error())
return
}
if plan != nil && includeOption { if includeOption {
options, err := object.GetPermissionsByRole(plan.Role) options := object.GetPermissionsByRole(plan.Role)
if err != nil {
c.ResponseError(err.Error())
return
}
for _, option := range options { for _, option := range options {
plan.Options = append(plan.Options, option.DisplayName) plan.Options = append(plan.Options, option.DisplayName)
} }
}
c.ResponseOk(plan) c.Data["json"] = plan
} else {
c.Data["json"] = plan
}
c.ServeJSON()
} }
// UpdatePlan // UpdatePlan
@ -108,29 +86,14 @@ func (c *ApiController) GetPlan() {
// @router /update-plan [post] // @router /update-plan [post]
func (c *ApiController) UpdatePlan() { func (c *ApiController) UpdatePlan() {
id := c.Input().Get("id") id := c.Input().Get("id")
owner := util.GetOwnerFromId(id)
var plan object.Plan var plan object.Plan
err := json.Unmarshal(c.Ctx.Input.RequestBody, &plan) err := json.Unmarshal(c.Ctx.Input.RequestBody, &plan)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
if plan.Product != "" {
productId := util.GetId(owner, plan.Product)
product, err := object.GetProduct(productId)
if err != nil {
c.ResponseError(err.Error())
return
}
if product != nil {
object.UpdateProductForPlan(&plan, product)
_, err = object.UpdateProduct(productId, product)
if err != nil {
c.ResponseError(err.Error())
return
}
}
}
c.Data["json"] = wrapActionResponse(object.UpdatePlan(id, &plan)) c.Data["json"] = wrapActionResponse(object.UpdatePlan(id, &plan))
c.ServeJSON() c.ServeJSON()
} }
@ -149,14 +112,7 @@ func (c *ApiController) AddPlan() {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
// Create a related product for plan
product := object.CreateProductForPlan(&plan)
_, err = object.AddProduct(product)
if err != nil {
c.ResponseError(err.Error())
return
}
plan.Product = product.Name
c.Data["json"] = wrapActionResponse(object.AddPlan(&plan)) c.Data["json"] = wrapActionResponse(object.AddPlan(&plan))
c.ServeJSON() c.ServeJSON()
} }
@ -175,13 +131,7 @@ func (c *ApiController) DeletePlan() {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
if plan.Product != "" {
_, err = object.DeleteProduct(&object.Product{Owner: plan.Owner, Name: plan.Product})
if err != nil {
c.ResponseError(err.Error())
return
}
}
c.Data["json"] = wrapActionResponse(object.DeletePlan(&plan)) c.Data["json"] = wrapActionResponse(object.DeletePlan(&plan))
c.ServeJSON() c.ServeJSON()
} }

View File

@ -37,30 +37,13 @@ func (c *ApiController) GetPricings() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
pricings, err := object.GetPricings(owner) c.Data["json"] = object.GetPricings(owner)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(pricings)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetPricingCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetPricingCount(owner, field, value)))
if err != nil { pricing := object.GetPaginatedPricings(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
pricing, err := object.GetPaginatedPricings(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(pricing, paginator.Nums()) c.ResponseOk(pricing, paginator.Nums())
} }
} }
@ -70,18 +53,15 @@ func (c *ApiController) GetPricings() {
// @Tag Pricing API // @Tag Pricing API
// @Description get pricing // @Description get pricing
// @Param id query string true "The id ( owner/name ) of the pricing" // @Param id query string true "The id ( owner/name ) of the pricing"
// @Success 200 {object} object.Pricing The Response object // @Success 200 {object} object.pricing The Response object
// @router /get-pricing [get] // @router /get-pricing [get]
func (c *ApiController) GetPricing() { func (c *ApiController) GetPricing() {
id := c.Input().Get("id") id := c.Input().Get("id")
pricing, err := object.GetPricing(id) pricing := object.GetPricing(id)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(pricing) c.Data["json"] = pricing
c.ServeJSON()
} }
// UpdatePricing // UpdatePricing

View File

@ -38,30 +38,13 @@ func (c *ApiController) GetProducts() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
products, err := object.GetProducts(owner) c.Data["json"] = object.GetProducts(owner)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(products)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetProductCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetProductCount(owner, field, value)))
if err != nil { products := object.GetPaginationProducts(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
products, err := object.GetPaginationProducts(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(products, paginator.Nums()) c.ResponseOk(products, paginator.Nums())
} }
} }
@ -76,19 +59,11 @@ func (c *ApiController) GetProducts() {
func (c *ApiController) GetProduct() { func (c *ApiController) GetProduct() {
id := c.Input().Get("id") id := c.Input().Get("id")
product, err := object.GetProduct(id) product := object.GetProduct(id)
if err != nil { object.ExtendProductWithProviders(product)
c.ResponseError(err.Error())
return
}
err = object.ExtendProductWithProviders(product) c.Data["json"] = product
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(product)
} }
// UpdateProduct // UpdateProduct
@ -161,39 +136,26 @@ func (c *ApiController) DeleteProduct() {
// @router /buy-product [post] // @router /buy-product [post]
func (c *ApiController) BuyProduct() { func (c *ApiController) BuyProduct() {
id := c.Input().Get("id") id := c.Input().Get("id")
host := c.Ctx.Request.Host
providerName := c.Input().Get("providerName") providerName := c.Input().Get("providerName")
paymentEnv := c.Input().Get("paymentEnv") host := c.Ctx.Request.Host
// buy `pricingName/planName` for `paidUserName` userId := c.GetSessionUsername()
pricingName := c.Input().Get("pricingName")
planName := c.Input().Get("planName")
paidUserName := c.Input().Get("userName")
owner, _ := util.GetOwnerAndNameFromId(id)
userId := util.GetId(owner, paidUserName)
if paidUserName == "" {
userId = c.GetSessionUsername()
}
if userId == "" { if userId == "" {
c.ResponseError(c.T("general:Please login first")) c.ResponseError(c.T("general:Please login first"))
return return
} }
user, err := object.GetUser(userId) user := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil { if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId)) c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId))
return return
} }
payment, attachInfo, err := object.BuyProduct(id, user, providerName, pricingName, planName, host, paymentEnv) payUrl, err := object.BuyProduct(id, providerName, user, host)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.ResponseOk(payment, attachInfo) c.ResponseOk(payUrl)
} }

View File

@ -20,7 +20,7 @@ import (
// GetPrometheusInfo // GetPrometheusInfo
// @Title GetPrometheusInfo // @Title GetPrometheusInfo
// @Tag System API // @Tag Prometheus 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]

View File

@ -44,29 +44,12 @@ func (c *ApiController) GetProviders() {
} }
if limit == "" || page == "" { if limit == "" || page == "" {
providers, err := object.GetProviders(owner) c.Data["json"] = object.GetMaskedProviders(object.GetProviders(owner), isMaskEnabled)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(object.GetMaskedProviders(providers, isMaskEnabled))
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetProviderCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetProviderCount(owner, field, value)))
if err != nil { providers := object.GetMaskedProviders(object.GetPaginationProviders(owner, paginator.Offset(), limit, field, value, sortField, sortOrder), isMaskEnabled)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
paginationProviders, err := object.GetPaginationProviders(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
providers := object.GetMaskedProviders(paginationProviders, isMaskEnabled)
c.ResponseOk(providers, paginator.Nums()) c.ResponseOk(providers, paginator.Nums())
} }
} }
@ -91,29 +74,12 @@ func (c *ApiController) GetGlobalProviders() {
} }
if limit == "" || page == "" { if limit == "" || page == "" {
globalProviders, err := object.GetGlobalProviders() c.Data["json"] = object.GetMaskedProviders(object.GetGlobalProviders(), isMaskEnabled)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(object.GetMaskedProviders(globalProviders, isMaskEnabled))
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetGlobalProviderCount(field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetGlobalProviderCount(field, value)))
if err != nil { providers := object.GetMaskedProviders(object.GetPaginationGlobalProviders(paginator.Offset(), limit, field, value, sortField, sortOrder), isMaskEnabled)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
paginationGlobalProviders, err := object.GetPaginationGlobalProviders(paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
providers := object.GetMaskedProviders(paginationGlobalProviders, isMaskEnabled)
c.ResponseOk(providers, paginator.Nums()) c.ResponseOk(providers, paginator.Nums())
} }
} }
@ -132,13 +98,9 @@ func (c *ApiController) GetProvider() {
if !ok { if !ok {
return return
} }
provider, err := object.GetProvider(id)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(object.GetMaskedProvider(provider, isMaskEnabled)) c.Data["json"] = object.GetMaskedProvider(object.GetProvider(id), isMaskEnabled)
c.ServeJSON()
} }
// UpdateProvider // UpdateProvider
@ -178,13 +140,8 @@ func (c *ApiController) AddProvider() {
return return
} }
count, err := object.GetProviderCount("", "", "") count := object.GetProviderCount("", "", "")
if err != nil { if err := checkQuotaForProvider(count); err != nil {
c.ResponseError(err.Error())
return
}
if err := checkQuotaForProvider(int(count)); err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }

95
controllers/record.go Normal file
View File

@ -0,0 +1,95 @@
// 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 controllers
import (
"encoding/json"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
// GetRecords
// @Title GetRecords
// @Tag Record API
// @Description get all records
// @Param pageSize query string true "The size of each page"
// @Param p query string true "The number of the page"
// @Success 200 {object} object.Record The Response object
// @router /get-records [get]
func (c *ApiController) GetRecords() {
organization, ok := c.RequireAdmin()
if !ok {
return
}
limit := c.Input().Get("pageSize")
page := c.Input().Get("p")
field := c.Input().Get("field")
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetRecords()
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
filterRecord := &object.Record{Organization: organization}
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetRecordCount(field, value, filterRecord)))
records := object.GetPaginationRecords(paginator.Offset(), limit, field, value, sortField, sortOrder, filterRecord)
c.ResponseOk(records, paginator.Nums())
}
}
// GetRecordsByFilter
// @Tag Record API
// @Title GetRecordsByFilter
// @Description get records by filter
// @Param filter body string true "filter Record message"
// @Success 200 {object} object.Record The Response object
// @router /get-records-filter [post]
func (c *ApiController) GetRecordsByFilter() {
body := string(c.Ctx.Input.RequestBody)
record := &object.Record{}
err := util.JsonToStruct(body, record)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = object.GetRecordsByField(record)
c.ServeJSON()
}
// AddRecord
// @Title AddRecord
// @Tag Record API
// @Description add a record
// @Param body body object.Record true "The details of the record"
// @Success 200 {object} controllers.Response The Response object
// @router /add-record [post]
func (c *ApiController) AddRecord() {
var record object.Record
err := json.Unmarshal(c.Ctx.Input.RequestBody, &record)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.AddRecord(&record))
c.ServeJSON()
}

View File

@ -29,19 +29,9 @@ import (
) )
// GetResources // GetResources
// @router /get-resources [get]
// @Tag Resource API // @Tag Resource API
// @Title GetResources // @Title GetResources
// @Description get resources
// @Param owner query string true "Owner"
// @Param user query string true "User"
// @Param pageSize query integer false "Page Size"
// @Param p query integer false "Page Number"
// @Param field query string false "Field"
// @Param value query string false "Value"
// @Param sortField query string false "Sort Field"
// @Param sortOrder query string false "Sort Order"
// @Success 200 {array} object.Resource The Response object
// @router /get-resources [get]
func (c *ApiController) GetResources() { func (c *ApiController) GetResources() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
user := c.Input().Get("user") user := c.Input().Get("user")
@ -52,44 +42,21 @@ func (c *ApiController) GetResources() {
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if sortField == "Direct" { userObj, ok := c.RequireSignedInUser()
provider, err := c.GetProviderFromContext("Storage") if !ok {
if err != nil { return
c.ResponseError(err.Error()) }
return if userObj.IsAdmin {
} user = ""
}
prefix := sortOrder if limit == "" || page == "" {
resources, err := object.GetDirectResources(owner, user, provider, prefix, c.GetAcceptLanguage()) c.Data["json"] = object.GetResources(owner, user)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(resources)
} else if limit == "" || page == "" {
resources, err := object.GetResources(owner, user)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(resources)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetResourceCount(owner, user, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetResourceCount(owner, user, field, value)))
if err != nil { resources := object.GetPaginationResources(owner, user, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
resources, err := object.GetPaginationResources(owner, user, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(resources, paginator.Nums()) c.ResponseOk(resources, paginator.Nums())
} }
} }
@ -97,29 +64,17 @@ func (c *ApiController) GetResources() {
// GetResource // GetResource
// @Tag Resource API // @Tag Resource API
// @Title GetResource // @Title GetResource
// @Description get resource
// @Param id query string true "The id ( owner/name ) of resource"
// @Success 200 {object} object.Resource The Response object
// @router /get-resource [get] // @router /get-resource [get]
func (c *ApiController) GetResource() { func (c *ApiController) GetResource() {
id := c.Input().Get("id") id := c.Input().Get("id")
resource, err := object.GetResource(id) c.Data["json"] = object.GetResource(id)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(resource)
} }
// UpdateResource // UpdateResource
// @Tag Resource API // @Tag Resource API
// @Title UpdateResource // @Title UpdateResource
// @Description get resource
// @Param id query string true "The id ( owner/name ) of resource"
// @Param resource body object.Resource true "The resource object"
// @Success 200 {object} controllers.Response Success or error
// @router /update-resource [post] // @router /update-resource [post]
func (c *ApiController) UpdateResource() { func (c *ApiController) UpdateResource() {
id := c.Input().Get("id") id := c.Input().Get("id")
@ -138,8 +93,6 @@ func (c *ApiController) UpdateResource() {
// AddResource // AddResource
// @Tag Resource API // @Tag Resource API
// @Title AddResource // @Title AddResource
// @Param resource body object.Resource true "Resource object"
// @Success 200 {object} controllers.Response Success or error
// @router /add-resource [post] // @router /add-resource [post]
func (c *ApiController) AddResource() { func (c *ApiController) AddResource() {
var resource object.Resource var resource object.Resource
@ -156,8 +109,6 @@ func (c *ApiController) AddResource() {
// DeleteResource // DeleteResource
// @Tag Resource API // @Tag Resource API
// @Title DeleteResource // @Title DeleteResource
// @Param resource body object.Resource true "Resource object"
// @Success 200 {object} controllers.Response Success or error
// @router /delete-resource [post] // @router /delete-resource [post]
func (c *ApiController) DeleteResource() { func (c *ApiController) DeleteResource() {
var resource object.Resource var resource object.Resource
@ -167,16 +118,10 @@ func (c *ApiController) DeleteResource() {
return return
} }
if resource.Provider != "" { provider, _, ok := c.GetProviderFromContext("Storage")
c.Input().Set("provider", resource.Provider) if !ok {
}
c.Input().Set("fullFilePath", resource.Name)
provider, err := c.GetProviderFromContext("Storage")
if err != nil {
c.ResponseError(err.Error())
return return
} }
_, resource.Name = refineFullFilePath(resource.Name)
err = object.DeleteFile(provider, resource.Name, c.GetAcceptLanguage()) err = object.DeleteFile(provider, resource.Name, c.GetAcceptLanguage())
if err != nil { if err != nil {
@ -191,16 +136,6 @@ func (c *ApiController) DeleteResource() {
// UploadResource // UploadResource
// @Tag Resource API // @Tag Resource API
// @Title UploadResource // @Title UploadResource
// @Param owner query string true "Owner"
// @Param user query string true "User"
// @Param application query string true "Application"
// @Param tag query string false "Tag"
// @Param parent query string false "Parent"
// @Param fullFilePath query string true "Full File Path"
// @Param createdTime query string false "Created Time"
// @Param description query string false "Description"
// @Param file formData file true "Resource file"
// @Success 200 {object} object.Resource FileUrl, objectKey
// @router /upload-resource [post] // @router /upload-resource [post]
func (c *ApiController) UploadResource() { func (c *ApiController) UploadResource() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
@ -231,33 +166,28 @@ func (c *ApiController) UploadResource() {
return return
} }
provider, err := c.GetProviderFromContext("Storage") provider, _, ok := c.GetProviderFromContext("Storage")
if err != nil { if !ok {
c.ResponseError(err.Error())
return return
} }
_, fullFilePath = refineFullFilePath(fullFilePath)
fileType := "unknown" fileType := "unknown"
contentType := header.Header.Get("Content-Type") contentType := header.Header.Get("Content-Type")
fileType, _ = util.GetOwnerAndNameFromIdNoCheck(contentType + "/") fileType, _ = util.GetOwnerAndNameFromId(contentType)
if fileType != "image" && fileType != "video" { if fileType != "image" && fileType != "video" {
ext := filepath.Ext(filename) ext := filepath.Ext(filename)
mimeType := mime.TypeByExtension(ext) mimeType := mime.TypeByExtension(ext)
fileType, _ = util.GetOwnerAndNameFromIdNoCheck(mimeType + "/") fileType, _ = util.GetOwnerAndNameFromId(mimeType)
} }
fullFilePath = object.GetTruncatedPath(provider, fullFilePath, 175) fullFilePath = object.GetTruncatedPath(provider, fullFilePath, 175)
if tag != "avatar" && tag != "termsOfUse" && !strings.HasPrefix(tag, "idCard") { if tag != "avatar" && tag != "termsOfUse" {
ext := filepath.Ext(filepath.Base(fullFilePath)) ext := filepath.Ext(filepath.Base(fullFilePath))
index := len(fullFilePath) - len(ext) index := len(fullFilePath) - len(ext)
for i := 1; ; i++ { for i := 1; ; i++ {
_, objectKey := object.GetUploadFileUrl(provider, fullFilePath, true) _, objectKey := object.GetUploadFileUrl(provider, fullFilePath, true)
if count, err := object.GetResourceCount(owner, username, "name", objectKey); err != nil { if object.GetResourceCount(owner, username, "name", objectKey) == 0 {
c.ResponseError(err.Error())
return
} else if count == 0 {
break break
} }
@ -272,11 +202,6 @@ 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()
} }
@ -298,39 +223,20 @@ func (c *ApiController) UploadResource() {
Url: fileUrl, Url: fileUrl,
Description: description, Description: description,
} }
_, err = object.AddOrUpdateResource(resource) object.AddOrUpdateResource(resource)
if err != nil {
c.ResponseError(err.Error())
return
}
switch tag { switch tag {
case "avatar": case "avatar":
user, err := object.GetUserNoCheck(util.GetId(owner, username)) user := object.GetUserNoCheck(util.GetId(owner, username))
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil { if user == nil {
c.ResponseError(c.T("resource:User is nil for tag: avatar")) c.ResponseError(c.T("resource:User is nil for tag: avatar"))
return return
} }
user.Avatar = fileUrl user.Avatar = fileUrl
_, err = object.UpdateUser(user.GetId(), user, []string{"avatar"}, false) object.UpdateUser(user.GetId(), user, []string{"avatar"}, false)
if err != nil {
c.ResponseError(err.Error())
return
}
case "termsOfUse": case "termsOfUse":
user, err := object.GetUserNoCheck(util.GetId(owner, username)) user := object.GetUserNoCheck(util.GetId(owner, username))
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil { if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(owner, username))) c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(owner, username)))
return return
@ -341,41 +247,10 @@ func (c *ApiController) UploadResource() {
return return
} }
_, applicationId := util.GetOwnerAndNameFromIdNoCheck(strings.TrimSuffix(fullFilePath, ".html")) _, applicationId := util.GetOwnerAndNameFromIdNoCheck(strings.TrimRight(fullFilePath, ".html"))
applicationObj, err := object.GetApplication(applicationId) applicationObj := object.GetApplication(applicationId)
if err != nil {
c.ResponseError(err.Error())
return
}
applicationObj.TermsOfUse = fileUrl applicationObj.TermsOfUse = fileUrl
_, err = object.UpdateApplication(applicationId, applicationObj) object.UpdateApplication(applicationId, applicationObj)
if err != nil {
c.ResponseError(err.Error())
return
}
case "idCardFront", "idCardBack", "idCardWithPerson":
user, err := object.GetUserNoCheck(util.GetId(owner, username))
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError(c.T("resource:User is nil for tag: avatar"))
return
}
if user.Properties == nil {
user.Properties = map[string]string{}
}
user.Properties[tag] = fileUrl
user.Properties["isIdCardVerified"] = "false"
_, err = object.UpdateUser(user.GetId(), user, []string{"properties"}, false)
if err != nil {
c.ResponseError(err.Error())
return
}
} }
c.ResponseOk(fileUrl, objectKey) c.ResponseOk(fileUrl, objectKey)

View File

@ -37,30 +37,13 @@ func (c *ApiController) GetRoles() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
roles, err := object.GetRoles(owner) c.Data["json"] = object.GetRoles(owner)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(roles)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetRoleCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetRoleCount(owner, field, value)))
if err != nil { roles := object.GetPaginationRoles(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
roles, err := object.GetPaginationRoles(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(roles, paginator.Nums()) c.ResponseOk(roles, paginator.Nums())
} }
} }
@ -75,13 +58,8 @@ func (c *ApiController) GetRoles() {
func (c *ApiController) GetRole() { func (c *ApiController) GetRole() {
id := c.Input().Get("id") id := c.Input().Get("id")
role, err := object.GetRole(id) c.Data["json"] = object.GetRole(id)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(role)
} }
// UpdateRole // UpdateRole

View File

@ -1,54 +0,0 @@
// 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 (
"fmt"
"os"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
func (c *ApiController) UploadRoles() {
userId := c.GetSessionUsername()
owner, user := util.GetOwnerAndNameFromId(userId)
file, header, err := c.Ctx.Request.FormFile("file")
if err != nil {
c.ResponseError(err.Error())
return
}
fileId := fmt.Sprintf("%s_%s_%s", owner, user, util.RemoveExt(header.Filename))
path := util.GetUploadXlsxPath(fileId)
defer os.Remove(path)
err = saveFile(path, &file)
if err != nil {
c.ResponseError(err.Error())
return
}
affected, err := object.UploadRoles(owner, path)
if err != nil {
c.ResponseError(err.Error())
}
if affected {
c.ResponseOk()
} else {
c.ResponseError(c.T("user_upload:Failed to import users"))
}
}

View File

@ -16,7 +16,6 @@ package controllers
import ( import (
"fmt" "fmt"
"net/http"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
) )
@ -24,43 +23,12 @@ import (
func (c *ApiController) GetSamlMeta() { func (c *ApiController) GetSamlMeta() {
host := c.Ctx.Request.Host host := c.Ctx.Request.Host
paramApp := c.Input().Get("application") paramApp := c.Input().Get("application")
application, err := object.GetApplication(paramApp) application := object.GetApplication(paramApp)
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil { if application == nil {
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)
enablePostBinding, err := c.GetBool("enablePostBinding", false)
if err != nil {
c.ResponseError(err.Error())
return
}
metadata, err := object.GetSamlMeta(application, host, enablePostBinding)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["xml"] = metadata c.Data["xml"] = metadata
c.ServeXML() c.ServeXML()
} }
func (c *ApiController) HandleSamlRedirect() {
host := c.Ctx.Request.Host
owner := c.Ctx.Input.Param(":owner")
application := c.Ctx.Input.Param(":application")
relayState := c.Input().Get("RelayState")
samlRequest := c.Input().Get("SAMLRequest")
targetURL := object.GetSamlRedirectAddress(owner, application, relayState, samlRequest, host)
c.Redirect(targetURL, http.StatusSeeOther)
}

View File

@ -40,10 +40,6 @@ type SmsForm struct {
OrgId string `json:"organizationId"` // e.g. "admin/built-in" OrgId string `json:"organizationId"` // e.g. "admin/built-in"
} }
type NotificationForm struct {
Content string `json:"content"`
}
// SendEmail // SendEmail
// @Title SendEmail // @Title SendEmail
// @Tag Service API // @Tag Service API
@ -51,14 +47,9 @@ 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} controllers.Response The Response object // @Success 200 {object} Response object
// @router /send-email [post] // @router /api/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)
@ -70,17 +61,12 @@ func (c *ApiController) SendEmail() {
var provider *object.Provider var provider *object.Provider
if emailForm.Provider != "" { if emailForm.Provider != "" {
// called by frontend's TestEmailWidget, provider name is set by frontend // called by frontend's TestEmailWidget, provider name is set by frontend
provider, err = object.GetProvider(util.GetId("admin", emailForm.Provider)) provider = object.GetProvider(util.GetId("admin", emailForm.Provider))
if err != nil {
c.ResponseError(err.Error())
return
}
} else { } else {
// called by Casdoor SDK via Client ID & Client Secret, so the used Email provider will be the application' Email provider or the default Email provider // called by Casdoor SDK via Client ID & Client Secret, so the used Email provider will be the application' Email provider or the default Email provider
provider, err = c.GetProviderFromContext("Email") var ok bool
if err != nil { provider, _, ok = c.GetProviderFromContext("Email")
c.ResponseError(err.Error()) if !ok {
return return
} }
} }
@ -113,22 +99,8 @@ 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 := strings.Replace(provider.Content, "%s", code, 1) content := fmt.Sprintf(emailForm.Content, code)
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 {
@ -147,28 +119,25 @@ 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} controllers.Response The Response object // @Success 200 {object} Response object
// @router /send-sms [post] // @router /api/send-sms [post]
func (c *ApiController) SendSms() { func (c *ApiController) SendSms() {
provider, err := c.GetProviderFromContext("SMS") provider, _, ok := c.GetProviderFromContext("SMS")
if err != nil { if !ok {
c.ResponseError(err.Error())
return return
} }
var smsForm SmsForm var smsForm SmsForm
err = json.Unmarshal(c.Ctx.Input.RequestBody, &smsForm) err := json.Unmarshal(c.Ctx.Input.RequestBody, &smsForm)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
if provider.Type != "Custom HTTP SMS" { invalidReceivers := getInvalidSmsReceivers(smsForm)
invalidReceivers := getInvalidSmsReceivers(smsForm) if len(invalidReceivers) != 0 {
if len(invalidReceivers) != 0 { c.ResponseError(fmt.Sprintf(c.T("service:Invalid phone receivers: %s"), strings.Join(invalidReceivers, ", ")))
c.ResponseError(fmt.Sprintf(c.T("service:Invalid phone receivers: %s"), strings.Join(invalidReceivers, ", "))) return
return
}
} }
err = object.SendSms(provider, smsForm.Content, smsForm.Receivers...) err = object.SendSms(provider, smsForm.Content, smsForm.Receivers...)
@ -179,33 +148,3 @@ func (c *ApiController) SendSms() {
c.ResponseOk() c.ResponseOk()
} }
// SendNotification
// @Title SendNotification
// @Tag Service API
// @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"
// @Success 200 {object} controllers.Response The Response object
// @router /send-notification [post]
func (c *ApiController) SendNotification() {
provider, err := c.GetProviderFromContext("Notification")
if err != nil {
c.ResponseError(err.Error())
return
}
var notificationForm NotificationForm
err = json.Unmarshal(c.Ctx.Input.RequestBody, &notificationForm)
if err != nil {
c.ResponseError(err.Error())
return
}
err = object.SendNotification(provider, notificationForm.Content)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk()
}

View File

@ -37,29 +37,13 @@ func (c *ApiController) GetSessions() {
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
if limit == "" || page == "" { if limit == "" || page == "" {
sessions, err := object.GetSessions(owner) c.Data["json"] = object.GetSessions(owner)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(sessions)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetSessionCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetSessionCount(owner, field, value)))
if err != nil { sessions := object.GetPaginationSessions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
sessions, err := object.GetPaginationSessions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(sessions, paginator.Nums()) c.ResponseOk(sessions, paginator.Nums())
} }
} }
@ -74,13 +58,8 @@ func (c *ApiController) GetSessions() {
func (c *ApiController) GetSingleSession() { func (c *ApiController) GetSingleSession() {
id := c.Input().Get("sessionPkId") id := c.Input().Get("sessionPkId")
session, err := object.GetSingleSession(id) c.Data["json"] = object.GetSingleSession(id)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(session)
} }
// UpdateSession // UpdateSession
@ -153,11 +132,8 @@ func (c *ApiController) IsSessionDuplicated() {
id := c.Input().Get("sessionPkId") id := c.Input().Get("sessionPkId")
sessionId := c.Input().Get("sessionId") sessionId := c.Input().Get("sessionId")
isUserSessionDuplicated, err := object.IsSessionDuplicated(id, sessionId) isUserSessionDuplicated := object.IsSessionDuplicated(id, sessionId)
if err != nil { c.Data["json"] = &Response{Status: "ok", Msg: "", Data: isUserSessionDuplicated}
c.ResponseError(err.Error())
return
}
c.ResponseOk(isUserSessionDuplicated) c.ServeJSON()
} }

View File

@ -37,30 +37,13 @@ func (c *ApiController) GetSubscriptions() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
subscriptions, err := object.GetSubscriptions(owner) c.Data["json"] = object.GetSubscriptions(owner)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(subscriptions)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetSubscriptionCount(owner, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetSubscriptionCount(owner, field, value)))
if err != nil { subscription := object.GetPaginationSubscriptions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
subscription, err := object.GetPaginationSubscriptions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(subscription, paginator.Nums()) c.ResponseOk(subscription, paginator.Nums())
} }
} }
@ -70,18 +53,15 @@ func (c *ApiController) GetSubscriptions() {
// @Tag Subscription API // @Tag Subscription API
// @Description get subscription // @Description get subscription
// @Param id query string true "The id ( owner/name ) of the subscription" // @Param id query string true "The id ( owner/name ) of the subscription"
// @Success 200 {object} object.Subscription The Response object // @Success 200 {object} object.subscription The Response object
// @router /get-subscription [get] // @router /get-subscription [get]
func (c *ApiController) GetSubscription() { func (c *ApiController) GetSubscription() {
id := c.Input().Get("id") id := c.Input().Get("id")
subscription, err := object.GetSubscription(id) subscription := object.GetSubscription(id)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(subscription) c.Data["json"] = subscription
c.ServeJSON()
} }
// UpdateSubscription // UpdateSubscription

View File

@ -38,30 +38,13 @@ func (c *ApiController) GetSyncers() {
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
organization := c.Input().Get("organization") organization := c.Input().Get("organization")
if limit == "" || page == "" { if limit == "" || page == "" {
syncers, err := object.GetMaskedSyncers(object.GetOrganizationSyncers(owner, organization)) c.Data["json"] = object.GetOrganizationSyncers(owner, organization)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(syncers)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetSyncerCount(owner, organization, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetSyncerCount(owner, organization, field, value)))
if err != nil { syncers := object.GetPaginationSyncers(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
syncers, err := object.GetMaskedSyncers(object.GetPaginationSyncers(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder))
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(syncers, paginator.Nums()) c.ResponseOk(syncers, paginator.Nums())
} }
} }
@ -76,13 +59,8 @@ 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.GetMaskedSyncer(object.GetSyncer(id)) c.Data["json"] = object.GetSyncer(id)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(syncer)
} }
// UpdateSyncer // UpdateSyncer
@ -154,17 +132,9 @@ func (c *ApiController) DeleteSyncer() {
// @router /run-syncer [get] // @router /run-syncer [get]
func (c *ApiController) RunSyncer() { func (c *ApiController) RunSyncer() {
id := c.Input().Get("id") id := c.Input().Get("id")
syncer, err := object.GetSyncer(id) syncer := object.GetSyncer(id)
if err != nil {
c.ResponseError(err.Error())
return
}
err = object.RunSyncer(syncer) object.RunSyncer(syncer)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk() c.ResponseOk()
} }

View File

@ -47,21 +47,16 @@ func (c *ApiController) GetSystemInfo() {
// @router /get-version-info [get] // @router /get-version-info [get]
func (c *ApiController) GetVersionInfo() { func (c *ApiController) GetVersionInfo() {
versionInfo, err := util.GetVersionInfo() versionInfo, err := util.GetVersionInfo()
if err != nil {
c.ResponseError(err.Error()) if versionInfo.Version == "" {
return versionInfo, err = util.GetVersionInfoFromFile()
if err != nil {
c.ResponseError(err.Error())
return
}
} }
if versionInfo.Version != "" {
c.ResponseOk(versionInfo)
return
}
versionInfo, err = util.GetVersionInfoFromFile()
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(versionInfo) c.ResponseOk(versionInfo)
} }

View File

@ -41,28 +41,12 @@ func (c *ApiController) GetTokens() {
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
organization := c.Input().Get("organization") organization := c.Input().Get("organization")
if limit == "" || page == "" { if limit == "" || page == "" {
token, err := object.GetTokens(owner, organization) c.Data["json"] = object.GetTokens(owner, organization)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(token)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetTokenCount(owner, organization, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetTokenCount(owner, organization, field, value)))
if err != nil { tokens := object.GetPaginationTokens(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
tokens, err := object.GetPaginationTokens(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(tokens, paginator.Nums()) c.ResponseOk(tokens, paginator.Nums())
} }
} }
@ -76,13 +60,9 @@ func (c *ApiController) GetTokens() {
// @router /get-token [get] // @router /get-token [get]
func (c *ApiController) GetToken() { func (c *ApiController) GetToken() {
id := c.Input().Get("id") id := c.Input().Get("id")
token, err := object.GetToken(id)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(token) c.Data["json"] = object.GetToken(id)
c.ServeJSON()
} }
// UpdateToken // UpdateToken
@ -158,9 +138,10 @@ func (c *ApiController) DeleteToken() {
// @Success 401 {object} object.TokenError The Response object // @Success 401 {object} object.TokenError The Response object
// @router /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")
@ -168,61 +149,30 @@ 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 len(c.Ctx.Input.RequestBody) != 0 { // If clientID is empty, try to read data from RequestBody
// If clientId is empty, try to read data from RequestBody
var tokenRequest TokenRequest var tokenRequest TokenRequest
err := json.Unmarshal(c.Ctx.Input.RequestBody, &tokenRequest) if err := json.Unmarshal(c.Ctx.Input.RequestBody, &tokenRequest); err == nil {
if err == nil { clientId = tokenRequest.ClientId
if clientId == "" { clientSecret = tokenRequest.ClientSecret
clientId = tokenRequest.ClientId grantType = tokenRequest.GrantType
} refreshToken = tokenRequest.RefreshToken
if clientSecret == "" { code = tokenRequest.Code
clientSecret = tokenRequest.ClientSecret verifier = tokenRequest.Verifier
} scope = tokenRequest.Scope
if grantType == "" { username = tokenRequest.Username
grantType = tokenRequest.GrantType password = tokenRequest.Password
} tag = tokenRequest.Tag
if code == "" { avatar = tokenRequest.Avatar
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
token, err := object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = token c.Data["json"] = object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
c.SetTokenErrorHttpStatus() c.SetTokenErrorHttpStatus()
c.ServeJSON() c.ServeJSON()
} }
@ -260,28 +210,13 @@ func (c *ApiController) RefreshToken() {
} }
} }
refreshToken2, err := object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host) c.Data["json"] = object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = refreshToken2
c.SetTokenErrorHttpStatus()
c.ServeJSON()
}
func (c *ApiController) ResponseTokenError(errorMsg string) {
c.Data["json"] = &object.TokenError{
Error: errorMsg,
}
c.SetTokenErrorHttpStatus() c.SetTokenErrorHttpStatus()
c.ServeJSON() c.ServeJSON()
} }
// 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
@ -301,33 +236,30 @@ func (c *ApiController) IntrospectToken() {
clientId = c.Input().Get("client_id") clientId = c.Input().Get("client_id")
clientSecret = c.Input().Get("client_secret") clientSecret = c.Input().Get("client_secret")
if clientId == "" || clientSecret == "" { if clientId == "" || clientSecret == "" {
c.ResponseTokenError(object.InvalidRequest) c.ResponseError(c.T("token:Empty clientId or clientSecret"))
c.Data["json"] = &object.TokenError{
Error: object.InvalidRequest,
}
c.SetTokenErrorHttpStatus()
c.ServeJSON()
return return
} }
} }
application := object.GetApplicationByClientId(clientId)
application, err := object.GetApplicationByClientId(clientId)
if err != nil {
c.ResponseTokenError(err.Error())
return
}
if application == nil || application.ClientSecret != clientSecret { if application == nil || application.ClientSecret != clientSecret {
c.ResponseTokenError(c.T("token:Invalid application or wrong clientSecret")) c.ResponseError(c.T("token:Invalid application or wrong clientSecret"))
return c.Data["json"] = &object.TokenError{
} Error: object.InvalidClient,
}
token, err := object.GetTokenByTokenValue(tokenValue) c.SetTokenErrorHttpStatus()
if err != nil {
c.ResponseTokenError(err.Error())
return return
} }
token := object.GetTokenByTokenAndApplication(tokenValue, application.Name)
if token == nil { if token == nil {
c.Data["json"] = &object.IntrospectionResponse{Active: false} c.Data["json"] = &object.IntrospectionResponse{Active: false}
c.ServeJSON() c.ServeJSON()
return return
} }
jwtToken, err := object.ParseJwtTokenByApplication(tokenValue, application) jwtToken, err := object.ParseJwtTokenByApplication(tokenValue, application)
if err != nil || jwtToken.Valid() != nil { if err != nil || jwtToken.Valid() != nil {
// and token revoked case. but we not implement // and token revoked case. but we not implement
@ -350,7 +282,7 @@ func (c *ApiController) IntrospectToken() {
Sub: jwtToken.Subject, Sub: jwtToken.Subject,
Aud: jwtToken.Audience, Aud: jwtToken.Audience,
Iss: jwtToken.Issuer, Iss: jwtToken.Issuer,
Jti: jwtToken.ID, Jti: jwtToken.Id,
} }
c.ServeJSON() c.ServeJSON()
} }

View File

@ -15,10 +15,10 @@
package controllers package controllers
type TokenRequest struct { type TokenRequest struct {
ClientId string `json:"client_id"`
ClientSecret string `json:"client_secret"`
GrantType string `json:"grant_type"` GrantType string `json:"grant_type"`
Code string `json:"code"` Code string `json:"code"`
ClientId string `json:"client_id"`
ClientSecret string `json:"client_secret"`
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"`

View File

@ -37,36 +37,14 @@ func (c *ApiController) GetGlobalUsers() {
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
users, err := object.GetMaskedUsers(object.GetGlobalUsers()) c.Data["json"] = object.GetMaskedUsers(object.GetGlobalUsers())
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(users)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetGlobalUserCount(field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetGlobalUserCount(field, value)))
if err != nil { users := object.GetPaginationGlobalUsers(paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error()) users = object.GetMaskedUsers(users)
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
users, err := object.GetPaginationGlobalUsers(paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
users, err = object.GetMaskedUsers(users)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(users, paginator.Nums()) c.ResponseOk(users, paginator.Nums())
} }
} }
@ -80,53 +58,20 @@ func (c *ApiController) GetGlobalUsers() {
// @router /get-users [get] // @router /get-users [get]
func (c *ApiController) GetUsers() { func (c *ApiController) GetUsers() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
groupName := c.Input().Get("groupName")
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")
value := c.Input().Get("value") value := c.Input().Get("value")
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
if groupName != "" { c.Data["json"] = object.GetMaskedUsers(object.GetUsers(owner))
users, err := object.GetMaskedUsers(object.GetGroupUsers(util.GetId(owner, groupName))) c.ServeJSON()
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(users)
return
}
users, err := object.GetMaskedUsers(object.GetUsers(owner))
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(users)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetUserCount(owner, field, value, groupName) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetUserCount(owner, field, value)))
if err != nil { users := object.GetPaginationUsers(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error()) users = object.GetMaskedUsers(users)
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
users, err := object.GetPaginationUsers(owner, paginator.Offset(), limit, field, value, sortField, sortOrder, groupName)
if err != nil {
c.ResponseError(err.Error())
return
}
users, err = object.GetMaskedUsers(users)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(users, paginator.Nums()) c.ResponseOk(users, paginator.Nums())
} }
} }
@ -148,91 +93,43 @@ func (c *ApiController) GetUser() {
phone := c.Input().Get("phone") phone := c.Input().Get("phone")
userId := c.Input().Get("userId") userId := c.Input().Get("userId")
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
var err error
var userFromUserId *object.User var userFromUserId *object.User
if userId != "" && owner != "" { if userId != "" && owner != "" {
userFromUserId, err = object.GetUserByUserId(owner, userId) userFromUserId = object.GetUserByUserId(owner, userId)
if err != nil {
c.ResponseError(err.Error())
return
}
id = util.GetId(userFromUserId.Owner, userFromUserId.Name) id = util.GetId(userFromUserId.Owner, userFromUserId.Name)
} }
var user *object.User if owner == "" {
if id == "" && owner == "" { owner = util.GetOwnerFromId(id)
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)
}
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 { organization := object.GetOrganization(util.GetId("admin", owner))
c.ResponseError(err.Error()) if !organization.IsProfilePublic {
return requestUserId := c.GetSessionUsername()
} hasPermission, err := object.CheckUserPermission(requestUserId, id, false, c.GetAcceptLanguage())
if !hasPermission {
if user != nil {
var organization *object.Organization
organization, err = object.GetOrganizationByUser(user)
if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return 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 { var user *object.User
user.MultiFactorAuths = object.GetAllMfaProps(user, true) switch {
case email != "":
user = object.GetUserByEmail(owner, email)
case phone != "":
user = object.GetUserByPhone(owner, phone)
case userId != "":
user = userFromUserId
default:
user = object.GetUser(id)
} }
err = object.ExtendUserWithRolesAndPermissions(user) object.ExtendUserWithRolesAndPermissions(user)
if err != nil {
c.ResponseError(err.Error())
return
}
isAdminOrSelf := c.IsAdminOrSelf(user) c.Data["json"] = object.GetMaskedUser(user)
user, err = object.GetMaskedUser(user, isAdminOrSelf) c.ServeJSON()
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(user)
} }
// UpdateUser // UpdateUser
@ -261,12 +158,7 @@ func (c *ApiController) UpdateUser() {
return return
} }
} }
oldUser, err := object.GetUser(id) oldUser := object.GetUser(id)
if err != nil {
c.ResponseError(err.Error())
return
}
if oldUser == nil { if oldUser == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), id)) c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), id))
return return
@ -277,13 +169,6 @@ func (c *ApiController) UpdateUser() {
return return
} }
if c.Input().Get("allowEmpty") == "" {
if user.DisplayName == "" {
c.ResponseError(c.T("user:Display name cannot be empty"))
return
}
}
if msg := object.CheckUpdateUser(oldUser, &user, c.GetAcceptLanguage()); msg != "" { if msg := object.CheckUpdateUser(oldUser, &user, c.GetAcceptLanguage()); msg != "" {
c.ResponseError(msg) c.ResponseError(msg)
return return
@ -300,18 +185,9 @@ func (c *ApiController) UpdateUser() {
columns = strings.Split(columnsStr, ",") columns = strings.Split(columnsStr, ",")
} }
affected, err := object.UpdateUser(id, &user, columns, isAdmin) affected := object.UpdateUser(id, &user, columns, isAdmin)
if err != nil {
c.ResponseError(err.Error())
return
}
if affected { if affected {
err = object.UpdateUserToOriginalDatabase(&user) object.UpdateUserToOriginalDatabase(&user)
if err != nil {
c.ResponseError(err.Error())
return
}
} }
c.Data["json"] = wrapActionResponse(affected) c.Data["json"] = wrapActionResponse(affected)
@ -333,13 +209,8 @@ func (c *ApiController) AddUser() {
return return
} }
count, err := object.GetUserCount("", "", "", "") count := object.GetUserCount("", "", "")
if err != nil { if err := checkQuotaForUser(count); err != nil {
c.ResponseError(err.Error())
return
}
if err := checkQuotaForUser(int(count)); err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
@ -390,12 +261,7 @@ func (c *ApiController) GetEmailAndPhone() {
organization := c.Ctx.Request.Form.Get("organization") organization := c.Ctx.Request.Form.Get("organization")
username := c.Ctx.Request.Form.Get("username") username := c.Ctx.Request.Form.Get("username")
user, err := object.GetUserByFields(organization, username) user := object.GetUserByFields(organization, username)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil { if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(organization, username))) c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(organization, username)))
return return
@ -445,12 +311,15 @@ func (c *ApiController) SetPassword() {
c.ResponseError(c.T("user:New password cannot contain blank space.")) c.ResponseError(c.T("user:New password cannot contain blank space."))
return return
} }
if len(newPassword) <= 5 {
c.ResponseError(c.T("user:New password must have at least 6 characters"))
return
}
userId := util.GetId(userOwner, userName) userId := util.GetId(userOwner, userName)
requestUserId := c.GetSessionUsername() requestUserId := c.GetSessionUsername()
if requestUserId == "" && code == "" { if requestUserId == "" && code == "" {
c.ResponseError(c.T("general:Please login first"), "Please login first")
return return
} else if code == "" { } else if code == "" {
hasPermission, err := object.CheckUserPermission(requestUserId, userId, true, c.GetAcceptLanguage()) hasPermission, err := object.CheckUserPermission(requestUserId, userId, true, c.GetAcceptLanguage())
@ -460,52 +329,24 @@ func (c *ApiController) SetPassword() {
} }
} else { } else {
if code != c.GetSession("verifiedCode") { if code != c.GetSession("verifiedCode") {
c.ResponseError(c.T("general:Missing parameter")) c.ResponseError("")
return return
} }
c.SetSession("verifiedCode", "") c.SetSession("verifiedCode", "")
} }
targetUser, err := object.GetUser(userId) targetUser := object.GetUser(userId)
if targetUser == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId))
return
}
if err != nil {
c.ResponseError(err.Error())
return
}
isAdmin := c.IsAdmin() if oldPassword != "" {
if isAdmin { msg := object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
if oldPassword != "" { if msg != "" {
err = object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage()) c.ResponseError(msg)
if err != nil {
c.ResponseError(err.Error())
return
}
}
} else if code == "" {
err = object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error())
return return
} }
} }
msg := object.CheckPasswordComplexity(targetUser, newPassword)
if msg != "" {
c.ResponseError(msg)
return
}
targetUser.Password = newPassword targetUser.Password = newPassword
_, err = object.SetUserField(targetUser, "password", targetUser.Password) object.SetUserField(targetUser, "password", targetUser.Password)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk() c.ResponseOk()
} }
@ -513,7 +354,6 @@ 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)
@ -522,11 +362,11 @@ func (c *ApiController) CheckUserPassword() {
return return
} }
_, err = object.CheckUserPassword(user.Owner, user.Name, user.Password, c.GetAcceptLanguage()) _, msg := object.CheckUserPassword(user.Owner, user.Name, user.Password, c.GetAcceptLanguage())
if err != nil { if msg == "" {
c.ResponseError(err.Error())
} else {
c.ResponseOk() c.ResponseOk()
} else {
c.ResponseError(msg)
} }
} }
@ -544,13 +384,8 @@ 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"))
users, err := object.GetMaskedUsers(object.GetSortedUsers(owner, sorter, limit)) c.Data["json"] = object.GetMaskedUsers(object.GetSortedUsers(owner, sorter, limit))
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(users)
} }
// GetUserCount // GetUserCount
@ -565,65 +400,13 @@ func (c *ApiController) GetUserCount() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
isOnline := c.Input().Get("isOnline") isOnline := c.Input().Get("isOnline")
var count int64 count := 0
var err error
if isOnline == "" { if isOnline == "" {
count, err = object.GetUserCount(owner, "", "", "") count = object.GetUserCount(owner, "", "")
} else { } else {
count, err = object.GetOnlineUserCount(owner, util.ParseInt(isOnline)) count = object.GetOnlineUserCount(owner, util.ParseInt(isOnline))
}
if err != nil {
c.ResponseError(err.Error())
return
} }
c.ResponseOk(count) c.Data["json"] = count
} c.ServeJSON()
// AddUserKeys
// @Title AddUserKeys
// @router /add-user-keys [post]
// @Tag User API
// @Success 200 {object} object.Userinfo The Response object
func (c *ApiController) AddUserKeys() {
var user object.User
err := json.Unmarshal(c.Ctx.Input.RequestBody, &user)
if err != nil {
c.ResponseError(err.Error())
return
}
isAdmin := c.IsAdmin()
affected, err := object.AddUserKeys(&user, isAdmin)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(affected)
}
func (c *ApiController) RemoveUserFromGroup() {
owner := c.Ctx.Request.Form.Get("owner")
name := c.Ctx.Request.Form.Get("name")
groupName := c.Ctx.Request.Form.Get("groupName")
organization, err := object.GetOrganization(util.GetId("admin", owner))
if err != nil {
return
}
item := object.GetAccountItemByName("Groups", organization)
res, msg := object.CheckAccountItemModifyRule(item, c.IsAdmin(), c.GetAcceptLanguage())
if !res {
c.ResponseError(msg)
return
}
affected, err := object.DeleteGroupForUser(util.GetId(owner, name), groupName)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(affected)
} }

View File

@ -19,14 +19,13 @@ import (
"io" "io"
"mime/multipart" "mime/multipart"
"os" "os"
"path/filepath"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
) )
func saveFile(path string, file *multipart.File) (err error) { func saveFile(path string, file *multipart.File) (err error) {
f, err := os.Create(filepath.Clean(path)) f, err := os.Create(path)
if err != nil { if err != nil {
return err return err
} }
@ -48,22 +47,17 @@ func (c *ApiController) UploadUsers() {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
fileId := fmt.Sprintf("%s_%s_%s", owner, user, util.RemoveExt(header.Filename)) fileId := fmt.Sprintf("%s_%s_%s", owner, user, util.RemoveExt(header.Filename))
path := util.GetUploadXlsxPath(fileId) path := util.GetUploadXlsxPath(fileId)
defer os.Remove(path) util.EnsureFileFolderExists(path)
err = saveFile(path, &file) err = saveFile(path, &file)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
affected, err := object.UploadUsers(owner, path) affected := object.UploadUsers(owner, fileId)
if err != nil {
c.ResponseError(err.Error())
return
}
if affected { if affected {
c.ResponseOk() c.ResponseOk()
} else { } else {

View File

@ -16,7 +16,6 @@ package controllers
import ( import (
"fmt" "fmt"
"strings"
"github.com/casdoor/casdoor/conf" "github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/i18n" "github.com/casdoor/casdoor/i18n"
@ -56,9 +55,6 @@ func (c *ApiController) T(error string) string {
// GetAcceptLanguage ... // GetAcceptLanguage ...
func (c *ApiController) GetAcceptLanguage() string { func (c *ApiController) GetAcceptLanguage() string {
language := c.Ctx.Request.Header.Get("Accept-Language") language := c.Ctx.Request.Header.Get("Accept-Language")
if len(language) > 2 {
language = language[0:2]
}
return conf.GetLanguage(language) return conf.GetLanguage(language)
} }
@ -96,19 +92,7 @@ func (c *ApiController) RequireSignedInUser() (*object.User, bool) {
return nil, false return nil, false
} }
if strings.HasPrefix(userId, "app/") { user := object.GetUser(userId)
tmpUserId := c.Input().Get("userId")
if tmpUserId != "" {
userId = tmpUserId
}
}
user, err := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return nil, false
}
if user == nil { if user == nil {
c.ClearUserSession() c.ClearUserSession()
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId)) c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId))
@ -151,68 +135,35 @@ func (c *ApiController) IsMaskedEnabled() (bool, bool) {
return true, isMaskEnabled return true, isMaskEnabled
} }
func refineFullFilePath(fullFilePath string) (string, string) { func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, *object.User, bool) {
tokens := strings.Split(fullFilePath, "/")
if len(tokens) >= 2 && tokens[0] == "Direct" && tokens[1] != "" {
providerName := tokens[1]
res := strings.Join(tokens[2:], "/")
return providerName, "/" + res
} else {
return "", fullFilePath
}
}
func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, error) {
providerName := c.Input().Get("provider") providerName := c.Input().Get("provider")
if providerName == "" {
field := c.Input().Get("field")
value := c.Input().Get("value")
if field == "provider" && value != "" {
providerName = value
} else {
fullFilePath := c.Input().Get("fullFilePath")
providerName, _ = refineFullFilePath(fullFilePath)
}
}
if providerName != "" { if providerName != "" {
provider, err := object.GetProvider(util.GetId("admin", providerName)) provider := object.GetProvider(util.GetId("admin", providerName))
if err != nil {
return nil, err
}
if provider == nil { if provider == nil {
err = fmt.Errorf(c.T("util:The provider: %s is not found"), providerName) c.ResponseError(fmt.Sprintf(c.T("util:The provider: %s is not found"), providerName))
return nil, err return nil, nil, false
} }
return provider, nil, true
return provider, nil
} }
userId, ok := c.RequireSignedIn() userId, ok := c.RequireSignedIn()
if !ok { if !ok {
return nil, fmt.Errorf(c.T("general:Please login first")) return nil, nil, false
}
application, err := object.GetApplicationByUserId(userId)
if err != nil {
return nil, err
} }
application, user := object.GetApplicationByUserId(userId)
if application == nil { if application == nil {
return nil, fmt.Errorf(c.T("util:No application is found for userId: %s"), userId) c.ResponseError(fmt.Sprintf(c.T("util:No application is found for userId: %s"), userId))
} return nil, nil, false
provider, err := application.GetProviderByCategory(category)
if err != nil {
return nil, err
} }
provider := application.GetProviderByCategory(category)
if provider == nil { if provider == nil {
return nil, fmt.Errorf(c.T("util:No provider for category: %s is found for application: %s"), category, application.Name) c.ResponseError(fmt.Sprintf(c.T("util:No provider for category: %s is found for application: %s"), category, application.Name))
return nil, nil, false
} }
return provider, nil return provider, user, true
} }
func checkQuotaForApplication(count int) error { func checkQuotaForApplication(count int) error {

View File

@ -39,7 +39,6 @@ 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)
@ -54,47 +53,21 @@ func (c *ApiController) SendVerificationCode() {
return return
} }
provider, err := object.GetCaptchaProviderByApplication(vform.ApplicationId, "false", c.GetAcceptLanguage()) if vform.CaptchaType != "none" {
if err != nil { if captchaProvider := captcha.GetCaptchaProvider(vform.CaptchaType); captchaProvider == nil {
c.ResponseError(err.Error()) c.ResponseError(c.T("general:don't support captchaProvider: ") + vform.CaptchaType)
return return
} } else if isHuman, err := captchaProvider.VerifyCaptcha(vform.CaptchaToken, vform.ClientSecret); err != nil {
c.ResponseError(err.Error())
if provider != nil { return
if vform.CaptchaType != provider.Type { } else if !isHuman {
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)
if err != nil {
c.ResponseError(err.Error())
return
}
organization, err := object.GetOrganization(util.GetId(application.Owner, application.Organization))
if err != nil {
c.ResponseError(c.T(err.Error()))
} }
application := object.GetApplication(vform.ApplicationId)
organization := object.GetOrganization(util.GetId(application.Owner, application.Organization))
if organization == nil { if organization == nil {
c.ResponseError(c.T("check:Organization does not exist")) c.ResponseError(c.T("check:Organization does not exist"))
return return
@ -104,29 +77,12 @@ func (c *ApiController) SendVerificationCode() {
// checkUser != "", means method is ForgetVerification // checkUser != "", means method is ForgetVerification
if vform.CheckUser != "" { if vform.CheckUser != "" {
owner := application.Organization owner := application.Organization
user, err = object.GetUser(util.GetId(owner, vform.CheckUser)) user = object.GetUser(util.GetId(owner, vform.CheckUser))
if err != nil {
c.ResponseError(err.Error())
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 // mfaSessionData != nil, means method is MfaSetupVerification
if mfaUserSession := c.getMfaUserSession(); mfaUserSession != "" { if mfaSessionData := c.getMfaSessionData(); mfaSessionData != nil {
user, err = object.GetUser(mfaUserSession) user = object.GetUser(mfaSessionData.UserId)
if err != nil {
c.ResponseError(err.Error())
return
}
} }
sendResp := errors.New("invalid dest type") sendResp := errors.New("invalid dest type")
@ -143,12 +99,7 @@ func (c *ApiController) SendVerificationCode() {
vform.Dest = user.Email vform.Dest = user.Email
} }
user, err = object.GetUserByEmail(organization.Name, vform.Dest) user = object.GetUserByEmail(organization.Name, vform.Dest)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil { if user == nil {
c.ResponseError(c.T("verification:the user does not exist, please sign up first")) c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
return return
@ -156,24 +107,13 @@ func (c *ApiController) SendVerificationCode() {
} else if vform.Method == ResetVerification { } else if vform.Method == ResetVerification {
user = c.getCurrentUser() user = c.getCurrentUser()
} else if vform.Method == MfaAuthVerification { } else if vform.Method == MfaAuthVerification {
mfaProps := user.GetPreferredMfaProps(false) mfaProps := user.GetPreferMfa(false)
if user != nil && util.GetMaskedEmail(mfaProps.Secret) == vform.Dest { if user != nil && util.GetMaskedEmail(mfaProps.Secret) == vform.Dest {
vform.Dest = mfaProps.Secret vform.Dest = mfaProps.Secret
} }
} else if vform.Method == MfaSetupVerification {
c.SetSession(MfaDestSession, vform.Dest)
}
provider, err := application.GetEmailProvider()
if err != nil {
c.ResponseError(err.Error())
return
}
if provider == nil {
c.ResponseError(fmt.Sprintf("please add an Email provider to the \"Providers\" list for the application: %s", application.Name))
return
} }
provider := application.GetEmailProvider()
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, remoteAddr, vform.Dest) sendResp = object.SendVerificationCodeToEmail(organization, user, provider, remoteAddr, vform.Dest)
case object.VerifyTypePhone: case object.VerifyTypePhone:
if vform.Method == LoginVerification || vform.Method == ForgetVerification { if vform.Method == LoginVerification || vform.Method == ForgetVerification {
@ -181,28 +121,18 @@ func (c *ApiController) SendVerificationCode() {
vform.Dest = user.Phone vform.Dest = user.Phone
} }
if user, err = object.GetUserByPhone(organization.Name, vform.Dest); err != nil { if user = object.GetUserByPhone(organization.Name, vform.Dest); user == nil {
c.ResponseError(err.Error())
return
} else if user == nil {
c.ResponseError(c.T("verification:the user does not exist, please sign up first")) c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
return return
} }
vform.CountryCode = user.GetCountryCode(vform.CountryCode) vform.CountryCode = user.GetCountryCode(vform.CountryCode)
} else if vform.Method == ResetVerification || vform.Method == MfaSetupVerification { } else if vform.Method == ResetVerification {
if vform.CountryCode == "" { if user = c.getCurrentUser(); user != nil {
if user = c.getCurrentUser(); user != nil { vform.CountryCode = user.GetCountryCode(vform.CountryCode)
vform.CountryCode = user.GetCountryCode(vform.CountryCode)
}
}
if vform.Method == MfaSetupVerification {
c.SetSession(MfaCountryCodeSession, vform.CountryCode)
c.SetSession(MfaDestSession, vform.Dest)
} }
} else if vform.Method == MfaAuthVerification { } else if vform.Method == MfaAuthVerification {
mfaProps := user.GetPreferredMfaProps(false) mfaProps := user.GetPreferMfa(false)
if user != nil && util.GetMaskedPhone(mfaProps.Secret) == vform.Dest { if user != nil && util.GetMaskedPhone(mfaProps.Secret) == vform.Dest {
vform.Dest = mfaProps.Secret vform.Dest = mfaProps.Secret
} }
@ -210,16 +140,7 @@ func (c *ApiController) SendVerificationCode() {
vform.CountryCode = mfaProps.CountryCode vform.CountryCode = mfaProps.CountryCode
} }
provider, err := application.GetSmsProvider() provider := application.GetSmsProvider()
if err != nil {
c.ResponseError(err.Error())
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))
return return
@ -228,6 +149,11 @@ func (c *ApiController) SendVerificationCode() {
} }
} }
if vform.Method == MfaSetupVerification {
c.SetSession(object.MfaSmsCountryCodeSession, vform.CountryCode)
c.SetSession(object.MfaSmsDestSession, vform.Dest)
}
if sendResp != nil { if sendResp != nil {
c.ResponseError(sendResp.Error()) c.ResponseError(sendResp.Error())
} else { } else {
@ -239,7 +165,6 @@ 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)
@ -253,16 +178,6 @@ 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."))
@ -281,8 +196,7 @@ func (c *ApiController) VerifyCaptcha() {
// ResetEmailOrPhone ... // ResetEmailOrPhone ...
// @Tag Account API // @Tag Account API
// @Title ResetEmailOrPhone // @Title ResetEmailOrPhone
// @router /reset-email-or-phone [post] // @router /api/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 {
@ -299,12 +213,7 @@ func (c *ApiController) ResetEmailOrPhone() {
} }
checkDest := dest checkDest := dest
organization, err := object.GetOrganizationByUser(user) organization := object.GetOrganizationByUser(user)
if err != nil {
c.ResponseError(c.T(err.Error()))
return
}
if destType == object.VerifyTypePhone { if destType == object.VerifyTypePhone {
if object.HasUserByField(user.Owner, "phone", dest) { if object.HasUserByField(user.Owner, "phone", dest) {
c.ResponseError(c.T("check:Phone already exists")) c.ResponseError(c.T("check:Phone already exists"))
@ -351,33 +260,23 @@ func (c *ApiController) ResetEmailOrPhone() {
switch destType { switch destType {
case object.VerifyTypeEmail: case object.VerifyTypeEmail:
user.Email = dest user.Email = dest
_, err = object.SetUserField(user, "email", user.Email) object.SetUserField(user, "email", user.Email)
case object.VerifyTypePhone: case object.VerifyTypePhone:
user.Phone = dest user.Phone = dest
_, err = object.SetUserField(user, "phone", user.Phone) object.SetUserField(user, "phone", user.Phone)
default: default:
c.ResponseError(c.T("verification:Unknown type")) c.ResponseError(c.T("verification:Unknown type"))
return return
} }
if err != nil {
c.ResponseError(err.Error())
return
}
err = object.DisableVerificationCode(checkDest)
if err != nil {
c.ResponseError(err.Error())
return
}
object.DisableVerificationCode(checkDest)
c.ResponseOk() c.ResponseOk()
} }
// VerifyCode // VerifyCode
// @Tag Verification API // @Tag Verification API
// @Title VerifyCode // @Title VerifyCode
// @router /verify-code [post] // @router /api/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)
@ -388,11 +287,7 @@ func (c *ApiController) VerifyCode() {
var user *object.User var user *object.User
if authForm.Name != "" { if authForm.Name != "" {
user, err = object.GetUserByFields(authForm.Organization, authForm.Name) user = object.GetUserByFields(authForm.Organization, authForm.Name)
if err != nil {
c.ResponseError(err.Error())
return
}
} }
var checkDest string var checkDest string
@ -407,10 +302,7 @@ func (c *ApiController) VerifyCode() {
} }
} }
if user, err = object.GetUserByFields(authForm.Organization, authForm.Username); err != nil { if user = object.GetUserByFields(authForm.Organization, authForm.Username); user == nil {
c.ResponseError(err.Error())
return
} else if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(authForm.Organization, authForm.Username))) c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(authForm.Organization, authForm.Username)))
return return
} }
@ -429,11 +321,7 @@ func (c *ApiController) VerifyCode() {
c.ResponseError(result.Msg) c.ResponseError(result.Msg)
return return
} }
err = object.DisableVerificationCode(checkDest) object.DisableVerificationCode(checkDest)
if err != nil {
c.ResponseError(err.Error())
return
}
c.SetSession("verifiedCode", authForm.Code) c.SetSession("verifiedCode", authForm.Code)
c.ResponseOk() c.ResponseOk()

View File

@ -33,12 +33,7 @@ import (
// @Success 200 {object} protocol.CredentialCreation The CredentialCreationOptions object // @Success 200 {object} protocol.CredentialCreation The CredentialCreationOptions object
// @router /webauthn/signup/begin [get] // @router /webauthn/signup/begin [get]
func (c *ApiController) WebAuthnSignupBegin() { func (c *ApiController) WebAuthnSignupBegin() {
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host) webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
if err != nil {
c.ResponseError(err.Error())
return
}
user := c.getCurrentUser() user := c.getCurrentUser()
if user == nil { if user == nil {
c.ResponseError(c.T("general:Please login first")) c.ResponseError(c.T("general:Please login first"))
@ -66,15 +61,10 @@ func (c *ApiController) WebAuthnSignupBegin() {
// @Tag User API // @Tag User API
// @Description WebAuthn Registration Flow 2nd stage // @Description WebAuthn Registration Flow 2nd stage
// @Param body body protocol.CredentialCreationResponse true "authenticator attestation Response" // @Param body body protocol.CredentialCreationResponse true "authenticator attestation Response"
// @Success 200 {object} controllers.Response "The Response object" // @Success 200 {object} Response "The Response object"
// @router /webauthn/signup/finish [post] // @router /webauthn/signup/finish [post]
func (c *ApiController) WebAuthnSignupFinish() { func (c *ApiController) WebAuthnSignupFinish() {
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host) webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
if err != nil {
c.ResponseError(err.Error())
return
}
user := c.getCurrentUser() user := c.getCurrentUser()
if user == nil { if user == nil {
c.ResponseError(c.T("general:Please login first")) c.ResponseError(c.T("general:Please login first"))
@ -94,12 +84,7 @@ func (c *ApiController) WebAuthnSignupFinish() {
return return
} }
isGlobalAdmin := c.IsGlobalAdmin() isGlobalAdmin := c.IsGlobalAdmin()
_, err = user.AddCredentials(*credential, isGlobalAdmin) user.AddCredentials(*credential, isGlobalAdmin)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk() c.ResponseOk()
} }
@ -112,20 +97,10 @@ func (c *ApiController) WebAuthnSignupFinish() {
// @Success 200 {object} protocol.CredentialAssertion The CredentialAssertion object // @Success 200 {object} protocol.CredentialAssertion The CredentialAssertion object
// @router /webauthn/signin/begin [get] // @router /webauthn/signin/begin [get]
func (c *ApiController) WebAuthnSigninBegin() { func (c *ApiController) WebAuthnSigninBegin() {
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host) webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
if err != nil {
c.ResponseError(err.Error())
return
}
userOwner := c.Input().Get("owner") userOwner := c.Input().Get("owner")
userName := c.Input().Get("name") userName := c.Input().Get("name")
user, err := object.GetUserByFields(userOwner, userName) user := object.GetUserByFields(userOwner, userName)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil { if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(userOwner, userName))) c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(userOwner, userName)))
return return
@ -146,21 +121,15 @@ func (c *ApiController) WebAuthnSigninBegin() {
} }
// WebAuthnSigninFinish // WebAuthnSigninFinish
// @Title WebAuthnSigninFinish // @Title WebAuthnSigninBegin
// @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"
// @Success 200 {object} controllers.Response "The Response object" // @Success 200 {object} Response "The Response object"
// @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 := object.GetWebAuthnObject(c.Ctx.Request.Host)
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host)
if err != nil {
c.ResponseError(err.Error())
return
}
sessionObj := c.GetSession("authentication") sessionObj := c.GetSession("authentication")
sessionData, ok := sessionObj.(webauthn.SessionData) sessionData, ok := sessionObj.(webauthn.SessionData)
if !ok { if !ok {
@ -169,13 +138,8 @@ func (c *ApiController) WebAuthnSigninFinish() {
} }
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody)) c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
userId := string(sessionData.UserID) userId := string(sessionData.UserID)
user, err := object.GetUser(userId) user := object.GetUser(userId)
if err != nil { _, err := webauthnObj.FinishLogin(user, sessionData, c.Ctx.Request)
c.ResponseError(err.Error())
return
}
_, err = webauthnObj.FinishLogin(user, sessionData, c.Ctx.Request)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -183,18 +147,7 @@ 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)
var application *object.Application application := object.GetApplicationByUser(user)
if clientId != "" && (responseType == ResponseTypeCode) {
application, err = object.GetApplicationByClientId(clientId)
} else {
application, err = object.GetApplicationByUser(user)
}
if err != nil {
c.ResponseError(err.Error())
return
}
var authForm form.AuthForm var authForm form.AuthForm
authForm.Type = responseType authForm.Type = responseType
resp := c.HandleLoggedIn(application, user, &authForm) resp := c.HandleLoggedIn(application, user, &authForm)

View File

@ -26,10 +26,9 @@ import (
// @Title GetWebhooks // @Title GetWebhooks
// @Tag Webhook API // @Tag Webhook API
// @Description get webhooks // @Description get webhooks
// @Param owner query string built-in/admin true "The owner of webhooks" // @Param owner query string true "The owner of webhooks"
// @Success 200 {array} object.Webhook The Response object // @Success 200 {array} object.Webhook The Response object
// @router /get-webhooks [get] // @router /get-webhooks [get]
// @Security test_apiKey
func (c *ApiController) GetWebhooks() { func (c *ApiController) GetWebhooks() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
limit := c.Input().Get("pageSize") limit := c.Input().Get("pageSize")
@ -39,31 +38,13 @@ func (c *ApiController) GetWebhooks() {
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
organization := c.Input().Get("organization") organization := c.Input().Get("organization")
if limit == "" || page == "" { if limit == "" || page == "" {
webhooks, err := object.GetWebhooks(owner, organization) c.Data["json"] = object.GetWebhooks(owner, organization)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(webhooks)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetWebhookCount(owner, organization, field, value) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetWebhookCount(owner, organization, field, value)))
if err != nil { webhooks := object.GetPaginationWebhooks(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
webhooks, err := object.GetPaginationWebhooks(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(webhooks, paginator.Nums()) c.ResponseOk(webhooks, paginator.Nums())
} }
} }
@ -72,26 +53,21 @@ func (c *ApiController) GetWebhooks() {
// @Title GetWebhook // @Title GetWebhook
// @Tag Webhook API // @Tag Webhook API
// @Description get webhook // @Description get webhook
// @Param id query string built-in/admin true "The id ( owner/name ) of the webhook" // @Param id query string true "The id ( owner/name ) of the webhook"
// @Success 200 {object} object.Webhook The Response object // @Success 200 {object} object.Webhook The Response object
// @router /get-webhook [get] // @router /get-webhook [get]
func (c *ApiController) GetWebhook() { func (c *ApiController) GetWebhook() {
id := c.Input().Get("id") id := c.Input().Get("id")
webhook, err := object.GetWebhook(id) c.Data["json"] = object.GetWebhook(id)
if err != nil { c.ServeJSON()
c.ResponseError(err.Error())
return
}
c.ResponseOk(webhook)
} }
// UpdateWebhook // UpdateWebhook
// @Title UpdateWebhook // @Title UpdateWebhook
// @Tag Webhook API // @Tag Webhook API
// @Description update webhook // @Description update webhook
// @Param id query string built-in/admin true "The id ( owner/name ) of the webhook" // @Param id query string true "The id ( owner/name ) of the webhook"
// @Param body body object.Webhook true "The details of the webhook" // @Param body body object.Webhook true "The details of the webhook"
// @Success 200 {object} controllers.Response The Response object // @Success 200 {object} controllers.Response The Response object
// @router /update-webhook [post] // @router /update-webhook [post]

View File

@ -24,8 +24,6 @@ func GetCredManager(passwordType string) CredManager {
return NewPlainCredManager() return NewPlainCredManager()
} else if passwordType == "salt" { } else if passwordType == "salt" {
return NewSha256SaltCredManager() return NewSha256SaltCredManager()
} else if passwordType == "sha512-salt" {
return NewSha512SaltCredManager()
} else if passwordType == "md5-salt" { } else if passwordType == "md5-salt" {
return NewMd5UserSaltCredManager() return NewMd5UserSaltCredManager()
} else if passwordType == "bcrypt" { } else if passwordType == "bcrypt" {

View File

@ -1,50 +0,0 @@
// Copyright 2024 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 cred
import (
"crypto/sha512"
"encoding/hex"
)
type Sha512SaltCredManager struct{}
func getSha512(data []byte) []byte {
hash := sha512.Sum512(data)
return hash[:]
}
func getSha512HexDigest(s string) string {
b := getSha512([]byte(s))
res := hex.EncodeToString(b)
return res
}
func NewSha512SaltCredManager() *Sha512SaltCredManager {
cm := &Sha512SaltCredManager{}
return cm
}
func (cm *Sha512SaltCredManager) GetHashedPassword(password string, userSalt string, organizationSalt string) string {
res := getSha512HexDigest(password)
if organizationSalt != "" {
res = getSha512HexDigest(res + organizationSalt)
}
return res
}
func (cm *Sha512SaltCredManager) IsPasswordCorrect(plainPwd string, hashedPwd string, userSalt string, organizationSalt string) bool {
return hashedPwd == cm.GetHashedPassword(plainPwd, userSalt, organizationSalt)
}

View File

@ -17,7 +17,6 @@ package deployment
import ( import (
"fmt" "fmt"
"os" "os"
"path/filepath"
"strings" "strings"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
@ -46,7 +45,7 @@ func uploadFolder(storageProvider oss.StorageInterface, folder string) {
continue continue
} }
file, err := os.Open(filepath.Clean(path + filename)) file, err := os.Open(path + filename)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -25,12 +25,6 @@ import (
) )
func TestDeployStaticFiles(t *testing.T) { func TestDeployStaticFiles(t *testing.T) {
object.InitConfig() provider := object.GetProvider(util.GetId("admin", "provider_storage_aliyun_oss"))
provider, err := object.GetProvider(util.GetId("admin", "provider_storage_aliyun_oss"))
if err != nil {
panic(err)
}
deployStaticFiles(provider) deployStaticFiles(provider)
} }

View File

@ -1,229 +0,0 @@
// 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 (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
"github.com/google/uuid"
)
const (
importanceNormal = "normal"
sendEmailEndpoint = "/emails:send"
apiVersion = "2023-03-31"
)
type Email struct {
Recipients Recipients `json:"recipients"`
SenderAddress string `json:"senderAddress"`
Content Content `json:"content"`
Headers []CustomHeader `json:"headers"`
Tracking bool `json:"disableUserEngagementTracking"`
Importance string `json:"importance"`
ReplyTo []EmailAddress `json:"replyTo"`
Attachments []Attachment `json:"attachments"`
}
type Recipients struct {
To []EmailAddress `json:"to"`
CC []EmailAddress `json:"cc"`
BCC []EmailAddress `json:"bcc"`
}
type EmailAddress struct {
DisplayName string `json:"displayName"`
Address string `json:"address"`
}
type Content struct {
Subject string `json:"subject"`
HTML string `json:"html"`
PlainText string `json:"plainText"`
}
type CustomHeader struct {
Name string `json:"name"`
Value string `json:"value"`
}
type Attachment struct {
Content string `json:"contentBytesBase64"`
AttachmentType string `json:"attachmentType"`
Name string `json:"name"`
}
type ErrorResponse struct {
Error CommunicationError `json:"error"`
}
// CommunicationError contains the error code and message
type CommunicationError struct {
Code string `json:"code"`
Message string `json:"message"`
}
type AzureACSEmailProvider struct {
AccessKey string
Endpoint string
}
func NewAzureACSEmailProvider(accessKey string, endpoint string) *AzureACSEmailProvider {
return &AzureACSEmailProvider{
AccessKey: accessKey,
Endpoint: endpoint,
}
}
func newEmail(fromAddress string, toAddress string, subject string, content string) *Email {
return &Email{
Recipients: Recipients{
To: []EmailAddress{
{
DisplayName: toAddress,
Address: toAddress,
},
},
},
SenderAddress: fromAddress,
Content: Content{
Subject: subject,
HTML: content,
},
Importance: importanceNormal,
}
}
func (a *AzureACSEmailProvider) sendEmail(e *Email) error {
postBody, err := json.Marshal(e)
if err != nil {
return fmt.Errorf("email JSON marshall failed: %s", err)
}
bodyBuffer := bytes.NewBuffer(postBody)
endpoint := strings.TrimSuffix(a.Endpoint, "/")
url := fmt.Sprintf("%s/emails:send?api-version=2023-03-31", endpoint)
req, err := http.NewRequest("POST", url, bodyBuffer)
if err != nil {
return fmt.Errorf("error creating AzureACS API request: %s", err)
}
// Sign the request using the AzureACS access key and HMAC-SHA256
err = signRequestHMAC(a.AccessKey, req)
if err != nil {
return fmt.Errorf("error signing AzureACS API request: %s", err)
}
req.Header.Set("Content-Type", "application/json")
// Some important header
req.Header.Set("repeatability-request-id", uuid.New().String())
req.Header.Set("repeatability-first-sent", time.Now().UTC().Format(http.TimeFormat))
// Send request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("error sending AzureACS API request: %s", err)
}
defer resp.Body.Close()
// Response error Handling
if resp.StatusCode == http.StatusBadRequest || resp.StatusCode == http.StatusUnauthorized {
commError := ErrorResponse{}
err = json.NewDecoder(resp.Body).Decode(&commError)
if err != nil {
return err
}
return fmt.Errorf("error sending email: %s", commError.Error.Message)
}
if resp.StatusCode != http.StatusAccepted {
return fmt.Errorf("error sending email: status: %d", resp.StatusCode)
}
return nil
}
func signRequestHMAC(secret string, req *http.Request) error {
method := req.Method
host := req.URL.Host
pathAndQuery := req.URL.Path
if req.URL.RawQuery != "" {
pathAndQuery = pathAndQuery + "?" + req.URL.RawQuery
}
var content []byte
var err error
if req.Body != nil {
content, err = io.ReadAll(req.Body)
if err != nil {
// return err
content = []byte{}
}
}
req.Body = io.NopCloser(bytes.NewBuffer(content))
key, err := base64.StdEncoding.DecodeString(secret)
if err != nil {
return fmt.Errorf("error decoding secret: %s", err)
}
timestamp := time.Now().UTC().Format(http.TimeFormat)
contentHash := GetContentHashBase64(content)
stringToSign := fmt.Sprintf("%s\n%s\n%s;%s;%s", strings.ToUpper(method), pathAndQuery, timestamp, host, contentHash)
signature := GetHmac(stringToSign, key)
req.Header.Set("x-ms-content-sha256", contentHash)
req.Header.Set("x-ms-date", timestamp)
req.Header.Set("Authorization", "HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature="+signature)
return nil
}
func GetContentHashBase64(content []byte) string {
hasher := sha256.New()
hasher.Write(content)
return base64.StdEncoding.EncodeToString(hasher.Sum(nil))
}
func GetHmac(content string, key []byte) string {
hmac := hmac.New(sha256.New, key)
hmac.Write([]byte(content))
return base64.StdEncoding.EncodeToString(hmac.Sum(nil))
}
func (a *AzureACSEmailProvider) Send(fromAddress string, fromName string, toAddress string, subject string, content string) error {
e := newEmail(fromAddress, toAddress, subject, content)
return a.sendEmail(e)
}

View File

@ -1,82 +0,0 @@
// 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
}

View File

@ -1,29 +0,0 @@
// 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
type EmailProvider interface {
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, endpoint string, method string) EmailProvider {
if typ == "Azure ACS" {
return NewAzureACSEmailProvider(clientSecret, host)
} else if typ == "Custom HTTP Email" {
return NewHttpEmailProvider(endpoint, method)
} else {
return NewSmtpEmailProvider(clientId, clientSecret, host, port, typ, disableSsl)
}
}

View File

@ -1,49 +0,0 @@
// 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 (
"crypto/tls"
"github.com/casdoor/gomail/v2"
)
type SmtpEmailProvider struct {
Dialer *gomail.Dialer
}
func NewSmtpEmailProvider(userName string, password string, host string, port int, typ string, disableSsl bool) *SmtpEmailProvider {
dialer := &gomail.Dialer{}
dialer = gomail.NewDialer(host, port, userName, password)
if typ == "SUBMAIL" {
dialer.TLSConfig = &tls.Config{InsecureSkipVerify: true}
}
dialer.SSL = !disableSsl
return &SmtpEmailProvider{Dialer: dialer}
}
func (s *SmtpEmailProvider) Send(fromAddress string, fromName string, toAddress string, subject string, content string) error {
message := gomail.NewMessage()
message.SetAddressHeader("From", fromAddress, fromName)
message.SetHeader("To", toAddress)
message.SetHeader("Subject", subject)
message.SetBody("text/html", content)
message.SkipUsernameCheck = true
return s.Dialer.DialAndSend(message)
}

View File

@ -14,24 +14,20 @@
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"`
Password string `json:"password"` Password string `json:"password"`
Name string `json:"name"` Name string `json:"name"`
FirstName string `json:"firstName"` FirstName string `json:"firstName"`
LastName string `json:"lastName"` LastName string `json:"lastName"`
Email string `json:"email"` Email string `json:"email"`
Phone string `json:"phone"` Phone string `json:"phone"`
Affiliation string `json:"affiliation"` Affiliation string `json:"affiliation"`
IdCard string `json:"idCard"` IdCard string `json:"idCard"`
Region string `json:"region"` Region string `json:"region"`
InvitationCode string `json:"invitationCode"`
Application string `json:"application"` Application string `json:"application"`
ClientId string `json:"clientId"` ClientId string `json:"clientId"`
@ -62,13 +58,3 @@ 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, ""
}

65
go.mod
View File

@ -4,68 +4,63 @@ 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/aliyun/alibaba-cloud-sdk-go v1.62.188 // indirect
github.com/beego/beego v1.12.12 github.com/aws/aws-sdk-go v1.44.4
github.com/beego/beego v1.12.11
github.com/beevik/etree v1.1.0 github.com/beevik/etree v1.1.0
github.com/casbin/casbin/v2 v2.77.2 github.com/casbin/casbin/v2 v2.30.1
github.com/casdoor/go-sms-sender v0.19.0 github.com/casdoor/go-sms-sender v0.6.1
github.com/casdoor/gomail/v2 v2.0.1 github.com/casdoor/gomail/v2 v2.0.1
github.com/casdoor/notify v0.45.0 github.com/casdoor/oss v1.2.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/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/dlclark/regexp2 v1.9.0 // 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.4.6 github.com/go-ldap/ldap/v3 v3.3.0
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-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.4.0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/json-iterator/go v1.1.12 github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
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.8.0
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
github.com/markbates/goth v1.78.0 github.com/markbates/goth v1.75.2
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/pkoukk/tiktoken-go v0.1.1
github.com/prometheus/client_golang v1.11.1 github.com/prometheus/client_golang v1.7.0
github.com/prometheus/client_model v0.4.0 github.com/prometheus/client_model v0.2.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.6.0
github.com/russellhaering/goxmldsig v1.2.0 github.com/russellhaering/goxmldsig v1.1.1
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect github.com/sashabaranov/go-openai v1.9.1
github.com/satori/go.uuid v1.2.0
github.com/shirou/gopsutil v3.21.11+incompatible github.com/shirou/gopsutil v3.21.11+incompatible
github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.2
github.com/stripe/stripe-go/v74 v74.29.0
github.com/tealeg/xlsx v1.0.5 github.com/tealeg/xlsx v1.0.5
github.com/thanhpk/randstr v1.0.4 github.com/thanhpk/randstr v1.0.4
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/xorm-io/builder v0.3.13
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.14.0 golang.org/x/crypto v0.6.0
golang.org/x/net v0.17.0 golang.org/x/net v0.6.0
golang.org/x/oauth2 v0.13.0 golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
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 gopkg.in/yaml.v2 v2.3.0 // indirect
maunium.net/go/mautrix v0.16.0 modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84
modernc.org/sqlite v1.18.2
) )

2198
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -33,18 +33,6 @@ func TestGenerateI18nFrontend(t *testing.T) {
applyToOtherLanguage("frontend", "ru", data) applyToOtherLanguage("frontend", "ru", data)
applyToOtherLanguage("frontend", "vi", data) applyToOtherLanguage("frontend", "vi", data)
applyToOtherLanguage("frontend", "pt", data) applyToOtherLanguage("frontend", "pt", data)
applyToOtherLanguage("frontend", "it", data)
applyToOtherLanguage("frontend", "ms", data)
applyToOtherLanguage("frontend", "tr", data)
applyToOtherLanguage("frontend", "ar", data)
applyToOtherLanguage("frontend", "he", data)
applyToOtherLanguage("frontend", "nl", data)
applyToOtherLanguage("frontend", "pl", data)
applyToOtherLanguage("frontend", "fi", data)
applyToOtherLanguage("frontend", "sv", data)
applyToOtherLanguage("frontend", "uk", data)
applyToOtherLanguage("frontend", "kk", data)
applyToOtherLanguage("frontend", "fa", data)
} }
func TestGenerateI18nBackend(t *testing.T) { func TestGenerateI18nBackend(t *testing.T) {
@ -61,16 +49,4 @@ func TestGenerateI18nBackend(t *testing.T) {
applyToOtherLanguage("backend", "ru", data) applyToOtherLanguage("backend", "ru", data)
applyToOtherLanguage("backend", "vi", data) applyToOtherLanguage("backend", "vi", data)
applyToOtherLanguage("backend", "pt", data) applyToOtherLanguage("backend", "pt", data)
applyToOtherLanguage("backend", "it", data)
applyToOtherLanguage("backend", "ms", data)
applyToOtherLanguage("backend", "tr", data)
applyToOtherLanguage("backend", "ar", data)
applyToOtherLanguage("backend", "he", data)
applyToOtherLanguage("backend", "nl", data)
applyToOtherLanguage("backend", "pl", data)
applyToOtherLanguage("backend", "fi", data)
applyToOtherLanguage("backend", "sv", data)
applyToOtherLanguage("backend", "uk", data)
applyToOtherLanguage("backend", "kk", data)
applyToOtherLanguage("backend", "fa", data)
} }

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"Username cannot start with a digit": "Username cannot start with a digit",
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
"Username must have at least 2 characters": "Username must have at least 2 characters",
"You 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",
"password or code is incorrect": "password or code is incorrect",
"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"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -15,22 +15,24 @@
"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",
"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"
}, },
"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": "Zugehörigkeit darf nicht leer sein", "Affiliation cannot be blank": "Zugehörigkeit darf nicht leer sein",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "Anzeigename kann nicht leer sein", "DisplayName cannot be blank": "Anzeigename kann nicht leer sein",
"DisplayName is not valid real name": "DisplayName ist kein gültiger Vorname", "DisplayName is not valid real name": "DisplayName ist kein gültiger Vorname",
"Email already exists": "E-Mail existiert bereits", "Email already exists": "E-Mail existiert bereits",
@ -38,26 +40,18 @@
"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",
@ -74,8 +68,7 @@
"Missing parameter": "Fehlender Parameter", "Missing parameter": "Fehlender Parameter",
"Please login first": "Bitte zuerst einloggen", "Please login first": "Bitte zuerst einloggen",
"The user: %s doesn't exist": "Der Benutzer %s existiert nicht", "The user: %s doesn't exist": "Der Benutzer %s existiert nicht",
"don't support captchaProvider: ": "Unterstütze captchaProvider nicht:", "don't support captchaProvider: ": "Unterstütze captchaProvider nicht:"
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
}, },
"ldap": { "ldap": {
"Ldap server exist": "Es gibt einen LDAP-Server" "Ldap server exist": "Es gibt einen LDAP-Server"
@ -126,7 +119,8 @@
}, },
"user": { "user": {
"Display name cannot be empty": "Anzeigename darf nicht leer sein", "Display name cannot be empty": "Anzeigename darf nicht leer sein",
"New password cannot contain blank space.": "Das neue Passwort darf keine Leerzeichen enthalten." "New password cannot contain blank space.": "Das neue Passwort darf keine Leerzeichen enthalten.",
"New password must have at least 6 characters": "Das neue Passwort muss mindestens 6 Zeichen haben"
}, },
"user_upload": { "user_upload": {
"Failed to import users": "Fehler beim Importieren von Benutzern" "Failed to import users": "Fehler beim Importieren von Benutzern"

View File

@ -15,22 +15,24 @@
"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",
"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",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank", "DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name", "DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists", "Email already exists": "Email already exists",
@ -38,26 +40,18 @@
"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",
@ -74,8 +68,7 @@
"Missing parameter": "Missing parameter", "Missing parameter": "Missing parameter",
"Please login first": "Please login first", "Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist", "The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ", "don't support captchaProvider: ": "don't support captchaProvider: "
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
}, },
"ldap": { "ldap": {
"Ldap server exist": "Ldap server exist" "Ldap server exist": "Ldap server exist"
@ -126,7 +119,8 @@
}, },
"user": { "user": {
"Display name cannot be empty": "Display name cannot be empty", "Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space." "New password cannot contain blank space.": "New password cannot contain blank space.",
"New password must have at least 6 characters": "New password must have at least 6 characters"
}, },
"user_upload": { "user_upload": {
"Failed to import users": "Failed to import users" "Failed to import users": "Failed to import users"

View File

@ -15,22 +15,24 @@
"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",
"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"
}, },
"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": "Afiliación no puede estar en blanco", "Affiliation cannot be blank": "Afiliación no puede estar en blanco",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "El nombre de visualización no puede estar en blanco", "DisplayName cannot be blank": "El nombre de visualización no puede estar en blanco",
"DisplayName is not valid real name": "El nombre de pantalla no es un nombre real válido", "DisplayName is not valid real name": "El nombre de pantalla no es un nombre real válido",
"Email already exists": "El correo electrónico ya existe", "Email already exists": "El correo electrónico ya existe",
@ -38,26 +40,18 @@
"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",
@ -74,8 +68,7 @@
"Missing parameter": "Parámetro faltante", "Missing parameter": "Parámetro faltante",
"Please login first": "Por favor, inicia sesión primero", "Please login first": "Por favor, inicia sesión primero",
"The user: %s doesn't exist": "El usuario: %s no existe", "The user: %s doesn't exist": "El usuario: %s no existe",
"don't support captchaProvider: ": "No apoyo a captchaProvider", "don't support captchaProvider: ": "No apoyo a captchaProvider"
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
}, },
"ldap": { "ldap": {
"Ldap server exist": "El servidor LDAP existe" "Ldap server exist": "El servidor LDAP existe"
@ -126,7 +119,8 @@
}, },
"user": { "user": {
"Display name cannot be empty": "El nombre de pantalla no puede estar vacío", "Display name cannot be empty": "El nombre de pantalla no puede estar vacío",
"New password cannot contain blank space.": "La nueva contraseña no puede contener espacios en blanco." "New password cannot contain blank space.": "La nueva contraseña no puede contener espacios en blanco.",
"New password must have at least 6 characters": "La nueva contraseña debe tener al menos 6 caracteres"
}, },
"user_upload": { "user_upload": {
"Failed to import users": "Error al importar usuarios" "Failed to import users": "Error al importar usuarios"

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"Username cannot start with a digit": "Username cannot start with a digit",
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
"Username must have at least 2 characters": "Username must have at least 2 characters",
"You 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",
"password or code is incorrect": "password or code is incorrect",
"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"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"Username cannot start with a digit": "Username cannot start with a digit",
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
"Username must have at least 2 characters": "Username must have at least 2 characters",
"You 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",
"password or code is incorrect": "password or code is incorrect",
"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"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -15,22 +15,24 @@
"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": "Le tag de lutilisateur %s nest pas répertorié dans les tags de lapplication",
"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"
}, },
"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 ne peut pas être vide", "Affiliation cannot be blank": "Affiliation ne peut pas être vide",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "Le nom d'affichage ne peut pas être vide", "DisplayName cannot be blank": "Le nom d'affichage ne peut pas être vide",
"DisplayName is not valid real name": "DisplayName n'est pas un nom réel valide", "DisplayName is not valid real name": "DisplayName n'est pas un nom réel valide",
"Email already exists": "E-mail déjà existant", "Email already exists": "E-mail déjà existant",
@ -38,26 +40,18 @@
"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": "L'utilisateur %s n'existe pas sur le serveur LDAP", "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.": "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",
@ -66,7 +60,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": "mot de passe ou code invalide", "password or code is incorrect": "password or code is incorrect",
"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"
}, },
@ -74,8 +68,7 @@
"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 prend pas en charge captchaProvider: ", "don't support captchaProvider: ": "Ne pas prendre en charge la captchaProvider"
"this operation is not allowed in demo mode": "cette opération nest pas autorisée en mode démo"
}, },
"ldap": { "ldap": {
"Ldap server exist": "Le serveur LDAP existe" "Ldap server exist": "Le serveur LDAP existe"
@ -126,7 +119,8 @@
}, },
"user": { "user": {
"Display name cannot be empty": "Le nom d'affichage ne peut pas être vide", "Display name cannot be empty": "Le nom d'affichage ne peut pas être vide",
"New password cannot contain blank space.": "Le nouveau mot de passe ne peut pas contenir d'espace." "New password cannot contain blank space.": "Le nouveau mot de passe ne peut pas contenir d'espace.",
"New password must have at least 6 characters": "Le nouveau mot de passe doit comporter au moins 6 caractères"
}, },
"user_upload": { "user_upload": {
"Failed to import users": "Échec de l'importation des utilisateurs" "Failed to import users": "Échec de l'importation des utilisateurs"

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"Username cannot start with a digit": "Username cannot start with a digit",
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
"Username must have at least 2 characters": "Username must have at least 2 characters",
"You 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",
"password or code is incorrect": "password or code is incorrect",
"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"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -15,22 +15,24 @@
"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",
"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"
}, },
"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": "Keterkaitan tidak boleh kosong", "Affiliation cannot be blank": "Keterkaitan tidak boleh kosong",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "Nama Pengguna tidak boleh kosong", "DisplayName cannot be blank": "Nama Pengguna tidak boleh kosong",
"DisplayName is not valid real name": "DisplayName bukanlah nama asli yang valid", "DisplayName is not valid real name": "DisplayName bukanlah nama asli yang valid",
"Email already exists": "Email sudah ada", "Email already exists": "Email sudah ada",
@ -38,26 +40,18 @@
"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",
@ -74,8 +68,7 @@
"Missing parameter": "Parameter hilang", "Missing parameter": "Parameter hilang",
"Please login first": "Silahkan login terlebih dahulu", "Please login first": "Silahkan login terlebih dahulu",
"The user: %s doesn't exist": "Pengguna: %s tidak ada", "The user: %s doesn't exist": "Pengguna: %s tidak ada",
"don't support captchaProvider: ": "Jangan mendukung captchaProvider:", "don't support captchaProvider: ": "Jangan mendukung captchaProvider:"
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
}, },
"ldap": { "ldap": {
"Ldap server exist": "Server ldap ada" "Ldap server exist": "Server ldap ada"
@ -126,7 +119,8 @@
}, },
"user": { "user": {
"Display name cannot be empty": "Nama tampilan tidak boleh kosong", "Display name cannot be empty": "Nama tampilan tidak boleh kosong",
"New password cannot contain blank space.": "Kata sandi baru tidak boleh mengandung spasi kosong." "New password cannot contain blank space.": "Kata sandi baru tidak boleh mengandung spasi kosong.",
"New password must have at least 6 characters": "Kata sandi baru harus memiliki setidaknya 6 karakter"
}, },
"user_upload": { "user_upload": {
"Failed to import users": "Gagal mengimpor pengguna" "Failed to import users": "Gagal mengimpor pengguna"

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"Username cannot start with a digit": "Username cannot start with a digit",
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
"Username must have at least 2 characters": "Username must have at least 2 characters",
"You 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",
"password or code is incorrect": "password or code is incorrect",
"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"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -15,22 +15,24 @@
"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",
"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は一致しません"
}, },
"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": "所属は空白にできません",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "表示名は空白にできません", "DisplayName cannot be blank": "表示名は空白にできません",
"DisplayName is not valid real name": "表示名は有効な実名ではありません", "DisplayName is not valid real name": "表示名は有効な実名ではありません",
"Email already exists": "メールは既に存在します", "Email already exists": "メールは既に存在します",
@ -38,26 +40,18 @@
"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": "ユーザ名にはスペースを含めることはできません",
@ -74,8 +68,7 @@
"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"
}, },
"ldap": { "ldap": {
"Ldap server exist": "LDAPサーバーは存在します" "Ldap server exist": "LDAPサーバーは存在します"
@ -126,7 +119,8 @@
}, },
"user": { "user": {
"Display name cannot be empty": "表示名は空にできません", "Display name cannot be empty": "表示名は空にできません",
"New password cannot contain blank space.": "新しいパスワードにはスペースを含めることはできません。" "New password cannot contain blank space.": "新しいパスワードにはスペースを含めることはできません。",
"New password must have at least 6 characters": "新しいパスワードは少なくとも6文字必要です"
}, },
"user_upload": { "user_upload": {
"Failed to import users": "ユーザーのインポートに失敗しました" "Failed to import users": "ユーザーのインポートに失敗しました"

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"Username cannot start with a digit": "Username cannot start with a digit",
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
"Username must have at least 2 characters": "Username must have at least 2 characters",
"You 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",
"password or code is incorrect": "password or code is incorrect",
"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"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -15,22 +15,24 @@
"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",
"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는 일치하지 않습니다"
}, },
"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": "소속은 비워 둘 수 없습니다",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName는 비어 있을 수 없습니다", "DisplayName cannot be blank": "DisplayName는 비어 있을 수 없습니다",
"DisplayName is not valid real name": "DisplayName는 유효한 실제 이름이 아닙니다", "DisplayName is not valid real name": "DisplayName는 유효한 실제 이름이 아닙니다",
"Email already exists": "이메일이 이미 존재합니다", "Email already exists": "이메일이 이미 존재합니다",
@ -38,26 +40,18 @@
"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": "사용자 이름에는 공백이 포함될 수 없습니다",
@ -74,8 +68,7 @@
"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"
}, },
"ldap": { "ldap": {
"Ldap server exist": "LDAP 서버가 존재합니다" "Ldap server exist": "LDAP 서버가 존재합니다"
@ -126,7 +119,8 @@
}, },
"user": { "user": {
"Display name cannot be empty": "디스플레이 이름은 비어 있을 수 없습니다", "Display name cannot be empty": "디스플레이 이름은 비어 있을 수 없습니다",
"New password cannot contain blank space.": "새 비밀번호에는 공백이 포함될 수 없습니다." "New password cannot contain blank space.": "새 비밀번호에는 공백이 포함될 수 없습니다.",
"New password must have at least 6 characters": "새로운 비밀번호는 최소 6자 이상이어야 합니다"
}, },
"user_upload": { "user_upload": {
"Failed to import users": "사용자 가져오기를 실패했습니다" "Failed to import users": "사용자 가져오기를 실패했습니다"

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"Username cannot start with a digit": "Username cannot start with a digit",
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
"Username must have at least 2 characters": "Username must have at least 2 characters",
"You 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",
"password or code is incorrect": "password or code is incorrect",
"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"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"Username cannot start with a digit": "Username cannot start with a digit",
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
"Username must have at least 2 characters": "Username must have at least 2 characters",
"You 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",
"password or code is incorrect": "password or code is incorrect",
"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"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"Username cannot start with a digit": "Username cannot start with a digit",
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
"Username must have at least 2 characters": "Username must have at least 2 characters",
"You 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",
"password or code is incorrect": "password or code is incorrect",
"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"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Falha ao adicionar usuário",
"Get init score failed, error: %w": "Obter pontuação inicial falhou, erro: %w",
"Please sign out first": "Por favor, saia da sessão primeiro",
"The application does not allow to sign up new account": "O aplicativo não permite a criação de uma nova conta"
},
"auth": {
"Challenge method should be S256": "Método de desafio deve ser S256",
"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": "Falha ao entrar em: %s",
"Invalid token": "Token inválido",
"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": "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": "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 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 provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"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).": "Nome de usuário é muito longo (máximo é 39 caracteres).",
"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",
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
"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",
"unsupported password type: %s": "unsupported password type: %s"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "O %s é imutável.",
"Unknown modify rule %s.": "Regra de modificação %s desconhecida."
},
"provider": {
"Invalid application id": "Id do aplicativo inválido",
"the provider: %s does not exist": "o provedor: %s não existe"
},
"resource": {
"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"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"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",
"Invalid application or wrong clientSecret": "Aplicativo inválido ou clientSecret errado",
"Invalid client_id": "client_id inválido",
"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 não encontrado, token de acesso inválido"
},
"user": {
"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."
},
"user_upload": {
"Failed to import users": "Falha ao importar usuários"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -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,22 +15,24 @@
"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": "Тег пользователя: %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 не совпадают"
}, },
"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": "Принадлежность не может быть пустым значением",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "Имя отображения не может быть пустым", "DisplayName cannot be blank": "Имя отображения не может быть пустым",
"DisplayName is not valid real name": "DisplayName не является действительным именем", "DisplayName is not valid real name": "DisplayName не является действительным именем",
"Email already exists": "Электронная почта уже существует", "Email already exists": "Электронная почта уже существует",
@ -38,26 +40,18 @@
"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": "Пользователь %s не существует на LDAP сервере", "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": "Имя пользователя не может содержать пробелы",
@ -66,7 +60,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"
}, },
@ -74,8 +68,7 @@
"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": "эта операция не разрешена в демо-режиме"
}, },
"ldap": { "ldap": {
"Ldap server exist": "LDAP-сервер существует" "Ldap server exist": "LDAP-сервер существует"
@ -114,7 +107,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": "Пустой идентификатор клиента или секрет клиента",
@ -126,14 +119,15 @@
}, },
"user": { "user": {
"Display name cannot be empty": "Отображаемое имя не может быть пустым", "Display name cannot be empty": "Отображаемое имя не может быть пустым",
"New password cannot contain blank space.": "Новый пароль не может содержать пробелы." "New password cannot contain blank space.": "Новый пароль не может содержать пробелы.",
"New password must have at least 6 characters": "Новый пароль должен содержать не менее 6 символов"
}, },
"user_upload": { "user_upload": {
"Failed to import users": "Не удалось импортировать пользователей" "Failed to import users": "Не удалось импортировать пользователей"
}, },
"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": {

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"Username cannot start with a digit": "Username cannot start with a digit",
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
"Username must have at least 2 characters": "Username must have at least 2 characters",
"You 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",
"password or code is incorrect": "password or code is incorrect",
"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"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"Phone already exists": "Telefon numarası zaten mevcut",
"Phone cannot be empty": "Telefon numarası boş olamaz",
"Phone number is invalid": "Telefon numarası geçersiz",
"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 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": "Kullanıcı adı zaten var",
"Username cannot be an email address": "Kullanıcı adı bir e-mail adresi olamaz",
"Username cannot contain white spaces": "Kullanıcı adı boşluk karakteri içeremez",
"Username cannot start with a digit": "Kullanıcı adı rakamla başlayamaz",
"Username is too long (maximum is 39 characters).": "Kullanıcı adı çok uzun (en fazla 39 karakter olmalı).",
"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",
"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",
"unsupported password type: %s": "unsupported password type: %s"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Görünen ad boş olamaz",
"New password cannot contain blank space.": "Yeni şifreniz boşluk karakteri içeremez."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Telefon numaranızın bulunduğu bölgeye hizmet veremiyoruz",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -1,155 +0,0 @@
{
"account": {
"Failed to add user": "Failed to add user",
"Get init score failed, error: %w": "Get init score failed, error: %w",
"Please sign out first": "Please sign out first",
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
},
"auth": {
"Challenge method should be S256": "Challenge method should be S256",
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
"Failed to login in: %s": "Failed to login in: %s",
"Invalid token": "Invalid token",
"State expected: %s, but got: %s": "State expected: %s, but got: %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, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
"The application: %s does not exist": "The application: %s does not exist",
"The 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": "The provider: %s is not enabled for the application",
"Unauthorized operation": "Unauthorized operation",
"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",
"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": {
"Service %s and %s do not match": "Service %s and %s do not match"
},
"check": {
"Affiliation cannot be blank": "Affiliation cannot be blank",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "DisplayName cannot be blank",
"DisplayName is not valid real name": "DisplayName is not valid real name",
"Email already exists": "Email already exists",
"Email cannot be empty": "Email cannot be empty",
"Email is invalid": "Email is invalid",
"Empty username.": "Empty username.",
"FirstName cannot be blank": "FirstName cannot be blank",
"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",
"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",
"Organization does not exist": "Organization does not exist",
"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 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",
"Username cannot start with a digit": "Username cannot start with a digit",
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
"Username must have at least 2 characters": "Username must have at least 2 characters",
"You 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",
"password or code is incorrect": "password or code is incorrect",
"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"
},
"general": {
"Missing parameter": "Missing parameter",
"Please login first": "Please login first",
"The user: %s doesn't exist": "The user: %s doesn't exist",
"don't support captchaProvider: ": "don't support captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Ldap server exist"
},
"link": {
"Please link first": "Please link first",
"This application has no providers": "This application has no providers",
"This application has no providers of type": "This application has no providers of type",
"This provider can't be unlinked": "This provider can't be unlinked",
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
},
"organization": {
"Only admin can modify the %s.": "Only admin can modify the %s.",
"The %s is immutable.": "The %s is immutable.",
"Unknown modify rule %s.": "Unknown modify rule %s."
},
"provider": {
"Invalid application id": "Invalid application id",
"the provider: %s does not exist": "the provider: %s does not exist"
},
"resource": {
"User is nil for tag: avatar": "User is nil for tag: avatar",
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
},
"saml": {
"Application %s not found": "Application %s not found"
},
"saml_sp": {
"provider %s's category is not SAML": "provider %s's category is not SAML"
},
"service": {
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
},
"storage": {
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
"The provider type: %s is not supported": "The provider type: %s is not supported"
},
"token": {
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
"Invalid client_id": "Invalid client_id",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"
},
"util": {
"No application is found for userId: %s": "No application is found for userId: %s",
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
"The provider: %s is not found": "The provider: %s is not found"
},
"verification": {
"Code has not been sent yet!": "Code has not been sent yet!",
"Invalid captcha provider.": "Invalid captcha provider.",
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
"Turing test failed.": "Turing test failed.",
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
"Unknown type": "Unknown type",
"Wrong verification code!": "Wrong verification code!",
"You should verify your code in %d min!": "You should verify your code in %d min!",
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
},
"webauthn": {
"Found no credentials for this user": "Found no credentials for this user",
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
}
}

View File

@ -15,22 +15,24 @@
"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",
"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"
}, },
"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": "Tình trạng liên kết không thể để trống", "Affiliation cannot be blank": "Tình trạng liên kết không thể để trống",
"Default code does not match the code's matching rules": "Default code does not match the code's matching rules",
"DisplayName cannot be blank": "Tên hiển thị không thể để trống", "DisplayName cannot be blank": "Tên hiển thị không thể để trống",
"DisplayName is not valid real name": "DisplayName không phải là tên thật hợp lệ", "DisplayName is not valid real name": "DisplayName không phải là tên thật hợp lệ",
"Email already exists": "Email đã tồn tại", "Email already exists": "Email đã tồn tại",
@ -38,26 +40,18 @@
"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",
@ -74,11 +68,10 @@
"Missing parameter": "Thiếu tham số", "Missing parameter": "Thiếu tham số",
"Please login first": "Vui lòng đăng nhập trước", "Please login first": "Vui lòng đăng nhập trước",
"The user: %s doesn't exist": "Người dùng: %s không tồn tại", "The user: %s doesn't exist": "Người dùng: %s không tồn tại",
"don't support captchaProvider: ": "không hỗ trợ captchaProvider: ", "don't support captchaProvider: ": "Không hỗ trợ captchaProvider:"
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
}, },
"ldap": { "ldap": {
"Ldap server exist": "Máy chủ LDAP tồn tại" "Ldap server exist": "Máy chủ Ldap tồn tại"
}, },
"link": { "link": {
"Please link first": "Vui lòng kết nối trước tiên", "Please link first": "Vui lòng kết nối trước tiên",
@ -126,7 +119,8 @@
}, },
"user": { "user": {
"Display name cannot be empty": "Tên hiển thị không thể trống", "Display name cannot be empty": "Tên hiển thị không thể trống",
"New password cannot contain blank space.": "Mật khẩu mới không thể chứa dấu trắng." "New password cannot contain blank space.": "Mật khẩu mới không thể chứa dấu trắng.",
"New password must have at least 6 characters": "Mật khẩu mới phải có ít nhất 6 ký tự"
}, },
"user_upload": { "user_upload": {
"Failed to import users": "Không thể nhập người dùng" "Failed to import users": "Không thể nhập người dùng"

View File

@ -15,22 +15,24 @@
"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不在该应用的标签列表中",
"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不匹配"
}, },
"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": "工作单位不可为空",
"Default code does not match the code's matching rules": "邀请码默认值和邀请码规则不匹配",
"DisplayName cannot be blank": "显示名称不可为空", "DisplayName cannot be blank": "显示名称不可为空",
"DisplayName is not valid real name": "显示名称必须是真实姓名", "DisplayName is not valid real name": "显示名称必须是真实姓名",
"Email already exists": "该邮箱已存在", "Email already exists": "该邮箱已存在",
@ -38,26 +40,18 @@
"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": "用户: %s 在LDAP服务器中未找到", "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\\\"": "值\\\"%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": "用户名禁止包含空格",
@ -74,8 +68,7 @@
"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: ": "不支持验证码提供商: ", "don't support captchaProvider: ": "不支持验证码提供商: "
"this operation is not allowed in demo mode": "demo模式下不允许该操作"
}, },
"ldap": { "ldap": {
"Ldap server exist": "LDAP服务器已存在" "Ldap server exist": "LDAP服务器已存在"
@ -90,7 +83,7 @@
}, },
"organization": { "organization": {
"Only admin can modify the %s.": "仅允许管理员可以修改%s", "Only admin can modify the %s.": "仅允许管理员可以修改%s",
"The %s is immutable.": "%s 是不可变的", "The %s is immutable.": "%s是不可变的",
"Unknown modify rule %s.": "未知的修改规则: %s" "Unknown modify rule %s.": "未知的修改规则: %s"
}, },
"provider": { "provider": {
@ -126,7 +119,8 @@
}, },
"user": { "user": {
"Display name cannot be empty": "显示名称不可为空", "Display name cannot be empty": "显示名称不可为空",
"New password cannot contain blank space.": "新密码不可以包含空格" "New password cannot contain blank space.": "新密码不可以包含空格",
"New password must have at least 6 characters": "新密码至少需要6位字符"
}, },
"user_upload": { "user_upload": {
"Failed to import users": "导入用户失败" "Failed to import users": "导入用户失败"
@ -149,7 +143,7 @@
"the user does not exist, please sign up first": "用户不存在,请先注册" "the user does not exist, please sign up first": "用户不存在,请先注册"
}, },
"webauthn": { "webauthn": {
"Found no credentials for this user": "该用户没有 WebAuthn 凭据", "Found no credentials for this user": "该用户没有WebAuthn凭据",
"Please call WebAuthnSigninBegin first": "请先调用WebAuthnSigninBegin函数" "Please call WebAuthnSigninBegin first": "请先调用WebAuthnSigninBegin函数"
} }
} }

View File

@ -19,6 +19,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"time" "time"
@ -83,14 +84,11 @@ 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
@ -99,10 +97,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, err return nil, fmt.Errorf("fail to unmarshal token response: %s", err.Error())
} }
if pToken.ErrMsg != "" { if pToken.ErrMsg != "" {
return nil, fmt.Errorf(pToken.ErrMsg) return nil, fmt.Errorf("pToken.Errmsg = %s", pToken.ErrMsg)
} }
token := &oauth2.Token{ token := &oauth2.Token{
@ -120,25 +118,11 @@ func (idp *AdfsIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
body, err := io.ReadAll(resp.Body) body, err := ioutil.ReadAll(resp.Body)
var respKeys struct { keyset, err := jwk.ParseKey(body)
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))

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