mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-09 01:13:41 +08:00
Compare commits
79 Commits
Author | SHA1 | Date | |
---|---|---|---|
d498bc60ce | |||
7bbe1e38c1 | |||
f465fc6ce0 | |||
c952c2f2f4 | |||
86ae97d1e5 | |||
6ea73e3eca | |||
a71a190db5 | |||
da69d94445 | |||
b8b915abe1 | |||
5d1548e989 | |||
a0dc6e06cd | |||
ae130788ec | |||
f075d0fd74 | |||
65d4946042 | |||
26acece8af | |||
48a0c8473f | |||
082ae3c91e | |||
1ee2ff1d30 | |||
c0d9969013 | |||
1bdee13150 | |||
d668022af0 | |||
e227875c2b | |||
e473de3162 | |||
c5ef841d3f | |||
d46288b591 | |||
b968bf033c | |||
eca2527bc0 | |||
ef836acfe9 | |||
a51f0d7c08 | |||
e3c36beaf4 | |||
19dce838d1 | |||
b41d8652f0 | |||
e705eecffe | |||
2bb2c36f22 | |||
1bb3d2dea9 | |||
96566a626b | |||
042e52bd16 | |||
e207fd243b | |||
30b7fd963f | |||
ca314bbfb5 | |||
812c44e070 | |||
78e45d07cf | |||
0856977b92 | |||
a44a4b0300 | |||
4b29dd8c41 | |||
165e2e33e3 | |||
d13a307ad5 | |||
27bd771fed | |||
9f3ee275a8 | |||
fcda64ad7d | |||
d815bf92bd | |||
7867060b71 | |||
8890d1d7c7 | |||
6e6a0a074a | |||
cff3007992 | |||
fe448cbcf4 | |||
2ab25df950 | |||
b895926754 | |||
5bb7a4153f | |||
b7cd598ee8 | |||
b10fb97c92 | |||
b337b908ea | |||
ba9d1e2388 | |||
29ec1d2d9c | |||
84a03f6c8e | |||
56ff06bbea | |||
7e756b8ee2 | |||
19ba37e0c2 | |||
b98ce19211 | |||
37d1a73c0c | |||
727877cf54 | |||
939b416717 | |||
f115843fbb | |||
aa6a4dc74f | |||
462a82a3d5 | |||
262aeba7e2 | |||
61c2fd5412 | |||
d542208eb8 | |||
f818200c95 |
21
.github/workflows/sync.yml
vendored
21
.github/workflows/sync.yml
vendored
@ -33,3 +33,24 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
CROWDIN_PROJECT_ID: '463556'
|
CROWDIN_PROJECT_ID: '463556'
|
||||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||||
|
|
||||||
|
- name: crowdin backend action
|
||||||
|
uses: crowdin/github-action@1.4.8
|
||||||
|
with:
|
||||||
|
upload_translations: true
|
||||||
|
|
||||||
|
download_translations: true
|
||||||
|
push_translations: true
|
||||||
|
commit_message: 'refactor: New Crowdin Backend translations by Github Action'
|
||||||
|
|
||||||
|
localization_branch_name: l10n_crowdin_action
|
||||||
|
create_pull_request: true
|
||||||
|
pull_request_title: 'refactor: New Crowdin Backend translations'
|
||||||
|
|
||||||
|
crowdin_branch_name: l10n_branch
|
||||||
|
config: './crowdin.yml'
|
||||||
|
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
CROWDIN_PROJECT_ID: '463556'
|
||||||
|
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||||
|
@ -44,14 +44,12 @@
|
|||||||
|
|
||||||
## Online demo
|
## Online demo
|
||||||
|
|
||||||
- International: https://door.casdoor.org (read-only)
|
- Read-only site: https://door.casdoor.com (any modification operation will fail)
|
||||||
- Asian mirror: https://door.casdoor.com (read-only)
|
- Writable site: https://demo.casdoor.com (original data will be restored for every 5 minutes)
|
||||||
- Asian mirror: https://demo.casdoor.com (read-write, will restore for every 5 minutes)
|
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- International: https://casdoor.org
|
https://casdoor.org
|
||||||
- Asian mirror: https://casdoor.cn
|
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
@ -32,7 +32,9 @@ func InitAuthz() {
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||||
a, err := xormadapter.NewAdapterWithTableName(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName()+conf.GetConfigString("dbName"), "casbin_rule", tableNamePrefix, true)
|
driverName := conf.GetConfigString("driverName")
|
||||||
|
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
|
||||||
|
a, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, "casbin_rule", tableNamePrefix, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -85,6 +87,8 @@ p, *, *, POST, /api/logout, *, *
|
|||||||
p, *, *, GET, /api/logout, *, *
|
p, *, *, GET, /api/logout, *, *
|
||||||
p, *, *, GET, /api/get-account, *, *
|
p, *, *, GET, /api/get-account, *, *
|
||||||
p, *, *, GET, /api/userinfo, *, *
|
p, *, *, GET, /api/userinfo, *, *
|
||||||
|
p, *, *, POST, /api/webhook, *, *
|
||||||
|
p, *, *, GET, /api/get-webhook-event, *, *
|
||||||
p, *, *, *, /api/login/oauth, *, *
|
p, *, *, *, /api/login/oauth, *, *
|
||||||
p, *, *, GET, /api/get-application, *, *
|
p, *, *, GET, /api/get-application, *, *
|
||||||
p, *, *, GET, /api/get-organization-applications, *, *
|
p, *, *, GET, /api/get-organization-applications, *, *
|
||||||
|
@ -31,6 +31,8 @@ func GetCaptchaProvider(captchaType string) CaptchaProvider {
|
|||||||
return NewAliyunCaptchaProvider()
|
return NewAliyunCaptchaProvider()
|
||||||
} else if captchaType == "GEETEST" {
|
} else if captchaType == "GEETEST" {
|
||||||
return NewGEETESTCaptchaProvider()
|
return NewGEETESTCaptchaProvider()
|
||||||
|
} else if captchaType == "Cloudflare Turnstile" {
|
||||||
|
return NewCloudflareTurnstileProvider()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
66
captcha/turnstile.go
Normal file
66
captcha/turnstile.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package captcha
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const CloudflareTurnstileVerifyUrl = "https://challenges.cloudflare.com/turnstile/v0/siteverify"
|
||||||
|
|
||||||
|
type CloudflareTurnstileProvider struct{}
|
||||||
|
|
||||||
|
func NewCloudflareTurnstileProvider() *CloudflareTurnstileProvider {
|
||||||
|
captcha := &CloudflareTurnstileProvider{}
|
||||||
|
return captcha
|
||||||
|
}
|
||||||
|
|
||||||
|
func (captcha *CloudflareTurnstileProvider) VerifyCaptcha(token, clientSecret string) (bool, error) {
|
||||||
|
reqData := url.Values{
|
||||||
|
"secret": {clientSecret},
|
||||||
|
"response": {token},
|
||||||
|
}
|
||||||
|
resp, err := http.PostForm(CloudflareTurnstileVerifyUrl, reqData)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type captchaResponse struct {
|
||||||
|
Success bool `json:"success"`
|
||||||
|
ErrorCodes []string `json:"error-codes"`
|
||||||
|
}
|
||||||
|
captchaResp := &captchaResponse{}
|
||||||
|
err = json.Unmarshal(body, captchaResp)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(captchaResp.ErrorCodes) > 0 {
|
||||||
|
return false, errors.New(strings.Join(captchaResp.ErrorCodes, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
return captchaResp.Success, nil
|
||||||
|
}
|
@ -21,3 +21,4 @@ isDemoMode = false
|
|||||||
batchSize = 100
|
batchSize = 100
|
||||||
ldapServerPort = 389
|
ldapServerPort = 389
|
||||||
languages = en,zh,es,fr,de,ja,ko,ru
|
languages = en,zh,es,fr,de,ja,ko,ru
|
||||||
|
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
||||||
|
35
conf/conf.go
35
conf/conf.go
@ -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 {
|
||||||
@ -95,3 +116,17 @@ func GetConfigBatchSize() int {
|
|||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetConfigQuota() *Quota {
|
||||||
|
return quota
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConfigRealDataSourceName(driverName string) string {
|
||||||
|
var dataSourceName string
|
||||||
|
if driverName != "mysql" {
|
||||||
|
dataSourceName = GetConfigDataSourceName()
|
||||||
|
} else {
|
||||||
|
dataSourceName = GetConfigDataSourceName() + GetConfigString("dbName")
|
||||||
|
}
|
||||||
|
return dataSourceName
|
||||||
|
}
|
||||||
|
@ -93,3 +93,19 @@ func TestGetConfBool(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetConfigQuota(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
description string
|
||||||
|
expected *Quota
|
||||||
|
}{
|
||||||
|
{"default", &Quota{-1, -1, -1, -1}},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := beego.LoadAppConfig("ini", "app.conf")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
for _, scenery := range scenarios {
|
||||||
|
quota := GetConfigQuota()
|
||||||
|
assert.Equal(t, scenery.expected, quota)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -102,7 +102,7 @@ type Captcha struct {
|
|||||||
// @router /signup [post]
|
// @router /signup [post]
|
||||||
func (c *ApiController) Signup() {
|
func (c *ApiController) Signup() {
|
||||||
if c.GetSessionUsername() != "" {
|
if c.GetSessionUsername() != "" {
|
||||||
c.ResponseError(c.T("SignUpErr.SignOutFirst"), c.GetSessionUsername())
|
c.ResponseError(c.T("account:Please sign out first before signing up"), c.GetSessionUsername())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ func (c *ApiController) Signup() {
|
|||||||
|
|
||||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||||
if !application.EnableSignUp {
|
if !application.EnableSignUp {
|
||||||
c.ResponseError(c.T("SignUpErr.DoNotAllowSignUp"))
|
c.ResponseError(c.T("account:The application does not allow to sign up new account"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ func (c *ApiController) Signup() {
|
|||||||
if application.IsSignupItemVisible("Email") && application.GetSignupItemRule("Email") != "No verification" && form.Email != "" {
|
if application.IsSignupItemVisible("Email") && application.GetSignupItemRule("Email") != "No verification" && form.Email != "" {
|
||||||
checkResult := object.CheckVerificationCode(form.Email, form.EmailCode, c.GetAcceptLanguage())
|
checkResult := object.CheckVerificationCode(form.Email, form.EmailCode, c.GetAcceptLanguage())
|
||||||
if len(checkResult) != 0 {
|
if len(checkResult) != 0 {
|
||||||
c.ResponseError(c.T("EmailErr.EmailCheckResult"), checkResult)
|
c.ResponseError(c.T("account:Email: %s"), checkResult)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +139,7 @@ func (c *ApiController) Signup() {
|
|||||||
checkPhone = fmt.Sprintf("+%s%s", form.PhonePrefix, form.Phone)
|
checkPhone = fmt.Sprintf("+%s%s", form.PhonePrefix, form.Phone)
|
||||||
checkResult := object.CheckVerificationCode(checkPhone, form.PhoneCode, c.GetAcceptLanguage())
|
checkResult := object.CheckVerificationCode(checkPhone, form.PhoneCode, c.GetAcceptLanguage())
|
||||||
if len(checkResult) != 0 {
|
if len(checkResult) != 0 {
|
||||||
c.ResponseError(c.T("PhoneErr.PhoneCheckResult"), checkResult)
|
c.ResponseError(c.T("account:Phone: %s"), checkResult)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,9 +161,9 @@ func (c *ApiController) Signup() {
|
|||||||
username = id
|
username = id
|
||||||
}
|
}
|
||||||
|
|
||||||
initScore, err := getInitScore()
|
initScore, err := getInitScore(organization)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(fmt.Errorf(c.T("InitErr.InitScoreFailed"), err).Error())
|
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ func (c *ApiController) Signup() {
|
|||||||
|
|
||||||
affected := object.AddUser(user)
|
affected := object.AddUser(user)
|
||||||
if !affected {
|
if !affected {
|
||||||
c.ResponseError(c.T("UserErr.InvalidInformation"), util.StructToJson(user))
|
c.ResponseError(c.T("account:Invalid information"), util.StructToJson(user))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ func (c *ApiController) GetApplications() {
|
|||||||
if organization == "" {
|
if organization == "" {
|
||||||
applications = object.GetApplications(owner)
|
applications = object.GetApplications(owner)
|
||||||
} else {
|
} else {
|
||||||
applications = object.GetApplicationsByOrganizationName(owner, organization)
|
applications = object.GetOrganizationApplications(owner, organization)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
||||||
@ -86,7 +86,7 @@ func (c *ApiController) GetUserApplication() {
|
|||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
user := object.GetUser(id)
|
user := object.GetUser(id)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("UserErr.DoNotExist"), id))
|
c.ResponseError(fmt.Sprintf(c.T("application:The user: %s doesn't exist"), id))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,17 +103,31 @@ func (c *ApiController) GetUserApplication() {
|
|||||||
// @router /get-organization-applications [get]
|
// @router /get-organization-applications [get]
|
||||||
func (c *ApiController) GetOrganizationApplications() {
|
func (c *ApiController) GetOrganizationApplications() {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
owner := c.Input().Get("owner")
|
|
||||||
organization := c.Input().Get("organization")
|
organization := c.Input().Get("organization")
|
||||||
|
owner := c.Input().Get("owner")
|
||||||
|
limit := c.Input().Get("pageSize")
|
||||||
|
page := c.Input().Get("p")
|
||||||
|
field := c.Input().Get("field")
|
||||||
|
value := c.Input().Get("value")
|
||||||
|
sortField := c.Input().Get("sortField")
|
||||||
|
sortOrder := c.Input().Get("sortOrder")
|
||||||
|
|
||||||
if organization == "" {
|
if organization == "" {
|
||||||
c.ResponseError(c.T("ParameterErr.OrgMissingErr"))
|
c.ResponseError(c.T("application:Parameter organization is missing"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
applications := object.GetApplicationsByOrganizationName(owner, organization)
|
if limit == "" || page == "" {
|
||||||
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
var applications []*object.Application
|
||||||
c.ServeJSON()
|
applications = object.GetOrganizationApplications(owner, organization)
|
||||||
|
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
||||||
|
c.ServeJSON()
|
||||||
|
} else {
|
||||||
|
limit := util.ParseInt(limit)
|
||||||
|
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetOrganizationApplicationCount(owner, organization, field, value)))
|
||||||
|
applications := object.GetMaskedApplications(object.GetPaginationOrganizationApplications(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder), userId)
|
||||||
|
c.ResponseOk(applications, paginator.Nums())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateApplication
|
// UpdateApplication
|
||||||
@ -153,6 +167,12 @@ func (c *ApiController) AddApplication() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
count := object.GetApplicationCount("", "", "")
|
||||||
|
if err := checkQuotaForApplication(count); err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.AddApplication(&application))
|
c.Data["json"] = wrapActionResponse(object.AddApplication(&application))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,16 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/captcha"
|
"github.com/casdoor/casdoor/captcha"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/idp"
|
"github.com/casdoor/casdoor/idp"
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
@ -33,6 +35,11 @@ import (
|
|||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
wechatScanType string
|
||||||
|
lock sync.RWMutex
|
||||||
|
)
|
||||||
|
|
||||||
func codeToResponse(code *object.Code) *Response {
|
func codeToResponse(code *object.Code) *Response {
|
||||||
if code.Code == "" {
|
if code.Code == "" {
|
||||||
return &Response{Status: "error", Msg: code.Message, Data: code.Code}
|
return &Response{Status: "error", Msg: code.Message, Data: code.Code}
|
||||||
@ -58,7 +65,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !allowed {
|
if !allowed {
|
||||||
c.ResponseError(c.T("AuthErr.Unauthorized"))
|
c.ResponseError(c.T("auth:Unauthorized operation"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +84,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
codeChallenge := c.Input().Get("code_challenge")
|
codeChallenge := c.Input().Get("code_challenge")
|
||||||
|
|
||||||
if challengeMethod != "S256" && challengeMethod != "null" && challengeMethod != "" {
|
if challengeMethod != "S256" && challengeMethod != "null" && challengeMethod != "" {
|
||||||
c.ResponseError(c.T("AuthErr.ChallengeMethodErr"))
|
c.ResponseError(c.T("auth:Challenge method should be S256"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
code := 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())
|
||||||
@ -163,7 +170,7 @@ func (c *ApiController) GetApplicationLogin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setHttpClient(idProvider idp.IdProvider, providerType string) {
|
func setHttpClient(idProvider idp.IdProvider, providerType string) {
|
||||||
if providerType == "GitHub" || providerType == "Google" || providerType == "Facebook" || providerType == "LinkedIn" || providerType == "Steam" {
|
if providerType == "GitHub" || providerType == "Google" || providerType == "Facebook" || providerType == "LinkedIn" || providerType == "Steam" || providerType == "Line" {
|
||||||
idProvider.SetHttpClient(proxy.ProxyHttpClient)
|
idProvider.SetHttpClient(proxy.ProxyHttpClient)
|
||||||
} else {
|
} else {
|
||||||
idProvider.SetHttpClient(proxy.DefaultHttpClient)
|
idProvider.SetHttpClient(proxy.DefaultHttpClient)
|
||||||
@ -198,7 +205,7 @@ func (c *ApiController) Login() {
|
|||||||
if form.Username != "" {
|
if form.Username != "" {
|
||||||
if form.Type == ResponseTypeLogin {
|
if form.Type == ResponseTypeLogin {
|
||||||
if c.GetSessionUsername() != "" {
|
if c.GetSessionUsername() != "" {
|
||||||
c.ResponseError(c.T("LoginErr.SignOutFirst"), c.GetSessionUsername())
|
c.ResponseError(c.T("auth:Please sign out first before signing in"), c.GetSessionUsername())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,7 +231,7 @@ func (c *ApiController) Login() {
|
|||||||
} else {
|
} else {
|
||||||
verificationCodeType = "phone"
|
verificationCodeType = "phone"
|
||||||
if len(form.PhonePrefix) == 0 {
|
if len(form.PhonePrefix) == 0 {
|
||||||
responseText := fmt.Sprintf(c.T("PhoneErr.NoPrefix"), verificationCodeType)
|
responseText := fmt.Sprintf(c.T("auth:%s No phone prefix"), verificationCodeType)
|
||||||
c.ResponseError(responseText)
|
c.ResponseError(responseText)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -249,13 +256,17 @@ func (c *ApiController) Login() {
|
|||||||
|
|
||||||
user = object.GetUserByFields(form.Organization, form.Username)
|
user = object.GetUserByFields(form.Organization, form.Username)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("LoginErr.UserDoNotExist"), form.Organization, form.Username))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The user: %s/%s doesn't exist"), form.Organization, form.Username))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||||
if application == nil {
|
if application == nil {
|
||||||
c.ResponseError(fmt.Sprintf("The application: %s does not exist", form.Application))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), form.Application))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !application.EnablePassword {
|
||||||
|
c.ResponseError(c.T("auth:The login method: login with password is not enabled for the application"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +278,7 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !isHuman {
|
if !isHuman {
|
||||||
c.ResponseError("Turing test failed.")
|
c.ResponseError(c.T("auth:Turing test failed."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -281,7 +292,7 @@ func (c *ApiController) Login() {
|
|||||||
} else {
|
} else {
|
||||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||||
if application == nil {
|
if application == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("LoginErr.AppDoNotExist"), form.Application))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), form.Application))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,15 +306,15 @@ func (c *ApiController) Login() {
|
|||||||
} else if form.Provider != "" {
|
} else if form.Provider != "" {
|
||||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||||
if application == nil {
|
if application == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("LoginErr.AppDoNotExist"), form.Application))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), form.Application))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", application.Organization))
|
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", application.Organization))
|
||||||
provider := object.GetProvider(fmt.Sprintf("admin/%s", form.Provider))
|
provider := object.GetProvider(util.GetId("admin", form.Provider))
|
||||||
providerItem := application.GetProviderItem(provider.Name)
|
providerItem := application.GetProviderItem(provider.Name)
|
||||||
if !providerItem.IsProviderVisible() {
|
if !providerItem.IsProviderVisible() {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("ProviderErr.ProviderNotEnabled"), provider.Name))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The provider: %s is not enabled for the application"), provider.Name))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,14 +338,14 @@ func (c *ApiController) Login() {
|
|||||||
|
|
||||||
idProvider := idp.GetIdProvider(provider.Type, provider.SubType, clientId, clientSecret, provider.AppId, form.RedirectUri, provider.Domain, provider.CustomAuthUrl, provider.CustomTokenUrl, provider.CustomUserInfoUrl)
|
idProvider := idp.GetIdProvider(provider.Type, provider.SubType, clientId, clientSecret, provider.AppId, form.RedirectUri, provider.Domain, provider.CustomAuthUrl, provider.CustomTokenUrl, provider.CustomUserInfoUrl)
|
||||||
if idProvider == nil {
|
if idProvider == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("ProviderErr.ProviderNotSupported"), provider.Type))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The provider type: %s is not supported"), provider.Type))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
setHttpClient(idProvider, provider.Type)
|
setHttpClient(idProvider, provider.Type)
|
||||||
|
|
||||||
if form.State != conf.GetConfigString("authState") && form.State != application.Name {
|
if form.State != conf.GetConfigString("authState") && form.State != application.Name {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("AuthErr.AuthStateWrong"), conf.GetConfigString("authState"), form.State))
|
c.ResponseError(fmt.Sprintf(c.T("auth:State expected: %s, but got: %s"), conf.GetConfigString("authState"), form.State))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,13 +357,13 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !token.Valid() {
|
if !token.Valid() {
|
||||||
c.ResponseError(c.T("TokenErr.InvalidToken"))
|
c.ResponseError(c.T("auth:Invalid token"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo, err = idProvider.GetUserInfo(token)
|
userInfo, err = idProvider.GetUserInfo(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("LoginErr.LoginFail"), err.Error()))
|
c.ResponseError(fmt.Sprintf(c.T("auth:Failed to login in: %s"), err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,7 +380,7 @@ func (c *ApiController) Login() {
|
|||||||
// Sign in via OAuth (want to sign up but already have account)
|
// Sign in via OAuth (want to sign up but already have account)
|
||||||
|
|
||||||
if user.IsForbidden {
|
if user.IsForbidden {
|
||||||
c.ResponseError(c.T("LoginErr.UserIsForbidden"))
|
c.ResponseError(c.T("auth:The user is forbidden to sign in, please contact the administrator"))
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = c.HandleLoggedIn(application, user, &form)
|
resp = c.HandleLoggedIn(application, user, &form)
|
||||||
@ -381,12 +392,12 @@ func (c *ApiController) Login() {
|
|||||||
} else if provider.Category == "OAuth" {
|
} else if provider.Category == "OAuth" {
|
||||||
// Sign up via OAuth
|
// Sign up via OAuth
|
||||||
if !application.EnableSignUp {
|
if !application.EnableSignUp {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("LoginErr.AppNotEnableSignUp"), provider.Type, userInfo.Username, userInfo.DisplayName))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support"), provider.Type, userInfo.Username, userInfo.DisplayName))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !providerItem.CanSignUp {
|
if !providerItem.CanSignUp {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("LoginErr.ProviderCanNotSignUp"), provider.Type, userInfo.Username, userInfo.DisplayName, provider.Type))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up"), provider.Type, userInfo.Username, userInfo.DisplayName, provider.Type))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,9 +416,9 @@ func (c *ApiController) Login() {
|
|||||||
|
|
||||||
properties := map[string]string{}
|
properties := map[string]string{}
|
||||||
properties["no"] = strconv.Itoa(len(object.GetUsers(application.Organization)) + 2)
|
properties["no"] = strconv.Itoa(len(object.GetUsers(application.Organization)) + 2)
|
||||||
initScore, err := getInitScore()
|
initScore, err := getInitScore(organization)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(fmt.Errorf(c.T("InitErr.InitScoreFailed"), err).Error())
|
c.ResponseError(fmt.Errorf(c.T("auth:Get init score failed, error: %w"), err).Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +445,7 @@ func (c *ApiController) Login() {
|
|||||||
|
|
||||||
affected := object.AddUser(user)
|
affected := object.AddUser(user)
|
||||||
if !affected {
|
if !affected {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("LoginErr.InvalidUserInformation"), util.StructToJson(user)))
|
c.ResponseError(fmt.Sprintf(c.T("auth:Failed to create user, user information is invalid: %s"), util.StructToJson(user)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,13 +470,13 @@ func (c *ApiController) Login() {
|
|||||||
} else { // form.Method != "signup"
|
} else { // form.Method != "signup"
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("LoginErr.AccountDoNotExist"), userInfo)
|
c.ResponseError(c.T("auth:The account does not exist"), userInfo)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
oldUser := object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
|
oldUser := object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
|
||||||
if oldUser != nil {
|
if oldUser != nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("LoginErr.OldUser"), 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
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,7 +497,7 @@ func (c *ApiController) Login() {
|
|||||||
// user already signed in to Casdoor, so let the user click the avatar button to do the quick sign-in
|
// user already signed in to Casdoor, so let the user click the avatar button to do the quick sign-in
|
||||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||||
if application == nil {
|
if application == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("LoginErr.AppDoNotExist"), form.Application))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), form.Application))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,7 +509,7 @@ func (c *ApiController) Login() {
|
|||||||
record.User = user.Name
|
record.User = user.Name
|
||||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||||
} else {
|
} else {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("LoginErr.UnknownAuthentication"), util.StructToJson(form)))
|
c.ResponseError(fmt.Sprintf(c.T("auth:Unknown authentication type (not password or provider), form = %s"), util.StructToJson(form)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -531,3 +542,46 @@ func (c *ApiController) HandleSamlLogin() {
|
|||||||
slice[4], relayState, samlResponse)
|
slice[4], relayState, samlResponse)
|
||||||
c.Redirect(targetUrl, 303)
|
c.Redirect(targetUrl, 303)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HandleOfficialAccountEvent ...
|
||||||
|
// @Tag HandleOfficialAccountEvent API
|
||||||
|
// @Title HandleOfficialAccountEvent
|
||||||
|
// @router /api/webhook [POST]
|
||||||
|
func (c *ApiController) HandleOfficialAccountEvent() {
|
||||||
|
respBytes, err := ioutil.ReadAll(c.Ctx.Request.Body)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
}
|
||||||
|
var data struct {
|
||||||
|
MsgType string `xml:"MsgType"`
|
||||||
|
Event string `xml:"Event"`
|
||||||
|
EventKey string `xml:"EventKey"`
|
||||||
|
}
|
||||||
|
err = xml.Unmarshal(respBytes, &data)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
}
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
if data.EventKey != "" {
|
||||||
|
wechatScanType = data.Event
|
||||||
|
c.Ctx.WriteString("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookEventType ...
|
||||||
|
// @Tag GetWebhookEventType API
|
||||||
|
// @Title GetWebhookEventType
|
||||||
|
// @router /api/get-webhook-event [GET]
|
||||||
|
func (c *ApiController) GetWebhookEventType() {
|
||||||
|
lock.Lock()
|
||||||
|
defer lock.Unlock()
|
||||||
|
resp := &Response{
|
||||||
|
Status: "ok",
|
||||||
|
Msg: "",
|
||||||
|
Data: wechatScanType,
|
||||||
|
}
|
||||||
|
c.Data["json"] = resp
|
||||||
|
wechatScanType = ""
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
@ -210,7 +210,7 @@ func (c *RootController) SamlValidate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !strings.HasPrefix(target, service) {
|
if !strings.HasPrefix(target, service) {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("CasErr.ServiceDoNotMatch"), target, service))
|
c.ResponseError(fmt.Sprintf(c.T("cas:Service %s and %s do not match"), target, service))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/beego/beego/utils/pagination"
|
"github.com/beego/beego/utils/pagination"
|
||||||
|
xormadapter "github.com/casbin/xorm-adapter/v3"
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
)
|
)
|
||||||
@ -31,8 +32,8 @@ func (c *ApiController) GetCasbinAdapters() {
|
|||||||
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 == "" {
|
||||||
c.Data["json"] = object.GetCasbinAdapters(owner)
|
adapters := object.GetCasbinAdapters(owner)
|
||||||
c.ServeJSON()
|
c.ResponseOk(adapters)
|
||||||
} else {
|
} else {
|
||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetCasbinAdapterCount(owner, field, value)))
|
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetCasbinAdapterCount(owner, field, value)))
|
||||||
@ -43,8 +44,8 @@ func (c *ApiController) GetCasbinAdapters() {
|
|||||||
|
|
||||||
func (c *ApiController) GetCasbinAdapter() {
|
func (c *ApiController) GetCasbinAdapter() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
c.Data["json"] = object.GetCasbinAdapter(id)
|
adapter := object.GetCasbinAdapter(id)
|
||||||
c.ServeJSON()
|
c.ResponseOk(adapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) UpdateCasbinAdapter() {
|
func (c *ApiController) UpdateCasbinAdapter() {
|
||||||
@ -89,6 +90,68 @@ func (c *ApiController) SyncPolicies() {
|
|||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
adapter := object.GetCasbinAdapter(id)
|
adapter := object.GetCasbinAdapter(id)
|
||||||
|
|
||||||
c.Data["json"] = object.SyncPolicies(adapter)
|
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()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (c *ApiController) Enforce() {
|
func (c *ApiController) Enforce() {
|
||||||
userId := c.GetSessionUsername()
|
|
||||||
if userId == "" {
|
|
||||||
c.ResponseError(c.T("EnforcerErr.SignInFirst"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var permissionRule object.PermissionRule
|
var permissionRule object.PermissionRule
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permissionRule)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permissionRule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -34,17 +28,11 @@ func (c *ApiController) Enforce() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.Enforce(userId, &permissionRule)
|
c.Data["json"] = object.Enforce(&permissionRule)
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) BatchEnforce() {
|
func (c *ApiController) BatchEnforce() {
|
||||||
userId := c.GetSessionUsername()
|
|
||||||
if userId == "" {
|
|
||||||
c.ResponseError(c.T("EnforcerErr.SignInFirst"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var permissionRules []object.PermissionRule
|
var permissionRules []object.PermissionRule
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permissionRules)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permissionRules)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -52,14 +40,14 @@ func (c *ApiController) BatchEnforce() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.BatchEnforce(userId, permissionRules)
|
c.Data["json"] = object.BatchEnforce(permissionRules)
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) GetAllObjects() {
|
func (c *ApiController) GetAllObjects() {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("EnforcerErr.SignInFirst"))
|
c.ResponseError(c.T("enforcer:Please sign in first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +58,7 @@ func (c *ApiController) GetAllObjects() {
|
|||||||
func (c *ApiController) GetAllActions() {
|
func (c *ApiController) GetAllActions() {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("EnforcerErr.SignInFirst"))
|
c.ResponseError(c.T("enforcer:Please sign in first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +69,7 @@ func (c *ApiController) GetAllActions() {
|
|||||||
func (c *ApiController) GetAllRoles() {
|
func (c *ApiController) GetAllRoles() {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("EnforcerErr.SignInFirst"))
|
c.ResponseError(c.T("enforcer:Please sign in first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ func (c *ApiController) GetLdapUser() {
|
|||||||
ldapServer := LdapServer{}
|
ldapServer := LdapServer{}
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldapServer)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldapServer)
|
||||||
if err != nil || util.IsStrsEmpty(ldapServer.Host, ldapServer.Admin, ldapServer.Passwd, ldapServer.BaseDn) {
|
if err != nil || util.IsStrsEmpty(ldapServer.Host, ldapServer.Admin, ldapServer.Passwd, ldapServer.BaseDn) {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing"))
|
c.ResponseError(c.T("ldap:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ func (c *ApiController) GetLdap() {
|
|||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
|
|
||||||
if util.IsStrsEmpty(id) {
|
if util.IsStrsEmpty(id) {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing"))
|
c.ResponseError(c.T("ldap:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,17 +136,17 @@ func (c *ApiController) AddLdap() {
|
|||||||
var ldap object.Ldap
|
var ldap object.Ldap
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldap)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing"))
|
c.ResponseError(c.T("ldap:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if util.IsStrsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
|
if util.IsStrsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing"))
|
c.ResponseError(c.T("ldap:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if object.CheckLdapExist(&ldap) {
|
if object.CheckLdapExist(&ldap) {
|
||||||
c.ResponseError(c.T("LdapErr.ServerExisted"))
|
c.ResponseError(c.T("ldap:Ldap server exist"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ func (c *ApiController) UpdateLdap() {
|
|||||||
var ldap object.Ldap
|
var ldap object.Ldap
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldap)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldap)
|
||||||
if err != nil || util.IsStrsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
|
if err != nil || util.IsStrsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing"))
|
c.ResponseError(c.T("ldap:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ func (c *ApiController) Unlink() {
|
|||||||
|
|
||||||
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("AuthErr.CanNotUnlinkUsers"))
|
c.ResponseError(c.T("link:You are not the global admin, you can't unlink other users"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,23 +55,23 @@ func (c *ApiController) Unlink() {
|
|||||||
// 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 := object.GetApplicationByUser(user)
|
application := object.GetApplicationByUser(user)
|
||||||
if application == nil {
|
if application == nil {
|
||||||
c.ResponseError(c.T("AuthErr.CanNotLinkMySelf"))
|
c.ResponseError(c.T("link:You can't unlink yourself, you are not a member of any application"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(application.Providers) == 0 {
|
if len(application.Providers) == 0 {
|
||||||
c.ResponseError(c.T("ApplicationErr.HasNoProviders"))
|
c.ResponseError(c.T("link:This application has no providers"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := application.GetProviderItemByType(providerType)
|
provider := application.GetProviderItemByType(providerType)
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
c.ResponseError(c.T("ApplicationErr.HasNoProvidersOfType") + providerType)
|
c.ResponseError(c.T("link:This application has no providers of type") + providerType)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !provider.CanUnlink {
|
if !provider.CanUnlink {
|
||||||
c.ResponseError(c.T("ProviderErr.CanNotBeUnlinked"))
|
c.ResponseError(c.T("link:This provider can't be unlinked"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ func (c *ApiController) Unlink() {
|
|||||||
value := object.GetUserField(&unlinkedUser, providerType)
|
value := object.GetUserField(&unlinkedUser, providerType)
|
||||||
|
|
||||||
if value == "" {
|
if value == "" {
|
||||||
c.ResponseError(c.T("ProviderErr.LinkFirstErr"), value)
|
c.ResponseError(c.T("link:Please link first"), value)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +99,12 @@ func (c *ApiController) AddOrganization() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
count := object.GetOrganizationCount("", "", "")
|
||||||
|
if err := checkQuotaForOrganization(count); err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.AddOrganization(&organization))
|
c.Data["json"] = wrapActionResponse(object.AddOrganization(&organization))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,20 @@ func (c *ApiController) GetPermissionsBySubmitter() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPermissionsByRole
|
||||||
|
// @Title GetPermissionsByRole
|
||||||
|
// @Tag Permission API
|
||||||
|
// @Description get permissions by role
|
||||||
|
// @Param id query string true "The id of the role"
|
||||||
|
// @Success 200 {array} object.Permission The Response object
|
||||||
|
// @router /get-permissions-by-role [get]
|
||||||
|
func (c *ApiController) GetPermissionsByRole() {
|
||||||
|
id := c.Input().Get("id")
|
||||||
|
permissions := object.GetPermissionsByRole(id)
|
||||||
|
c.ResponseOk(permissions, len(permissions))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// GetPermission
|
// GetPermission
|
||||||
// @Title GetPermission
|
// @Title GetPermission
|
||||||
// @Tag Permission API
|
// @Tag Permission API
|
||||||
|
@ -141,13 +141,13 @@ func (c *ApiController) BuyProduct() {
|
|||||||
|
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("LoginErr.LoginFirst"))
|
c.ResponseError(c.T("product:Please login first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user := object.GetUser(userId)
|
user := object.GetUser(userId)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("UserErr.DoNotExist"), userId))
|
c.ResponseError(fmt.Sprintf(c.T("product:The user: %s doesn't exist"), userId))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,6 @@ func (c *ApiController) GetGlobalProviders() {
|
|||||||
// @router /get-provider [get]
|
// @router /get-provider [get]
|
||||||
func (c *ApiController) GetProvider() {
|
func (c *ApiController) GetProvider() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
|
|
||||||
c.Data["json"] = object.GetMaskedProvider(object.GetProvider(id))
|
c.Data["json"] = object.GetMaskedProvider(object.GetProvider(id))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
@ -123,6 +122,12 @@ func (c *ApiController) AddProvider() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
count := object.GetProviderCount("", "", "")
|
||||||
|
if err := checkQuotaForProvider(count); err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.AddProvider(&provider))
|
c.Data["json"] = wrapActionResponse(object.AddProvider(&provider))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,15 @@ func (c *ApiController) GetResources() {
|
|||||||
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")
|
||||||
|
|
||||||
|
userObj, ok := c.RequireSignedInUser()
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if userObj.IsAdmin {
|
||||||
|
user = ""
|
||||||
|
}
|
||||||
|
|
||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
c.Data["json"] = object.GetResources(owner, user)
|
c.Data["json"] = object.GetResources(owner, user)
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
@ -145,7 +154,7 @@ func (c *ApiController) UploadResource() {
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
if username == "" || fullFilePath == "" {
|
if username == "" || fullFilePath == "" {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("ResourceErr.UsernameOrFilePathEmpty"), username, fullFilePath))
|
c.ResponseError(fmt.Sprintf(c.T("resource:Username or fullFilePath is empty: username = %s, fullFilePath = %s"), username, fullFilePath))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +165,7 @@ func (c *ApiController) UploadResource() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, user, ok := c.GetProviderFromContext("Storage")
|
provider, _, ok := c.GetProviderFromContext("Storage")
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -171,6 +180,20 @@ func (c *ApiController) UploadResource() {
|
|||||||
fileType, _ = util.GetOwnerAndNameFromId(mimeType)
|
fileType, _ = util.GetOwnerAndNameFromId(mimeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tag != "avatar" && tag != "termsOfUse" {
|
||||||
|
ext := filepath.Ext(filepath.Base(fullFilePath))
|
||||||
|
index := len(fullFilePath) - len(ext)
|
||||||
|
for i := 1; ; i++ {
|
||||||
|
_, objectKey := object.GetUploadFileUrl(provider, fullFilePath, true)
|
||||||
|
if object.GetResourceCount(owner, username, "name", objectKey) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// duplicated fullFilePath found, change it
|
||||||
|
fullFilePath = fullFilePath[:index] + fmt.Sprintf("-%d", i) + ext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fileUrl, objectKey, err := object.UploadFileSafe(provider, fullFilePath, fileBuffer)
|
fileUrl, objectKey, err := object.UploadFileSafe(provider, fullFilePath, fileBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
@ -202,12 +225,10 @@ func (c *ApiController) UploadResource() {
|
|||||||
|
|
||||||
switch tag {
|
switch tag {
|
||||||
case "avatar":
|
case "avatar":
|
||||||
|
user := object.GetUserNoCheck(util.GetId(owner, username))
|
||||||
if user == nil {
|
if user == nil {
|
||||||
user = object.GetUserNoCheck(username)
|
c.ResponseError(c.T("resource:User is nil for tag: avatar"))
|
||||||
if user == nil {
|
return
|
||||||
c.ResponseError(c.T("ResourceErr.UserIsNil"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Avatar = fileUrl
|
user.Avatar = fileUrl
|
||||||
|
@ -25,7 +25,7 @@ func (c *ApiController) GetSamlMeta() {
|
|||||||
paramApp := c.Input().Get("application")
|
paramApp := c.Input().Get("application")
|
||||||
application := object.GetApplication(paramApp)
|
application := object.GetApplication(paramApp)
|
||||||
if application == nil {
|
if application == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("ApplicationErr.AppNotFound"), paramApp))
|
c.ResponseError(fmt.Sprintf(c.T("saml:Application %s not found"), paramApp))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
metadata, _ := object.GetSamlMeta(application, host)
|
metadata, _ := object.GetSamlMeta(application, host)
|
||||||
|
@ -60,7 +60,7 @@ 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 = object.GetProvider(fmt.Sprintf("admin/%s", emailForm.Provider))
|
provider = object.GetProvider(util.GetId("admin", emailForm.Provider))
|
||||||
} 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
|
||||||
var ok bool
|
var ok bool
|
||||||
@ -81,7 +81,7 @@ func (c *ApiController) SendEmail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if util.IsStrsEmpty(emailForm.Title, emailForm.Content, emailForm.Sender) {
|
if util.IsStrsEmpty(emailForm.Title, emailForm.Content, emailForm.Sender) {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("EmailErr.EmptyParam"), emailForm))
|
c.ResponseError(fmt.Sprintf(c.T("service:Empty parameters for emailForm: %v"), emailForm))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ func (c *ApiController) SendEmail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(invalidReceivers) != 0 {
|
if len(invalidReceivers) != 0 {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("EmailErr.InvalidReceivers"), invalidReceivers))
|
c.ResponseError(fmt.Sprintf(c.T("service:Invalid Email receivers: %s"), invalidReceivers))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ func (c *ApiController) SendSms() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(invalidReceivers) != 0 {
|
if len(invalidReceivers) != 0 {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("PhoneErr.InvalidReceivers"), invalidReceivers))
|
c.ResponseError(fmt.Sprintf(c.T("service:Invalid phone receivers: %s"), invalidReceivers))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ func (c *ApiController) GetSystemInfo() {
|
|||||||
|
|
||||||
user := object.GetUser(id)
|
user := object.GetUser(id)
|
||||||
if user == nil || !user.IsGlobalAdmin {
|
if user == nil || !user.IsGlobalAdmin {
|
||||||
c.ResponseError(c.T("ResourceErr.NotAuthorized"))
|
c.ResponseError(c.T("system_info:You are not authorized to access this resource"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ func (c *ApiController) GetOAuthCode() {
|
|||||||
codeChallenge := c.Input().Get("code_challenge")
|
codeChallenge := c.Input().Get("code_challenge")
|
||||||
|
|
||||||
if challengeMethod != "S256" && challengeMethod != "null" && challengeMethod != "" {
|
if challengeMethod != "S256" && challengeMethod != "null" && challengeMethod != "" {
|
||||||
c.ResponseError(c.T("AuthErr.ChallengeMethodErr"))
|
c.ResponseError(c.T("token:Challenge method should be S256"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
host := c.Ctx.Request.Host
|
host := c.Ctx.Request.Host
|
||||||
@ -261,7 +261,7 @@ func (c *ApiController) TokenLogout() {
|
|||||||
flag, application := object.DeleteTokenByAccessToken(token)
|
flag, application := object.DeleteTokenByAccessToken(token)
|
||||||
redirectUri := c.Input().Get("post_logout_redirect_uri")
|
redirectUri := c.Input().Get("post_logout_redirect_uri")
|
||||||
state := c.Input().Get("state")
|
state := c.Input().Get("state")
|
||||||
if application != nil && object.CheckRedirectUriValid(application, redirectUri) {
|
if application != nil && application.IsRedirectUriValid(redirectUri) {
|
||||||
c.Ctx.Redirect(http.StatusFound, redirectUri+"?state="+state)
|
c.Ctx.Redirect(http.StatusFound, redirectUri+"?state="+state)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -290,7 +290,7 @@ 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.ResponseError(c.T("TokenErr.EmptyClientID"))
|
c.ResponseError(c.T("token:Empty clientId or clientSecret"))
|
||||||
c.Data["json"] = &object.TokenError{
|
c.Data["json"] = &object.TokenError{
|
||||||
Error: object.InvalidRequest,
|
Error: object.InvalidRequest,
|
||||||
}
|
}
|
||||||
@ -301,7 +301,7 @@ func (c *ApiController) IntrospectToken() {
|
|||||||
}
|
}
|
||||||
application := object.GetApplicationByClientId(clientId)
|
application := object.GetApplicationByClientId(clientId)
|
||||||
if application == nil || application.ClientSecret != clientSecret {
|
if application == nil || application.ClientSecret != clientSecret {
|
||||||
c.ResponseError(c.T("TokenErr.InvalidAppOrWrongClientSecret"))
|
c.ResponseError(c.T("token:Invalid application or wrong clientSecret"))
|
||||||
c.Data["json"] = &object.TokenError{
|
c.Data["json"] = &object.TokenError{
|
||||||
Error: object.InvalidClient,
|
Error: object.InvalidClient,
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ func (c *ApiController) UpdateUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if user.DisplayName == "" {
|
if user.DisplayName == "" {
|
||||||
c.ResponseError(c.T("UserErr.DisplayNameCanNotBeEmpty"))
|
c.ResponseError(c.T("user:Display name cannot be empty"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,6 +183,12 @@ func (c *ApiController) AddUser() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
count := object.GetUserCount("", "", "")
|
||||||
|
if err := checkQuotaForUser(count); err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
msg := object.CheckUsername(user.Name, c.GetAcceptLanguage())
|
msg := object.CheckUsername(user.Name, c.GetAcceptLanguage())
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
c.ResponseError(msg)
|
c.ResponseError(msg)
|
||||||
@ -230,7 +236,7 @@ func (c *ApiController) GetEmailAndPhone() {
|
|||||||
|
|
||||||
user := object.GetUserByFields(form.Organization, form.Username)
|
user := object.GetUserByFields(form.Organization, form.Username)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("UserErr.DoNotExistInOrg"), form.Organization, form.Username))
|
c.ResponseError(fmt.Sprintf(c.T("user:The user: %s/%s doesn't exist"), form.Organization, form.Username))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,12 +294,12 @@ func (c *ApiController) SetPassword() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(newPassword, " ") {
|
if strings.Contains(newPassword, " ") {
|
||||||
c.ResponseError(c.T("SetPasswordErr.CanNotContainBlank"))
|
c.ResponseError(c.T("user:New password cannot contain blank space."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(newPassword) <= 5 {
|
if len(newPassword) <= 5 {
|
||||||
c.ResponseError(c.T("SetPasswordErr.LessThanSixCharacters"))
|
c.ResponseError(c.T("user:New password must have at least 6 characters"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,6 @@ func (c *ApiController) UploadUsers() {
|
|||||||
if affected {
|
if affected {
|
||||||
c.ResponseOk()
|
c.ResponseOk()
|
||||||
} else {
|
} else {
|
||||||
c.ResponseError(c.T("UserErr.FailToImportUsers"))
|
c.ResponseError(c.T("user_upload:Failed to import users"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/i18n"
|
"github.com/casdoor/casdoor/i18n"
|
||||||
@ -56,7 +57,7 @@ func (c *ApiController) T(error string) string {
|
|||||||
// GetAcceptLanguage ...
|
// GetAcceptLanguage ...
|
||||||
func (c *ApiController) GetAcceptLanguage() string {
|
func (c *ApiController) GetAcceptLanguage() string {
|
||||||
lang := c.Ctx.Request.Header.Get("Accept-Language")
|
lang := c.Ctx.Request.Header.Get("Accept-Language")
|
||||||
if lang == "" {
|
if lang == "" || !strings.Contains(conf.GetConfigString("languages"), lang[0:2]) {
|
||||||
lang = "en"
|
lang = "en"
|
||||||
}
|
}
|
||||||
return lang[0:2]
|
return lang[0:2]
|
||||||
@ -83,7 +84,7 @@ func (c *ApiController) SetTokenErrorHttpStatus() {
|
|||||||
func (c *ApiController) RequireSignedIn() (string, bool) {
|
func (c *ApiController) RequireSignedIn() (string, bool) {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("LoginErr.LoginFirst"), "Please login first")
|
c.ResponseError(c.T("util:Please login first"), "Please login first")
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
return userId, true
|
return userId, true
|
||||||
@ -99,7 +100,7 @@ func (c *ApiController) RequireSignedInUser() (*object.User, bool) {
|
|||||||
user := object.GetUser(userId)
|
user := object.GetUser(userId)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ClearUserSession()
|
c.ClearUserSession()
|
||||||
c.ResponseError(fmt.Sprintf(c.T("UserErr.DoNotExist"), userId))
|
c.ResponseError(fmt.Sprintf(c.T("util:The user: %s doesn't exist"), userId))
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
return user, true
|
return user, true
|
||||||
@ -118,16 +119,20 @@ func (c *ApiController) RequireAdmin() (string, bool) {
|
|||||||
return user.Owner, true
|
return user.Owner, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInitScore() (int, error) {
|
func getInitScore(organization *object.Organization) (int, error) {
|
||||||
return strconv.Atoi(conf.GetConfigString("initScore"))
|
if organization != nil {
|
||||||
|
return organization.InitScore, nil
|
||||||
|
} else {
|
||||||
|
return strconv.Atoi(conf.GetConfigString("initScore"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, *object.User, bool) {
|
func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, *object.User, bool) {
|
||||||
providerName := c.Input().Get("provider")
|
providerName := c.Input().Get("provider")
|
||||||
if providerName != "" {
|
if providerName != "" {
|
||||||
provider := object.GetProvider(util.GetId(providerName))
|
provider := object.GetProvider(util.GetId("admin", providerName))
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
c.ResponseError(c.T("ProviderErr.ProviderNotFound"), providerName)
|
c.ResponseError(c.T("util:The provider: %s is not found"), providerName)
|
||||||
return nil, nil, false
|
return nil, nil, false
|
||||||
}
|
}
|
||||||
return provider, nil, true
|
return provider, nil, true
|
||||||
@ -140,15 +145,59 @@ func (c *ApiController) GetProviderFromContext(category string) (*object.Provide
|
|||||||
|
|
||||||
application, user := object.GetApplicationByUserId(userId)
|
application, user := object.GetApplicationByUserId(userId)
|
||||||
if application == nil {
|
if application == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("ApplicationErr.AppNotFoundForUserID"), userId))
|
c.ResponseError(fmt.Sprintf(c.T("util:No application is found for userId: %s"), userId))
|
||||||
return nil, nil, false
|
return nil, nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := application.GetProviderByCategory(category)
|
provider := application.GetProviderByCategory(category)
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("ProviderErr.ProviderNotFoundForCategory"), 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 nil, nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return provider, user, true
|
return provider, user, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkQuotaForApplication(count int) error {
|
||||||
|
quota := conf.GetConfigQuota().Application
|
||||||
|
if quota == -1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if count >= quota {
|
||||||
|
return fmt.Errorf("application quota is exceeded")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkQuotaForOrganization(count int) error {
|
||||||
|
quota := conf.GetConfigQuota().Organization
|
||||||
|
if quota == -1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if count >= quota {
|
||||||
|
return fmt.Errorf("organization quota is exceeded")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkQuotaForProvider(count int) error {
|
||||||
|
quota := conf.GetConfigQuota().Provider
|
||||||
|
if quota == -1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if count >= quota {
|
||||||
|
return fmt.Errorf("provider quota is exceeded")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkQuotaForUser(count int) error {
|
||||||
|
quota := conf.GetConfigQuota().User
|
||||||
|
if quota == -1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if count >= quota {
|
||||||
|
return fmt.Errorf("user quota is exceeded")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -47,26 +47,27 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
checkKey := c.Ctx.Request.Form.Get("checkKey")
|
checkKey := c.Ctx.Request.Form.Get("checkKey")
|
||||||
checkUser := c.Ctx.Request.Form.Get("checkUser")
|
checkUser := c.Ctx.Request.Form.Get("checkUser")
|
||||||
applicationId := c.Ctx.Request.Form.Get("applicationId")
|
applicationId := c.Ctx.Request.Form.Get("applicationId")
|
||||||
|
method := c.Ctx.Request.Form.Get("method")
|
||||||
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
||||||
|
|
||||||
if destType == "" {
|
if destType == "" {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing") + ": type.")
|
c.ResponseError(c.T("verification:Missing parameter") + ": type.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if dest == "" {
|
if dest == "" {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing") + ": dest.")
|
c.ResponseError(c.T("verification:Missing parameter") + ": dest.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if applicationId == "" {
|
if applicationId == "" {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing") + ": applicationId.")
|
c.ResponseError(c.T("verification:Missing parameter") + ": applicationId.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !strings.Contains(applicationId, "/") {
|
if !strings.Contains(applicationId, "/") {
|
||||||
c.ResponseError(c.T("ParameterErr.Wrong") + ": applicationId.")
|
c.ResponseError(c.T("verification:Wrong parameter") + ": applicationId.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if checkType == "" {
|
if checkType == "" {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing") + ": checkType.")
|
c.ResponseError(c.T("verification:Missing parameter") + ": checkType.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
|
|
||||||
if captchaProvider != nil {
|
if captchaProvider != nil {
|
||||||
if checkKey == "" {
|
if checkKey == "" {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing") + ": checkKey.")
|
c.ResponseError(c.T("verification:Missing parameter") + ": checkKey.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isHuman, err := captchaProvider.VerifyCaptcha(checkKey, checkId)
|
isHuman, err := captchaProvider.VerifyCaptcha(checkKey, checkId)
|
||||||
@ -84,7 +85,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !isHuman {
|
if !isHuman {
|
||||||
c.ResponseError(c.T("AuthErr.NotHuman"))
|
c.ResponseError(c.T("verification:Turing test failed."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,9 +93,13 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
user := c.getCurrentUser()
|
user := c.getCurrentUser()
|
||||||
application := object.GetApplication(applicationId)
|
application := object.GetApplication(applicationId)
|
||||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", application.Owner, application.Organization))
|
organization := object.GetOrganization(fmt.Sprintf("%s/%s", application.Owner, application.Organization))
|
||||||
|
if organization == nil {
|
||||||
|
c.ResponseError(c.T("verification:Organization does not exist"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if checkUser == "true" && user == nil && object.GetUserByFields(organization.Name, dest) == nil {
|
if checkUser == "true" && user == nil && object.GetUserByFields(organization.Name, dest) == nil {
|
||||||
c.ResponseError(c.T("LoginErr.LoginFirst"))
|
c.ResponseError(c.T("verification:Please login first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +115,13 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
dest = user.Email
|
dest = user.Email
|
||||||
}
|
}
|
||||||
if !util.IsEmailValid(dest) {
|
if !util.IsEmailValid(dest) {
|
||||||
c.ResponseError(c.T("EmailErr.EmailInvalid"))
|
c.ResponseError(c.T("verification:Email is invalid"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userByEmail := object.GetUserByEmail(organization.Name, dest)
|
||||||
|
if userByEmail == nil && method != "signup" && method != "reset" {
|
||||||
|
c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,11 +132,13 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
dest = user.Phone
|
dest = user.Phone
|
||||||
}
|
}
|
||||||
if !util.IsPhoneCnValid(dest) {
|
if !util.IsPhoneCnValid(dest) {
|
||||||
c.ResponseError(c.T("PhoneErr.NumberInvalid"))
|
c.ResponseError(c.T("verification:Phone number is invalid"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if organization == nil {
|
|
||||||
c.ResponseError(c.T("OrgErr.DoNotExist"))
|
userByPhone := object.GetUserByPhone(organization.Name, dest)
|
||||||
|
if userByPhone == nil && method != "signup" && method != "reset" {
|
||||||
|
c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +170,7 @@ func (c *ApiController) ResetEmailOrPhone() {
|
|||||||
dest := c.Ctx.Request.Form.Get("dest")
|
dest := c.Ctx.Request.Form.Get("dest")
|
||||||
code := c.Ctx.Request.Form.Get("code")
|
code := c.Ctx.Request.Form.Get("code")
|
||||||
if len(dest) == 0 || len(code) == 0 || len(destType) == 0 {
|
if len(dest) == 0 || len(code) == 0 || len(destType) == 0 {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing"))
|
c.ResponseError(c.T("verification:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +179,7 @@ func (c *ApiController) ResetEmailOrPhone() {
|
|||||||
if destType == "phone" {
|
if destType == "phone" {
|
||||||
phoneItem := object.GetAccountItemByName("Phone", org)
|
phoneItem := object.GetAccountItemByName("Phone", org)
|
||||||
if phoneItem == nil {
|
if phoneItem == nil {
|
||||||
c.ResponseError(c.T("PhoneErr.UnableGetModifyRule"))
|
c.ResponseError(c.T("verification:Unable to get the phone modify rule."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +196,7 @@ func (c *ApiController) ResetEmailOrPhone() {
|
|||||||
} else if destType == "email" {
|
} else if destType == "email" {
|
||||||
emailItem := object.GetAccountItemByName("Email", org)
|
emailItem := object.GetAccountItemByName("Email", org)
|
||||||
if emailItem == nil {
|
if emailItem == nil {
|
||||||
c.ResponseError(c.T("EmailErr.UnableGetModifyRule"))
|
c.ResponseError(c.T("verification:Unable to get the email modify rule."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +218,7 @@ func (c *ApiController) ResetEmailOrPhone() {
|
|||||||
user.Phone = dest
|
user.Phone = dest
|
||||||
object.SetUserField(user, "phone", user.Phone)
|
object.SetUserField(user, "phone", user.Phone)
|
||||||
default:
|
default:
|
||||||
c.ResponseError(c.T("ParameterErr.UnknownType"))
|
c.ResponseError(c.T("verification:Unknown type"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,17 +237,17 @@ func (c *ApiController) VerifyCaptcha() {
|
|||||||
captchaToken := c.Ctx.Request.Form.Get("captchaToken")
|
captchaToken := c.Ctx.Request.Form.Get("captchaToken")
|
||||||
clientSecret := c.Ctx.Request.Form.Get("clientSecret")
|
clientSecret := c.Ctx.Request.Form.Get("clientSecret")
|
||||||
if captchaToken == "" {
|
if captchaToken == "" {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing") + ": captchaToken.")
|
c.ResponseError(c.T("verification:Missing parameter") + ": captchaToken.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if clientSecret == "" {
|
if clientSecret == "" {
|
||||||
c.ResponseError(c.T("ParameterErr.Missing") + ": clientSecret.")
|
c.ResponseError(c.T("verification:Missing parameter") + ": clientSecret.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := captcha.GetCaptchaProvider(captchaType)
|
provider := captcha.GetCaptchaProvider(captchaType)
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
c.ResponseError(c.T("ProviderErr.InvalidProvider"))
|
c.ResponseError(c.T("verification:Invalid captcha provider."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ func (c *ApiController) WebAuthnSignupBegin() {
|
|||||||
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||||
user := c.getCurrentUser()
|
user := c.getCurrentUser()
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(c.T("LoginErr.LoginFirst"))
|
c.ResponseError(c.T("webauthn:Please login first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,13 +66,13 @@ func (c *ApiController) WebAuthnSignupFinish() {
|
|||||||
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||||
user := c.getCurrentUser()
|
user := c.getCurrentUser()
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(c.T("LoginErr.LoginFirst"))
|
c.ResponseError(c.T("webauthn:Please login first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sessionObj := c.GetSession("registration")
|
sessionObj := c.GetSession("registration")
|
||||||
sessionData, ok := sessionObj.(webauthn.SessionData)
|
sessionData, ok := sessionObj.(webauthn.SessionData)
|
||||||
if !ok {
|
if !ok {
|
||||||
c.ResponseError(c.T("AuthErr.CallWebAuthnSigninBegin"))
|
c.ResponseError(c.T("webauthn:Please call WebAuthnSigninBegin first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
||||||
@ -101,9 +101,14 @@ func (c *ApiController) WebAuthnSigninBegin() {
|
|||||||
userName := c.Input().Get("name")
|
userName := c.Input().Get("name")
|
||||||
user := object.GetUserByFields(userOwner, userName)
|
user := object.GetUserByFields(userOwner, userName)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("UserErr.DoNotExistInOrg"), userOwner, userName))
|
c.ResponseError(fmt.Sprintf(c.T("webauthn:The user: %s/%s doesn't exist"), userOwner, userName))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if len(user.WebauthnCredentials) == 0 {
|
||||||
|
c.ResponseError(c.T("webauthn:Found no credentials for this user"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
options, sessionData, err := webauthnObj.BeginLogin(user)
|
options, sessionData, err := webauthnObj.BeginLogin(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
@ -127,7 +132,7 @@ func (c *ApiController) WebAuthnSigninFinish() {
|
|||||||
sessionObj := c.GetSession("authentication")
|
sessionObj := c.GetSession("authentication")
|
||||||
sessionData, ok := sessionObj.(webauthn.SessionData)
|
sessionData, ok := sessionObj.(webauthn.SessionData)
|
||||||
if !ok {
|
if !ok {
|
||||||
c.ResponseError(c.T("AuthErr.CallWebAuthnSigninBegin"))
|
c.ResponseError(c.T("webauthn:Please call WebAuthnSigninBegin first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
||||||
|
10
crowdin.yml
Normal file
10
crowdin.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
project_id: '491513'
|
||||||
|
api_token_env: 'CROWDIN_PERSONAL_TOKEN'
|
||||||
|
preserve_hierarchy: true
|
||||||
|
files: [
|
||||||
|
# JSON translation files
|
||||||
|
{
|
||||||
|
source: '/i18n/locales/en/data.json',
|
||||||
|
translation: '/i18n/locales/%two_letters_code%/data.json',
|
||||||
|
},
|
||||||
|
]
|
@ -21,9 +21,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
|
"github.com/casdoor/casdoor/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDeployStaticFiles(t *testing.T) {
|
func TestDeployStaticFiles(t *testing.T) {
|
||||||
provider := object.GetProvider("admin/provider_storage_aliyun_oss")
|
provider := object.GetProvider(util.GetId("admin", "provider_storage_aliyun_oss"))
|
||||||
deployStaticFiles(provider)
|
deployStaticFiles(provider)
|
||||||
}
|
}
|
||||||
|
15
go.mod
15
go.mod
@ -4,7 +4,6 @@ go 1.16
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b
|
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b
|
||||||
github.com/Unknwon/goconfig v1.0.0
|
|
||||||
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.44.4
|
github.com/aws/aws-sdk-go v1.44.4
|
||||||
github.com/beego/beego v1.12.11
|
github.com/beego/beego v1.12.11
|
||||||
@ -12,7 +11,6 @@ require (
|
|||||||
github.com/casbin/casbin/v2 v2.30.1
|
github.com/casbin/casbin/v2 v2.30.1
|
||||||
github.com/casbin/xorm-adapter/v3 v3.0.1
|
github.com/casbin/xorm-adapter/v3 v3.0.1
|
||||||
github.com/casdoor/go-sms-sender v0.5.1
|
github.com/casdoor/go-sms-sender v0.5.1
|
||||||
github.com/casdoor/goth v1.69.0-FIX2
|
|
||||||
github.com/casdoor/oss v1.2.0
|
github.com/casdoor/oss v1.2.0
|
||||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc
|
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc
|
||||||
@ -23,12 +21,14 @@ require (
|
|||||||
github.com/go-pay/gopay v1.5.72
|
github.com/go-pay/gopay v1.5.72
|
||||||
github.com/go-sql-driver/mysql v1.5.0
|
github.com/go-sql-driver/mysql v1.5.0
|
||||||
github.com/golang-jwt/jwt/v4 v4.2.0
|
github.com/golang-jwt/jwt/v4 v4.2.0
|
||||||
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/go-cmp v0.5.8 // indirect
|
github.com/google/go-cmp v0.5.8 // indirect
|
||||||
github.com/google/uuid v1.2.0
|
github.com/google/uuid v1.2.0
|
||||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||||
github.com/lestrrat-go/jwx v0.9.0
|
github.com/lestrrat-go/jwx v1.2.21
|
||||||
github.com/lib/pq v1.8.0
|
github.com/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.75.2
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||||
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
|
||||||
@ -36,21 +36,22 @@ require (
|
|||||||
github.com/russellhaering/goxmldsig v1.1.1
|
github.com/russellhaering/goxmldsig v1.1.1
|
||||||
github.com/satori/go.uuid v1.2.0
|
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/smartystreets/goconvey v1.6.4 // indirect
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.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/tklauser/go-sysconf v0.3.10 // indirect
|
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220208233918-bba287dce954
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
||||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
|
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0
|
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
|
||||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||||
|
xorm.io/builder v0.3.12 // indirect
|
||||||
xorm.io/core v0.7.2
|
xorm.io/core v0.7.2
|
||||||
xorm.io/xorm v1.0.4
|
xorm.io/xorm v1.0.5
|
||||||
)
|
)
|
||||||
|
46
go.sum
46
go.sum
@ -61,8 +61,6 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go
|
|||||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b h1:EgJ6N2S0h1WfFIjU5/VVHWbMSVYXAluop97Qxpr/lfQ=
|
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b h1:EgJ6N2S0h1WfFIjU5/VVHWbMSVYXAluop97Qxpr/lfQ=
|
||||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b/go.mod h1:3SAoF0F5EbcOuBD5WT9nYkbIJieBS84cUQXADbXeBsU=
|
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b/go.mod h1:3SAoF0F5EbcOuBD5WT9nYkbIJieBS84cUQXADbXeBsU=
|
||||||
github.com/Unknwon/goconfig v1.0.0 h1:9IAu/BYbSLQi8puFjUQApZTxIHqSwrj5d8vpP8vTq4A=
|
|
||||||
github.com/Unknwon/goconfig v1.0.0/go.mod h1:wngxua9XCNjvHjDiTiV26DaKDT+0c63QR6H5hjVUUxw=
|
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
@ -102,8 +100,6 @@ github.com/casbin/xorm-adapter/v3 v3.0.1 h1:0l0zkYxo6cNuIdrBZgFxlje1TRvmheYa/zIp
|
|||||||
github.com/casbin/xorm-adapter/v3 v3.0.1/go.mod h1:1BL7rHEDXrxO+vQdSo/ZaWKRivXl7YTos67GdMYcd20=
|
github.com/casbin/xorm-adapter/v3 v3.0.1/go.mod h1:1BL7rHEDXrxO+vQdSo/ZaWKRivXl7YTos67GdMYcd20=
|
||||||
github.com/casdoor/go-sms-sender v0.5.1 h1:1/Wp1OLkVAVY4lEGQhekSNetSAWhnPcxYPV7xpCZgC0=
|
github.com/casdoor/go-sms-sender v0.5.1 h1:1/Wp1OLkVAVY4lEGQhekSNetSAWhnPcxYPV7xpCZgC0=
|
||||||
github.com/casdoor/go-sms-sender v0.5.1/go.mod h1:kBykbqwgRDXbXdMAIxmZKinVM1WjdqEbej5LAbUbcfI=
|
github.com/casdoor/go-sms-sender v0.5.1/go.mod h1:kBykbqwgRDXbXdMAIxmZKinVM1WjdqEbej5LAbUbcfI=
|
||||||
github.com/casdoor/goth v1.69.0-FIX2 h1:RgfIMkL9kekylgxHHK2ZY8ASAwOGns2HVlaBwLu7Bcs=
|
|
||||||
github.com/casdoor/goth v1.69.0-FIX2/go.mod h1:Om55nRo8CkeDkPSNBbzXW4G5uI28ZUkSk5S69dPek3s=
|
|
||||||
github.com/casdoor/oss v1.2.0 h1:ozLAE+nnNdFQBWbzH8U9spzaO8h8NrB57lBcdyMUUQ8=
|
github.com/casdoor/oss v1.2.0 h1:ozLAE+nnNdFQBWbzH8U9spzaO8h8NrB57lBcdyMUUQ8=
|
||||||
github.com/casdoor/oss v1.2.0/go.mod h1:qii35VBuxnR/uEuYSKpS0aJ8htQFOcCVsZ4FHgHLuss=
|
github.com/casdoor/oss v1.2.0/go.mod h1:qii35VBuxnR/uEuYSKpS0aJ8htQFOcCVsZ4FHgHLuss=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
@ -127,6 +123,9 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f h1:q/DpyjJjZs94bziQ7YkBmIlpqbVP7yw179rnzoNVX1M=
|
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f h1:q/DpyjJjZs94bziQ7YkBmIlpqbVP7yw179rnzoNVX1M=
|
||||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWWHQYQ3QU9bw9Y9OPNfxccGzfb41qjvVeXtY=
|
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f/go.mod h1:QGrK8vMWWHQYQ3QU9bw9Y9OPNfxccGzfb41qjvVeXtY=
|
||||||
|
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||||
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d h1:1iy2qD6JEhHKKhUOA9IWs7mjco7lnw2qx8FsRI2wirE=
|
||||||
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg=
|
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||||
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b h1:L63RATZFZuFMXy6ixnKmv3eNAXwYQF6HW1vd4IYsQqQ=
|
github.com/duo-labs/webauthn v0.0.0-20211221191814-a22482edaa3b h1:L63RATZFZuFMXy6ixnKmv3eNAXwYQF6HW1vd4IYsQqQ=
|
||||||
@ -175,6 +174,8 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
|
|||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/goccy/go-json v0.9.6 h1:5/4CtRQdtsX0sal8fdVhTaiMN01Ri8BExZZ8iRmHQ6E=
|
||||||
|
github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||||
@ -213,8 +214,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
|||||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
|
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
|
||||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
@ -248,7 +250,6 @@ github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
|
|||||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
@ -282,7 +283,6 @@ github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr
|
|||||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
|
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
|
||||||
@ -301,8 +301,18 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
|
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
|
||||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
github.com/lestrrat-go/jwx v0.9.0 h1:Fnd0EWzTm0kFrBPzE/PEPp9nzllES5buMkksPMjEKpM=
|
github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=
|
||||||
github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/YNA/UnBk=
|
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
|
||||||
|
github.com/lestrrat-go/blackmagic v1.0.0 h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4=
|
||||||
|
github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
|
||||||
|
github.com/lestrrat-go/httpcc v1.0.0 h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc=
|
||||||
|
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
|
||||||
|
github.com/lestrrat-go/iter v1.0.1 h1:q8faalr2dY6o8bV45uwrxq12bRa1ezKrB6oM9FUgN4A=
|
||||||
|
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
|
||||||
|
github.com/lestrrat-go/jwx v1.2.21 h1:n+yG95UMm5ZFsDdvsZmui+bqat4Cj/di4ys6XbgSlE8=
|
||||||
|
github.com/lestrrat-go/jwx v1.2.21/go.mod h1:9cfxnOH7G1gN75CaJP2hKGcxFEx5sPh1abRIA/ZJVh4=
|
||||||
|
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4=
|
||||||
|
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
|
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
|
||||||
@ -311,6 +321,8 @@ github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 h1:wIONC+HMNRqmWBjuM
|
|||||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0=
|
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0=
|
||||||
github.com/markbates/going v1.0.0 h1:DQw0ZP7NbNlFGcKbcE/IVSOAFzScxRtLpd0rLMzLhq0=
|
github.com/markbates/going v1.0.0 h1:DQw0ZP7NbNlFGcKbcE/IVSOAFzScxRtLpd0rLMzLhq0=
|
||||||
github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA=
|
github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA=
|
||||||
|
github.com/markbates/goth v1.75.2 h1:C7KloBMMk50JyXaHhzfqWYLW6+bDcSVIvUGHXneLWro=
|
||||||
|
github.com/markbates/goth v1.75.2/go.mod h1:X6xdNgpapSENS0O35iTBBcMHoJDQDfI9bJl+APCkYMc=
|
||||||
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911 h1:erppMjjp69Rertg1zlgRbLJH1u+eCmRPxKjMZ5I8/Ro=
|
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911 h1:erppMjjp69Rertg1zlgRbLJH1u+eCmRPxKjMZ5I8/Ro=
|
||||||
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
|
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
|
||||||
github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI=
|
github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI=
|
||||||
@ -394,11 +406,10 @@ github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKz
|
|||||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||||
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
|
||||||
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
|
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
@ -462,8 +473,9 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP
|
|||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20220208233918-bba287dce954 h1:BkypuErRT9A9I/iljuaG3/zdMjd/J6m8tKKJQtGfSdA=
|
|
||||||
golang.org/x/crypto v0.0.0-20220208233918-bba287dce954/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220208233918-bba287dce954/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
||||||
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -527,7 +539,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
|
|||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200930145003-4acb6c075d10/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
@ -787,10 +798,11 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
|
|||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI=
|
|
||||||
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||||
|
xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
|
||||||
|
xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||||
xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw=
|
xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw=
|
||||||
xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM=
|
xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM=
|
||||||
xorm.io/xorm v1.0.3/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
xorm.io/xorm v1.0.3/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
||||||
xorm.io/xorm v1.0.4 h1:UBXA4I3NhiyjXfPqxXUkS2t5hMta9SSPATeMMaZg9oA=
|
xorm.io/xorm v1.0.5 h1:LRr5PfOUb4ODPR63YwbowkNDwcolT2LnkwP/TUaMaB0=
|
||||||
xorm.io/xorm v1.0.4/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
xorm.io/xorm v1.0.5/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
|
||||||
|
@ -83,7 +83,7 @@ func parseToData() *I18nData {
|
|||||||
|
|
||||||
data := I18nData{}
|
data := I18nData{}
|
||||||
for _, word := range allWords {
|
for _, word := range allWords {
|
||||||
tokens := strings.Split(word, ":")
|
tokens := strings.SplitN(word, ":", 2)
|
||||||
namespace := tokens[0]
|
namespace := tokens[0]
|
||||||
key := tokens[1]
|
key := tokens[1]
|
||||||
|
|
||||||
|
@ -15,13 +15,11 @@
|
|||||||
package i18n
|
package i18n
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Unknwon/goconfig"
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -43,7 +41,7 @@ func GetAllI18nStrings(fileContent string, path string) []string {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
for _, match := range matches {
|
for _, match := range matches {
|
||||||
match := strings.Split(match[1], ",")
|
match := strings.SplitN(match[1], ",", 2)
|
||||||
res = append(res, match[1][2:])
|
res = append(res, match[1][2:])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -84,39 +82,34 @@ func getAllGoFilePaths() []string {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func getErrName(paths []string) map[string]bool {
|
func getErrName(paths []string) map[string]string {
|
||||||
ErrName := make(map[string]bool)
|
ErrName := make(map[string]string)
|
||||||
for i := 0; i < len(paths); i++ {
|
for i := 0; i < len(paths); i++ {
|
||||||
content := util.ReadStringFromPath(paths[i])
|
content := util.ReadStringFromPath(paths[i])
|
||||||
words := GetAllI18nStrings(content, paths[i])
|
words := GetAllI18nStrings(content, paths[i])
|
||||||
for i := 0; i < len(words); i++ {
|
for j := 0; j < len(words); j++ {
|
||||||
ErrName[words[i]] = true
|
ErrName[words[j]] = paths[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ErrName
|
return ErrName
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeToAllLanguageFiles(errName map[string]bool) {
|
func getI18nJSONData(errName map[string]string) *I18nData {
|
||||||
languages := "en,zh,es,fr,de,ja,ko,ru"
|
data := I18nData{}
|
||||||
languageArr := strings.Split(languages, ",")
|
for k, v := range errName {
|
||||||
var c [10]*goconfig.ConfigFile
|
var index int
|
||||||
for i := 0; i < len(languageArr); i++ {
|
if strings.Contains(v, "/") {
|
||||||
var err error
|
index = strings.LastIndex(v, "/")
|
||||||
c[i], err = goconfig.LoadConfigFile("../i18n/languages/" + "locale_" + languageArr[i] + ".ini")
|
} else {
|
||||||
if err != nil {
|
index = strings.LastIndex(v, "\\")
|
||||||
log.Println(err.Error())
|
|
||||||
}
|
}
|
||||||
for j := range errName {
|
namespace := v[index+1 : len(v)-3]
|
||||||
parts := strings.Split(j, ".")
|
key := k[len(namespace)+1:]
|
||||||
_, err := c[i].GetValue(parts[0], parts[1])
|
// fmt.Printf("k=%s,v=%s,namespace=%s,key=%s\n", k, v, namespace, key)
|
||||||
if err != nil {
|
if _, ok := data[namespace]; !ok {
|
||||||
c[i].SetValue(parts[0], parts[1], parts[1])
|
data[namespace] = map[string]string{}
|
||||||
}
|
|
||||||
}
|
|
||||||
c[i].SetPrettyFormat(true)
|
|
||||||
err = goconfig.SaveConfigFile(c[i], "../i18n/languages/"+"locale_"+languageArr[i]+".ini")
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
}
|
||||||
|
data[namespace][key] = key
|
||||||
}
|
}
|
||||||
|
return &data
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,17 @@ func TestGenerateI18nStringsForBackend(t *testing.T) {
|
|||||||
|
|
||||||
errName := getErrName(paths)
|
errName := getErrName(paths)
|
||||||
|
|
||||||
writeToAllLanguageFiles(errName)
|
dataEn := getI18nJSONData(errName)
|
||||||
|
|
||||||
|
writeI18nFile("backend_en", dataEn)
|
||||||
|
|
||||||
|
applyToOtherLanguage(dataEn, "backend_de")
|
||||||
|
applyToOtherLanguage(dataEn, "backend_es")
|
||||||
|
applyToOtherLanguage(dataEn, "backend_fr")
|
||||||
|
applyToOtherLanguage(dataEn, "backend_ja")
|
||||||
|
applyToOtherLanguage(dataEn, "backend_ko")
|
||||||
|
applyToOtherLanguage(dataEn, "backend_ru")
|
||||||
|
applyToOtherLanguage(dataEn, "backend_zh")
|
||||||
|
|
||||||
fmt.Println("Total Err Words:", len(errName))
|
fmt.Println("Total Err Words:", len(errName))
|
||||||
|
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
[ApplicationErr]
|
|
||||||
AppNotFound = Application %s not found
|
|
||||||
AppNotFoundForUserID = No application is found for userId: %s
|
|
||||||
GrantTypeNotSupport = Grant_type: %s is not supported in this application
|
|
||||||
HasNoProviders = This application has no providers
|
|
||||||
HasNoProvidersOfType = This application has no providers of type
|
|
||||||
InvalidID = Invalid application id
|
|
||||||
|
|
||||||
[AuthErr]
|
|
||||||
AuthStateWrong = State expected: %s, but got: %s
|
|
||||||
ChallengeMethodErr = Challenge method should be S256
|
|
||||||
CanNotUnlinkUsers = You are not the global admin, you can't unlink other users
|
|
||||||
CanNotLinkMySelf = You can't unlink yourself, you are not a member of any application
|
|
||||||
CallWebAuthnSigninBegin = Please call WebAuthnSigninBegin first
|
|
||||||
NotHuman = Turing test failed.
|
|
||||||
Unauthorized = Unauthorized operation
|
|
||||||
WrongPasswordManyTimes = WrongPasswordManyTimes
|
|
||||||
|
|
||||||
[CasErr]
|
|
||||||
ServiceDoNotMatch = Service %s and %s do not match
|
|
||||||
|
|
||||||
[EmailErr]
|
|
||||||
ExistedErr = Email already exists
|
|
||||||
EmptyErr = Email cannot be empty
|
|
||||||
EmailInvalid = Email is invalid
|
|
||||||
EmailCheckResult = Email: %s
|
|
||||||
EmptyParam = Empty parameters for emailForm: %v
|
|
||||||
InvalidReceivers = Invalid Email receivers: %s
|
|
||||||
UnableGetModifyRule = Unable to get the email modify rule.
|
|
||||||
|
|
||||||
[EnforcerErr]
|
|
||||||
SignInFirst = Please sign in first
|
|
||||||
|
|
||||||
[InitErr]
|
|
||||||
InitScoreFailed = Get init score failed, error: %%w
|
|
||||||
|
|
||||||
[LdapErr]
|
|
||||||
MultipleAccounts = Multiple accounts with same uid, please check your ldap server
|
|
||||||
PasswordWrong = Ldap user name or password incorrect
|
|
||||||
ServerExisted = Ldap server exist
|
|
||||||
|
|
||||||
[LoginErr]
|
|
||||||
AppDoNotExist = The application: %s does not exist
|
|
||||||
AppNotEnableSignUp = 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
|
|
||||||
AccountDoNotExist = The account does not exist
|
|
||||||
InvalidUserInformation = Failed to create user, user information is invalid: %s
|
|
||||||
LoginFirst = Please login first
|
|
||||||
LoginFail = Failed to login in: %s
|
|
||||||
NoPermission = You don't have the permission to do this
|
|
||||||
OldUser = The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)
|
|
||||||
ProviderCanNotSignUp = 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
|
|
||||||
SessionOutdated = Session outdated, please login again
|
|
||||||
SignOutFirst = Please sign out first before signing in
|
|
||||||
UserDoNotExist = The user: %s/%s doesn't exist
|
|
||||||
UserIsForbidden = The user is forbidden to sign in, please contact the administrator
|
|
||||||
UnknownAuthentication = Unknown authentication type (not password or provider), form = %s
|
|
||||||
UnsupportedPasswordType = unsupported password type: %s
|
|
||||||
|
|
||||||
[OrgErr]
|
|
||||||
DoNotExist = Organization does not exist
|
|
||||||
Immutable = The %s is immutable.
|
|
||||||
OnlyAdmin = Only admin can modify the %s.
|
|
||||||
UnknownModifyRule = Unknown modify rule %s.
|
|
||||||
|
|
||||||
[ParameterErr]
|
|
||||||
OrgMissingErr = Parameter organization is missing
|
|
||||||
Missing = Missing parameter
|
|
||||||
UnknownType = Unknown type
|
|
||||||
Wrong = Wrong parameter
|
|
||||||
|
|
||||||
[PhoneErr]
|
|
||||||
CodeNotSent = Code has not been sent yet!
|
|
||||||
CodeTimeOut = You should verify your code in %d min!
|
|
||||||
ExistedErr = Phone already exists
|
|
||||||
EmptyErr = Phone cannot be empty
|
|
||||||
InvalidReceivers = Invalid phone receivers: %s
|
|
||||||
NumberInvalid = Phone number is invalid
|
|
||||||
NoPrefix = %s No phone prefix
|
|
||||||
PhoneCheckResult = Phone: %s
|
|
||||||
UnableGetModifyRule = Unable to get the phone modify rule.
|
|
||||||
|
|
||||||
[ProviderErr]
|
|
||||||
CanNotBeUnlinked = This provider can't be unlinked
|
|
||||||
CategoryNotSAML = provider %s's category is not SAML
|
|
||||||
DoNotExist = the provider: %s does not exist
|
|
||||||
InvalidProvider = Invalid captcha provider.
|
|
||||||
LinkFirstErr = Please link first
|
|
||||||
ProviderNotEnabled = The provider: %s is not enabled for the application
|
|
||||||
ProviderNotSupported = The provider type: %s is not supported
|
|
||||||
ProviderNotFound = The provider: %s is not found
|
|
||||||
ProviderNotFoundForCategory = No provider for category: %s is found for application: %s
|
|
||||||
|
|
||||||
[ResourceErr]
|
|
||||||
NotAuthorized = You are not authorized to access this resource
|
|
||||||
UserIsNil = User is nil for tag: /"avatar/"
|
|
||||||
UsernameOrFilePathEmpty = Username or fullFilePath is empty: username = %s, fullFilePath = %s
|
|
||||||
|
|
||||||
[SetPasswordErr]
|
|
||||||
CanNotContainBlank = New password cannot contain blank space.
|
|
||||||
LessThanSixCharacters = New password must have at least 6 characters
|
|
||||||
|
|
||||||
[SignUpErr]
|
|
||||||
DoNotAllowSignUp = The application does not allow to sign up new account
|
|
||||||
SignOutFirst = Please sign out first before signing up
|
|
||||||
|
|
||||||
[StorageErr]
|
|
||||||
ObjectKeyNotAllowed = The objectKey: %s is not allowed
|
|
||||||
|
|
||||||
[TokenErr]
|
|
||||||
EmptyClientID = Empty clientId or clientSecret
|
|
||||||
InvalidToken = Invalid token
|
|
||||||
InvalidAppOrWrongClientSecret = Invalid application or wrong clientSecret
|
|
||||||
InvalidClientId = Invalid client_id
|
|
||||||
RedirectURIDoNotExist = Redirect URI: %s doesn't exist in the allowed Redirect URI list
|
|
||||||
|
|
||||||
[UserErr]
|
|
||||||
AffiliationBlankErr = Affiliation cannot be blank
|
|
||||||
DisplayNameBlankErr = DisplayName cannot be blank
|
|
||||||
DisplayNameInvalid = DisplayName is not valid real name
|
|
||||||
DisplayNameCanNotBeEmpty = Display name cannot be empty
|
|
||||||
DoNotExist = The user: %s doesn't exist
|
|
||||||
DoNotExistInOrg = The user: %s/%s doesn't exist
|
|
||||||
DoNotExistSignUp = the user does not exist, please sign up first
|
|
||||||
FirstNameBlankErr = FirstName cannot be blank
|
|
||||||
FailToImportUsers = Failed to import users
|
|
||||||
LastNameBlankErr = LastName cannot be blank
|
|
||||||
NameLessThanTwoCharacters = Username must have at least 2 characters
|
|
||||||
NameStartWithADigitErr = Username cannot start with a digit
|
|
||||||
NameIsEmailErr = Username cannot be an email address
|
|
||||||
NameCantainWhitSpaceErr = Username cannot contain white spaces
|
|
||||||
NameExistedErr = Username already exists
|
|
||||||
NameEmptyErr = Empty username.
|
|
||||||
NameTooLang = Username is too long (maximum is 39 characters).
|
|
||||||
NameFormatErr = 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.
|
|
||||||
PasswordLessThanSixCharacters = Password must have at least 6 characters
|
|
||||||
InvalidInformation = Invalid information
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
|||||||
[ApplicationErr]
|
|
||||||
AppNotFound = Application %s not found
|
|
||||||
AppNotFoundForUserID = No application is found for userId: %s
|
|
||||||
GrantTypeNotSupport = Grant_type: %s is not supported in this application
|
|
||||||
HasNoProviders = This application has no providers
|
|
||||||
HasNoProvidersOfType = This application has no providers of type
|
|
||||||
InvalidID = Invalid application id
|
|
||||||
|
|
||||||
[AuthErr]
|
|
||||||
AuthStateWrong = State expected: %s, but got: %s
|
|
||||||
ChallengeMethodErr = Challenge method should be S256
|
|
||||||
CanNotUnlinkUsers = You are not the global admin, you can't unlink other users
|
|
||||||
CanNotLinkMySelf = You can't unlink yourself, you are not a member of any application
|
|
||||||
CallWebAuthnSigninBegin = Please call WebAuthnSigninBegin first
|
|
||||||
NotHuman = Turing test failed.
|
|
||||||
WrongPasswordManyTimes = You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again
|
|
||||||
Unauthorized = Unauthorized operation
|
|
||||||
|
|
||||||
[CasErr]
|
|
||||||
ServiceDoNotMatch = Service %s and %s do not match
|
|
||||||
|
|
||||||
[EmailErr]
|
|
||||||
ExistedErr = Email already exists
|
|
||||||
EmptyErr = Email cannot be empty
|
|
||||||
EmailInvalid = Email is invalid
|
|
||||||
EmailCheckResult = Email: %s
|
|
||||||
EmptyParam = Empty parameters for emailForm: %v
|
|
||||||
InvalidReceivers = Invalid Email receivers: %s
|
|
||||||
UnableGetModifyRule = Unable to get the email modify rule.
|
|
||||||
|
|
||||||
[EnforcerErr]
|
|
||||||
SignInFirst = Please sign in first
|
|
||||||
|
|
||||||
[InitErr]
|
|
||||||
InitScoreFailed = Get init score failed, error: %%w
|
|
||||||
|
|
||||||
[LdapErr]
|
|
||||||
MultipleAccounts = Multiple accounts with same uid, please check your ldap server
|
|
||||||
PasswordWrong = Ldap user name or password incorrect
|
|
||||||
ServerExisted = Ldap server exist
|
|
||||||
|
|
||||||
[LoginErr]
|
|
||||||
AppDoNotExist = The application: %s does not exist
|
|
||||||
AppNotEnableSignUp = 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
|
|
||||||
AccountDoNotExist = The account does not exist
|
|
||||||
InvalidUserInformation = Failed to create user, user information is invalid: %s
|
|
||||||
LoginFirst = Please login first
|
|
||||||
LoginFail = Failed to login in: %s
|
|
||||||
NoPermission = You don't have the permission to do this
|
|
||||||
OldUser = The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)
|
|
||||||
ProviderCanNotSignUp = 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
|
|
||||||
SessionOutdated = Session outdated, please login again
|
|
||||||
SignOutFirst = Please sign out first before signing in
|
|
||||||
UserDoNotExist = The user: %s/%s doesn't exist
|
|
||||||
UserIsForbidden = The user is forbidden to sign in, please contact the administrator
|
|
||||||
UnknownAuthentication = Unknown authentication type (not password or provider), form = %s
|
|
||||||
UnsupportedPasswordType = unsupported password type: %s
|
|
||||||
|
|
||||||
[OrgErr]
|
|
||||||
DoNotExist = Organization does not exist
|
|
||||||
Immutable = The %s is immutable.
|
|
||||||
OnlyAdmin = Only admin can modify the %s.
|
|
||||||
UnknownModifyRule = Unknown modify rule %s.
|
|
||||||
|
|
||||||
[ParameterErr]
|
|
||||||
OrgMissingErr = Parameter organization is missing
|
|
||||||
Missing = Missing parameter
|
|
||||||
UnknownType = Unknown type
|
|
||||||
Wrong = Wrong parameter
|
|
||||||
|
|
||||||
[PhoneErr]
|
|
||||||
CodeNotSent = Code has not been sent yet!
|
|
||||||
CodeTimeOut = You should verify your code in %d min!
|
|
||||||
ExistedErr = Phone already exists
|
|
||||||
EmptyErr = Phone cannot be empty
|
|
||||||
InvalidReceivers = Invalid phone receivers: %s
|
|
||||||
NumberInvalid = Phone number is invalid
|
|
||||||
NoPrefix = %s No phone prefix
|
|
||||||
PhoneCheckResult = Phone: %s
|
|
||||||
UnableGetModifyRule = Unable to get the phone modify rule.
|
|
||||||
|
|
||||||
[ProviderErr]
|
|
||||||
CanNotBeUnlinked = This provider can't be unlinked
|
|
||||||
CategoryNotSAML = provider %s's category is not SAML
|
|
||||||
DoNotExist = the provider: %s does not exist
|
|
||||||
InvalidProvider = Invalid captcha provider.
|
|
||||||
LinkFirstErr = Please link first
|
|
||||||
ProviderNotEnabled = The provider: %s is not enabled for the application
|
|
||||||
ProviderNotSupported = The provider type: %s is not supported
|
|
||||||
ProviderNotFound = The provider: %s is not found
|
|
||||||
ProviderNotFoundForCategory = No provider for category: %s is found for application: %s
|
|
||||||
|
|
||||||
[ResourceErr]
|
|
||||||
NotAuthorized = You are not authorized to access this resource
|
|
||||||
UserIsNil = User is nil for tag: /"avatar/"
|
|
||||||
UsernameOrFilePathEmpty = Username or fullFilePath is empty: username = %s, fullFilePath = %s
|
|
||||||
|
|
||||||
[SetPasswordErr]
|
|
||||||
CanNotContainBlank = New password cannot contain blank space.
|
|
||||||
LessThanSixCharacters = New password must have at least 6 characters
|
|
||||||
|
|
||||||
[SignUpErr]
|
|
||||||
DoNotAllowSignUp = The application does not allow to sign up new account
|
|
||||||
SignOutFirst = Please sign out first before signing up
|
|
||||||
|
|
||||||
[StorageErr]
|
|
||||||
ObjectKeyNotAllowed = The objectKey: %s is not allowed
|
|
||||||
|
|
||||||
[TokenErr]
|
|
||||||
EmptyClientID = Empty clientId or clientSecret
|
|
||||||
InvalidToken = Invalid token
|
|
||||||
InvalidAppOrWrongClientSecret = Invalid application or wrong clientSecret
|
|
||||||
InvalidClientId = Invalid client_id
|
|
||||||
RedirectURIDoNotExist = Redirect URI: %s doesn't exist in the allowed Redirect URI list
|
|
||||||
|
|
||||||
[UserErr]
|
|
||||||
AffiliationBlankErr = Affiliation cannot be blank
|
|
||||||
DisplayNameBlankErr = DisplayName cannot be blank
|
|
||||||
DisplayNameInvalid = DisplayName is not valid real name
|
|
||||||
DisplayNameCanNotBeEmpty = Display name cannot be empty
|
|
||||||
DoNotExist = The user: %s doesn't exist
|
|
||||||
DoNotExistInOrg = The user: %s/%s doesn't exist
|
|
||||||
DoNotExistSignUp = the user does not exist, please sign up first
|
|
||||||
FirstNameBlankErr = FirstName cannot be blank
|
|
||||||
FailToImportUsers = Failed to import users
|
|
||||||
LastNameBlankErr = LastName cannot be blank
|
|
||||||
NameLessThanTwoCharacters = Username must have at least 2 characters
|
|
||||||
NameStartWithADigitErr = Username cannot start with a digit
|
|
||||||
NameIsEmailErr = Username cannot be an email address
|
|
||||||
NameCantainWhitSpaceErr = Username cannot contain white spaces
|
|
||||||
NameExistedErr = Username already exists
|
|
||||||
NameEmptyErr = Empty username.
|
|
||||||
NameTooLang = Username is too long (maximum is 39 characters).
|
|
||||||
NameFormatErr = 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.
|
|
||||||
PasswordLessThanSixCharacters = Password must have at least 6 characters
|
|
||||||
InvalidInformation = Invalid information
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
|||||||
[ApplicationErr]
|
|
||||||
AppNotFound = Application %s not found
|
|
||||||
AppNotFoundForUserID = No application is found for userId: %s
|
|
||||||
GrantTypeNotSupport = Grant_type: %s is not supported in this application
|
|
||||||
HasNoProviders = This application has no providers
|
|
||||||
HasNoProvidersOfType = This application has no providers of type
|
|
||||||
InvalidID = Invalid application id
|
|
||||||
|
|
||||||
[AuthErr]
|
|
||||||
AuthStateWrong = State expected: %s, but got: %s
|
|
||||||
ChallengeMethodErr = Challenge method should be S256
|
|
||||||
CanNotUnlinkUsers = You are not the global admin, you can't unlink other users
|
|
||||||
CanNotLinkMySelf = You can't unlink yourself, you are not a member of any application
|
|
||||||
CallWebAuthnSigninBegin = Please call WebAuthnSigninBegin first
|
|
||||||
NotHuman = Turing test failed.
|
|
||||||
Unauthorized = Unauthorized operation
|
|
||||||
WrongPasswordManyTimes = WrongPasswordManyTimes
|
|
||||||
|
|
||||||
[CasErr]
|
|
||||||
ServiceDoNotMatch = Service %s and %s do not match
|
|
||||||
|
|
||||||
[EmailErr]
|
|
||||||
ExistedErr = Email already exists
|
|
||||||
EmptyErr = Email cannot be empty
|
|
||||||
EmailInvalid = Email is invalid
|
|
||||||
EmailCheckResult = Email: %s
|
|
||||||
EmptyParam = Empty parameters for emailForm: %v
|
|
||||||
InvalidReceivers = Invalid Email receivers: %s
|
|
||||||
UnableGetModifyRule = Unable to get the email modify rule.
|
|
||||||
|
|
||||||
[EnforcerErr]
|
|
||||||
SignInFirst = Please sign in first
|
|
||||||
|
|
||||||
[InitErr]
|
|
||||||
InitScoreFailed = Get init score failed, error: %%w
|
|
||||||
|
|
||||||
[LdapErr]
|
|
||||||
MultipleAccounts = Multiple accounts with same uid, please check your ldap server
|
|
||||||
PasswordWrong = Ldap user name or password incorrect
|
|
||||||
ServerExisted = Ldap server exist
|
|
||||||
|
|
||||||
[LoginErr]
|
|
||||||
AppDoNotExist = The application: %s does not exist
|
|
||||||
AppNotEnableSignUp = 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
|
|
||||||
AccountDoNotExist = The account does not exist
|
|
||||||
InvalidUserInformation = Failed to create user, user information is invalid: %s
|
|
||||||
LoginFirst = Please login first
|
|
||||||
LoginFail = Failed to login in: %s
|
|
||||||
NoPermission = You don't have the permission to do this
|
|
||||||
OldUser = The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)
|
|
||||||
ProviderCanNotSignUp = 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
|
|
||||||
SessionOutdated = Session outdated, please login again
|
|
||||||
SignOutFirst = Please sign out first before signing in
|
|
||||||
UserDoNotExist = The user: %s/%s doesn't exist
|
|
||||||
UserIsForbidden = The user is forbidden to sign in, please contact the administrator
|
|
||||||
UnknownAuthentication = Unknown authentication type (not password or provider), form = %s
|
|
||||||
UnsupportedPasswordType = unsupported password type: %s
|
|
||||||
|
|
||||||
[OrgErr]
|
|
||||||
DoNotExist = Organization does not exist
|
|
||||||
Immutable = The %s is immutable.
|
|
||||||
OnlyAdmin = Only admin can modify the %s.
|
|
||||||
UnknownModifyRule = Unknown modify rule %s.
|
|
||||||
|
|
||||||
[ParameterErr]
|
|
||||||
OrgMissingErr = Parameter organization is missing
|
|
||||||
Missing = Missing parameter
|
|
||||||
UnknownType = Unknown type
|
|
||||||
Wrong = Wrong parameter
|
|
||||||
|
|
||||||
[PhoneErr]
|
|
||||||
CodeNotSent = Code has not been sent yet!
|
|
||||||
CodeTimeOut = You should verify your code in %d min!
|
|
||||||
ExistedErr = Phone already exists
|
|
||||||
EmptyErr = Phone cannot be empty
|
|
||||||
InvalidReceivers = Invalid phone receivers: %s
|
|
||||||
NumberInvalid = Phone number is invalid
|
|
||||||
NoPrefix = %s No phone prefix
|
|
||||||
PhoneCheckResult = Phone: %s
|
|
||||||
UnableGetModifyRule = Unable to get the phone modify rule.
|
|
||||||
|
|
||||||
[ProviderErr]
|
|
||||||
CanNotBeUnlinked = This provider can't be unlinked
|
|
||||||
CategoryNotSAML = provider %s's category is not SAML
|
|
||||||
DoNotExist = the provider: %s does not exist
|
|
||||||
InvalidProvider = Invalid captcha provider.
|
|
||||||
LinkFirstErr = Please link first
|
|
||||||
ProviderNotEnabled = The provider: %s is not enabled for the application
|
|
||||||
ProviderNotSupported = The provider type: %s is not supported
|
|
||||||
ProviderNotFound = The provider: %s is not found
|
|
||||||
ProviderNotFoundForCategory = No provider for category: %s is found for application: %s
|
|
||||||
|
|
||||||
[ResourceErr]
|
|
||||||
NotAuthorized = You are not authorized to access this resource
|
|
||||||
UserIsNil = User is nil for tag: /"avatar/"
|
|
||||||
UsernameOrFilePathEmpty = Username or fullFilePath is empty: username = %s, fullFilePath = %s
|
|
||||||
|
|
||||||
[SetPasswordErr]
|
|
||||||
CanNotContainBlank = New password cannot contain blank space.
|
|
||||||
LessThanSixCharacters = New password must have at least 6 characters
|
|
||||||
|
|
||||||
[SignUpErr]
|
|
||||||
DoNotAllowSignUp = The application does not allow to sign up new account
|
|
||||||
SignOutFirst = Please sign out first before signing up
|
|
||||||
|
|
||||||
[StorageErr]
|
|
||||||
ObjectKeyNotAllowed = The objectKey: %s is not allowed
|
|
||||||
|
|
||||||
[TokenErr]
|
|
||||||
EmptyClientID = Empty clientId or clientSecret
|
|
||||||
InvalidToken = Invalid token
|
|
||||||
InvalidAppOrWrongClientSecret = Invalid application or wrong clientSecret
|
|
||||||
InvalidClientId = Invalid client_id
|
|
||||||
RedirectURIDoNotExist = Redirect URI: %s doesn't exist in the allowed Redirect URI list
|
|
||||||
|
|
||||||
[UserErr]
|
|
||||||
AffiliationBlankErr = Affiliation cannot be blank
|
|
||||||
DisplayNameBlankErr = DisplayName cannot be blank
|
|
||||||
DisplayNameInvalid = DisplayName is not valid real name
|
|
||||||
DisplayNameCanNotBeEmpty = Display name cannot be empty
|
|
||||||
DoNotExist = The user: %s doesn't exist
|
|
||||||
DoNotExistInOrg = The user: %s/%s doesn't exist
|
|
||||||
DoNotExistSignUp = the user does not exist, please sign up first
|
|
||||||
FirstNameBlankErr = FirstName cannot be blank
|
|
||||||
FailToImportUsers = Failed to import users
|
|
||||||
LastNameBlankErr = LastName cannot be blank
|
|
||||||
NameLessThanTwoCharacters = Username must have at least 2 characters
|
|
||||||
NameStartWithADigitErr = Username cannot start with a digit
|
|
||||||
NameIsEmailErr = Username cannot be an email address
|
|
||||||
NameCantainWhitSpaceErr = Username cannot contain white spaces
|
|
||||||
NameExistedErr = Username already exists
|
|
||||||
NameEmptyErr = Empty username.
|
|
||||||
NameTooLang = Username is too long (maximum is 39 characters).
|
|
||||||
NameFormatErr = 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.
|
|
||||||
PasswordLessThanSixCharacters = Password must have at least 6 characters
|
|
||||||
InvalidInformation = Invalid information
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
|||||||
[ApplicationErr]
|
|
||||||
AppNotFound = Application %s not found
|
|
||||||
AppNotFoundForUserID = No application is found for userId: %s
|
|
||||||
GrantTypeNotSupport = Grant_type: %s is not supported in this application
|
|
||||||
HasNoProviders = This application has no providers
|
|
||||||
HasNoProvidersOfType = This application has no providers of type
|
|
||||||
InvalidID = Invalid application id
|
|
||||||
|
|
||||||
[AuthErr]
|
|
||||||
AuthStateWrong = State expected: %s, but got: %s
|
|
||||||
ChallengeMethodErr = Challenge method should be S256
|
|
||||||
CanNotUnlinkUsers = You are not the global admin, you can't unlink other users
|
|
||||||
CanNotLinkMySelf = You can't unlink yourself, you are not a member of any application
|
|
||||||
CallWebAuthnSigninBegin = Please call WebAuthnSigninBegin first
|
|
||||||
NotHuman = Turing test failed.
|
|
||||||
Unauthorized = Unauthorized operation
|
|
||||||
WrongPasswordManyTimes = WrongPasswordManyTimes
|
|
||||||
|
|
||||||
[CasErr]
|
|
||||||
ServiceDoNotMatch = Service %s and %s do not match
|
|
||||||
|
|
||||||
[EmailErr]
|
|
||||||
ExistedErr = Email already exists
|
|
||||||
EmptyErr = Email cannot be empty
|
|
||||||
EmailInvalid = Email is invalid
|
|
||||||
EmailCheckResult = Email: %s
|
|
||||||
EmptyParam = Empty parameters for emailForm: %v
|
|
||||||
InvalidReceivers = Invalid Email receivers: %s
|
|
||||||
UnableGetModifyRule = Unable to get the email modify rule.
|
|
||||||
|
|
||||||
[EnforcerErr]
|
|
||||||
SignInFirst = Please sign in first
|
|
||||||
|
|
||||||
[InitErr]
|
|
||||||
InitScoreFailed = Get init score failed, error: %%w
|
|
||||||
|
|
||||||
[LdapErr]
|
|
||||||
MultipleAccounts = Multiple accounts with same uid, please check your ldap server
|
|
||||||
PasswordWrong = Ldap user name or password incorrect
|
|
||||||
ServerExisted = Ldap server exist
|
|
||||||
|
|
||||||
[LoginErr]
|
|
||||||
AppDoNotExist = The application: %s does not exist
|
|
||||||
AppNotEnableSignUp = 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
|
|
||||||
AccountDoNotExist = The account does not exist
|
|
||||||
InvalidUserInformation = Failed to create user, user information is invalid: %s
|
|
||||||
LoginFirst = Please login first
|
|
||||||
LoginFail = Failed to login in: %s
|
|
||||||
NoPermission = You don't have the permission to do this
|
|
||||||
OldUser = The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)
|
|
||||||
ProviderCanNotSignUp = 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
|
|
||||||
SessionOutdated = Session outdated, please login again
|
|
||||||
SignOutFirst = Please sign out first before signing in
|
|
||||||
UserDoNotExist = The user: %s/%s doesn't exist
|
|
||||||
UserIsForbidden = The user is forbidden to sign in, please contact the administrator
|
|
||||||
UnknownAuthentication = Unknown authentication type (not password or provider), form = %s
|
|
||||||
UnsupportedPasswordType = unsupported password type: %s
|
|
||||||
|
|
||||||
[OrgErr]
|
|
||||||
DoNotExist = Organization does not exist
|
|
||||||
Immutable = The %s is immutable.
|
|
||||||
OnlyAdmin = Only admin can modify the %s.
|
|
||||||
UnknownModifyRule = Unknown modify rule %s.
|
|
||||||
|
|
||||||
[ParameterErr]
|
|
||||||
OrgMissingErr = Parameter organization is missing
|
|
||||||
Missing = Missing parameter
|
|
||||||
UnknownType = Unknown type
|
|
||||||
Wrong = Wrong parameter
|
|
||||||
|
|
||||||
[PhoneErr]
|
|
||||||
CodeNotSent = Code has not been sent yet!
|
|
||||||
CodeTimeOut = You should verify your code in %d min!
|
|
||||||
ExistedErr = Phone already exists
|
|
||||||
EmptyErr = Phone cannot be empty
|
|
||||||
InvalidReceivers = Invalid phone receivers: %s
|
|
||||||
NumberInvalid = Phone number is invalid
|
|
||||||
NoPrefix = %s No phone prefix
|
|
||||||
PhoneCheckResult = Phone: %s
|
|
||||||
UnableGetModifyRule = Unable to get the phone modify rule.
|
|
||||||
|
|
||||||
[ProviderErr]
|
|
||||||
CanNotBeUnlinked = This provider can't be unlinked
|
|
||||||
CategoryNotSAML = provider %s's category is not SAML
|
|
||||||
DoNotExist = the provider: %s does not exist
|
|
||||||
InvalidProvider = Invalid captcha provider.
|
|
||||||
LinkFirstErr = Please link first
|
|
||||||
ProviderNotEnabled = The provider: %s is not enabled for the application
|
|
||||||
ProviderNotSupported = The provider type: %s is not supported
|
|
||||||
ProviderNotFound = The provider: %s is not found
|
|
||||||
ProviderNotFoundForCategory = No provider for category: %s is found for application: %s
|
|
||||||
|
|
||||||
[ResourceErr]
|
|
||||||
NotAuthorized = You are not authorized to access this resource
|
|
||||||
UserIsNil = User is nil for tag: /"avatar/"
|
|
||||||
UsernameOrFilePathEmpty = Username or fullFilePath is empty: username = %s, fullFilePath = %s
|
|
||||||
|
|
||||||
[SetPasswordErr]
|
|
||||||
CanNotContainBlank = New password cannot contain blank space.
|
|
||||||
LessThanSixCharacters = New password must have at least 6 characters
|
|
||||||
|
|
||||||
[SignUpErr]
|
|
||||||
DoNotAllowSignUp = The application does not allow to sign up new account
|
|
||||||
SignOutFirst = Please sign out first before signing up
|
|
||||||
|
|
||||||
[StorageErr]
|
|
||||||
ObjectKeyNotAllowed = The objectKey: %s is not allowed
|
|
||||||
|
|
||||||
[TokenErr]
|
|
||||||
EmptyClientID = Empty clientId or clientSecret
|
|
||||||
InvalidToken = Invalid token
|
|
||||||
InvalidAppOrWrongClientSecret = Invalid application or wrong clientSecret
|
|
||||||
InvalidClientId = Invalid client_id
|
|
||||||
RedirectURIDoNotExist = Redirect URI: %s doesn't exist in the allowed Redirect URI list
|
|
||||||
|
|
||||||
[UserErr]
|
|
||||||
AffiliationBlankErr = Affiliation cannot be blank
|
|
||||||
DisplayNameBlankErr = DisplayName cannot be blank
|
|
||||||
DisplayNameInvalid = DisplayName is not valid real name
|
|
||||||
DisplayNameCanNotBeEmpty = Display name cannot be empty
|
|
||||||
DoNotExist = The user: %s doesn't exist
|
|
||||||
DoNotExistInOrg = The user: %s/%s doesn't exist
|
|
||||||
DoNotExistSignUp = the user does not exist, please sign up first
|
|
||||||
FirstNameBlankErr = FirstName cannot be blank
|
|
||||||
FailToImportUsers = Failed to import users
|
|
||||||
LastNameBlankErr = LastName cannot be blank
|
|
||||||
NameLessThanTwoCharacters = Username must have at least 2 characters
|
|
||||||
NameStartWithADigitErr = Username cannot start with a digit
|
|
||||||
NameIsEmailErr = Username cannot be an email address
|
|
||||||
NameCantainWhitSpaceErr = Username cannot contain white spaces
|
|
||||||
NameExistedErr = Username already exists
|
|
||||||
NameEmptyErr = Empty username.
|
|
||||||
NameTooLang = Username is too long (maximum is 39 characters).
|
|
||||||
NameFormatErr = 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.
|
|
||||||
PasswordLessThanSixCharacters = Password must have at least 6 characters
|
|
||||||
InvalidInformation = Invalid information
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
|||||||
[ApplicationErr]
|
|
||||||
AppNotFound = Application %s not found
|
|
||||||
AppNotFoundForUserID = No application is found for userId: %s
|
|
||||||
GrantTypeNotSupport = Grant_type: %s is not supported in this application
|
|
||||||
HasNoProviders = This application has no providers
|
|
||||||
HasNoProvidersOfType = This application has no providers of type
|
|
||||||
InvalidID = Invalid application id
|
|
||||||
|
|
||||||
[AuthErr]
|
|
||||||
AuthStateWrong = State expected: %s, but got: %s
|
|
||||||
ChallengeMethodErr = Challenge method should be S256
|
|
||||||
CanNotUnlinkUsers = You are not the global admin, you can't unlink other users
|
|
||||||
CanNotLinkMySelf = You can't unlink yourself, you are not a member of any application
|
|
||||||
CallWebAuthnSigninBegin = Please call WebAuthnSigninBegin first
|
|
||||||
NotHuman = Turing test failed.
|
|
||||||
Unauthorized = Unauthorized operation
|
|
||||||
WrongPasswordManyTimes = WrongPasswordManyTimes
|
|
||||||
|
|
||||||
[CasErr]
|
|
||||||
ServiceDoNotMatch = Service %s and %s do not match
|
|
||||||
|
|
||||||
[EmailErr]
|
|
||||||
ExistedErr = Email already exists
|
|
||||||
EmptyErr = Email cannot be empty
|
|
||||||
EmailInvalid = Email is invalid
|
|
||||||
EmailCheckResult = Email: %s
|
|
||||||
EmptyParam = Empty parameters for emailForm: %v
|
|
||||||
InvalidReceivers = Invalid Email receivers: %s
|
|
||||||
UnableGetModifyRule = Unable to get the email modify rule.
|
|
||||||
|
|
||||||
[EnforcerErr]
|
|
||||||
SignInFirst = Please sign in first
|
|
||||||
|
|
||||||
[InitErr]
|
|
||||||
InitScoreFailed = Get init score failed, error: %%w
|
|
||||||
|
|
||||||
[LdapErr]
|
|
||||||
MultipleAccounts = Multiple accounts with same uid, please check your ldap server
|
|
||||||
PasswordWrong = Ldap user name or password incorrect
|
|
||||||
ServerExisted = Ldap server exist
|
|
||||||
|
|
||||||
[LoginErr]
|
|
||||||
AppDoNotExist = The application: %s does not exist
|
|
||||||
AppNotEnableSignUp = 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
|
|
||||||
AccountDoNotExist = The account does not exist
|
|
||||||
InvalidUserInformation = Failed to create user, user information is invalid: %s
|
|
||||||
LoginFirst = Please login first
|
|
||||||
LoginFail = Failed to login in: %s
|
|
||||||
NoPermission = You don't have the permission to do this
|
|
||||||
OldUser = The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)
|
|
||||||
ProviderCanNotSignUp = 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
|
|
||||||
SessionOutdated = Session outdated, please login again
|
|
||||||
SignOutFirst = Please sign out first before signing in
|
|
||||||
UserDoNotExist = The user: %s/%s doesn't exist
|
|
||||||
UserIsForbidden = The user is forbidden to sign in, please contact the administrator
|
|
||||||
UnknownAuthentication = Unknown authentication type (not password or provider), form = %s
|
|
||||||
UnsupportedPasswordType = unsupported password type: %s
|
|
||||||
|
|
||||||
[OrgErr]
|
|
||||||
DoNotExist = Organization does not exist
|
|
||||||
Immutable = The %s is immutable.
|
|
||||||
OnlyAdmin = Only admin can modify the %s.
|
|
||||||
UnknownModifyRule = Unknown modify rule %s.
|
|
||||||
|
|
||||||
[ParameterErr]
|
|
||||||
OrgMissingErr = Parameter organization is missing
|
|
||||||
Missing = Missing parameter
|
|
||||||
UnknownType = Unknown type
|
|
||||||
Wrong = Wrong parameter
|
|
||||||
|
|
||||||
[PhoneErr]
|
|
||||||
CodeNotSent = Code has not been sent yet!
|
|
||||||
CodeTimeOut = You should verify your code in %d min!
|
|
||||||
ExistedErr = Phone already exists
|
|
||||||
EmptyErr = Phone cannot be empty
|
|
||||||
InvalidReceivers = Invalid phone receivers: %s
|
|
||||||
NumberInvalid = Phone number is invalid
|
|
||||||
NoPrefix = %s No phone prefix
|
|
||||||
PhoneCheckResult = Phone: %s
|
|
||||||
UnableGetModifyRule = Unable to get the phone modify rule.
|
|
||||||
|
|
||||||
[ProviderErr]
|
|
||||||
CanNotBeUnlinked = This provider can't be unlinked
|
|
||||||
CategoryNotSAML = provider %s's category is not SAML
|
|
||||||
DoNotExist = the provider: %s does not exist
|
|
||||||
InvalidProvider = Invalid captcha provider.
|
|
||||||
LinkFirstErr = Please link first
|
|
||||||
ProviderNotEnabled = The provider: %s is not enabled for the application
|
|
||||||
ProviderNotSupported = The provider type: %s is not supported
|
|
||||||
ProviderNotFound = The provider: %s is not found
|
|
||||||
ProviderNotFoundForCategory = No provider for category: %s is found for application: %s
|
|
||||||
|
|
||||||
[ResourceErr]
|
|
||||||
NotAuthorized = You are not authorized to access this resource
|
|
||||||
UserIsNil = User is nil for tag: /"avatar/"
|
|
||||||
UsernameOrFilePathEmpty = Username or fullFilePath is empty: username = %s, fullFilePath = %s
|
|
||||||
|
|
||||||
[SetPasswordErr]
|
|
||||||
CanNotContainBlank = New password cannot contain blank space.
|
|
||||||
LessThanSixCharacters = New password must have at least 6 characters
|
|
||||||
|
|
||||||
[SignUpErr]
|
|
||||||
DoNotAllowSignUp = The application does not allow to sign up new account
|
|
||||||
SignOutFirst = Please sign out first before signing up
|
|
||||||
|
|
||||||
[StorageErr]
|
|
||||||
ObjectKeyNotAllowed = The objectKey: %s is not allowed
|
|
||||||
|
|
||||||
[TokenErr]
|
|
||||||
EmptyClientID = Empty clientId or clientSecret
|
|
||||||
InvalidToken = Invalid token
|
|
||||||
InvalidAppOrWrongClientSecret = Invalid application or wrong clientSecret
|
|
||||||
InvalidClientId = Invalid client_id
|
|
||||||
RedirectURIDoNotExist = Redirect URI: %s doesn't exist in the allowed Redirect URI list
|
|
||||||
|
|
||||||
[UserErr]
|
|
||||||
AffiliationBlankErr = Affiliation cannot be blank
|
|
||||||
DisplayNameBlankErr = DisplayName cannot be blank
|
|
||||||
DisplayNameInvalid = DisplayName is not valid real name
|
|
||||||
DisplayNameCanNotBeEmpty = Display name cannot be empty
|
|
||||||
DoNotExist = The user: %s doesn't exist
|
|
||||||
DoNotExistInOrg = The user: %s/%s doesn't exist
|
|
||||||
DoNotExistSignUp = the user does not exist, please sign up first
|
|
||||||
FirstNameBlankErr = FirstName cannot be blank
|
|
||||||
FailToImportUsers = Failed to import users
|
|
||||||
LastNameBlankErr = LastName cannot be blank
|
|
||||||
NameLessThanTwoCharacters = Username must have at least 2 characters
|
|
||||||
NameStartWithADigitErr = Username cannot start with a digit
|
|
||||||
NameIsEmailErr = Username cannot be an email address
|
|
||||||
NameCantainWhitSpaceErr = Username cannot contain white spaces
|
|
||||||
NameExistedErr = Username already exists
|
|
||||||
NameEmptyErr = Empty username.
|
|
||||||
NameTooLang = Username is too long (maximum is 39 characters).
|
|
||||||
NameFormatErr = 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.
|
|
||||||
PasswordLessThanSixCharacters = Password must have at least 6 characters
|
|
||||||
InvalidInformation = Invalid information
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
|||||||
[ApplicationErr]
|
|
||||||
AppNotFound = Application %s not found
|
|
||||||
AppNotFoundForUserID = No application is found for userId: %s
|
|
||||||
GrantTypeNotSupport = Grant_type: %s is not supported in this application
|
|
||||||
HasNoProviders = This application has no providers
|
|
||||||
HasNoProvidersOfType = This application has no providers of type
|
|
||||||
InvalidID = Invalid application id
|
|
||||||
|
|
||||||
[AuthErr]
|
|
||||||
AuthStateWrong = State expected: %s, but got: %s
|
|
||||||
ChallengeMethodErr = Challenge method should be S256
|
|
||||||
CanNotUnlinkUsers = You are not the global admin, you can't unlink other users
|
|
||||||
CanNotLinkMySelf = You can't unlink yourself, you are not a member of any application
|
|
||||||
CallWebAuthnSigninBegin = Please call WebAuthnSigninBegin first
|
|
||||||
NotHuman = Turing test failed.
|
|
||||||
Unauthorized = Unauthorized operation
|
|
||||||
WrongPasswordManyTimes = WrongPasswordManyTimes
|
|
||||||
|
|
||||||
[CasErr]
|
|
||||||
ServiceDoNotMatch = Service %s and %s do not match
|
|
||||||
|
|
||||||
[EmailErr]
|
|
||||||
ExistedErr = Email already exists
|
|
||||||
EmptyErr = Email cannot be empty
|
|
||||||
EmailInvalid = Email is invalid
|
|
||||||
EmailCheckResult = Email: %s
|
|
||||||
EmptyParam = Empty parameters for emailForm: %v
|
|
||||||
InvalidReceivers = Invalid Email receivers: %s
|
|
||||||
UnableGetModifyRule = Unable to get the email modify rule.
|
|
||||||
|
|
||||||
[EnforcerErr]
|
|
||||||
SignInFirst = Please sign in first
|
|
||||||
|
|
||||||
[InitErr]
|
|
||||||
InitScoreFailed = Get init score failed, error: %%w
|
|
||||||
|
|
||||||
[LdapErr]
|
|
||||||
MultipleAccounts = Multiple accounts with same uid, please check your ldap server
|
|
||||||
PasswordWrong = Ldap user name or password incorrect
|
|
||||||
ServerExisted = Ldap server exist
|
|
||||||
|
|
||||||
[LoginErr]
|
|
||||||
AppDoNotExist = The application: %s does not exist
|
|
||||||
AppNotEnableSignUp = 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
|
|
||||||
AccountDoNotExist = The account does not exist
|
|
||||||
InvalidUserInformation = Failed to create user, user information is invalid: %s
|
|
||||||
LoginFirst = Please login first
|
|
||||||
LoginFail = Failed to login in: %s
|
|
||||||
NoPermission = You don't have the permission to do this
|
|
||||||
OldUser = The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)
|
|
||||||
ProviderCanNotSignUp = 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
|
|
||||||
SessionOutdated = Session outdated, please login again
|
|
||||||
SignOutFirst = Please sign out first before signing in
|
|
||||||
UserDoNotExist = The user: %s/%s doesn't exist
|
|
||||||
UserIsForbidden = The user is forbidden to sign in, please contact the administrator
|
|
||||||
UnknownAuthentication = Unknown authentication type (not password or provider), form = %s
|
|
||||||
UnsupportedPasswordType = unsupported password type: %s
|
|
||||||
|
|
||||||
[OrgErr]
|
|
||||||
DoNotExist = Organization does not exist
|
|
||||||
Immutable = The %s is immutable.
|
|
||||||
OnlyAdmin = Only admin can modify the %s.
|
|
||||||
UnknownModifyRule = Unknown modify rule %s.
|
|
||||||
|
|
||||||
[ParameterErr]
|
|
||||||
OrgMissingErr = Parameter organization is missing
|
|
||||||
Missing = Missing parameter
|
|
||||||
UnknownType = Unknown type
|
|
||||||
Wrong = Wrong parameter
|
|
||||||
|
|
||||||
[PhoneErr]
|
|
||||||
CodeNotSent = Code has not been sent yet!
|
|
||||||
CodeTimeOut = You should verify your code in %d min!
|
|
||||||
ExistedErr = Phone already exists
|
|
||||||
EmptyErr = Phone cannot be empty
|
|
||||||
InvalidReceivers = Invalid phone receivers: %s
|
|
||||||
NumberInvalid = Phone number is invalid
|
|
||||||
NoPrefix = %s No phone prefix
|
|
||||||
PhoneCheckResult = Phone: %s
|
|
||||||
UnableGetModifyRule = Unable to get the phone modify rule.
|
|
||||||
|
|
||||||
[ProviderErr]
|
|
||||||
CanNotBeUnlinked = This provider can't be unlinked
|
|
||||||
CategoryNotSAML = provider %s's category is not SAML
|
|
||||||
DoNotExist = the provider: %s does not exist
|
|
||||||
InvalidProvider = Invalid captcha provider.
|
|
||||||
LinkFirstErr = Please link first
|
|
||||||
ProviderNotEnabled = The provider: %s is not enabled for the application
|
|
||||||
ProviderNotSupported = The provider type: %s is not supported
|
|
||||||
ProviderNotFound = The provider: %s is not found
|
|
||||||
ProviderNotFoundForCategory = No provider for category: %s is found for application: %s
|
|
||||||
|
|
||||||
[ResourceErr]
|
|
||||||
NotAuthorized = You are not authorized to access this resource
|
|
||||||
UserIsNil = User is nil for tag: /"avatar/"
|
|
||||||
UsernameOrFilePathEmpty = Username or fullFilePath is empty: username = %s, fullFilePath = %s
|
|
||||||
|
|
||||||
[SetPasswordErr]
|
|
||||||
CanNotContainBlank = New password cannot contain blank space.
|
|
||||||
LessThanSixCharacters = New password must have at least 6 characters
|
|
||||||
|
|
||||||
[SignUpErr]
|
|
||||||
DoNotAllowSignUp = The application does not allow to sign up new account
|
|
||||||
SignOutFirst = Please sign out first before signing up
|
|
||||||
|
|
||||||
[StorageErr]
|
|
||||||
ObjectKeyNotAllowed = The objectKey: %s is not allowed
|
|
||||||
|
|
||||||
[TokenErr]
|
|
||||||
EmptyClientID = Empty clientId or clientSecret
|
|
||||||
InvalidToken = Invalid token
|
|
||||||
InvalidAppOrWrongClientSecret = Invalid application or wrong clientSecret
|
|
||||||
InvalidClientId = Invalid client_id
|
|
||||||
RedirectURIDoNotExist = Redirect URI: %s doesn't exist in the allowed Redirect URI list
|
|
||||||
|
|
||||||
[UserErr]
|
|
||||||
AffiliationBlankErr = Affiliation cannot be blank
|
|
||||||
DisplayNameBlankErr = DisplayName cannot be blank
|
|
||||||
DisplayNameInvalid = DisplayName is not valid real name
|
|
||||||
DisplayNameCanNotBeEmpty = Display name cannot be empty
|
|
||||||
DoNotExist = The user: %s doesn't exist
|
|
||||||
DoNotExistInOrg = The user: %s/%s doesn't exist
|
|
||||||
DoNotExistSignUp = the user does not exist, please sign up first
|
|
||||||
FirstNameBlankErr = FirstName cannot be blank
|
|
||||||
FailToImportUsers = Failed to import users
|
|
||||||
LastNameBlankErr = LastName cannot be blank
|
|
||||||
NameLessThanTwoCharacters = Username must have at least 2 characters
|
|
||||||
NameStartWithADigitErr = Username cannot start with a digit
|
|
||||||
NameIsEmailErr = Username cannot be an email address
|
|
||||||
NameCantainWhitSpaceErr = Username cannot contain white spaces
|
|
||||||
NameExistedErr = Username already exists
|
|
||||||
NameEmptyErr = Empty username.
|
|
||||||
NameTooLang = Username is too long (maximum is 39 characters).
|
|
||||||
NameFormatErr = 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.
|
|
||||||
PasswordLessThanSixCharacters = Password must have at least 6 characters
|
|
||||||
InvalidInformation = Invalid information
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
|||||||
[ApplicationErr]
|
|
||||||
AppNotFound = Application %s not found
|
|
||||||
AppNotFoundForUserID = No application is found for userId: %s
|
|
||||||
GrantTypeNotSupport = Grant_type: %s is not supported in this application
|
|
||||||
HasNoProviders = This application has no providers
|
|
||||||
HasNoProvidersOfType = This application has no providers of type
|
|
||||||
InvalidID = Invalid application id
|
|
||||||
|
|
||||||
[AuthErr]
|
|
||||||
AuthStateWrong = State expected: %s, but got: %s
|
|
||||||
ChallengeMethodErr = Challenge method should be S256
|
|
||||||
CanNotUnlinkUsers = You are not the global admin, you can't unlink other users
|
|
||||||
CanNotLinkMySelf = You can't unlink yourself, you are not a member of any application
|
|
||||||
CallWebAuthnSigninBegin = Please call WebAuthnSigninBegin first
|
|
||||||
NotHuman = Turing test failed.
|
|
||||||
Unauthorized = Unauthorized operation
|
|
||||||
WrongPasswordManyTimes = WrongPasswordManyTimes
|
|
||||||
|
|
||||||
[CasErr]
|
|
||||||
ServiceDoNotMatch = Service %s and %s do not match
|
|
||||||
|
|
||||||
[EmailErr]
|
|
||||||
ExistedErr = Email already exists
|
|
||||||
EmptyErr = Email cannot be empty
|
|
||||||
EmailInvalid = Email is invalid
|
|
||||||
EmailCheckResult = Email: %s
|
|
||||||
EmptyParam = Empty parameters for emailForm: %v
|
|
||||||
InvalidReceivers = Invalid Email receivers: %s
|
|
||||||
UnableGetModifyRule = Unable to get the email modify rule.
|
|
||||||
|
|
||||||
[EnforcerErr]
|
|
||||||
SignInFirst = Please sign in first
|
|
||||||
|
|
||||||
[InitErr]
|
|
||||||
InitScoreFailed = Get init score failed, error: %%w
|
|
||||||
|
|
||||||
[LdapErr]
|
|
||||||
MultipleAccounts = Multiple accounts with same uid, please check your ldap server
|
|
||||||
PasswordWrong = Ldap user name or password incorrect
|
|
||||||
ServerExisted = Ldap server exist
|
|
||||||
|
|
||||||
[LoginErr]
|
|
||||||
AppDoNotExist = The application: %s does not exist
|
|
||||||
AppNotEnableSignUp = 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
|
|
||||||
AccountDoNotExist = The account does not exist
|
|
||||||
InvalidUserInformation = Failed to create user, user information is invalid: %s
|
|
||||||
LoginFirst = Please login first
|
|
||||||
LoginFail = Failed to login in: %s
|
|
||||||
NoPermission = You don't have the permission to do this
|
|
||||||
OldUser = The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)
|
|
||||||
ProviderCanNotSignUp = 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
|
|
||||||
SessionOutdated = Session outdated, please login again
|
|
||||||
SignOutFirst = Please sign out first before signing in
|
|
||||||
UserDoNotExist = The user: %s/%s doesn't exist
|
|
||||||
UserIsForbidden = The user is forbidden to sign in, please contact the administrator
|
|
||||||
UnknownAuthentication = Unknown authentication type (not password or provider), form = %s
|
|
||||||
UnsupportedPasswordType = unsupported password type: %s
|
|
||||||
|
|
||||||
[OrgErr]
|
|
||||||
DoNotExist = Organization does not exist
|
|
||||||
Immutable = The %s is immutable.
|
|
||||||
OnlyAdmin = Only admin can modify the %s.
|
|
||||||
UnknownModifyRule = Unknown modify rule %s.
|
|
||||||
|
|
||||||
[ParameterErr]
|
|
||||||
OrgMissingErr = Parameter organization is missing
|
|
||||||
Missing = Missing parameter
|
|
||||||
UnknownType = Unknown type
|
|
||||||
Wrong = Wrong parameter
|
|
||||||
|
|
||||||
[PhoneErr]
|
|
||||||
CodeNotSent = Code has not been sent yet!
|
|
||||||
CodeTimeOut = You should verify your code in %d min!
|
|
||||||
ExistedErr = Phone already exists
|
|
||||||
EmptyErr = Phone cannot be empty
|
|
||||||
InvalidReceivers = Invalid phone receivers: %s
|
|
||||||
NumberInvalid = Phone number is invalid
|
|
||||||
NoPrefix = %s No phone prefix
|
|
||||||
PhoneCheckResult = Phone: %s
|
|
||||||
UnableGetModifyRule = Unable to get the phone modify rule.
|
|
||||||
|
|
||||||
[ProviderErr]
|
|
||||||
CanNotBeUnlinked = This provider can't be unlinked
|
|
||||||
CategoryNotSAML = provider %s's category is not SAML
|
|
||||||
DoNotExist = the provider: %s does not exist
|
|
||||||
InvalidProvider = Invalid captcha provider.
|
|
||||||
LinkFirstErr = Please link first
|
|
||||||
ProviderNotEnabled = The provider: %s is not enabled for the application
|
|
||||||
ProviderNotSupported = The provider type: %s is not supported
|
|
||||||
ProviderNotFound = The provider: %s is not found
|
|
||||||
ProviderNotFoundForCategory = No provider for category: %s is found for application: %s
|
|
||||||
|
|
||||||
[ResourceErr]
|
|
||||||
NotAuthorized = You are not authorized to access this resource
|
|
||||||
UserIsNil = User is nil for tag: /"avatar/"
|
|
||||||
UsernameOrFilePathEmpty = Username or fullFilePath is empty: username = %s, fullFilePath = %s
|
|
||||||
|
|
||||||
[SetPasswordErr]
|
|
||||||
CanNotContainBlank = New password cannot contain blank space.
|
|
||||||
LessThanSixCharacters = New password must have at least 6 characters
|
|
||||||
|
|
||||||
[SignUpErr]
|
|
||||||
DoNotAllowSignUp = The application does not allow to sign up new account
|
|
||||||
SignOutFirst = Please sign out first before signing up
|
|
||||||
|
|
||||||
[StorageErr]
|
|
||||||
ObjectKeyNotAllowed = The objectKey: %s is not allowed
|
|
||||||
|
|
||||||
[TokenErr]
|
|
||||||
EmptyClientID = Empty clientId or clientSecret
|
|
||||||
InvalidToken = Invalid token
|
|
||||||
InvalidAppOrWrongClientSecret = Invalid application or wrong clientSecret
|
|
||||||
InvalidClientId = Invalid client_id
|
|
||||||
RedirectURIDoNotExist = Redirect URI: %s doesn't exist in the allowed Redirect URI list
|
|
||||||
|
|
||||||
[UserErr]
|
|
||||||
AffiliationBlankErr = Affiliation cannot be blank
|
|
||||||
DisplayNameBlankErr = DisplayName cannot be blank
|
|
||||||
DisplayNameInvalid = DisplayName is not valid real name
|
|
||||||
DisplayNameCanNotBeEmpty = Display name cannot be empty
|
|
||||||
DoNotExist = The user: %s doesn't exist
|
|
||||||
DoNotExistInOrg = The user: %s/%s doesn't exist
|
|
||||||
DoNotExistSignUp = the user does not exist, please sign up first
|
|
||||||
FirstNameBlankErr = FirstName cannot be blank
|
|
||||||
FailToImportUsers = Failed to import users
|
|
||||||
LastNameBlankErr = LastName cannot be blank
|
|
||||||
NameLessThanTwoCharacters = Username must have at least 2 characters
|
|
||||||
NameStartWithADigitErr = Username cannot start with a digit
|
|
||||||
NameIsEmailErr = Username cannot be an email address
|
|
||||||
NameCantainWhitSpaceErr = Username cannot contain white spaces
|
|
||||||
NameExistedErr = Username already exists
|
|
||||||
NameEmptyErr = Empty username.
|
|
||||||
NameTooLang = Username is too long (maximum is 39 characters).
|
|
||||||
NameFormatErr = 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.
|
|
||||||
PasswordLessThanSixCharacters = Password must have at least 6 characters
|
|
||||||
InvalidInformation = Invalid information
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
|||||||
[ApplicationErr]
|
|
||||||
AppNotFound = 应用 %%s 未找到
|
|
||||||
AppNotFoundForUserID = 找不到该用户的应用程序 %s
|
|
||||||
GrantTypeNotSupport = 此应用中不支持此授权类型
|
|
||||||
HasNoProviders = 该应用无提供商
|
|
||||||
HasNoProvidersOfType = 应用没有该类型的提供商
|
|
||||||
InvalidID = 无效的Application ID
|
|
||||||
|
|
||||||
[AuthErr]
|
|
||||||
AuthStateWrong = 期望状态位: %s, 实际状态为: %s
|
|
||||||
ChallengeMethodErr = Challenge 方法应该为 S256
|
|
||||||
CanNotUnlinkUsers = 您不是全局管理员,无法取消链接其他用户
|
|
||||||
CanNotLinkMySelf = 您无法取消链接,您不是任何应用程序的成员
|
|
||||||
CallWebAuthnSigninBegin = 请先调用WebAuthnSigninBegin
|
|
||||||
NotHuman = 真人验证失败
|
|
||||||
Unauthorized = 未授权的操作
|
|
||||||
WrongPasswordManyTimes = 输入密码错误次数已达上限,请在 %d 分 %d 秒后重试
|
|
||||||
|
|
||||||
[CasErr]
|
|
||||||
ServiceDoNotMatch = 服务 %s 与 %s 不匹配
|
|
||||||
|
|
||||||
[EmailErr]
|
|
||||||
ExistedErr = 该邮箱已存在
|
|
||||||
EmptyErr = 邮箱不可为空
|
|
||||||
EmailInvalid = 无效邮箱
|
|
||||||
EmailCheckResult = Email: %s
|
|
||||||
EmptyParam = 邮件参数为空: %v
|
|
||||||
InvalidReceivers = 无效的邮箱接收者: %%s
|
|
||||||
UnableGetModifyRule = 无法得到Email修改规则
|
|
||||||
|
|
||||||
[EnforcerErr]
|
|
||||||
SignInFirst = 请先登录
|
|
||||||
|
|
||||||
[InitErr]
|
|
||||||
InitScoreFailed = 初始化分数失败: %w
|
|
||||||
|
|
||||||
[LdapErr]
|
|
||||||
MultipleAccounts = 多个帐户具有相同的uid,请检查您的 ldap 服务器
|
|
||||||
PasswordWrong = Ldap密码错误
|
|
||||||
ServerExisted = Ldap服务器已存在
|
|
||||||
|
|
||||||
[LoginErr]
|
|
||||||
AppDoNotExist = 应用不存在: %s
|
|
||||||
AppNotEnableSignUp = 提供商账户: %s 与用户名: %s (%s) 不存在且 不允许注册新账户, 请联系IT支持
|
|
||||||
AccountDoNotExist = 账户不存在
|
|
||||||
InvalidUserInformation = 创建用户失败,用户信息无效: %%s
|
|
||||||
LoginFirst = 请先登录
|
|
||||||
LoginFail = 无法登录: %s
|
|
||||||
NoPermission = 您没有权限执行此操作
|
|
||||||
OldUser = 提供商账户: %s 与用户名: %s (%s) 已经与其他账户绑定: %s (%s)
|
|
||||||
ProviderCanNotSignUp = 提供商账户: %s 与用户名: %s (%s) 不存在且 不允许通过 %s 注册新账户, 请使用其他方式注册
|
|
||||||
SignOutFirst = 请在登录前登出
|
|
||||||
SessionOutdated = Session已过期,请重新登陆
|
|
||||||
UserDoNotExist = 用户不存在: %s/%s
|
|
||||||
UserIsForbidden = 该用户被禁止登陆,请联系管理员
|
|
||||||
UnknownAuthentication = 未知的认证类型 (非密码或提供商认证), form = %s
|
|
||||||
UnsupportedPasswordType = 不支持此密码类型
|
|
||||||
|
|
||||||
[OrgErr]
|
|
||||||
DoNotExist = 组织不存在
|
|
||||||
Immutable = %s是不可变的
|
|
||||||
OnlyAdmin = 只有管理员用户有此权限
|
|
||||||
UnknownModifyRule = 未知的修改规则
|
|
||||||
|
|
||||||
[ParameterErr]
|
|
||||||
Missing = 参数丢失
|
|
||||||
OrgMissingErr = Organization参数丢失
|
|
||||||
UnknownType = 未知类型
|
|
||||||
Wrong = 参数错误
|
|
||||||
|
|
||||||
[PhoneErr]
|
|
||||||
CodeNotSent = 验证码还未发送
|
|
||||||
CodeTimeOut = 验证码过期
|
|
||||||
ExistedErr = 该电话已存在
|
|
||||||
EmptyErr = 电话不可为空
|
|
||||||
InvalidReceivers = 无效的电话接收者: %s
|
|
||||||
NumberInvalid = 无效电话
|
|
||||||
PhoneCheckResult = 电话: %s
|
|
||||||
UnableGetModifyRule = 无法得到电话修改规则
|
|
||||||
NoPrefix = %s 无此电话前缀
|
|
||||||
|
|
||||||
[ProviderErr]
|
|
||||||
CanNotBeUnlinked = 该提供商不可被链接
|
|
||||||
InvalidProvider = 无效的验证码提供商
|
|
||||||
LinkFirstErr = 请先绑定
|
|
||||||
ProviderNotEnabled = 提供商: %s 未被启用
|
|
||||||
ProviderNotSupported = 不支持该类型的提供商: %s
|
|
||||||
ProviderNotFound = 该提供商未找到: %s
|
|
||||||
ProviderNotFoundForCategory = 该类型的提供商: %s 在应用中未找到: %s
|
|
||||||
DoNotExist = 提供商: %s 不存在
|
|
||||||
CategoryNotSAML = 提供商 %s类型不是SAML
|
|
||||||
|
|
||||||
[ResourceErr]
|
|
||||||
NotAuthorized = 您无权获取此资源
|
|
||||||
UserIsNil = 用户头像标签为空
|
|
||||||
UsernameOrFilePathEmpty = username或FilePath为空: username = %s, fullFilePath = %s
|
|
||||||
|
|
||||||
[SetPasswordErr]
|
|
||||||
CanNotContainBlank = 新密码不可以包含空客
|
|
||||||
LessThanSixCharacters = 新密码至少为6位
|
|
||||||
|
|
||||||
[SignUpErr]
|
|
||||||
DoNotAllowSignUp = 该应用不允许注册新账户
|
|
||||||
SignOutFirst = 请在登陆前登出
|
|
||||||
|
|
||||||
[TokenErr]
|
|
||||||
EmptyClientID = clientId或clientSecret为空
|
|
||||||
InvalidAppOrWrongClientSecret = 无效应用或错误的clientSecret
|
|
||||||
InvalidToken = 无效token
|
|
||||||
InvalidClientId = 无效的ClientId
|
|
||||||
RedirectURIDoNotExist = 重定向 URI:%s 在可列表中未找到
|
|
||||||
|
|
||||||
[UserErr]
|
|
||||||
AffiliationBlankErr = 联系方式不可为空
|
|
||||||
DisplayNameBlankErr = 展示名称不可为空
|
|
||||||
DisplayNameInvalid = 展示名称无效
|
|
||||||
DisplayNameCanNotBeEmpty = 展示名称不可为空
|
|
||||||
DoNotExist = 用户不存在: %s
|
|
||||||
DoNotExistInOrg = 用户不存在: %s/%s
|
|
||||||
FirstNameBlankErr = 名不可以为空
|
|
||||||
FailToImportUsers = 导入用户失败
|
|
||||||
LastNameBlankErr = 姓不可以为空
|
|
||||||
NameLessThanTwoCharacters = 用户名至少要有2个字符
|
|
||||||
NameStartWithADigitErr = 用户名禁止使用数字作为第一个字符
|
|
||||||
NameIsEmailErr = 用户名不可以是邮箱地址
|
|
||||||
NameCantainWhitSpaceErr = 用户名不可以包含空格
|
|
||||||
NameExistedErr = 用户名已存在
|
|
||||||
NameEmptyErr = 用户名不可为空
|
|
||||||
NameTooLang = 用户名过长(最大长度为39个字符)
|
|
||||||
NameFormatErr = 用户名只能包含字母数字字符、下划线或连字符,不能有连续的连字符或下划线,也不能以连字符或下划线开头或结尾
|
|
||||||
PasswordLessThanSixCharacters = 密码至少为6字符
|
|
||||||
DoNotExistSignUp = 用户不存在,请先注册
|
|
||||||
InvalidInformation = 无效信息
|
|
||||||
|
|
||||||
[StorageErr]
|
|
||||||
ObjectKeyNotAllowed = object key :%s 不被允许
|
|
||||||
|
|
173
i18n/locales/de/data.json
Normal file
173
i18n/locales/de/data.json
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"Email: %s": "Email: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid information": "Invalid information",
|
||||||
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"Parameter organization is missing": "Parameter organization is missing",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid token": "Invalid token",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
|
"The account does not exist": "The account does not exist",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The 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 type: %s is not supported": "The provider type: %s is not supported",
|
||||||
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
|
},
|
||||||
|
"cas": {
|
||||||
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
|
},
|
||||||
|
"check": {
|
||||||
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
|
"Email already exists": "Email already exists",
|
||||||
|
"Email cannot be empty": "Email cannot be empty",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Empty username.": "Empty username.",
|
||||||
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
|
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||||
|
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||||
|
"Phone already exists": "Phone already exists",
|
||||||
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The user doesn't exist": "The user doesn't exist",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
|
"Username already exists": "Username already exists",
|
||||||
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
|
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||||
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
|
},
|
||||||
|
"check_util": {
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||||
|
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||||
|
},
|
||||||
|
"enforcer": {
|
||||||
|
"Please sign in first": "Please sign in first"
|
||||||
|
},
|
||||||
|
"ldap": {
|
||||||
|
"Ldap server exist": "Ldap server exist",
|
||||||
|
"Missing parameter": "Missing parameter"
|
||||||
|
},
|
||||||
|
"link": {
|
||||||
|
"Please link first": "Please link first",
|
||||||
|
"This application has no providers": "This application has no providers",
|
||||||
|
"This application has no providers of type": "This application has no providers of type",
|
||||||
|
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||||
|
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||||
|
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||||
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"Invalid application id": "Invalid application id",
|
||||||
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||||
|
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||||
|
},
|
||||||
|
"saml": {
|
||||||
|
"Application %s not found": "Application %s not found"
|
||||||
|
},
|
||||||
|
"saml_sp": {
|
||||||
|
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||||
|
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||||
|
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
|
},
|
||||||
|
"system_info": {
|
||||||
|
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
|
"Invalid client_id": "Invalid client_id",
|
||||||
|
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
|
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
},
|
||||||
|
"user_upload": {
|
||||||
|
"Failed to import users": "Failed to import users"
|
||||||
|
},
|
||||||
|
"util": {
|
||||||
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The provider: %s is not found": "The provider: %s is not found",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"verification": {
|
||||||
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
|
"Missing parameter": "Missing parameter",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
"Unknown type": "Unknown type",
|
||||||
|
"Wrong parameter": "Wrong parameter",
|
||||||
|
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||||
|
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||||
|
},
|
||||||
|
"webauthn": {
|
||||||
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
}
|
||||||
|
}
|
173
i18n/locales/en/data.json
Normal file
173
i18n/locales/en/data.json
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"Email: %s": "Email: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid information": "Invalid information",
|
||||||
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"Parameter organization is missing": "Parameter organization is missing",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid token": "Invalid token",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
|
"The account does not exist": "The account does not exist",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The 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 type: %s is not supported": "The provider type: %s is not supported",
|
||||||
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
|
},
|
||||||
|
"cas": {
|
||||||
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
|
},
|
||||||
|
"check": {
|
||||||
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
|
"Email already exists": "Email already exists",
|
||||||
|
"Email cannot be empty": "Email cannot be empty",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Empty username.": "Empty username.",
|
||||||
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
|
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||||
|
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||||
|
"Phone already exists": "Phone already exists",
|
||||||
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The user doesn't exist": "The user doesn't exist",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
|
"Username already exists": "Username already exists",
|
||||||
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
|
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||||
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
|
},
|
||||||
|
"check_util": {
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||||
|
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||||
|
},
|
||||||
|
"enforcer": {
|
||||||
|
"Please sign in first": "Please sign in first"
|
||||||
|
},
|
||||||
|
"ldap": {
|
||||||
|
"Ldap server exist": "Ldap server exist",
|
||||||
|
"Missing parameter": "Missing parameter"
|
||||||
|
},
|
||||||
|
"link": {
|
||||||
|
"Please link first": "Please link first",
|
||||||
|
"This application has no providers": "This application has no providers",
|
||||||
|
"This application has no providers of type": "This application has no providers of type",
|
||||||
|
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||||
|
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||||
|
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||||
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"Invalid application id": "Invalid application id",
|
||||||
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||||
|
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||||
|
},
|
||||||
|
"saml": {
|
||||||
|
"Application %s not found": "Application %s not found"
|
||||||
|
},
|
||||||
|
"saml_sp": {
|
||||||
|
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||||
|
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||||
|
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
|
},
|
||||||
|
"system_info": {
|
||||||
|
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
|
"Invalid client_id": "Invalid client_id",
|
||||||
|
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
|
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
},
|
||||||
|
"user_upload": {
|
||||||
|
"Failed to import users": "Failed to import users"
|
||||||
|
},
|
||||||
|
"util": {
|
||||||
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The provider: %s is not found": "The provider: %s is not found",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"verification": {
|
||||||
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
|
"Missing parameter": "Missing parameter",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
"Unknown type": "Unknown type",
|
||||||
|
"Wrong parameter": "Wrong parameter",
|
||||||
|
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||||
|
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||||
|
},
|
||||||
|
"webauthn": {
|
||||||
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
}
|
||||||
|
}
|
173
i18n/locales/es/data.json
Normal file
173
i18n/locales/es/data.json
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"Email: %s": "Email: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid information": "Invalid information",
|
||||||
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"Parameter organization is missing": "Parameter organization is missing",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid token": "Invalid token",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
|
"The account does not exist": "The account does not exist",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The 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 type: %s is not supported": "The provider type: %s is not supported",
|
||||||
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
|
},
|
||||||
|
"cas": {
|
||||||
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
|
},
|
||||||
|
"check": {
|
||||||
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
|
"Email already exists": "Email already exists",
|
||||||
|
"Email cannot be empty": "Email cannot be empty",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Empty username.": "Empty username.",
|
||||||
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
|
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||||
|
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||||
|
"Phone already exists": "Phone already exists",
|
||||||
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The user doesn't exist": "The user doesn't exist",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
|
"Username already exists": "Username already exists",
|
||||||
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
|
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||||
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
|
},
|
||||||
|
"check_util": {
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||||
|
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||||
|
},
|
||||||
|
"enforcer": {
|
||||||
|
"Please sign in first": "Please sign in first"
|
||||||
|
},
|
||||||
|
"ldap": {
|
||||||
|
"Ldap server exist": "Ldap server exist",
|
||||||
|
"Missing parameter": "Missing parameter"
|
||||||
|
},
|
||||||
|
"link": {
|
||||||
|
"Please link first": "Please link first",
|
||||||
|
"This application has no providers": "This application has no providers",
|
||||||
|
"This application has no providers of type": "This application has no providers of type",
|
||||||
|
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||||
|
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||||
|
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||||
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"Invalid application id": "Invalid application id",
|
||||||
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||||
|
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||||
|
},
|
||||||
|
"saml": {
|
||||||
|
"Application %s not found": "Application %s not found"
|
||||||
|
},
|
||||||
|
"saml_sp": {
|
||||||
|
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||||
|
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||||
|
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
|
},
|
||||||
|
"system_info": {
|
||||||
|
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
|
"Invalid client_id": "Invalid client_id",
|
||||||
|
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
|
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
},
|
||||||
|
"user_upload": {
|
||||||
|
"Failed to import users": "Failed to import users"
|
||||||
|
},
|
||||||
|
"util": {
|
||||||
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The provider: %s is not found": "The provider: %s is not found",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"verification": {
|
||||||
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
|
"Missing parameter": "Missing parameter",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
"Unknown type": "Unknown type",
|
||||||
|
"Wrong parameter": "Wrong parameter",
|
||||||
|
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||||
|
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||||
|
},
|
||||||
|
"webauthn": {
|
||||||
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
}
|
||||||
|
}
|
173
i18n/locales/fr/data.json
Normal file
173
i18n/locales/fr/data.json
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"Email: %s": "Email: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid information": "Invalid information",
|
||||||
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"Parameter organization is missing": "Parameter organization is missing",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid token": "Invalid token",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
|
"The account does not exist": "The account does not exist",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The 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 type: %s is not supported": "The provider type: %s is not supported",
|
||||||
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
|
},
|
||||||
|
"cas": {
|
||||||
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
|
},
|
||||||
|
"check": {
|
||||||
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
|
"Email already exists": "Email already exists",
|
||||||
|
"Email cannot be empty": "Email cannot be empty",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Empty username.": "Empty username.",
|
||||||
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
|
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||||
|
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||||
|
"Phone already exists": "Phone already exists",
|
||||||
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The user doesn't exist": "The user doesn't exist",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
|
"Username already exists": "Username already exists",
|
||||||
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
|
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||||
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
|
},
|
||||||
|
"check_util": {
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||||
|
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||||
|
},
|
||||||
|
"enforcer": {
|
||||||
|
"Please sign in first": "Please sign in first"
|
||||||
|
},
|
||||||
|
"ldap": {
|
||||||
|
"Ldap server exist": "Ldap server exist",
|
||||||
|
"Missing parameter": "Missing parameter"
|
||||||
|
},
|
||||||
|
"link": {
|
||||||
|
"Please link first": "Please link first",
|
||||||
|
"This application has no providers": "This application has no providers",
|
||||||
|
"This application has no providers of type": "This application has no providers of type",
|
||||||
|
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||||
|
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||||
|
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||||
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"Invalid application id": "Invalid application id",
|
||||||
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||||
|
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||||
|
},
|
||||||
|
"saml": {
|
||||||
|
"Application %s not found": "Application %s not found"
|
||||||
|
},
|
||||||
|
"saml_sp": {
|
||||||
|
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||||
|
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||||
|
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
|
},
|
||||||
|
"system_info": {
|
||||||
|
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
|
"Invalid client_id": "Invalid client_id",
|
||||||
|
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
|
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
},
|
||||||
|
"user_upload": {
|
||||||
|
"Failed to import users": "Failed to import users"
|
||||||
|
},
|
||||||
|
"util": {
|
||||||
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The provider: %s is not found": "The provider: %s is not found",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"verification": {
|
||||||
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
|
"Missing parameter": "Missing parameter",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
"Unknown type": "Unknown type",
|
||||||
|
"Wrong parameter": "Wrong parameter",
|
||||||
|
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||||
|
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||||
|
},
|
||||||
|
"webauthn": {
|
||||||
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
}
|
||||||
|
}
|
173
i18n/locales/ja/data.json
Normal file
173
i18n/locales/ja/data.json
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"Email: %s": "Email: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid information": "Invalid information",
|
||||||
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"Parameter organization is missing": "Parameter organization is missing",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid token": "Invalid token",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
|
"The account does not exist": "The account does not exist",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The 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 type: %s is not supported": "The provider type: %s is not supported",
|
||||||
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
|
},
|
||||||
|
"cas": {
|
||||||
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
|
},
|
||||||
|
"check": {
|
||||||
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
|
"Email already exists": "Email already exists",
|
||||||
|
"Email cannot be empty": "Email cannot be empty",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Empty username.": "Empty username.",
|
||||||
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
|
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||||
|
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||||
|
"Phone already exists": "Phone already exists",
|
||||||
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The user doesn't exist": "The user doesn't exist",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
|
"Username already exists": "Username already exists",
|
||||||
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
|
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||||
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
|
},
|
||||||
|
"check_util": {
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||||
|
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||||
|
},
|
||||||
|
"enforcer": {
|
||||||
|
"Please sign in first": "Please sign in first"
|
||||||
|
},
|
||||||
|
"ldap": {
|
||||||
|
"Ldap server exist": "Ldap server exist",
|
||||||
|
"Missing parameter": "Missing parameter"
|
||||||
|
},
|
||||||
|
"link": {
|
||||||
|
"Please link first": "Please link first",
|
||||||
|
"This application has no providers": "This application has no providers",
|
||||||
|
"This application has no providers of type": "This application has no providers of type",
|
||||||
|
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||||
|
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||||
|
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||||
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"Invalid application id": "Invalid application id",
|
||||||
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||||
|
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||||
|
},
|
||||||
|
"saml": {
|
||||||
|
"Application %s not found": "Application %s not found"
|
||||||
|
},
|
||||||
|
"saml_sp": {
|
||||||
|
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||||
|
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||||
|
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
|
},
|
||||||
|
"system_info": {
|
||||||
|
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
|
"Invalid client_id": "Invalid client_id",
|
||||||
|
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
|
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
},
|
||||||
|
"user_upload": {
|
||||||
|
"Failed to import users": "Failed to import users"
|
||||||
|
},
|
||||||
|
"util": {
|
||||||
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The provider: %s is not found": "The provider: %s is not found",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"verification": {
|
||||||
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
|
"Missing parameter": "Missing parameter",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
"Unknown type": "Unknown type",
|
||||||
|
"Wrong parameter": "Wrong parameter",
|
||||||
|
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||||
|
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||||
|
},
|
||||||
|
"webauthn": {
|
||||||
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
}
|
||||||
|
}
|
173
i18n/locales/ko/data.json
Normal file
173
i18n/locales/ko/data.json
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"Email: %s": "Email: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid information": "Invalid information",
|
||||||
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"Parameter organization is missing": "Parameter organization is missing",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid token": "Invalid token",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
|
"The account does not exist": "The account does not exist",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The 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 type: %s is not supported": "The provider type: %s is not supported",
|
||||||
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
|
},
|
||||||
|
"cas": {
|
||||||
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
|
},
|
||||||
|
"check": {
|
||||||
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
|
"Email already exists": "Email already exists",
|
||||||
|
"Email cannot be empty": "Email cannot be empty",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Empty username.": "Empty username.",
|
||||||
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
|
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||||
|
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||||
|
"Phone already exists": "Phone already exists",
|
||||||
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The user doesn't exist": "The user doesn't exist",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
|
"Username already exists": "Username already exists",
|
||||||
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
|
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||||
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
|
},
|
||||||
|
"check_util": {
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||||
|
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||||
|
},
|
||||||
|
"enforcer": {
|
||||||
|
"Please sign in first": "Please sign in first"
|
||||||
|
},
|
||||||
|
"ldap": {
|
||||||
|
"Ldap server exist": "Ldap server exist",
|
||||||
|
"Missing parameter": "Missing parameter"
|
||||||
|
},
|
||||||
|
"link": {
|
||||||
|
"Please link first": "Please link first",
|
||||||
|
"This application has no providers": "This application has no providers",
|
||||||
|
"This application has no providers of type": "This application has no providers of type",
|
||||||
|
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||||
|
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||||
|
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||||
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"Invalid application id": "Invalid application id",
|
||||||
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||||
|
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||||
|
},
|
||||||
|
"saml": {
|
||||||
|
"Application %s not found": "Application %s not found"
|
||||||
|
},
|
||||||
|
"saml_sp": {
|
||||||
|
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||||
|
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||||
|
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
|
},
|
||||||
|
"system_info": {
|
||||||
|
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
|
"Invalid client_id": "Invalid client_id",
|
||||||
|
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
|
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
},
|
||||||
|
"user_upload": {
|
||||||
|
"Failed to import users": "Failed to import users"
|
||||||
|
},
|
||||||
|
"util": {
|
||||||
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The provider: %s is not found": "The provider: %s is not found",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"verification": {
|
||||||
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
|
"Missing parameter": "Missing parameter",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
"Unknown type": "Unknown type",
|
||||||
|
"Wrong parameter": "Wrong parameter",
|
||||||
|
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||||
|
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||||
|
},
|
||||||
|
"webauthn": {
|
||||||
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
}
|
||||||
|
}
|
173
i18n/locales/ru/data.json
Normal file
173
i18n/locales/ru/data.json
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"Email: %s": "Email: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid information": "Invalid information",
|
||||||
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"Parameter organization is missing": "Parameter organization is missing",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid token": "Invalid token",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
|
"The account does not exist": "The account does not exist",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The 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 type: %s is not supported": "The provider type: %s is not supported",
|
||||||
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
|
},
|
||||||
|
"cas": {
|
||||||
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
|
},
|
||||||
|
"check": {
|
||||||
|
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||||
|
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||||
|
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||||
|
"Email already exists": "Email already exists",
|
||||||
|
"Email cannot be empty": "Email cannot be empty",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Empty username.": "Empty username.",
|
||||||
|
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||||
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
|
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||||
|
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||||
|
"Phone already exists": "Phone already exists",
|
||||||
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
|
"The user doesn't exist": "The user doesn't exist",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
|
"Username already exists": "Username already exists",
|
||||||
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
|
"You don't have the permission to do this": "You don't have the permission to do this",
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
||||||
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
|
},
|
||||||
|
"check_util": {
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
||||||
|
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
||||||
|
},
|
||||||
|
"enforcer": {
|
||||||
|
"Please sign in first": "Please sign in first"
|
||||||
|
},
|
||||||
|
"ldap": {
|
||||||
|
"Ldap server exist": "Ldap server exist",
|
||||||
|
"Missing parameter": "Missing parameter"
|
||||||
|
},
|
||||||
|
"link": {
|
||||||
|
"Please link first": "Please link first",
|
||||||
|
"This application has no providers": "This application has no providers",
|
||||||
|
"This application has no providers of type": "This application has no providers of type",
|
||||||
|
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||||
|
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||||
|
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||||
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"Invalid application id": "Invalid application id",
|
||||||
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||||
|
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||||
|
},
|
||||||
|
"saml": {
|
||||||
|
"Application %s not found": "Application %s not found"
|
||||||
|
},
|
||||||
|
"saml_sp": {
|
||||||
|
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||||
|
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||||
|
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
|
},
|
||||||
|
"system_info": {
|
||||||
|
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
|
"Invalid client_id": "Invalid client_id",
|
||||||
|
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
|
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
},
|
||||||
|
"user_upload": {
|
||||||
|
"Failed to import users": "Failed to import users"
|
||||||
|
},
|
||||||
|
"util": {
|
||||||
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The provider: %s is not found": "The provider: %s is not found",
|
||||||
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
|
},
|
||||||
|
"verification": {
|
||||||
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
|
"Missing parameter": "Missing parameter",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
"Unknown type": "Unknown type",
|
||||||
|
"Wrong parameter": "Wrong parameter",
|
||||||
|
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||||
|
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||||
|
},
|
||||||
|
"webauthn": {
|
||||||
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
||||||
|
"Please login first": "Please login first",
|
||||||
|
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
||||||
|
}
|
||||||
|
}
|
173
i18n/locales/zh/data.json
Normal file
173
i18n/locales/zh/data.json
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"Email: %s": "邮件: %s",
|
||||||
|
"Get init score failed, error: %w": "初始化分数失败: %w",
|
||||||
|
"Invalid information": "无效信息",
|
||||||
|
"Phone: %s": "电话: %s",
|
||||||
|
"Please sign out first before signing up": "请在登陆前登出",
|
||||||
|
"The application does not allow to sign up new account": "该应用不允许注册新账户"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"Parameter organization is missing": "Organization参数丢失",
|
||||||
|
"The user: %s doesn't exist": "用户不存在: %s"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"%s No phone prefix": "%s 无此电话前缀",
|
||||||
|
"Challenge method should be S256": "Challenge 方法应该为 S256",
|
||||||
|
"Failed to create user, user information is invalid: %s": "创建用户失败,用户信息无效: %s",
|
||||||
|
"Failed to login in: %s": "无法登录: %s",
|
||||||
|
"Get init score failed, error: %w": "初始化分数失败: %w",
|
||||||
|
"Invalid token": "无效token",
|
||||||
|
"Please sign out first before signing in": "请在登陆前登出",
|
||||||
|
"State expected: %s, but got: %s": "期望状态位: %s, 实际状态为: %s",
|
||||||
|
"The account does not exist": "账户不存在",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "提供商账户: %s 与用户名: %s (%s) 不存在且 不允许通过 %s 注册新账户, 请使用其他方式注册",
|
||||||
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "提供商账户: %s 与用户名: %s (%s) 不存在且 不允许注册新账户, 请联系IT支持",
|
||||||
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "提供商账户: %s 与用户名: %s (%s) 已经与其他账户绑定: %s (%s)",
|
||||||
|
"The application: %s does not exist": "应用 %s 不存在",
|
||||||
|
"The 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 type: %s is not supported": "不支持该类型的提供商: %s",
|
||||||
|
"The provider: %s is not enabled for the application": "提供商: %s 未被启用",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "该用户被禁止登陆,请联系管理员",
|
||||||
|
"The user: %s/%s doesn't exist": "用户不存在: %s/%s",
|
||||||
|
"Turing test failed.": "真人验证失败",
|
||||||
|
"Unauthorized operation": "未授权的操作",
|
||||||
|
"Unknown authentication type (not password or provider), form = %s": "未知的认证类型(非密码或第三方提供商):%s"
|
||||||
|
},
|
||||||
|
"cas": {
|
||||||
|
"Service %s and %s do not match": "服务 %s 与 %s 不匹配"
|
||||||
|
},
|
||||||
|
"check": {
|
||||||
|
"Affiliation cannot be blank": "联系方式不可为空",
|
||||||
|
"DisplayName cannot be blank": "展示名称不可为空",
|
||||||
|
"DisplayName is not valid real name": "展示名称无效",
|
||||||
|
"Email already exists": "该邮箱已存在",
|
||||||
|
"Email cannot be empty": "邮箱不可为空",
|
||||||
|
"Email is invalid": "无效邮箱",
|
||||||
|
"Empty username.": "用户名不可为空",
|
||||||
|
"FirstName cannot be blank": "名不可以为空",
|
||||||
|
"LastName cannot be blank": "姓不可以为空",
|
||||||
|
"Ldap user name or password incorrect": "Ldap密码错误",
|
||||||
|
"Multiple accounts with same uid, please check your ldap server": "多个帐户具有相同的uid,请检查您的 ldap 服务器",
|
||||||
|
"Organization does not exist": "组织不存在",
|
||||||
|
"Password must have at least 6 characters": "新密码至少为6位",
|
||||||
|
"Phone already exists": "该电话已存在",
|
||||||
|
"Phone cannot be empty": "电话不可为空",
|
||||||
|
"Phone number is invalid": "无效电话",
|
||||||
|
"Please login first": "请先登录",
|
||||||
|
"Session outdated, please login again": "Session已过期,请重新登陆",
|
||||||
|
"The user doesn't exist": "用户不存在",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "该用户被禁止登陆,请联系管理员",
|
||||||
|
"The user: %s doesn't exist": "用户不存在: %s",
|
||||||
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "用户名只能包含字母数字字符、下划线或连字符,不能有连续的连字符或下划线,也不能以连字符或下划线开头或结尾",
|
||||||
|
"Username already exists": "用户名已存在",
|
||||||
|
"Username cannot be an email address": "用户名不可以是邮箱地址",
|
||||||
|
"Username cannot contain white spaces": "用户名不可以包含空格",
|
||||||
|
"Username cannot start with a digit": "用户名禁止使用数字作为第一个字符",
|
||||||
|
"Username is too long (maximum is 39 characters).": "用户名过长(最大长度为39个字符)",
|
||||||
|
"Username must have at least 2 characters": "用户名至少要有2个字符",
|
||||||
|
"You don't have the permission to do this": "用户名至少要有2个字符",
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "输入密码错误次数已达上限,请在 %d 分 %d 秒后重试",
|
||||||
|
"unsupported password type: %s": "不支持的密码类型: %s"
|
||||||
|
},
|
||||||
|
"check_util": {
|
||||||
|
"You have entered the wrong password too many times, please wait for %d minutes and try again": "输入密码错误次数已达上限,请在 %d 分后重试",
|
||||||
|
"password is incorrect, you have %d remaining chances": "密码错误,您还有 %d 次尝试的机会"
|
||||||
|
},
|
||||||
|
"enforcer": {
|
||||||
|
"Please sign in first": "请先登录"
|
||||||
|
},
|
||||||
|
"ldap": {
|
||||||
|
"Ldap server exist": "Ldap服务器已存在",
|
||||||
|
"Missing parameter": "参数丢失"
|
||||||
|
},
|
||||||
|
"link": {
|
||||||
|
"Please link first": "请先绑定",
|
||||||
|
"This application has no providers": "该应用无提供商",
|
||||||
|
"This application has no providers of type": "应用没有该类型的提供商",
|
||||||
|
"This provider can't be unlinked": "该提供商不可被链接",
|
||||||
|
"You are not the global admin, you can't unlink other users": "您不是全局管理员,无法取消链接其他用户",
|
||||||
|
"You can't unlink yourself, you are not a member of any application": "您无法取消链接,您不是任何应用程序的成员"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"Only admin can modify the %s.": "您无法取消链接,您不是任何应用程序的成员",
|
||||||
|
"The %s is immutable.": "%s是不可变的",
|
||||||
|
"Unknown modify rule %s.": "未知的修改规则"
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"Please login first": "请先登录",
|
||||||
|
"The user: %s doesn't exist": "用户不存在: %s"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"Invalid application id": "无效的Application ID",
|
||||||
|
"the provider: %s does not exist": "提供商: %s 不存在"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"User is nil for tag: avatar": "用户头像标签为空",
|
||||||
|
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "username或FilePath为空: username = %s, fullFilePath = %s"
|
||||||
|
},
|
||||||
|
"saml": {
|
||||||
|
"Application %s not found": "应用 %s 未找到"
|
||||||
|
},
|
||||||
|
"saml_sp": {
|
||||||
|
"provider %s's category is not SAML": "提供商 %s类型不是SAML"
|
||||||
|
},
|
||||||
|
"service": {
|
||||||
|
"Empty parameters for emailForm: %v": "邮件参数为空: %v",
|
||||||
|
"Invalid Email receivers: %s": " 无效的邮箱接收者: %s",
|
||||||
|
"Invalid phone receivers: %s": "无效的电话接收者: %s"
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"The objectKey: %s is not allowed": "object key :%s 不被允许",
|
||||||
|
"The provider type: %s is not supported": "提供商类型: %s 尚未支持"
|
||||||
|
},
|
||||||
|
"system_info": {
|
||||||
|
"You are not authorized to access this resource": "您无权获取此资源"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"Challenge method should be S256": "Challenge 方法应该为 S256",
|
||||||
|
"Empty clientId or clientSecret": "clientId或clientSecret为空",
|
||||||
|
"Grant_type: %s is not supported in this application": "此应用中不支持此授权类型: %s",
|
||||||
|
"Invalid application or wrong clientSecret": "无效应用或错误的clientSecret",
|
||||||
|
"Invalid client_id": "无效的ClientId",
|
||||||
|
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "重定向 URI:%s 在可列表中未找到"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"Display name cannot be empty": "展示名称不可为空",
|
||||||
|
"New password cannot contain blank space.": "新密码不可以包含空格",
|
||||||
|
"New password must have at least 6 characters": "新密码至少需要6位字符",
|
||||||
|
"The user: %s/%s doesn't exist": "用户不存在: %s/%s"
|
||||||
|
},
|
||||||
|
"user_upload": {
|
||||||
|
"Failed to import users": "导入用户失败"
|
||||||
|
},
|
||||||
|
"util": {
|
||||||
|
"No application is found for userId: %s": "找不到该用户的应用程序 %s",
|
||||||
|
"No provider for category: %s is found for application: %s": "找不到该用户的应用程序 %s",
|
||||||
|
"Please login first": "请先登录",
|
||||||
|
"The provider: %s is not found": "该提供商未找到: %s",
|
||||||
|
"The user: %s doesn't exist": "用户不存在: %s"
|
||||||
|
},
|
||||||
|
"verification": {
|
||||||
|
"Code has not been sent yet!": "验证码还未发送",
|
||||||
|
"Email is invalid": "非法的邮箱",
|
||||||
|
"Invalid captcha provider.": "非法的验证码提供商",
|
||||||
|
"Missing parameter": "参数丢失",
|
||||||
|
"Organization does not exist": "组织不存在",
|
||||||
|
"Phone number is invalid": "非法的电话号码",
|
||||||
|
"Please login first": "请先登录",
|
||||||
|
"Turing test failed.": "验证码还未发送",
|
||||||
|
"Unable to get the email modify rule.": "无法得到邮箱修改规则",
|
||||||
|
"Unable to get the phone modify rule.": "无法得到电话修改规则",
|
||||||
|
"Unknown type": "未知类型",
|
||||||
|
"Wrong parameter": "参数错误",
|
||||||
|
"You should verify your code in %d min!": "请在 %d 分钟内输入正确验证码",
|
||||||
|
"the user does not exist, please sign up first": "用户不存在,请先注册"
|
||||||
|
},
|
||||||
|
"webauthn": {
|
||||||
|
"Found no credentials for this user": "该用户没有WebAuthn凭据",
|
||||||
|
"Please call WebAuthnSigninBegin first": "请先调用 WebAuthnSigninBegi",
|
||||||
|
"Please login first": "请先登录",
|
||||||
|
"The user: %s/%s doesn't exist": "用户: %s/%s 不存在"
|
||||||
|
}
|
||||||
|
}
|
41
i18n/util.go
41
i18n/util.go
@ -17,23 +17,24 @@ package i18n
|
|||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"gopkg.in/ini.v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed languages/*.ini
|
//go:embed locales/*/data.json
|
||||||
var f embed.FS
|
var f embed.FS
|
||||||
|
|
||||||
var (
|
var langMap = make(map[string]map[string]map[string]string) // for example : langMap[en][account][Invalid information] = Invalid information
|
||||||
langMapConfig = make(map[string]*ini.File)
|
|
||||||
isNotFirstLoad = make(map[string]bool)
|
|
||||||
)
|
|
||||||
|
|
||||||
func getI18nFilePath(language string) string {
|
func getI18nFilePath(language string) string {
|
||||||
return fmt.Sprintf("../web/src/locales/%s/data.json", language)
|
if strings.Contains(language, "backend") {
|
||||||
|
// change language from 'backend_en' to 'en'
|
||||||
|
language = language[8:]
|
||||||
|
return fmt.Sprintf("../i18n/locales/%s/data.json", language)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("../web/src/locales/%s/data.json", language)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readI18nFile(language string) *I18nData {
|
func readI18nFile(language string) *I18nData {
|
||||||
@ -75,18 +76,20 @@ func applyData(data1 *I18nData, data2 *I18nData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Translate(lang string, error string) string {
|
func Translate(lang string, error string) string {
|
||||||
parts := strings.Split(error, ".")
|
parts := strings.SplitN(error, ":", 2)
|
||||||
if !strings.Contains(error, ".") || len(parts) != 2 {
|
if !strings.Contains(error, ":") || len(parts) != 2 {
|
||||||
log.Println("Invalid Error Name")
|
return "Translate Error: " + error
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
if langMap[lang] != nil {
|
||||||
if isNotFirstLoad[lang] {
|
return langMap[lang][parts[0]][parts[1]]
|
||||||
return langMapConfig[lang].Section(parts[0]).Key(parts[1]).String()
|
|
||||||
} else {
|
} else {
|
||||||
file, _ := f.ReadFile("languages/locale_" + lang + ".ini")
|
file, _ := f.ReadFile("locales/" + lang + "/data.json")
|
||||||
langMapConfig[lang], _ = ini.Load(file)
|
data := I18nData{}
|
||||||
isNotFirstLoad[lang] = true
|
err := util.JsonToStruct(string(file), &data)
|
||||||
return langMapConfig[lang].Section(parts[0]).Key(parts[1]).String()
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
langMap[lang] = data
|
||||||
|
return langMap[lang][parts[0]][parts[1]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
package idp
|
package idp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
@ -118,13 +118,14 @@ func (idp *AdfsIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
keyset, err := jwk.Parse(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
keyset, err := jwk.ParseKey(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tokenSrc := []byte(token.AccessToken)
|
tokenSrc := []byte(token.AccessToken)
|
||||||
publicKey, _ := keyset.Keys[0].Materialize()
|
publicKey, _ := keyset.PublicKey()
|
||||||
idToken, _ := jwt.Parse(bytes.NewReader(tokenSrc), jwt.WithVerify(jwa.RS256, publicKey))
|
idToken, _ := jwt.Parse(tokenSrc, jwt.WithVerify(jwa.RS256, publicKey))
|
||||||
sid, _ := idToken.Get("sid")
|
sid, _ := idToken.Get("sid")
|
||||||
upn, _ := idToken.Get("upn")
|
upn, _ := idToken.Get("upn")
|
||||||
name, _ := idToken.Get("unique_name")
|
name, _ := idToken.Get("unique_name")
|
||||||
|
@ -256,6 +256,8 @@ func (idp *DingTalkIdProvider) isUserInOrg(unionId string) (bool, error) {
|
|||||||
}
|
}
|
||||||
if data.ErrCode == 60121 {
|
if data.ErrCode == 60121 {
|
||||||
return false, fmt.Errorf("the user is not found in the organization where clientId and clientSecret belong")
|
return false, fmt.Errorf("the user is not found in the organization where clientId and clientSecret belong")
|
||||||
|
} else if data.ErrCode != 0 {
|
||||||
|
return false, fmt.Errorf(data.ErrMessage)
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
64
idp/goth.go
64
idp/goth.go
@ -22,35 +22,35 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"github.com/casdoor/goth"
|
"github.com/markbates/goth"
|
||||||
"github.com/casdoor/goth/providers/amazon"
|
"github.com/markbates/goth/providers/amazon"
|
||||||
"github.com/casdoor/goth/providers/apple"
|
"github.com/markbates/goth/providers/apple"
|
||||||
"github.com/casdoor/goth/providers/azuread"
|
"github.com/markbates/goth/providers/azureadv2"
|
||||||
"github.com/casdoor/goth/providers/bitbucket"
|
"github.com/markbates/goth/providers/bitbucket"
|
||||||
"github.com/casdoor/goth/providers/digitalocean"
|
"github.com/markbates/goth/providers/digitalocean"
|
||||||
"github.com/casdoor/goth/providers/discord"
|
"github.com/markbates/goth/providers/discord"
|
||||||
"github.com/casdoor/goth/providers/dropbox"
|
"github.com/markbates/goth/providers/dropbox"
|
||||||
"github.com/casdoor/goth/providers/facebook"
|
"github.com/markbates/goth/providers/facebook"
|
||||||
"github.com/casdoor/goth/providers/gitea"
|
"github.com/markbates/goth/providers/gitea"
|
||||||
"github.com/casdoor/goth/providers/github"
|
"github.com/markbates/goth/providers/github"
|
||||||
"github.com/casdoor/goth/providers/gitlab"
|
"github.com/markbates/goth/providers/gitlab"
|
||||||
"github.com/casdoor/goth/providers/google"
|
"github.com/markbates/goth/providers/google"
|
||||||
"github.com/casdoor/goth/providers/heroku"
|
"github.com/markbates/goth/providers/heroku"
|
||||||
"github.com/casdoor/goth/providers/instagram"
|
"github.com/markbates/goth/providers/instagram"
|
||||||
"github.com/casdoor/goth/providers/kakao"
|
"github.com/markbates/goth/providers/kakao"
|
||||||
"github.com/casdoor/goth/providers/line"
|
"github.com/markbates/goth/providers/line"
|
||||||
"github.com/casdoor/goth/providers/linkedin"
|
"github.com/markbates/goth/providers/linkedin"
|
||||||
"github.com/casdoor/goth/providers/microsoftonline"
|
"github.com/markbates/goth/providers/microsoftonline"
|
||||||
"github.com/casdoor/goth/providers/paypal"
|
"github.com/markbates/goth/providers/paypal"
|
||||||
"github.com/casdoor/goth/providers/salesforce"
|
"github.com/markbates/goth/providers/salesforce"
|
||||||
"github.com/casdoor/goth/providers/shopify"
|
"github.com/markbates/goth/providers/shopify"
|
||||||
"github.com/casdoor/goth/providers/slack"
|
"github.com/markbates/goth/providers/slack"
|
||||||
"github.com/casdoor/goth/providers/steam"
|
"github.com/markbates/goth/providers/steam"
|
||||||
"github.com/casdoor/goth/providers/tumblr"
|
"github.com/markbates/goth/providers/tumblr"
|
||||||
"github.com/casdoor/goth/providers/twitter"
|
"github.com/markbates/goth/providers/twitter"
|
||||||
"github.com/casdoor/goth/providers/yahoo"
|
"github.com/markbates/goth/providers/yahoo"
|
||||||
"github.com/casdoor/goth/providers/yandex"
|
"github.com/markbates/goth/providers/yandex"
|
||||||
"github.com/casdoor/goth/providers/zoom"
|
"github.com/markbates/goth/providers/zoom"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -74,8 +74,8 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
|
|||||||
}
|
}
|
||||||
case "AzureAD":
|
case "AzureAD":
|
||||||
idp = GothIdProvider{
|
idp = GothIdProvider{
|
||||||
Provider: azuread.New(clientId, clientSecret, redirectUrl, nil),
|
Provider: azureadv2.New(clientId, clientSecret, redirectUrl, azureadv2.ProviderOptions{Tenant: "common"}),
|
||||||
Session: &azuread.Session{},
|
Session: &azureadv2.Session{},
|
||||||
}
|
}
|
||||||
case "Bitbucket":
|
case "Bitbucket":
|
||||||
idp = GothIdProvider{
|
idp = GothIdProvider{
|
||||||
@ -202,6 +202,8 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
|
|||||||
Provider: zoom.New(clientId, clientSecret, redirectUrl),
|
Provider: zoom.New(clientId, clientSecret, redirectUrl),
|
||||||
Session: &zoom.Session{},
|
Session: &zoom.Session{},
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &idp
|
return &idp
|
||||||
|
@ -98,7 +98,7 @@ func GetIdProvider(typ string, subType string, clientId string, clientSecret str
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var gothList = []string{"Apple", "AzureAd", "Slack", "Steam"}
|
var gothList = []string{"Apple", "AzureAD", "Slack", "Steam", "Line"}
|
||||||
|
|
||||||
func isGothSupport(provider string) bool {
|
func isGothSupport(provider string) bool {
|
||||||
for _, value := range gothList {
|
for _, value := range gothList {
|
||||||
|
@ -16,14 +16,17 @@ package idp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/skip2/go-qrcode"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -191,3 +194,54 @@ func (idp *WeChatIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
}
|
}
|
||||||
return &userInfo, nil
|
return &userInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetWechatOfficialAccountAccessToken(clientId string, clientSecret string) (string, error) {
|
||||||
|
accessTokenUrl := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", clientId, clientSecret)
|
||||||
|
request, err := http.NewRequest("GET", accessTokenUrl, nil)
|
||||||
|
client := new(http.Client)
|
||||||
|
resp, err := client.Do(request)
|
||||||
|
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var data struct {
|
||||||
|
ExpireIn int `json:"expires_in"`
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(respBytes, &data)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return data.AccessToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetWechatOfficialAccountQRCode(clientId string, clientSecret string) (string, error) {
|
||||||
|
accessToken, err := GetWechatOfficialAccountAccessToken(clientId, clientSecret)
|
||||||
|
client := new(http.Client)
|
||||||
|
params := "{\"action_name\": \"QR_LIMIT_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"test\"}}}"
|
||||||
|
bodyData := bytes.NewReader([]byte(params))
|
||||||
|
qrCodeUrl := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", accessToken)
|
||||||
|
requeset, err := http.NewRequest("POST", qrCodeUrl, bodyData)
|
||||||
|
resp, err := client.Do(requeset)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var data struct {
|
||||||
|
Ticket string `json:"ticket"`
|
||||||
|
ExpireSeconds int `json:"expire_seconds"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(respBytes, &data)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var png []byte
|
||||||
|
png, err = qrcode.Encode(data.URL, qrcode.Medium, 256)
|
||||||
|
base64Image := base64.StdEncoding.EncodeToString(png)
|
||||||
|
return base64Image, nil
|
||||||
|
}
|
||||||
|
@ -156,5 +156,187 @@
|
|||||||
"autoSync": 0,
|
"autoSync": 0,
|
||||||
"lastSync": ""
|
"lastSync": ""
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"models": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name": "",
|
||||||
|
"modelText": "",
|
||||||
|
"displayName": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"displayName": "",
|
||||||
|
"effect": "",
|
||||||
|
"isEnabled": true,
|
||||||
|
"model": "",
|
||||||
|
"name": "",
|
||||||
|
"owner": "",
|
||||||
|
"resourceType": "",
|
||||||
|
"resources": [
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"roles": [
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"users": [
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payments": [
|
||||||
|
{
|
||||||
|
"currency": "",
|
||||||
|
"detail": "",
|
||||||
|
"displayName": "",
|
||||||
|
"invoiceRemark": "",
|
||||||
|
"invoiceTaxId": "",
|
||||||
|
"invoiceTitle": "",
|
||||||
|
"invoiceType": "",
|
||||||
|
"invoiceUrl": "",
|
||||||
|
"message": "",
|
||||||
|
"name": "",
|
||||||
|
"organization": "",
|
||||||
|
"owner": "",
|
||||||
|
"payUrl": "",
|
||||||
|
"personEmail": "",
|
||||||
|
"personIdCard": "",
|
||||||
|
"personName": "",
|
||||||
|
"personPhone": "",
|
||||||
|
"price": 0,
|
||||||
|
"productDisplayName": "",
|
||||||
|
"productName": "",
|
||||||
|
"provider": "",
|
||||||
|
"returnUrl": "",
|
||||||
|
"state": "",
|
||||||
|
"tag": "",
|
||||||
|
"type": "",
|
||||||
|
"user": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"currency": "",
|
||||||
|
"detail": "",
|
||||||
|
"displayName": "",
|
||||||
|
"image": "",
|
||||||
|
"name": "",
|
||||||
|
"owner": "",
|
||||||
|
"price": 0,
|
||||||
|
"providers": [
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"quantity": 0,
|
||||||
|
"returnUrl": "",
|
||||||
|
"sold": 0,
|
||||||
|
"state": "",
|
||||||
|
"tag": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"owner": "",
|
||||||
|
"name": "",
|
||||||
|
"user": "",
|
||||||
|
"provider": "",
|
||||||
|
"application": "",
|
||||||
|
"tag": "",
|
||||||
|
"parent": "",
|
||||||
|
"fileName": "",
|
||||||
|
"fileType": "",
|
||||||
|
"fileFormat": "",
|
||||||
|
"url": "",
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"displayName": "",
|
||||||
|
"isEnabled": true,
|
||||||
|
"name": "",
|
||||||
|
"owner": "",
|
||||||
|
"roles": [
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"users": [
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"syncers": [
|
||||||
|
{
|
||||||
|
"affiliationTable": "",
|
||||||
|
"avatarBaseUrl": "",
|
||||||
|
"database": "",
|
||||||
|
"databaseType": "",
|
||||||
|
"errorText": "",
|
||||||
|
"host": "",
|
||||||
|
"isEnabled": true,
|
||||||
|
"name": "",
|
||||||
|
"organization": "",
|
||||||
|
"owner": "",
|
||||||
|
"password": "",
|
||||||
|
"port": 0,
|
||||||
|
"syncInterval": 0,
|
||||||
|
"table": "",
|
||||||
|
"tableColumns": [
|
||||||
|
{
|
||||||
|
"casdoorName": "",
|
||||||
|
"isHashed": true,
|
||||||
|
"name": "",
|
||||||
|
"type": "",
|
||||||
|
"values": [
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tablePrimaryKey": "",
|
||||||
|
"type": "",
|
||||||
|
"user": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tokens": [
|
||||||
|
{
|
||||||
|
"accessToken": "",
|
||||||
|
"application": "",
|
||||||
|
"code": "",
|
||||||
|
"codeChallenge": "",
|
||||||
|
"codeExpireIn": 0,
|
||||||
|
"codeIsUsed": true,
|
||||||
|
"createdTime": "",
|
||||||
|
"expiresIn": 0,
|
||||||
|
"name": "",
|
||||||
|
"organization": "",
|
||||||
|
"owner": "",
|
||||||
|
"refreshToken": "",
|
||||||
|
"scope": "",
|
||||||
|
"tokenType": "",
|
||||||
|
"user": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"webhooks": [
|
||||||
|
{
|
||||||
|
"contentType": "",
|
||||||
|
"events": [
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"headers": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isEnabled": true,
|
||||||
|
"isUserExtended": true,
|
||||||
|
"method": "",
|
||||||
|
"name": "",
|
||||||
|
"organization": "",
|
||||||
|
"owner": "",
|
||||||
|
"url": ""
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,10 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/idp"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"xorm.io/core"
|
"xorm.io/core"
|
||||||
)
|
)
|
||||||
@ -50,6 +50,7 @@ type Application struct {
|
|||||||
EnableCodeSignin bool `json:"enableCodeSignin"`
|
EnableCodeSignin bool `json:"enableCodeSignin"`
|
||||||
EnableSamlCompress bool `json:"enableSamlCompress"`
|
EnableSamlCompress bool `json:"enableSamlCompress"`
|
||||||
EnableWebAuthn bool `json:"enableWebAuthn"`
|
EnableWebAuthn bool `json:"enableWebAuthn"`
|
||||||
|
SamlReplyUrl string `xorm:"varchar(100)" json:"samlReplyUrl"`
|
||||||
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
|
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
|
||||||
SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
|
SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
|
||||||
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`
|
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`
|
||||||
@ -84,6 +85,16 @@ func GetApplicationCount(owner, field, value string) int {
|
|||||||
return int(count)
|
return int(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetOrganizationApplicationCount(owner, Organization, field, value string) int {
|
||||||
|
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||||
|
count, err := session.Count(&Application{Organization: Organization})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(count)
|
||||||
|
}
|
||||||
|
|
||||||
func GetApplications(owner string) []*Application {
|
func GetApplications(owner string) []*Application {
|
||||||
applications := []*Application{}
|
applications := []*Application{}
|
||||||
err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Owner: owner})
|
err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Owner: owner})
|
||||||
@ -94,8 +105,18 @@ func GetApplications(owner string) []*Application {
|
|||||||
return applications
|
return applications
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPaginationApplications(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Application {
|
func GetOrganizationApplications(owner string, organization string) []*Application {
|
||||||
applications := []*Application{}
|
applications := []*Application{}
|
||||||
|
err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Owner: owner, Organization: organization})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return applications
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPaginationApplications(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Application {
|
||||||
|
var applications []*Application
|
||||||
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
||||||
err := session.Find(&applications)
|
err := session.Find(&applications)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -105,9 +126,10 @@ func GetPaginationApplications(owner string, offset, limit int, field, value, so
|
|||||||
return applications
|
return applications
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetApplicationsByOrganizationName(owner string, organization string) []*Application {
|
func GetPaginationOrganizationApplications(owner, organization string, offset, limit int, field, value, sortField, sortOrder string) []*Application {
|
||||||
applications := []*Application{}
|
applications := []*Application{}
|
||||||
err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Owner: owner, Organization: organization})
|
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
||||||
|
err := session.Find(&applications, &Application{Owner: owner, Organization: organization})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -119,9 +141,11 @@ func getProviderMap(owner string) map[string]*Provider {
|
|||||||
providers := GetProviders(owner)
|
providers := GetProviders(owner)
|
||||||
m := map[string]*Provider{}
|
m := map[string]*Provider{}
|
||||||
for _, provider := range providers {
|
for _, provider := range providers {
|
||||||
//if provider.Category != "OAuth" {
|
// Get QRCode only once
|
||||||
// continue
|
if provider.Type == "WeChat" && provider.DisableSsl == true && provider.Content == "" {
|
||||||
//}
|
provider.Content, _ = idp.GetWechatOfficialAccountQRCode(provider.ClientId2, provider.ClientSecret2)
|
||||||
|
UpdateProvider(provider.Owner+"/"+provider.Name, provider)
|
||||||
|
}
|
||||||
|
|
||||||
m[provider.Name] = GetMaskedProvider(provider)
|
m[provider.Name] = GetMaskedProvider(provider)
|
||||||
}
|
}
|
||||||
@ -129,7 +153,7 @@ func getProviderMap(owner string) map[string]*Provider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func extendApplicationWithProviders(application *Application) {
|
func extendApplicationWithProviders(application *Application) {
|
||||||
m := getProviderMap(application.Owner)
|
m := getProviderMap(application.Organization)
|
||||||
for _, providerItem := range application.Providers {
|
for _, providerItem := range application.Providers {
|
||||||
if provider, ok := m[providerItem.Name]; ok {
|
if provider, ok := m[providerItem.Name]; ok {
|
||||||
providerItem.Provider = provider
|
providerItem.Provider = provider
|
||||||
@ -329,56 +353,30 @@ func (application *Application) GetId() string {
|
|||||||
return fmt.Sprintf("%s/%s", application.Owner, application.Name)
|
return fmt.Sprintf("%s/%s", application.Owner, application.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckRedirectUriValid(application *Application, redirectUri string) bool {
|
func (application *Application) IsRedirectUriValid(redirectUri string) bool {
|
||||||
validUri := false
|
isValid := false
|
||||||
for _, tmpUri := range application.RedirectUris {
|
for _, targetUri := range application.RedirectUris {
|
||||||
tmpUriRegex := regexp.MustCompile(tmpUri)
|
targetUriRegex := regexp.MustCompile(targetUri)
|
||||||
if tmpUriRegex.MatchString(redirectUri) || strings.Contains(redirectUri, tmpUri) {
|
if targetUriRegex.MatchString(redirectUri) || strings.Contains(redirectUri, targetUri) {
|
||||||
validUri = true
|
isValid = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return validUri
|
return isValid
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsAllowOrigin(origin string) bool {
|
func IsOriginAllowed(origin string) bool {
|
||||||
allowOrigin := false
|
applications := GetApplications("")
|
||||||
originUrl, err := url.Parse(origin)
|
for _, application := range applications {
|
||||||
if err != nil {
|
if application.IsRedirectUriValid(origin) {
|
||||||
return false
|
return true
|
||||||
}
|
|
||||||
|
|
||||||
rows, err := adapter.Engine.Cols("redirect_uris").Rows(&Application{})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
application := Application{}
|
|
||||||
for rows.Next() {
|
|
||||||
err := rows.Scan(&application)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for _, tmpRedirectUri := range application.RedirectUris {
|
|
||||||
u1, err := url.Parse(tmpRedirectUri)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if u1.Scheme == originUrl.Scheme && u1.Host == originUrl.Host {
|
|
||||||
allowOrigin = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if allowOrigin {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
return allowOrigin
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getApplicationMap(organization string) map[string]*Application {
|
func getApplicationMap(organization string) map[string]*Application {
|
||||||
applications := GetApplicationsByOrganizationName("admin", organization)
|
applications := GetOrganizationApplications("admin", organization)
|
||||||
|
|
||||||
applicationMap := make(map[string]*Application)
|
applicationMap := make(map[string]*Application)
|
||||||
for _, application := range applications {
|
for _, application := range applications {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
package object
|
package object
|
||||||
|
|
||||||
func (application *Application) GetProviderByCategory(category string) *Provider {
|
func (application *Application) GetProviderByCategory(category string) *Provider {
|
||||||
providers := GetProviders(application.Owner)
|
providers := GetProviders(application.Organization)
|
||||||
m := map[string]*Provider{}
|
m := map[string]*Provider{}
|
||||||
for _, provider := range providers {
|
for _, provider := range providers {
|
||||||
if provider.Category != category {
|
if provider.Category != category {
|
||||||
|
@ -60,7 +60,7 @@ func getPermanentAvatarUrl(organization string, username string, url string, upl
|
|||||||
}
|
}
|
||||||
|
|
||||||
fullFilePath := fmt.Sprintf("/avatar/%s/%s.png", organization, username)
|
fullFilePath := fmt.Sprintf("/avatar/%s/%s.png", organization, username)
|
||||||
uploadedFileUrl, _ := getUploadFileUrl(defaultStorageProvider, fullFilePath, false)
|
uploadedFileUrl, _ := GetUploadFileUrl(defaultStorageProvider, fullFilePath, false)
|
||||||
|
|
||||||
if upload {
|
if upload {
|
||||||
DownloadAndUpload(url, fullFilePath)
|
DownloadAndUpload(url, fullFilePath)
|
||||||
|
@ -148,34 +148,7 @@ func (casbinAdapter *CasbinAdapter) getTable() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func safeReturn(policy []string, i int) string {
|
func initEnforcer(modelObj *Model, casbinAdapter *CasbinAdapter) (*casbin.Enforcer, error) {
|
||||||
if len(policy) > i {
|
|
||||||
return policy[i]
|
|
||||||
} else {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func matrixToCasbinRules(pType string, policies [][]string) []*xormadapter.CasbinRule {
|
|
||||||
res := []*xormadapter.CasbinRule{}
|
|
||||||
|
|
||||||
for _, policy := range policies {
|
|
||||||
line := xormadapter.CasbinRule{
|
|
||||||
Ptype: pType,
|
|
||||||
V0: safeReturn(policy, 0),
|
|
||||||
V1: safeReturn(policy, 1),
|
|
||||||
V2: safeReturn(policy, 2),
|
|
||||||
V3: safeReturn(policy, 3),
|
|
||||||
V4: safeReturn(policy, 4),
|
|
||||||
V5: safeReturn(policy, 5),
|
|
||||||
}
|
|
||||||
res = append(res, &line)
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func SyncPolicies(casbinAdapter *CasbinAdapter) []*xormadapter.CasbinRule {
|
|
||||||
// init Adapter
|
// init Adapter
|
||||||
if casbinAdapter.Adapter == nil {
|
if casbinAdapter.Adapter == nil {
|
||||||
var dataSourceName string
|
var dataSourceName string
|
||||||
@ -191,20 +164,60 @@ func SyncPolicies(casbinAdapter *CasbinAdapter) []*xormadapter.CasbinRule {
|
|||||||
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
|
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
|
||||||
}
|
}
|
||||||
|
|
||||||
casbinAdapter.Adapter, _ = xormadapter.NewAdapterByEngineWithTableName(NewAdapter(casbinAdapter.DatabaseType, dataSourceName, casbinAdapter.Database).Engine, casbinAdapter.getTable(), "")
|
var err error
|
||||||
|
casbinAdapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(NewAdapter(casbinAdapter.DatabaseType, dataSourceName, casbinAdapter.Database).Engine, casbinAdapter.getTable(), "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// init Model
|
// init Model
|
||||||
modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
|
|
||||||
m, err := model.NewModelFromString(modelObj.ModelText)
|
m, err := model.NewModelFromString(modelObj.ModelText)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// init Enforcer
|
// init Enforcer
|
||||||
enforcer, err := casbin.NewEnforcer(m, casbinAdapter.Adapter)
|
enforcer, err := casbin.NewEnforcer(m, casbinAdapter.Adapter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return enforcer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func safeReturn(policy []string, i int) string {
|
||||||
|
if len(policy) > i {
|
||||||
|
return policy[i]
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func matrixToCasbinRules(Ptype string, policies [][]string) []*xormadapter.CasbinRule {
|
||||||
|
res := []*xormadapter.CasbinRule{}
|
||||||
|
|
||||||
|
for _, policy := range policies {
|
||||||
|
line := xormadapter.CasbinRule{
|
||||||
|
Ptype: Ptype,
|
||||||
|
V0: safeReturn(policy, 0),
|
||||||
|
V1: safeReturn(policy, 1),
|
||||||
|
V2: safeReturn(policy, 2),
|
||||||
|
V3: safeReturn(policy, 3),
|
||||||
|
V4: safeReturn(policy, 4),
|
||||||
|
V5: safeReturn(policy, 5),
|
||||||
|
}
|
||||||
|
res = append(res, &line)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func SyncPolicies(casbinAdapter *CasbinAdapter) ([]*xormadapter.CasbinRule, error) {
|
||||||
|
modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
|
||||||
|
enforcer, err := initEnforcer(modelObj, casbinAdapter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
policies := matrixToCasbinRules("p", enforcer.GetPolicy())
|
policies := matrixToCasbinRules("p", enforcer.GetPolicy())
|
||||||
@ -212,5 +225,48 @@ func SyncPolicies(casbinAdapter *CasbinAdapter) []*xormadapter.CasbinRule {
|
|||||||
policies = append(policies, matrixToCasbinRules("g", enforcer.GetGroupingPolicy())...)
|
policies = append(policies, matrixToCasbinRules("g", enforcer.GetGroupingPolicy())...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return policies
|
return policies, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdatePolicy(oldPolicy, newPolicy []string, casbinAdapter *CasbinAdapter) (bool, error) {
|
||||||
|
modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
|
||||||
|
enforcer, err := initEnforcer(modelObj, casbinAdapter)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
affected, err := enforcer.UpdatePolicy(oldPolicy, newPolicy)
|
||||||
|
if err != nil {
|
||||||
|
return affected, err
|
||||||
|
}
|
||||||
|
return affected, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddPolicy(policy []string, casbinAdapter *CasbinAdapter) (bool, error) {
|
||||||
|
modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
|
||||||
|
enforcer, err := initEnforcer(modelObj, casbinAdapter)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
affected, err := enforcer.AddPolicy(policy)
|
||||||
|
if err != nil {
|
||||||
|
return affected, err
|
||||||
|
}
|
||||||
|
return affected, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemovePolicy(policy []string, casbinAdapter *CasbinAdapter) (bool, error) {
|
||||||
|
modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
|
||||||
|
enforcer, err := initEnforcer(modelObj, casbinAdapter)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
affected, err := enforcer.RemovePolicy(policy)
|
||||||
|
if err != nil {
|
||||||
|
return affected, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return affected, nil
|
||||||
}
|
}
|
||||||
|
@ -44,21 +44,21 @@ func init() {
|
|||||||
|
|
||||||
func CheckUserSignup(application *Application, organization *Organization, username string, password string, displayName string, firstName string, lastName string, email string, phone string, affiliation string, lang string) string {
|
func CheckUserSignup(application *Application, organization *Organization, username string, password string, displayName string, firstName string, lastName string, email string, phone string, affiliation string, lang string) string {
|
||||||
if organization == nil {
|
if organization == nil {
|
||||||
return i18n.Translate(lang, "OrgErr.DoNotExist")
|
return i18n.Translate(lang, "check:Organization does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.IsSignupItemVisible("Username") {
|
if application.IsSignupItemVisible("Username") {
|
||||||
if len(username) <= 1 {
|
if len(username) <= 1 {
|
||||||
return i18n.Translate(lang, "UserErr.NameLessThanTwoCharacters")
|
return i18n.Translate(lang, "check:Username must have at least 2 characters")
|
||||||
}
|
}
|
||||||
if unicode.IsDigit(rune(username[0])) {
|
if unicode.IsDigit(rune(username[0])) {
|
||||||
return i18n.Translate(lang, "UserErr.NameStartWithADigitErr")
|
return i18n.Translate(lang, "check:Username cannot start with a digit")
|
||||||
}
|
}
|
||||||
if util.IsEmailValid(username) {
|
if util.IsEmailValid(username) {
|
||||||
return i18n.Translate(lang, "UserErr.NameIsEmailErr")
|
return i18n.Translate(lang, "check:Username cannot be an email address")
|
||||||
}
|
}
|
||||||
if reWhiteSpace.MatchString(username) {
|
if reWhiteSpace.MatchString(username) {
|
||||||
return i18n.Translate(lang, "UserErr.NameCantainWhitSpaceErr")
|
return i18n.Translate(lang, "check:Username cannot contain white spaces")
|
||||||
}
|
}
|
||||||
msg := CheckUsername(username, lang)
|
msg := CheckUsername(username, lang)
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
@ -66,65 +66,65 @@ func CheckUserSignup(application *Application, organization *Organization, usern
|
|||||||
}
|
}
|
||||||
|
|
||||||
if HasUserByField(organization.Name, "name", username) {
|
if HasUserByField(organization.Name, "name", username) {
|
||||||
return i18n.Translate(lang, "UserErr.NameExistedErr")
|
return i18n.Translate(lang, "check:Username already exists")
|
||||||
}
|
}
|
||||||
if HasUserByField(organization.Name, "email", email) {
|
if HasUserByField(organization.Name, "email", email) {
|
||||||
return i18n.Translate(lang, "EmailErr.ExistedErr")
|
return i18n.Translate(lang, "check:Email already exists")
|
||||||
}
|
}
|
||||||
if HasUserByField(organization.Name, "phone", phone) {
|
if HasUserByField(organization.Name, "phone", phone) {
|
||||||
return i18n.Translate(lang, "PhoneErr.ExistedErr")
|
return i18n.Translate(lang, "check:Phone already exists")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(password) <= 5 {
|
if len(password) <= 5 {
|
||||||
return i18n.Translate(lang, "UserErr.PasswordLessThanSixCharacters")
|
return i18n.Translate(lang, "check:Password must have at least 6 characters")
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.IsSignupItemVisible("Email") {
|
if application.IsSignupItemVisible("Email") {
|
||||||
if email == "" {
|
if email == "" {
|
||||||
if application.IsSignupItemRequired("Email") {
|
if application.IsSignupItemRequired("Email") {
|
||||||
return i18n.Translate(lang, "EmailErr.EmptyErr")
|
return i18n.Translate(lang, "check:Email cannot be empty")
|
||||||
} else {
|
} else {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if HasUserByField(organization.Name, "email", email) {
|
if HasUserByField(organization.Name, "email", email) {
|
||||||
return i18n.Translate(lang, "EmailErr.ExistedErr")
|
return i18n.Translate(lang, "check:Email already exists")
|
||||||
} else if !util.IsEmailValid(email) {
|
} else if !util.IsEmailValid(email) {
|
||||||
return i18n.Translate(lang, "EmailErr.EmailInvalid")
|
return i18n.Translate(lang, "check:Email is invalid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.IsSignupItemVisible("Phone") {
|
if application.IsSignupItemVisible("Phone") {
|
||||||
if phone == "" {
|
if phone == "" {
|
||||||
if application.IsSignupItemRequired("Phone") {
|
if application.IsSignupItemRequired("Phone") {
|
||||||
return i18n.Translate(lang, "PhoneErr.EmptyErr")
|
return i18n.Translate(lang, "check:Phone cannot be empty")
|
||||||
} else {
|
} else {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if HasUserByField(organization.Name, "phone", phone) {
|
if HasUserByField(organization.Name, "phone", phone) {
|
||||||
return i18n.Translate(lang, "PhoneErr.ExistedErr")
|
return i18n.Translate(lang, "check:Phone already exists")
|
||||||
} else if organization.PhonePrefix == "86" && !util.IsPhoneCnValid(phone) {
|
} else if organization.PhonePrefix == "86" && !util.IsPhoneCnValid(phone) {
|
||||||
return i18n.Translate(lang, "PhoneErr.NumberInvalid")
|
return i18n.Translate(lang, "check:Phone number is invalid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if application.IsSignupItemVisible("Display name") {
|
if application.IsSignupItemVisible("Display name") {
|
||||||
if application.GetSignupItemRule("Display name") == "First, last" && (firstName != "" || lastName != "") {
|
if application.GetSignupItemRule("Display name") == "First, last" && (firstName != "" || lastName != "") {
|
||||||
if firstName == "" {
|
if firstName == "" {
|
||||||
return i18n.Translate(lang, "UserErr.FirstNameBlankErr")
|
return i18n.Translate(lang, "check:FirstName cannot be blank")
|
||||||
} else if lastName == "" {
|
} else if lastName == "" {
|
||||||
return i18n.Translate(lang, "UserErr.LastNameBlankErr")
|
return i18n.Translate(lang, "check:LastName cannot be blank")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if displayName == "" {
|
if displayName == "" {
|
||||||
return i18n.Translate(lang, "UserErr.DisplayNameBlankErr")
|
return i18n.Translate(lang, "check:DisplayName cannot be blank")
|
||||||
} else if application.GetSignupItemRule("Display name") == "Real name" {
|
} else if application.GetSignupItemRule("Display name") == "Real name" {
|
||||||
if !isValidRealName(displayName) {
|
if !isValidRealName(displayName) {
|
||||||
return i18n.Translate(lang, "UserErr.DisplayNameInvalid")
|
return i18n.Translate(lang, "check:DisplayName is not valid real name")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ func CheckUserSignup(application *Application, organization *Organization, usern
|
|||||||
|
|
||||||
if application.IsSignupItemVisible("Affiliation") {
|
if application.IsSignupItemVisible("Affiliation") {
|
||||||
if affiliation == "" {
|
if affiliation == "" {
|
||||||
return i18n.Translate(lang, "UserErr.AffiliationBlankErr")
|
return i18n.Translate(lang, "check:Affiliation cannot be blank")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ func checkSigninErrorTimes(user *User, lang string) string {
|
|||||||
|
|
||||||
// deny the login if the error times is greater than the limit and the last login time is less than the duration
|
// deny the login if the error times is greater than the limit and the last login time is less than the duration
|
||||||
if seconds > 0 {
|
if seconds > 0 {
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "AuthErr.WrongPasswordManyTimes"), seconds/60, seconds%60)
|
return fmt.Sprintf(i18n.Translate(lang, "check:You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again"), seconds/60, seconds%60)
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the error times
|
// reset the error times
|
||||||
@ -167,7 +167,7 @@ func CheckPassword(user *User, password string, lang string) string {
|
|||||||
|
|
||||||
organization := GetOrganizationByUser(user)
|
organization := GetOrganizationByUser(user)
|
||||||
if organization == nil {
|
if organization == nil {
|
||||||
return i18n.Translate(lang, "OrgErr.DoNotExist")
|
return i18n.Translate(lang, "check:Organization does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
credManager := cred.GetCredManager(organization.PasswordType)
|
credManager := cred.GetCredManager(organization.PasswordType)
|
||||||
@ -184,9 +184,9 @@ func CheckPassword(user *User, password string, lang string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return recordSigninErrorInfo(user)
|
return recordSigninErrorInfo(user, lang)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "LoginErr.UnsupportedPasswordType"), organization.PasswordType)
|
return fmt.Sprintf(i18n.Translate(lang, "check:unsupported password type: %s"), organization.PasswordType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ func checkLdapUserPassword(user *User, password string, lang string) (*User, str
|
|||||||
if len(searchResult.Entries) == 0 {
|
if len(searchResult.Entries) == 0 {
|
||||||
continue
|
continue
|
||||||
} else if len(searchResult.Entries) > 1 {
|
} else if len(searchResult.Entries) > 1 {
|
||||||
return nil, i18n.Translate(lang, "LdapErr.MultipleAccounts")
|
return nil, i18n.Translate(lang, "check:Multiple accounts with same uid, please check your ldap server")
|
||||||
}
|
}
|
||||||
|
|
||||||
dn := searchResult.Entries[0].DN
|
dn := searchResult.Entries[0].DN
|
||||||
@ -221,7 +221,7 @@ func checkLdapUserPassword(user *User, password string, lang string) (*User, str
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !ldapLoginSuccess {
|
if !ldapLoginSuccess {
|
||||||
return nil, i18n.Translate(lang, "LdapErr.PasswordWrong")
|
return nil, i18n.Translate(lang, "check:Ldap user name or password incorrect")
|
||||||
}
|
}
|
||||||
return user, ""
|
return user, ""
|
||||||
}
|
}
|
||||||
@ -229,11 +229,11 @@ func checkLdapUserPassword(user *User, password string, lang string) (*User, str
|
|||||||
func CheckUserPassword(organization string, username string, password string, lang string) (*User, string) {
|
func CheckUserPassword(organization string, username string, password string, lang string) (*User, string) {
|
||||||
user := GetUserByFields(organization, username)
|
user := GetUserByFields(organization, username)
|
||||||
if user == nil || user.IsDeleted == true {
|
if user == nil || user.IsDeleted == true {
|
||||||
return nil, i18n.Translate(lang, "UserErr.DoNotExistSignUp")
|
return nil, i18n.Translate(lang, "check:The user doesn't exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.IsForbidden {
|
if user.IsForbidden {
|
||||||
return nil, i18n.Translate(lang, "LoginErr.UserIsForbidden")
|
return nil, i18n.Translate(lang, "check:The user is forbidden to sign in, please contact the administrator")
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Ldap != "" {
|
if user.Ldap != "" {
|
||||||
@ -254,13 +254,13 @@ func filterField(field string) bool {
|
|||||||
|
|
||||||
func CheckUserPermission(requestUserId, userId, userOwner string, strict bool, lang string) (bool, error) {
|
func CheckUserPermission(requestUserId, userId, userOwner string, strict bool, lang string) (bool, error) {
|
||||||
if requestUserId == "" {
|
if requestUserId == "" {
|
||||||
return false, fmt.Errorf(i18n.Translate(lang, "LoginErr.LoginFirst"))
|
return false, fmt.Errorf(i18n.Translate(lang, "check:Please login first"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if userId != "" {
|
if userId != "" {
|
||||||
targetUser := GetUser(userId)
|
targetUser := GetUser(userId)
|
||||||
if targetUser == nil {
|
if targetUser == nil {
|
||||||
return false, fmt.Errorf(i18n.Translate(lang, "UserErr.DoNotExist"), userId)
|
return false, fmt.Errorf(i18n.Translate(lang, "check:The user: %s doesn't exist"), userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
userOwner = targetUser.Owner
|
userOwner = targetUser.Owner
|
||||||
@ -272,7 +272,7 @@ func CheckUserPermission(requestUserId, userId, userOwner string, strict bool, l
|
|||||||
} else {
|
} else {
|
||||||
requestUser := GetUser(requestUserId)
|
requestUser := GetUser(requestUserId)
|
||||||
if requestUser == nil {
|
if requestUser == nil {
|
||||||
return false, fmt.Errorf(i18n.Translate(lang, "LoginErr.SessionOutdated"))
|
return false, fmt.Errorf(i18n.Translate(lang, "check:Session outdated, please login again"))
|
||||||
}
|
}
|
||||||
if requestUser.IsGlobalAdmin {
|
if requestUser.IsGlobalAdmin {
|
||||||
hasPermission = true
|
hasPermission = true
|
||||||
@ -287,7 +287,7 @@ func CheckUserPermission(requestUserId, userId, userOwner string, strict bool, l
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hasPermission, fmt.Errorf(i18n.Translate(lang, "LoginErr.NoPermission"))
|
return hasPermission, fmt.Errorf(i18n.Translate(lang, "check:You don't have the permission to do this"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckAccessPermission(userId string, application *Application) (bool, error) {
|
func CheckAccessPermission(userId string, application *Application) (bool, error) {
|
||||||
@ -313,8 +313,9 @@ func CheckAccessPermission(userId string, application *Application) (bool, error
|
|||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
enforcer := getEnforcer(permission)
|
enforcer := getEnforcer(permission)
|
||||||
allowed, err = enforcer.Enforce(userId, application.Name, "read")
|
if allowed, err = enforcer.Enforce(userId, application.Name, "read"); allowed {
|
||||||
break
|
return allowed, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return allowed, err
|
return allowed, err
|
||||||
@ -322,9 +323,9 @@ func CheckAccessPermission(userId string, application *Application) (bool, error
|
|||||||
|
|
||||||
func CheckUsername(username string, lang string) string {
|
func CheckUsername(username string, lang string) string {
|
||||||
if username == "" {
|
if username == "" {
|
||||||
return i18n.Translate(lang, "UserErr.NameEmptyErr")
|
return i18n.Translate(lang, "check:Empty username.")
|
||||||
} else if len(username) > 39 {
|
} else if len(username) > 39 {
|
||||||
return i18n.Translate(lang, "UserErr.NameTooLang")
|
return i18n.Translate(lang, "check:Username is too long (maximum is 39 characters).")
|
||||||
}
|
}
|
||||||
|
|
||||||
exclude, _ := regexp.Compile("^[\u0021-\u007E]+$")
|
exclude, _ := regexp.Compile("^[\u0021-\u007E]+$")
|
||||||
@ -335,7 +336,7 @@ func CheckUsername(username string, lang string) string {
|
|||||||
// https://stackoverflow.com/questions/58726546/github-username-convention-using-regex
|
// https://stackoverflow.com/questions/58726546/github-username-convention-using-regex
|
||||||
re, _ := regexp.Compile("^[a-zA-Z0-9]+((?:-[a-zA-Z0-9]+)|(?:_[a-zA-Z0-9]+))*$")
|
re, _ := regexp.Compile("^[a-zA-Z0-9]+((?:-[a-zA-Z0-9]+)|(?:_[a-zA-Z0-9]+))*$")
|
||||||
if !re.MatchString(username) {
|
if !re.MatchString(username) {
|
||||||
return i18n.Translate(lang, "UserErr.NameFormatErr")
|
return i18n.Translate(lang, "check: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.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
@ -18,6 +18,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/i18n"
|
||||||
)
|
)
|
||||||
|
|
||||||
var reRealName *regexp.Regexp
|
var reRealName *regexp.Regexp
|
||||||
@ -43,7 +45,7 @@ func resetUserSigninErrorTimes(user *User) {
|
|||||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
||||||
}
|
}
|
||||||
|
|
||||||
func recordSigninErrorInfo(user *User) string {
|
func recordSigninErrorInfo(user *User, lang string) string {
|
||||||
// increase failed login count
|
// increase failed login count
|
||||||
user.SigninWrongTimes++
|
user.SigninWrongTimes++
|
||||||
|
|
||||||
@ -56,9 +58,9 @@ func recordSigninErrorInfo(user *User) string {
|
|||||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
||||||
leftChances := SigninWrongTimesLimit - user.SigninWrongTimes
|
leftChances := SigninWrongTimesLimit - user.SigninWrongTimes
|
||||||
if leftChances > 0 {
|
if leftChances > 0 {
|
||||||
return fmt.Sprintf("password is incorrect, you have %d remaining chances", leftChances)
|
return fmt.Sprintf(i18n.Translate(lang, "check_util:password is incorrect, you have %d remaining chances"), leftChances)
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't show the chance error message if the user has no chance left
|
// don't show the chance error message if the user has no chance left
|
||||||
return fmt.Sprintf("You have entered the wrong password too many times, please wait for %d minutes and try again", int(LastSignWrongTimeDuration.Minutes()))
|
return fmt.Sprintf(i18n.Translate(lang, "check_util:You have entered the wrong password too many times, please wait for %d minutes and try again"), int(LastSignWrongTimeDuration.Minutes()))
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,8 @@ func initBuiltInOrganization() bool {
|
|||||||
PhonePrefix: "86",
|
PhonePrefix: "86",
|
||||||
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
|
Languages: []string{"en", "zh", "es", "fr", "de", "ja", "ko", "ru"},
|
||||||
|
InitScore: 2000,
|
||||||
AccountItems: []*AccountItem{
|
AccountItems: []*AccountItem{
|
||||||
{Name: "Organization", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
{Name: "Organization", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
{Name: "ID", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
{Name: "ID", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
@ -157,7 +159,7 @@ func initBuiltInApplication() {
|
|||||||
},
|
},
|
||||||
RedirectUris: []string{},
|
RedirectUris: []string{},
|
||||||
ExpireInHours: 168,
|
ExpireInHours: 168,
|
||||||
FormOffset: 8,
|
FormOffset: 2,
|
||||||
}
|
}
|
||||||
AddApplication(application)
|
AddApplication(application)
|
||||||
}
|
}
|
||||||
@ -221,7 +223,7 @@ func initBuiltInLdap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initBuiltInProvider() {
|
func initBuiltInProvider() {
|
||||||
provider := GetProvider("admin/provider_captcha_default")
|
provider := GetProvider(util.GetId("admin", "provider_captcha_default"))
|
||||||
if provider != nil {
|
if provider != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,15 @@ type InitData struct {
|
|||||||
Certs []*Cert `json:"certs"`
|
Certs []*Cert `json:"certs"`
|
||||||
Providers []*Provider `json:"providers"`
|
Providers []*Provider `json:"providers"`
|
||||||
Ldaps []*Ldap `json:"ldaps"`
|
Ldaps []*Ldap `json:"ldaps"`
|
||||||
|
Models []*Model `json:"models"`
|
||||||
|
Permissions []*Permission `json:"permissions"`
|
||||||
|
Payments []*Payment `json:"payments"`
|
||||||
|
Products []*Product `json:"products"`
|
||||||
|
Resources []*Resource `json:"resources"`
|
||||||
|
Roles []*Role `json:"roles"`
|
||||||
|
Syncers []*Syncer `json:"syncers"`
|
||||||
|
Tokens []*Token `json:"tokens"`
|
||||||
|
Webhooks []*Webhook `json:"webhooks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitFromFile() {
|
func InitFromFile() {
|
||||||
@ -46,6 +55,33 @@ func InitFromFile() {
|
|||||||
for _, ldap := range initData.Ldaps {
|
for _, ldap := range initData.Ldaps {
|
||||||
initDefinedLdap(ldap)
|
initDefinedLdap(ldap)
|
||||||
}
|
}
|
||||||
|
for _, model := range initData.Models {
|
||||||
|
initDefinedModel(model)
|
||||||
|
}
|
||||||
|
for _, permission := range initData.Permissions {
|
||||||
|
initDefinedPermission(permission)
|
||||||
|
}
|
||||||
|
for _, payment := range initData.Payments {
|
||||||
|
initDefinedPayment(payment)
|
||||||
|
}
|
||||||
|
for _, product := range initData.Products {
|
||||||
|
initDefinedProduct(product)
|
||||||
|
}
|
||||||
|
for _, resource := range initData.Resources {
|
||||||
|
initDefinedResource(resource)
|
||||||
|
}
|
||||||
|
for _, role := range initData.Roles {
|
||||||
|
initDefinedRole(role)
|
||||||
|
}
|
||||||
|
for _, syncer := range initData.Syncers {
|
||||||
|
initDefinedSyncer(syncer)
|
||||||
|
}
|
||||||
|
for _, token := range initData.Tokens {
|
||||||
|
initDefinedToken(token)
|
||||||
|
}
|
||||||
|
for _, webhook := range initData.Webhooks {
|
||||||
|
initDefinedWebhook(webhook)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +99,15 @@ func readInitDataFromFile(filePath string) *InitData {
|
|||||||
Certs: []*Cert{},
|
Certs: []*Cert{},
|
||||||
Providers: []*Provider{},
|
Providers: []*Provider{},
|
||||||
Ldaps: []*Ldap{},
|
Ldaps: []*Ldap{},
|
||||||
|
Models: []*Model{},
|
||||||
|
Permissions: []*Permission{},
|
||||||
|
Payments: []*Payment{},
|
||||||
|
Products: []*Product{},
|
||||||
|
Resources: []*Resource{},
|
||||||
|
Roles: []*Role{},
|
||||||
|
Syncers: []*Syncer{},
|
||||||
|
Tokens: []*Token{},
|
||||||
|
Webhooks: []*Webhook{},
|
||||||
}
|
}
|
||||||
err := util.JsonToStruct(s, data)
|
err := util.JsonToStruct(s, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -89,6 +134,41 @@ func readInitDataFromFile(filePath string) *InitData {
|
|||||||
application.RedirectUris = []string{}
|
application.RedirectUris = []string{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, permission := range data.Permissions {
|
||||||
|
if permission.Actions == nil {
|
||||||
|
permission.Actions = []string{}
|
||||||
|
}
|
||||||
|
if permission.Resources == nil {
|
||||||
|
permission.Resources = []string{}
|
||||||
|
}
|
||||||
|
if permission.Roles == nil {
|
||||||
|
permission.Roles = []string{}
|
||||||
|
}
|
||||||
|
if permission.Users == nil {
|
||||||
|
permission.Users = []string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, role := range data.Roles {
|
||||||
|
if role.Roles == nil {
|
||||||
|
role.Roles = []string{}
|
||||||
|
}
|
||||||
|
if role.Users == nil {
|
||||||
|
role.Users = []string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, syncer := range data.Syncers {
|
||||||
|
if syncer.TableColumns == nil {
|
||||||
|
syncer.TableColumns = []*TableColumn{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, webhook := range data.Webhooks {
|
||||||
|
if webhook.Events == nil {
|
||||||
|
webhook.Events = []string{}
|
||||||
|
}
|
||||||
|
if webhook.Headers == nil {
|
||||||
|
webhook.Headers = []*Header{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
@ -168,9 +248,90 @@ func initDefinedLdap(ldap *Ldap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initDefinedProvider(provider *Provider) {
|
func initDefinedProvider(provider *Provider) {
|
||||||
existed := GetProvider(provider.GetId())
|
existed := GetProvider(util.GetId("admin", provider.Name))
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
AddProvider(provider)
|
AddProvider(provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initDefinedModel(model *Model) {
|
||||||
|
existed := GetModel(model.GetId())
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
model.CreatedTime = util.GetCurrentTime()
|
||||||
|
AddModel(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedPermission(permission *Permission) {
|
||||||
|
existed := GetPermission(permission.GetId())
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
permission.CreatedTime = util.GetCurrentTime()
|
||||||
|
AddPermission(permission)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedPayment(payment *Payment) {
|
||||||
|
existed := GetPayment(payment.GetId())
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
payment.CreatedTime = util.GetCurrentTime()
|
||||||
|
AddPayment(payment)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedProduct(product *Product) {
|
||||||
|
existed := GetProduct(product.GetId())
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
product.CreatedTime = util.GetCurrentTime()
|
||||||
|
AddProduct(product)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedResource(resource *Resource) {
|
||||||
|
existed := GetResource(resource.GetId())
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resource.CreatedTime = util.GetCurrentTime()
|
||||||
|
AddResource(resource)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedRole(role *Role) {
|
||||||
|
existed := GetRole(role.GetId())
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
role.CreatedTime = util.GetCurrentTime()
|
||||||
|
AddRole(role)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedSyncer(syncer *Syncer) {
|
||||||
|
existed := GetSyncer(syncer.GetId())
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
syncer.CreatedTime = util.GetCurrentTime()
|
||||||
|
AddSyncer(syncer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedToken(token *Token) {
|
||||||
|
existed := GetToken(token.GetId())
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
token.CreatedTime = util.GetCurrentTime()
|
||||||
|
AddToken(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefinedWebhook(webhook *Webhook) {
|
||||||
|
existed := GetWebhook(webhook.GetId())
|
||||||
|
if existed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
webhook.CreatedTime = util.GetCurrentTime()
|
||||||
|
AddWebhook(webhook)
|
||||||
|
}
|
||||||
|
@ -45,7 +45,9 @@ type Organization struct {
|
|||||||
DefaultAvatar string `xorm:"varchar(100)" json:"defaultAvatar"`
|
DefaultAvatar string `xorm:"varchar(100)" json:"defaultAvatar"`
|
||||||
DefaultApplication string `xorm:"varchar(100)" json:"defaultApplication"`
|
DefaultApplication string `xorm:"varchar(100)" json:"defaultApplication"`
|
||||||
Tags []string `xorm:"mediumtext" json:"tags"`
|
Tags []string `xorm:"mediumtext" json:"tags"`
|
||||||
|
Languages []string `xorm:"varchar(255)" json:"languages"`
|
||||||
MasterPassword string `xorm:"varchar(100)" json:"masterPassword"`
|
MasterPassword string `xorm:"varchar(100)" json:"masterPassword"`
|
||||||
|
InitScore int `json:"initScore"`
|
||||||
EnableSoftDeletion bool `json:"enableSoftDeletion"`
|
EnableSoftDeletion bool `json:"enableSoftDeletion"`
|
||||||
IsProfilePublic bool `json:"isProfilePublic"`
|
IsProfilePublic bool `json:"isProfilePublic"`
|
||||||
|
|
||||||
@ -203,14 +205,14 @@ func CheckAccountItemModifyRule(accountItem *AccountItem, user *User, lang strin
|
|||||||
switch accountItem.ModifyRule {
|
switch accountItem.ModifyRule {
|
||||||
case "Admin":
|
case "Admin":
|
||||||
if !(user.IsAdmin || user.IsGlobalAdmin) {
|
if !(user.IsAdmin || user.IsGlobalAdmin) {
|
||||||
return false, fmt.Sprintf(i18n.Translate(lang, "OrgErr.OnlyAdmin"), accountItem.Name)
|
return false, fmt.Sprintf(i18n.Translate(lang, "organization:Only admin can modify the %s."), accountItem.Name)
|
||||||
}
|
}
|
||||||
case "Immutable":
|
case "Immutable":
|
||||||
return false, fmt.Sprintf(i18n.Translate(lang, "OrgErr.Immutable"), accountItem.Name)
|
return false, fmt.Sprintf(i18n.Translate(lang, "organization:The %s is immutable."), accountItem.Name)
|
||||||
case "Self":
|
case "Self":
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
return false, fmt.Sprintf(i18n.Translate(lang, "OrgErr.UnknownModifyRule"), accountItem.ModifyRule)
|
return false, fmt.Sprintf(i18n.Translate(lang, "organization:Unknown modify rule %s."), accountItem.ModifyRule)
|
||||||
}
|
}
|
||||||
return true, ""
|
return true, ""
|
||||||
}
|
}
|
||||||
@ -222,7 +224,12 @@ func GetDefaultApplication(id string) (*Application, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if organization.DefaultApplication != "" {
|
if organization.DefaultApplication != "" {
|
||||||
return getApplication("admin", organization.DefaultApplication), fmt.Errorf("The default application: %s does not exist", organization.DefaultApplication)
|
defaultApplication := getApplication("admin", organization.DefaultApplication)
|
||||||
|
if defaultApplication == nil {
|
||||||
|
return nil, fmt.Errorf("The default application: %s does not exist", organization.DefaultApplication)
|
||||||
|
} else {
|
||||||
|
return defaultApplication, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applications := []*Application{}
|
applications := []*Application{}
|
||||||
|
@ -35,7 +35,7 @@ type Payment struct {
|
|||||||
ProductName string `xorm:"varchar(100)" json:"productName"`
|
ProductName string `xorm:"varchar(100)" json:"productName"`
|
||||||
ProductDisplayName string `xorm:"varchar(100)" json:"productDisplayName"`
|
ProductDisplayName string `xorm:"varchar(100)" json:"productDisplayName"`
|
||||||
|
|
||||||
Detail string `xorm:"varchar(100)" json:"detail"`
|
Detail string `xorm:"varchar(255)" json:"detail"`
|
||||||
Tag string `xorm:"varchar(100)" json:"tag"`
|
Tag string `xorm:"varchar(100)" json:"tag"`
|
||||||
Currency string `xorm:"varchar(100)" json:"currency"`
|
Currency string `xorm:"varchar(100)" json:"currency"`
|
||||||
Price float64 `json:"price"`
|
Price float64 `json:"price"`
|
||||||
|
@ -111,7 +111,27 @@ func GetPermission(id string) *Permission {
|
|||||||
return getPermission(owner, name)
|
return getPermission(owner, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkPermissionValid verifies if the permission is valid
|
||||||
|
func checkPermissionValid(permission *Permission) {
|
||||||
|
enforcer := getEnforcer(permission)
|
||||||
|
enforcer.EnableAutoSave(false)
|
||||||
|
policies, groupingPolicies := getPolicies(permission)
|
||||||
|
|
||||||
|
if len(groupingPolicies) > 0 {
|
||||||
|
_, err := enforcer.AddGroupingPolicies(groupingPolicies)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := enforcer.AddPolicies(policies)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func UpdatePermission(id string, permission *Permission) bool {
|
func UpdatePermission(id string, permission *Permission) bool {
|
||||||
|
checkPermissionValid(permission)
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
oldPermission := getPermission(owner, name)
|
oldPermission := getPermission(owner, name)
|
||||||
if oldPermission == nil {
|
if oldPermission == nil {
|
||||||
|
@ -29,7 +29,9 @@ func getEnforcer(permission *Permission) *casbin.Enforcer {
|
|||||||
tableName = permission.Adapter
|
tableName = permission.Adapter
|
||||||
}
|
}
|
||||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||||
adapter, err := xormadapter.NewAdapterWithTableName(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName()+conf.GetConfigString("dbName"), tableName, tableNamePrefix, true)
|
driverName := conf.GetConfigString("driverName")
|
||||||
|
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
|
||||||
|
adapter, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, tableName, tableNamePrefix, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -39,7 +41,7 @@ func getEnforcer(permission *Permission) *casbin.Enforcer {
|
|||||||
r = sub, obj, act
|
r = sub, obj, act
|
||||||
|
|
||||||
[policy_definition]
|
[policy_definition]
|
||||||
p = sub, obj, act
|
p = sub, obj, act, "", "", permissionId
|
||||||
|
|
||||||
[role_definition]
|
[role_definition]
|
||||||
g = _, _
|
g = _, _
|
||||||
@ -63,22 +65,27 @@ m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load Policy with a specific Permission
|
||||||
|
enforcer.LoadFilteredPolicy(xormadapter.Filter{
|
||||||
|
V5: []string{permission.Owner + "/" + permission.Name},
|
||||||
|
})
|
||||||
return enforcer
|
return enforcer
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPolicies(permission *Permission) ([][]string, [][]string) {
|
func getPolicies(permission *Permission) ([][]string, [][]string) {
|
||||||
var policies [][]string
|
var policies [][]string
|
||||||
var groupingPolicies [][]string
|
var groupingPolicies [][]string
|
||||||
|
permissionId := permission.Owner + "/" + permission.Name
|
||||||
domainExist := len(permission.Domains) > 0
|
domainExist := len(permission.Domains) > 0
|
||||||
for _, user := range permission.Users {
|
for _, user := range permission.Users {
|
||||||
for _, resource := range permission.Resources {
|
for _, resource := range permission.Resources {
|
||||||
for _, action := range permission.Actions {
|
for _, action := range permission.Actions {
|
||||||
if domainExist {
|
if domainExist {
|
||||||
for _, domain := range permission.Domains {
|
for _, domain := range permission.Domains {
|
||||||
policies = append(policies, []string{user, domain, resource, strings.ToLower(action)})
|
policies = append(policies, []string{user, domain, resource, strings.ToLower(action), "", permissionId})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
policies = append(policies, []string{user, resource, strings.ToLower(action)})
|
policies = append(policies, []string{user, resource, strings.ToLower(action), "", "", permissionId})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,29 +95,29 @@ func getPolicies(permission *Permission) ([][]string, [][]string) {
|
|||||||
for _, subUser := range roleObj.Users {
|
for _, subUser := range roleObj.Users {
|
||||||
if domainExist {
|
if domainExist {
|
||||||
for _, domain := range permission.Domains {
|
for _, domain := range permission.Domains {
|
||||||
groupingPolicies = append(groupingPolicies, []string{subUser, domain, role})
|
groupingPolicies = append(groupingPolicies, []string{subUser, domain, role, "", "", permissionId})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
groupingPolicies = append(groupingPolicies, []string{subUser, role})
|
groupingPolicies = append(groupingPolicies, []string{subUser, role, "", "", "", permissionId})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, subRole := range roleObj.Roles {
|
for _, subRole := range roleObj.Roles {
|
||||||
if domainExist {
|
if domainExist {
|
||||||
for _, domain := range permission.Domains {
|
for _, domain := range permission.Domains {
|
||||||
groupingPolicies = append(groupingPolicies, []string{subRole, domain, role})
|
groupingPolicies = append(groupingPolicies, []string{subRole, domain, role, "", "", permissionId})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
groupingPolicies = append(groupingPolicies, []string{subRole, role})
|
groupingPolicies = append(groupingPolicies, []string{subRole, role, "", "", "", permissionId})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, resource := range permission.Resources {
|
for _, resource := range permission.Resources {
|
||||||
for _, action := range permission.Actions {
|
for _, action := range permission.Actions {
|
||||||
if domainExist {
|
if domainExist {
|
||||||
for _, domain := range permission.Domains {
|
for _, domain := range permission.Domains {
|
||||||
policies = append(policies, []string{role, domain, resource, strings.ToLower(action)})
|
policies = append(policies, []string{role, domain, resource, strings.ToLower(action), "", permissionId})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
policies = append(policies, []string{role, resource, strings.ToLower(action)})
|
policies = append(policies, []string{role, resource, strings.ToLower(action), "", "", permissionId})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,20 +159,29 @@ func removePolicies(permission *Permission) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Enforce(userId string, permissionRule *PermissionRule) bool {
|
func Enforce(permissionRule *PermissionRule) bool {
|
||||||
permission := GetPermission(permissionRule.Id)
|
permission := GetPermission(permissionRule.Id)
|
||||||
enforcer := getEnforcer(permission)
|
enforcer := getEnforcer(permission)
|
||||||
allow, err := enforcer.Enforce(userId, permissionRule.V1, permissionRule.V2)
|
|
||||||
|
request := []interface{}{permissionRule.V0, permissionRule.V1, permissionRule.V2}
|
||||||
|
if permissionRule.V3 != "" {
|
||||||
|
request = append(request, permissionRule.V3)
|
||||||
|
}
|
||||||
|
allow, err := enforcer.Enforce(request...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return allow
|
return allow
|
||||||
}
|
}
|
||||||
|
|
||||||
func BatchEnforce(userId string, permissionRules []PermissionRule) []bool {
|
func BatchEnforce(permissionRules []PermissionRule) []bool {
|
||||||
var requests [][]interface{}
|
var requests [][]interface{}
|
||||||
for _, permissionRule := range permissionRules {
|
for _, permissionRule := range permissionRules {
|
||||||
requests = append(requests, []interface{}{userId, permissionRule.V1, permissionRule.V2})
|
if permissionRule.V3 != "" {
|
||||||
|
requests = append(requests, []interface{}{permissionRule.V0, permissionRule.V1, permissionRule.V2, permissionRule.V3})
|
||||||
|
} else {
|
||||||
|
requests = append(requests, []interface{}{permissionRule.V0, permissionRule.V1, permissionRule.V2})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
permission := GetPermission(permissionRules[0].Id)
|
permission := GetPermission(permissionRules[0].Id)
|
||||||
enforcer := getEnforcer(permission)
|
enforcer := getEnforcer(permission)
|
||||||
|
@ -27,15 +27,16 @@ type Product struct {
|
|||||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||||
|
|
||||||
Image string `xorm:"varchar(100)" json:"image"`
|
Image string `xorm:"varchar(100)" json:"image"`
|
||||||
Detail string `xorm:"varchar(100)" json:"detail"`
|
Detail string `xorm:"varchar(255)" json:"detail"`
|
||||||
Tag string `xorm:"varchar(100)" json:"tag"`
|
Description string `xorm:"varchar(100)" json:"description"`
|
||||||
Currency string `xorm:"varchar(100)" json:"currency"`
|
Tag string `xorm:"varchar(100)" json:"tag"`
|
||||||
Price float64 `json:"price"`
|
Currency string `xorm:"varchar(100)" json:"currency"`
|
||||||
Quantity int `json:"quantity"`
|
Price float64 `json:"price"`
|
||||||
Sold int `json:"sold"`
|
Quantity int `json:"quantity"`
|
||||||
Providers []string `xorm:"varchar(100)" json:"providers"`
|
Sold int `json:"sold"`
|
||||||
ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"`
|
Providers []string `xorm:"varchar(100)" json:"providers"`
|
||||||
|
ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"`
|
||||||
|
|
||||||
State string `xorm:"varchar(100)" json:"state"`
|
State string `xorm:"varchar(100)" json:"state"`
|
||||||
|
|
||||||
@ -213,6 +214,10 @@ func BuyProduct(id string, providerName string, user *User, host string) (string
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ExtendProductWithProviders(product *Product) {
|
func ExtendProductWithProviders(product *Product) {
|
||||||
|
if product == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
product.ProviderObjs = []*Provider{}
|
product.ProviderObjs = []*Provider{}
|
||||||
|
|
||||||
m := getProviderMap(product.Owner)
|
m := getProviderMap(product.Owner)
|
||||||
|
@ -25,7 +25,7 @@ import (
|
|||||||
|
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
||||||
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
Name string `xorm:"varchar(100) notnull pk unique" json:"name"`
|
||||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||||
|
|
||||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||||
@ -46,9 +46,9 @@ type Provider struct {
|
|||||||
|
|
||||||
Host string `xorm:"varchar(100)" json:"host"`
|
Host string `xorm:"varchar(100)" json:"host"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
DisableSsl bool `json:"disableSsl"`
|
DisableSsl bool `json:"disableSsl"` // If the provider type is WeChat, DisableSsl means EnableQRCode
|
||||||
Title string `xorm:"varchar(100)" json:"title"`
|
Title string `xorm:"varchar(100)" json:"title"`
|
||||||
Content string `xorm:"varchar(1000)" json:"content"`
|
Content string `xorm:"varchar(1000)" json:"content"` // If provider type is WeChat, Content means QRCode string by Base64 encoding
|
||||||
Receiver string `xorm:"varchar(100)" json:"receiver"`
|
Receiver string `xorm:"varchar(100)" json:"receiver"`
|
||||||
|
|
||||||
RegionId string `xorm:"varchar(100)" json:"regionId"`
|
RegionId string `xorm:"varchar(100)" json:"regionId"`
|
||||||
@ -93,8 +93,8 @@ func GetMaskedProviders(providers []*Provider) []*Provider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetProviderCount(owner, field, value string) int {
|
func GetProviderCount(owner, field, value string) int {
|
||||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
session := GetSession("", -1, -1, field, value, "", "")
|
||||||
count, err := session.Count(&Provider{})
|
count, err := session.Where("owner = ? or owner = ? ", "admin", owner).Count(&Provider{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ func GetGlobalProviderCount(field, value string) int {
|
|||||||
|
|
||||||
func GetProviders(owner string) []*Provider {
|
func GetProviders(owner string) []*Provider {
|
||||||
providers := []*Provider{}
|
providers := []*Provider{}
|
||||||
err := adapter.Engine.Desc("created_time").Find(&providers, &Provider{Owner: owner})
|
err := adapter.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&providers, &Provider{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -133,9 +133,9 @@ func GetGlobalProviders() []*Provider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetPaginationProviders(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Provider {
|
func GetPaginationProviders(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Provider {
|
||||||
var providers []*Provider
|
providers := []*Provider{}
|
||||||
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
|
||||||
err := session.Find(&providers)
|
err := session.Where("owner = ? or owner = ? ", "admin", owner).Find(&providers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ func GetPaginationProviders(owner string, offset, limit int, field, value, sortF
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetPaginationGlobalProviders(offset, limit int, field, value, sortField, sortOrder string) []*Provider {
|
func GetPaginationGlobalProviders(offset, limit int, field, value, sortField, sortOrder string) []*Provider {
|
||||||
var providers []*Provider
|
providers := []*Provider{}
|
||||||
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
|
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
|
||||||
err := session.Find(&providers)
|
err := session.Find(&providers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -159,7 +159,7 @@ func getProvider(owner string, name string) *Provider {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := Provider{Owner: owner, Name: name}
|
provider := Provider{Name: name}
|
||||||
existed, err := adapter.Engine.Get(&provider)
|
existed, err := adapter.Engine.Get(&provider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -277,7 +277,7 @@ func GetCaptchaProviderByOwnerName(applicationId, lang string) (*Provider, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !existed {
|
if !existed {
|
||||||
return nil, fmt.Errorf(i18n.Translate(lang, "ProviderErr.DoNotExist"), applicationId)
|
return nil, fmt.Errorf(i18n.Translate(lang, "provider:the provider: %s does not exist"), applicationId)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &provider, nil
|
return &provider, nil
|
||||||
@ -289,7 +289,7 @@ func GetCaptchaProviderByApplication(applicationId, isCurrentProvider, lang stri
|
|||||||
}
|
}
|
||||||
application := GetApplication(applicationId)
|
application := GetApplication(applicationId)
|
||||||
if application == nil || len(application.Providers) == 0 {
|
if application == nil || len(application.Providers) == 0 {
|
||||||
return nil, fmt.Errorf(i18n.Translate(lang, "ApplicationErr.InvalidID"))
|
return nil, fmt.Errorf(i18n.Translate(lang, "provider:Invalid application id"))
|
||||||
}
|
}
|
||||||
for _, provider := range application.Providers {
|
for _, provider := range application.Providers {
|
||||||
if provider.Provider == nil {
|
if provider.Provider == nil {
|
||||||
|
@ -15,7 +15,9 @@
|
|||||||
package object
|
package object
|
||||||
|
|
||||||
type ProviderItem struct {
|
type ProviderItem struct {
|
||||||
Name string `json:"name"`
|
Owner string `json:"owner"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
CanSignUp bool `json:"canSignUp"`
|
CanSignUp bool `json:"canSignUp"`
|
||||||
CanSignIn bool `json:"canSignIn"`
|
CanSignIn bool `json:"canSignIn"`
|
||||||
CanUnlink bool `json:"canUnlink"`
|
CanUnlink bool `json:"canUnlink"`
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
|
|
||||||
type Resource struct {
|
type Resource struct {
|
||||||
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
||||||
Name string `xorm:"varchar(250) notnull pk" json:"name"`
|
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||||
|
|
||||||
User string `xorm:"varchar(100)" json:"user"`
|
User string `xorm:"varchar(100)" json:"user"`
|
||||||
@ -31,12 +31,12 @@ type Resource struct {
|
|||||||
Application string `xorm:"varchar(100)" json:"application"`
|
Application string `xorm:"varchar(100)" json:"application"`
|
||||||
Tag string `xorm:"varchar(100)" json:"tag"`
|
Tag string `xorm:"varchar(100)" json:"tag"`
|
||||||
Parent string `xorm:"varchar(100)" json:"parent"`
|
Parent string `xorm:"varchar(100)" json:"parent"`
|
||||||
FileName string `xorm:"varchar(1000)" json:"fileName"`
|
FileName string `xorm:"varchar(255)" json:"fileName"`
|
||||||
FileType string `xorm:"varchar(100)" json:"fileType"`
|
FileType string `xorm:"varchar(100)" json:"fileType"`
|
||||||
FileFormat string `xorm:"varchar(100)" json:"fileFormat"`
|
FileFormat string `xorm:"varchar(100)" json:"fileFormat"`
|
||||||
FileSize int `json:"fileSize"`
|
FileSize int `json:"fileSize"`
|
||||||
Url string `xorm:"varchar(1000)" json:"url"`
|
Url string `xorm:"varchar(255)" json:"url"`
|
||||||
Description string `xorm:"varchar(1000)" json:"description"`
|
Description string `xorm:"varchar(255)" json:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetResourceCount(owner, user, field, value string) int {
|
func GetResourceCount(owner, user, field, value string) int {
|
||||||
|
@ -240,8 +240,8 @@ func GetSamlResponse(application *Application, user *User, samlRequest string, h
|
|||||||
}
|
}
|
||||||
|
|
||||||
// verify samlRequest
|
// verify samlRequest
|
||||||
if valid := CheckRedirectUriValid(application, authnRequest.Issuer.Url); !valid {
|
if isValid := application.IsRedirectUriValid(authnRequest.Issuer.Url); !isValid {
|
||||||
return "", "", fmt.Errorf("err: invalid issuer url")
|
return "", "", fmt.Errorf("err: Issuer URI: %s doesn't exist in the allowed Redirect URI list", authnRequest.Issuer.Url)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get certificate string
|
// get certificate string
|
||||||
@ -251,6 +251,11 @@ func GetSamlResponse(application *Application, user *User, samlRequest string, h
|
|||||||
|
|
||||||
_, originBackend := getOriginFromHost(host)
|
_, originBackend := getOriginFromHost(host)
|
||||||
|
|
||||||
|
// redirect Url (Assertion Consumer Url)
|
||||||
|
if application.SamlReplyUrl != "" {
|
||||||
|
authnRequest.AssertionConsumerServiceURL = application.SamlReplyUrl
|
||||||
|
}
|
||||||
|
|
||||||
// build signedResponse
|
// build signedResponse
|
||||||
samlResponse, _ := NewSamlResponse(user, originBackend, certificate, authnRequest.AssertionConsumerServiceURL, authnRequest.Issuer.Url, authnRequest.ID, application.RedirectUris)
|
samlResponse, _ := NewSamlResponse(user, originBackend, certificate, authnRequest.AssertionConsumerServiceURL, authnRequest.Issuer.Url, authnRequest.ID, application.RedirectUris)
|
||||||
randomKeyStore := &X509Key{
|
randomKeyStore := &X509Key{
|
||||||
|
@ -45,7 +45,7 @@ func ParseSamlResponse(samlResponse string, providerType string) (string, error)
|
|||||||
func GenerateSamlLoginUrl(id, relayState, lang string) (string, string, error) {
|
func GenerateSamlLoginUrl(id, relayState, lang string) (string, string, error) {
|
||||||
provider := GetProvider(id)
|
provider := GetProvider(id)
|
||||||
if provider.Category != "SAML" {
|
if provider.Category != "SAML" {
|
||||||
return "", "", fmt.Errorf(i18n.Translate(lang, "ProviderErr.CategoryNotSAML"), provider.Name)
|
return "", "", fmt.Errorf(i18n.Translate(lang, "saml_sp:provider %s's category is not SAML"), provider.Name)
|
||||||
}
|
}
|
||||||
sp, err := buildSp(provider, "")
|
sp, err := buildSp(provider, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -54,7 +54,7 @@ func escapePath(path string) string {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool) (string, string) {
|
func GetUploadFileUrl(provider *Provider, fullFilePath string, hasTimestamp bool) (string, string) {
|
||||||
escapedPath := util.UrlJoin(provider.PathPrefix, escapePath(fullFilePath))
|
escapedPath := util.UrlJoin(provider.PathPrefix, escapePath(fullFilePath))
|
||||||
objectKey := util.UrlJoin(util.GetUrlPath(provider.Domain), escapedPath)
|
objectKey := util.UrlJoin(util.GetUrlPath(provider.Domain), escapedPath)
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ func uploadFile(provider *Provider, fullFilePath string, fileBuffer *bytes.Buffe
|
|||||||
UpdateProvider(provider.GetId(), provider)
|
UpdateProvider(provider.GetId(), provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileUrl, objectKey := getUploadFileUrl(provider, fullFilePath, true)
|
fileUrl, objectKey := GetUploadFileUrl(provider, fullFilePath, true)
|
||||||
|
|
||||||
_, err := storageProvider.Put(objectKey, fileBuffer)
|
_, err := storageProvider.Put(objectKey, fileBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -130,13 +130,13 @@ func UploadFileSafe(provider *Provider, fullFilePath string, fileBuffer *bytes.B
|
|||||||
func DeleteFile(provider *Provider, objectKey string, lang string) error {
|
func DeleteFile(provider *Provider, objectKey string, lang string) error {
|
||||||
// check fullFilePath is there security issue
|
// check fullFilePath is there security issue
|
||||||
if strings.Contains(objectKey, "..") {
|
if strings.Contains(objectKey, "..") {
|
||||||
return fmt.Errorf(i18n.Translate(lang, "StorageErr.ObjectKeyNotAllowed"), objectKey)
|
return fmt.Errorf(i18n.Translate(lang, "storage:The objectKey: %s is not allowed"), objectKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint := getProviderEndpoint(provider)
|
endpoint := getProviderEndpoint(provider)
|
||||||
storageProvider := storage.GetStorageProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.RegionId, provider.Bucket, endpoint)
|
storageProvider := storage.GetStorageProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.RegionId, provider.Bucket, endpoint)
|
||||||
if storageProvider == nil {
|
if storageProvider == nil {
|
||||||
return fmt.Errorf(i18n.Translate(lang, "ProviderErr.ProviderNotSupported"), provider.Type)
|
return fmt.Errorf(i18n.Translate(lang, "storage:The provider type: %s is not supported"), provider.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
if provider.Domain == "" {
|
if provider.Domain == "" {
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/i18n"
|
"github.com/casdoor/casdoor/i18n"
|
||||||
@ -169,6 +168,10 @@ func GetToken(id string) *Token {
|
|||||||
return getToken(owner, name)
|
return getToken(owner, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (token *Token) GetId() string {
|
||||||
|
return fmt.Sprintf("%s/%s", token.Owner, token.Name)
|
||||||
|
}
|
||||||
|
|
||||||
func UpdateToken(id string, token *Token) bool {
|
func UpdateToken(id string, token *Token) bool {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
if getToken(owner, name) == nil {
|
if getToken(owner, name) == nil {
|
||||||
@ -241,23 +244,16 @@ func GetTokenByTokenAndApplication(token string, application string) *Token {
|
|||||||
|
|
||||||
func CheckOAuthLogin(clientId string, responseType string, redirectUri string, scope string, state string, lang string) (string, *Application) {
|
func CheckOAuthLogin(clientId string, responseType string, redirectUri string, scope string, state string, lang string) (string, *Application) {
|
||||||
if responseType != "code" && responseType != "token" && responseType != "id_token" {
|
if responseType != "code" && responseType != "token" && responseType != "id_token" {
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "ApplicationErr.GrantTypeNotSupport"), responseType), nil
|
return fmt.Sprintf(i18n.Translate(lang, "token:Grant_type: %s is not supported in this application"), responseType), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
application := GetApplicationByClientId(clientId)
|
application := GetApplicationByClientId(clientId)
|
||||||
if application == nil {
|
if application == nil {
|
||||||
return i18n.Translate(lang, "TokenErr.InvalidClientId"), nil
|
return i18n.Translate(lang, "token:Invalid client_id"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
validUri := false
|
if !application.IsRedirectUriValid(redirectUri) {
|
||||||
for _, tmpUri := range application.RedirectUris {
|
return fmt.Sprintf(i18n.Translate(lang, "token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), redirectUri), application
|
||||||
if strings.Contains(redirectUri, tmpUri) {
|
|
||||||
validUri = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !validUri {
|
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "TokenErr.RedirectURIDoNotExist"), redirectUri), application
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mask application for /api/get-app-login
|
// Mask application for /api/get-app-login
|
||||||
@ -269,7 +265,7 @@ func GetOAuthCode(userId string, clientId string, responseType string, redirectU
|
|||||||
user := GetUser(userId)
|
user := GetUser(userId)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return &Code{
|
return &Code{
|
||||||
Message: fmt.Sprintf("The user: %s doesn't exist", userId),
|
Message: fmt.Sprintf("token:The user: %s doesn't exist", userId),
|
||||||
Code: "",
|
Code: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -678,7 +674,7 @@ func GetWechatMiniProgramToken(application *Application, code string, host strin
|
|||||||
ErrorDescription: "the application does not support wechat mini program",
|
ErrorDescription: "the application does not support wechat mini program",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
provider := GetProvider(util.GetId(mpProvider.Name))
|
provider := GetProvider(util.GetId("admin", mpProvider.Name))
|
||||||
mpIdp := idp.NewWeChatMiniProgramIdProvider(provider.ClientId, provider.ClientSecret)
|
mpIdp := idp.NewWeChatMiniProgramIdProvider(provider.ClientId, provider.ClientSecret)
|
||||||
session, err := mpIdp.GetSessionByCode(code)
|
session, err := mpIdp.GetSessionByCode(code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -24,9 +24,10 @@ import (
|
|||||||
|
|
||||||
type Claims struct {
|
type Claims struct {
|
||||||
*User
|
*User
|
||||||
Nonce string `json:"nonce,omitempty"`
|
TokenType string `json:"tokenType,omitempty"`
|
||||||
Tag string `json:"tag,omitempty"`
|
Nonce string `json:"nonce,omitempty"`
|
||||||
Scope string `json:"scope,omitempty"`
|
Tag string `json:"tag,omitempty"`
|
||||||
|
Scope string `json:"scope,omitempty"`
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,8 +38,9 @@ type UserShort struct {
|
|||||||
|
|
||||||
type ClaimsShort struct {
|
type ClaimsShort struct {
|
||||||
*UserShort
|
*UserShort
|
||||||
Nonce string `json:"nonce,omitempty"`
|
TokenType string `json:"tokenType,omitempty"`
|
||||||
Scope string `json:"scope,omitempty"`
|
Nonce string `json:"nonce,omitempty"`
|
||||||
|
Scope string `json:"scope,omitempty"`
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,6 +55,7 @@ func getShortUser(user *User) *UserShort {
|
|||||||
func getShortClaims(claims Claims) ClaimsShort {
|
func getShortClaims(claims Claims) ClaimsShort {
|
||||||
res := ClaimsShort{
|
res := ClaimsShort{
|
||||||
UserShort: getShortUser(claims.User),
|
UserShort: getShortUser(claims.User),
|
||||||
|
TokenType: claims.TokenType,
|
||||||
Nonce: claims.Nonce,
|
Nonce: claims.Nonce,
|
||||||
Scope: claims.Scope,
|
Scope: claims.Scope,
|
||||||
RegisteredClaims: claims.RegisteredClaims,
|
RegisteredClaims: claims.RegisteredClaims,
|
||||||
@ -72,8 +75,9 @@ func generateJwtToken(application *Application, user *User, nonce string, scope
|
|||||||
jti := fmt.Sprintf("%s/%s", application.Owner, name)
|
jti := fmt.Sprintf("%s/%s", application.Owner, name)
|
||||||
|
|
||||||
claims := Claims{
|
claims := Claims{
|
||||||
User: user,
|
User: user,
|
||||||
Nonce: nonce,
|
TokenType: "access-token",
|
||||||
|
Nonce: nonce,
|
||||||
// FIXME: A workaround for custom claim by reusing `tag` in user info
|
// FIXME: A workaround for custom claim by reusing `tag` in user info
|
||||||
Tag: user.Tag,
|
Tag: user.Tag,
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
@ -97,10 +101,12 @@ func generateJwtToken(application *Application, user *User, nonce string, scope
|
|||||||
|
|
||||||
token = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsShort)
|
token = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsShort)
|
||||||
claimsShort.ExpiresAt = jwt.NewNumericDate(refreshExpireTime)
|
claimsShort.ExpiresAt = jwt.NewNumericDate(refreshExpireTime)
|
||||||
|
claimsShort.TokenType = "refresh-token"
|
||||||
refreshToken = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsShort)
|
refreshToken = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsShort)
|
||||||
} else {
|
} else {
|
||||||
token = jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
|
token = jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
|
||||||
claims.ExpiresAt = jwt.NewNumericDate(refreshExpireTime)
|
claims.ExpiresAt = jwt.NewNumericDate(refreshExpireTime)
|
||||||
|
claims.TokenType = "refresh-token"
|
||||||
refreshToken = jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
|
refreshToken = jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +102,7 @@ type User struct {
|
|||||||
Bilibili string `xorm:"bilibili varchar(100)" json:"bilibili"`
|
Bilibili string `xorm:"bilibili varchar(100)" json:"bilibili"`
|
||||||
Okta string `xorm:"okta varchar(100)" json:"okta"`
|
Okta string `xorm:"okta varchar(100)" json:"okta"`
|
||||||
Douyin string `xorm:"douyin varchar(100)" json:"douyin"`
|
Douyin string `xorm:"douyin varchar(100)" json:"douyin"`
|
||||||
|
Line string `xorm:"line varchar(100)" json:"line"`
|
||||||
Custom string `xorm:"custom varchar(100)" json:"custom"`
|
Custom string `xorm:"custom varchar(100)" json:"custom"`
|
||||||
|
|
||||||
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
|
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
|
||||||
|
@ -41,38 +41,7 @@ type VerificationRecord struct {
|
|||||||
IsUsed bool
|
IsUsed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendVerificationCodeToEmail(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
|
func IsAllowSend(user *User, remoteAddr, recordType string) error {
|
||||||
if provider == nil {
|
|
||||||
return fmt.Errorf("please set an Email provider first")
|
|
||||||
}
|
|
||||||
|
|
||||||
sender := organization.DisplayName
|
|
||||||
title := provider.Title
|
|
||||||
code := getRandomCode(6)
|
|
||||||
// "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes."
|
|
||||||
content := fmt.Sprintf(provider.Content, code)
|
|
||||||
|
|
||||||
if err := SendEmail(provider, title, content, dest, sender); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return AddToVerificationRecord(user, provider, remoteAddr, provider.Category, dest, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendVerificationCodeToPhone(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
|
|
||||||
if provider == nil {
|
|
||||||
return errors.New("please set a SMS provider first")
|
|
||||||
}
|
|
||||||
|
|
||||||
code := getRandomCode(6)
|
|
||||||
if err := SendSms(provider, code, dest); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return AddToVerificationRecord(user, provider, remoteAddr, provider.Category, dest, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddToVerificationRecord(user *User, provider *Provider, remoteAddr, recordType, dest, code string) error {
|
|
||||||
var record VerificationRecord
|
var record VerificationRecord
|
||||||
record.RemoteAddr = remoteAddr
|
record.RemoteAddr = remoteAddr
|
||||||
record.Type = recordType
|
record.Type = recordType
|
||||||
@ -89,6 +58,63 @@ func AddToVerificationRecord(user *User, provider *Provider, remoteAddr, recordT
|
|||||||
return errors.New("you can only send one code in 60s")
|
return errors.New("you can only send one code in 60s")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendVerificationCodeToEmail(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
|
||||||
|
if provider == nil {
|
||||||
|
return fmt.Errorf("please set an Email provider first")
|
||||||
|
}
|
||||||
|
|
||||||
|
sender := organization.DisplayName
|
||||||
|
title := provider.Title
|
||||||
|
code := getRandomCode(6)
|
||||||
|
// "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes."
|
||||||
|
content := fmt.Sprintf(provider.Content, code)
|
||||||
|
|
||||||
|
if err := IsAllowSend(user, remoteAddr, provider.Category); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := SendEmail(provider, title, content, dest, sender); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := AddToVerificationRecord(user, provider, remoteAddr, provider.Category, dest, code); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendVerificationCodeToPhone(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
|
||||||
|
if provider == nil {
|
||||||
|
return errors.New("please set a SMS provider first")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := IsAllowSend(user, remoteAddr, provider.Category); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
code := getRandomCode(6)
|
||||||
|
if err := SendSms(provider, code, dest); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := AddToVerificationRecord(user, provider, remoteAddr, provider.Category, dest, code); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddToVerificationRecord(user *User, provider *Provider, remoteAddr, recordType, dest, code string) error {
|
||||||
|
var record VerificationRecord
|
||||||
|
record.RemoteAddr = remoteAddr
|
||||||
|
record.Type = recordType
|
||||||
|
if user != nil {
|
||||||
|
record.User = user.GetId()
|
||||||
|
}
|
||||||
record.Owner = provider.Owner
|
record.Owner = provider.Owner
|
||||||
record.Name = util.GenerateId()
|
record.Name = util.GenerateId()
|
||||||
record.CreatedTime = util.GetCurrentTime()
|
record.CreatedTime = util.GetCurrentTime()
|
||||||
@ -99,10 +125,10 @@ func AddToVerificationRecord(user *User, provider *Provider, remoteAddr, recordT
|
|||||||
|
|
||||||
record.Receiver = dest
|
record.Receiver = dest
|
||||||
record.Code = code
|
record.Code = code
|
||||||
record.Time = now
|
record.Time = time.Now().Unix()
|
||||||
record.IsUsed = false
|
record.IsUsed = false
|
||||||
|
|
||||||
_, err = adapter.Engine.Insert(record)
|
_, err := adapter.Engine.Insert(record)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -127,7 +153,7 @@ func CheckVerificationCode(dest, code, lang string) string {
|
|||||||
record := getVerificationRecord(dest)
|
record := getVerificationRecord(dest)
|
||||||
|
|
||||||
if record == nil {
|
if record == nil {
|
||||||
return i18n.Translate(lang, "PhoneErr.CodeNotSent")
|
return i18n.Translate(lang, "verification:Code has not been sent yet!")
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout, err := conf.GetConfigInt64("verificationCodeTimeout")
|
timeout, err := conf.GetConfigInt64("verificationCodeTimeout")
|
||||||
@ -137,7 +163,7 @@ func CheckVerificationCode(dest, code, lang string) string {
|
|||||||
|
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
if now-record.Time > timeout*60 {
|
if now-record.Time > timeout*60 {
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "PhoneErr.CodeTimeOut"), timeout)
|
return fmt.Sprintf(i18n.Translate(lang, "verification:You should verify your code in %d min!"), timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
if record.Code != code {
|
if record.Code != code {
|
||||||
|
@ -37,7 +37,7 @@ type Webhook struct {
|
|||||||
Method string `xorm:"varchar(100)" json:"method"`
|
Method string `xorm:"varchar(100)" json:"method"`
|
||||||
ContentType string `xorm:"varchar(100)" json:"contentType"`
|
ContentType string `xorm:"varchar(100)" json:"contentType"`
|
||||||
Headers []*Header `xorm:"mediumtext" json:"headers"`
|
Headers []*Header `xorm:"mediumtext" json:"headers"`
|
||||||
Events []string `xorm:"varchar(100)" json:"events"`
|
Events []string `xorm:"varchar(1000)" json:"events"`
|
||||||
IsUserExtended bool `json:"isUserExtended"`
|
IsUserExtended bool `json:"isUserExtended"`
|
||||||
IsEnabled bool `json:"isEnabled"`
|
IsEnabled bool `json:"isEnabled"`
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ func CorsFilter(ctx *context.Context) {
|
|||||||
originConf := conf.GetConfigString("origin")
|
originConf := conf.GetConfigString("origin")
|
||||||
|
|
||||||
if origin != "" && originConf != "" && origin != originConf {
|
if origin != "" && originConf != "" && origin != originConf {
|
||||||
if object.IsAllowOrigin(origin) {
|
if object.IsOriginAllowed(origin) {
|
||||||
ctx.Output.Header(headerAllowOrigin, origin)
|
ctx.Output.Header(headerAllowOrigin, origin)
|
||||||
ctx.Output.Header(headerAllowMethods, "POST, GET, OPTIONS")
|
ctx.Output.Header(headerAllowMethods, "POST, GET, OPTIONS")
|
||||||
ctx.Output.Header(headerAllowHeaders, "Content-Type, Authorization")
|
ctx.Output.Header(headerAllowHeaders, "Content-Type, Authorization")
|
||||||
|
@ -54,6 +54,8 @@ func initAPI() {
|
|||||||
beego.Router("/api/get-saml-login", &controllers.ApiController{}, "GET:GetSamlLogin")
|
beego.Router("/api/get-saml-login", &controllers.ApiController{}, "GET:GetSamlLogin")
|
||||||
beego.Router("/api/acs", &controllers.ApiController{}, "POST:HandleSamlLogin")
|
beego.Router("/api/acs", &controllers.ApiController{}, "POST:HandleSamlLogin")
|
||||||
beego.Router("/api/saml/metadata", &controllers.ApiController{}, "GET:GetSamlMeta")
|
beego.Router("/api/saml/metadata", &controllers.ApiController{}, "GET:GetSamlMeta")
|
||||||
|
beego.Router("/api/webhook", &controllers.ApiController{}, "POST:HandleOfficialAccountEvent")
|
||||||
|
beego.Router("/api/get-webhook-event", &controllers.ApiController{}, "GET:GetWebhookEventType")
|
||||||
|
|
||||||
beego.Router("/api/get-organizations", &controllers.ApiController{}, "GET:GetOrganizations")
|
beego.Router("/api/get-organizations", &controllers.ApiController{}, "GET:GetOrganizations")
|
||||||
beego.Router("/api/get-organization", &controllers.ApiController{}, "GET:GetOrganization")
|
beego.Router("/api/get-organization", &controllers.ApiController{}, "GET:GetOrganization")
|
||||||
@ -80,6 +82,7 @@ func initAPI() {
|
|||||||
|
|
||||||
beego.Router("/api/get-permissions", &controllers.ApiController{}, "GET:GetPermissions")
|
beego.Router("/api/get-permissions", &controllers.ApiController{}, "GET:GetPermissions")
|
||||||
beego.Router("/api/get-permissions-by-submitter", &controllers.ApiController{}, "GET:GetPermissionsBySubmitter")
|
beego.Router("/api/get-permissions-by-submitter", &controllers.ApiController{}, "GET:GetPermissionsBySubmitter")
|
||||||
|
beego.Router("/api/get-permissions-by-role", &controllers.ApiController{}, "GET:GetPermissionsByRole")
|
||||||
beego.Router("/api/get-permission", &controllers.ApiController{}, "GET:GetPermission")
|
beego.Router("/api/get-permission", &controllers.ApiController{}, "GET:GetPermission")
|
||||||
beego.Router("/api/update-permission", &controllers.ApiController{}, "POST:UpdatePermission")
|
beego.Router("/api/update-permission", &controllers.ApiController{}, "POST:UpdatePermission")
|
||||||
beego.Router("/api/add-permission", &controllers.ApiController{}, "POST:AddPermission")
|
beego.Router("/api/add-permission", &controllers.ApiController{}, "POST:AddPermission")
|
||||||
@ -103,6 +106,9 @@ func initAPI() {
|
|||||||
beego.Router("/api/add-adapter", &controllers.ApiController{}, "POST:AddCasbinAdapter")
|
beego.Router("/api/add-adapter", &controllers.ApiController{}, "POST:AddCasbinAdapter")
|
||||||
beego.Router("/api/delete-adapter", &controllers.ApiController{}, "POST:DeleteCasbinAdapter")
|
beego.Router("/api/delete-adapter", &controllers.ApiController{}, "POST:DeleteCasbinAdapter")
|
||||||
beego.Router("/api/sync-policies", &controllers.ApiController{}, "GET:SyncPolicies")
|
beego.Router("/api/sync-policies", &controllers.ApiController{}, "GET:SyncPolicies")
|
||||||
|
beego.Router("/api/update-policy", &controllers.ApiController{}, "POST:UpdatePolicy")
|
||||||
|
beego.Router("/api/add-policy", &controllers.ApiController{}, "POST:AddPolicy")
|
||||||
|
beego.Router("/api/remove-policy", &controllers.ApiController{}, "POST:RemovePolicy")
|
||||||
|
|
||||||
beego.Router("/api/set-password", &controllers.ApiController{}, "POST:SetPassword")
|
beego.Router("/api/set-password", &controllers.ApiController{}, "POST:SetPassword")
|
||||||
beego.Router("/api/check-user-password", &controllers.ApiController{}, "POST:CheckUserPassword")
|
beego.Router("/api/check-user-password", &controllers.ApiController{}, "POST:CheckUserPassword")
|
||||||
|
@ -123,8 +123,8 @@ func GenerateSimpleTimeId() string {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetId(name string) string {
|
func GetId(owner, name string) string {
|
||||||
return fmt.Sprintf("admin/%s", name)
|
return fmt.Sprintf("%s/%s", owner, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMd5Hash(text string) string {
|
func GetMd5Hash(text string) string {
|
||||||
|
@ -137,16 +137,16 @@ func TestGenerateId(t *testing.T) {
|
|||||||
func TestGetId(t *testing.T) {
|
func TestGetId(t *testing.T) {
|
||||||
scenarios := []struct {
|
scenarios := []struct {
|
||||||
description string
|
description string
|
||||||
input string
|
input []string
|
||||||
expected interface{}
|
expected interface{}
|
||||||
}{
|
}{
|
||||||
{"Scenery one", "casdoor", "admin/casdoor"},
|
{"Scenery one", []string{"admin", "casdoor"}, "admin/casdoor"},
|
||||||
{"Scenery two", "casbin", "admin/casbin"},
|
{"Scenery two", []string{"admin", "casbin"}, "admin/casbin"},
|
||||||
{"Scenery three", "lorem ipsum", "admin/lorem ipsum"},
|
{"Scenery three", []string{"test", "lorem ipsum"}, "test/lorem ipsum"},
|
||||||
}
|
}
|
||||||
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 := GetId(scenery.input)
|
actual := GetId(scenery.input[0], scenery.input[1])
|
||||||
assert.Equal(t, scenery.expected, actual, "This not is a valid MD5")
|
assert.Equal(t, scenery.expected, actual, "This not is a valid MD5")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
29
util/struct.go
Normal file
29
util/struct.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// 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 util
|
||||||
|
|
||||||
|
import xormadapter "github.com/casbin/xorm-adapter/v3"
|
||||||
|
|
||||||
|
func CasbinToSlice(casbinRule xormadapter.CasbinRule) []string {
|
||||||
|
s := []string{
|
||||||
|
casbinRule.V0,
|
||||||
|
casbinRule.V1,
|
||||||
|
casbinRule.V2,
|
||||||
|
casbinRule.V3,
|
||||||
|
casbinRule.V4,
|
||||||
|
casbinRule.V5,
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
@ -9,7 +9,7 @@
|
|||||||
"@testing-library/jest-dom": "^4.2.4",
|
"@testing-library/jest-dom": "^4.2.4",
|
||||||
"@testing-library/react": "^9.3.2",
|
"@testing-library/react": "^9.3.2",
|
||||||
"@testing-library/user-event": "^7.1.2",
|
"@testing-library/user-event": "^7.1.2",
|
||||||
"antd": "^4.22.8",
|
"antd": "5.0.5",
|
||||||
"codemirror": "^5.61.1",
|
"codemirror": "^5.61.1",
|
||||||
"copy-to-clipboard": "^3.3.1",
|
"copy-to-clipboard": "^3.3.1",
|
||||||
"core-js": "^3.25.0",
|
"core-js": "^3.25.0",
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Card, Col, Input, InputNumber, Row, Select, Switch, Table, Tooltip} from "antd";
|
import {Button, Card, Col, Input, InputNumber, Row, Select, Switch} from "antd";
|
||||||
import * as AdapterBackend from "./backend/AdapterBackend";
|
import * as AdapterBackend from "./backend/AdapterBackend";
|
||||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
@ -21,7 +21,7 @@ import i18next from "i18next";
|
|||||||
|
|
||||||
import "codemirror/lib/codemirror.css";
|
import "codemirror/lib/codemirror.css";
|
||||||
import * as ModelBackend from "./backend/ModelBackend";
|
import * as ModelBackend from "./backend/ModelBackend";
|
||||||
import {EditOutlined, MinusOutlined} from "@ant-design/icons";
|
import PolicyTable from "./common/PoliciyTable";
|
||||||
require("codemirror/theme/material-darker.css");
|
require("codemirror/theme/material-darker.css");
|
||||||
require("codemirror/mode/javascript/javascript");
|
require("codemirror/mode/javascript/javascript");
|
||||||
|
|
||||||
@ -32,12 +32,11 @@ class AdapterEditPage extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
classes: props,
|
classes: props,
|
||||||
organizationName: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
|
owner: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
|
||||||
adapterName: props.match.params.adapterName,
|
adapterName: props.match.params.adapterName,
|
||||||
adapter: null,
|
adapter: null,
|
||||||
organizations: [],
|
organizations: [],
|
||||||
models: [],
|
models: [],
|
||||||
policyLists: [],
|
|
||||||
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -48,18 +47,20 @@ class AdapterEditPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getAdapter() {
|
getAdapter() {
|
||||||
AdapterBackend.getAdapter(this.state.organizationName, this.state.adapterName)
|
AdapterBackend.getAdapter(this.state.owner, this.state.adapterName)
|
||||||
.then((adapter) => {
|
.then((res) => {
|
||||||
this.setState({
|
if (res.status === "ok") {
|
||||||
adapter: adapter,
|
this.setState({
|
||||||
});
|
adapter: res.data,
|
||||||
|
});
|
||||||
|
|
||||||
this.getModels(adapter.owner);
|
this.getModels(this.state.owner);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getOrganizations() {
|
getOrganizations() {
|
||||||
OrganizationBackend.getOrganizations(this.state.organizationName)
|
OrganizationBackend.getOrganizations("admin")
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
organizations: (res.msg === undefined) ? res : [],
|
organizations: (res.msg === undefined) ? res : [],
|
||||||
@ -93,93 +94,6 @@ class AdapterEditPage extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
synPolicies() {
|
|
||||||
this.setState({loading: true});
|
|
||||||
AdapterBackend.syncPolicies(this.state.adapter.owner, this.state.adapter.name)
|
|
||||||
.then((res) => {
|
|
||||||
this.setState({loading: false, policyLists: res});
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
this.setState({loading: false});
|
|
||||||
Setting.showMessage("error", `Adapter failed to get policies: ${error}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
renderTable(table) {
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: "Rule Type",
|
|
||||||
dataIndex: "PType",
|
|
||||||
key: "PType",
|
|
||||||
width: "100px",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "V0",
|
|
||||||
dataIndex: "V0",
|
|
||||||
key: "V0",
|
|
||||||
width: "100px",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "V1",
|
|
||||||
dataIndex: "V1",
|
|
||||||
key: "V1",
|
|
||||||
width: "100px",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "V2",
|
|
||||||
dataIndex: "V2",
|
|
||||||
key: "V2",
|
|
||||||
width: "100px",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "V3",
|
|
||||||
dataIndex: "V3",
|
|
||||||
key: "V3",
|
|
||||||
width: "100px",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "V4",
|
|
||||||
dataIndex: "V4",
|
|
||||||
key: "V4",
|
|
||||||
width: "100px",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "V5",
|
|
||||||
dataIndex: "V5",
|
|
||||||
key: "V5",
|
|
||||||
width: "100px",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Option",
|
|
||||||
key: "option",
|
|
||||||
width: "100px",
|
|
||||||
render: (text, record, index) => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Tooltip placement="topLeft" title="Edit">
|
|
||||||
<Button style={{marginRight: "0.5rem"}} icon={<EditOutlined />} size="small" />
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip placement="topLeft" title="Delete">
|
|
||||||
<Button icon={<MinusOutlined />} size="small" />
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Table
|
|
||||||
pagination={{
|
|
||||||
defaultPageSize: 10,
|
|
||||||
}}
|
|
||||||
columns={columns} dataSource={table} rowKey="name" size="middle" bordered
|
|
||||||
loading={this.state.loading}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderAdapter() {
|
renderAdapter() {
|
||||||
return (
|
return (
|
||||||
<Card size="small" title={
|
<Card size="small" title={
|
||||||
@ -195,7 +109,7 @@ class AdapterEditPage extends React.Component {
|
|||||||
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Select virtual={false} style={{width: "100%"}} value={this.state.adapter.organization} onChange={(value => {this.updateadapterField("organization", value);})}>
|
<Select virtual={false} style={{width: "100%"}} value={this.state.adapter.organization} onChange={(value => {this.updateAdapterField("organization", value);})}>
|
||||||
{
|
{
|
||||||
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
||||||
}
|
}
|
||||||
@ -329,19 +243,8 @@ class AdapterEditPage extends React.Component {
|
|||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("adapter:Policies"), i18next.t("adapter:Policies - Tooltip"))} :
|
{Setting.getLabel(i18next.t("adapter:Policies"), i18next.t("adapter:Policies - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={2}>
|
<Col span={22}>
|
||||||
<Button type="primary" onClick={() => {this.synPolicies();}}>
|
<PolicyTable owner={this.state.owner} name={this.state.adapterName} mode={this.state.mode} />
|
||||||
{i18next.t("adapter:Sync")}
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row style={{marginTop: "20px"}} >
|
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
|
||||||
</Col>
|
|
||||||
<Col span={22} >
|
|
||||||
{
|
|
||||||
this.renderTable(this.state.policyLists)
|
|
||||||
}
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
@ -362,8 +265,8 @@ class AdapterEditPage extends React.Component {
|
|||||||
const adapter = Setting.deepCopy(this.state.adapter);
|
const adapter = Setting.deepCopy(this.state.adapter);
|
||||||
AdapterBackend.updateAdapter(this.state.adapter.owner, this.state.adapterName, adapter)
|
AdapterBackend.updateAdapter(this.state.adapter.owner, this.state.adapterName, adapter)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.msg === "") {
|
if (res.status === "ok") {
|
||||||
Setting.showMessage("success", "Successfully saved");
|
Setting.showMessage("success", i18next.t("general:Successfully saved"));
|
||||||
this.setState({
|
this.setState({
|
||||||
adapterName: this.state.adapter.name,
|
adapterName: this.state.adapter.name,
|
||||||
});
|
});
|
||||||
@ -371,25 +274,29 @@ class AdapterEditPage extends React.Component {
|
|||||||
if (willExist) {
|
if (willExist) {
|
||||||
this.props.history.push("/adapters");
|
this.props.history.push("/adapters");
|
||||||
} else {
|
} else {
|
||||||
this.props.history.push(`/adapters/${this.state.adapter.name}`);
|
this.props.history.push(`/adapters/${this.state.owner}/${this.state.adapter.name}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", res.msg);
|
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||||
this.updateAdapterField("name", this.state.adapterName);
|
this.updateAdapterField("name", this.state.adapterName);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `Failed to connect to server: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteAdapter() {
|
deleteAdapter() {
|
||||||
AdapterBackend.deleteAdapter(this.state.adapter)
|
AdapterBackend.deleteAdapter(this.state.adapter)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
this.props.history.push("/adapters");
|
if (res.status === "ok") {
|
||||||
|
this.props.history.push("/adapters");
|
||||||
|
} else {
|
||||||
|
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `adapter failed to delete: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,26 +45,33 @@ class AdapterListPage extends BaseListPage {
|
|||||||
const newAdapter = this.newAdapter();
|
const newAdapter = this.newAdapter();
|
||||||
AdapterBackend.addAdapter(newAdapter)
|
AdapterBackend.addAdapter(newAdapter)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.props.history.push({pathname: `/adapters/${newAdapter.owner}/${newAdapter.name}`, mode: "add"});
|
if (res.status === "ok") {
|
||||||
}
|
this.props.history.push({pathname: `/adapters/${newAdapter.organization}/${newAdapter.name}`, mode: "add"});
|
||||||
)
|
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
||||||
|
} else {
|
||||||
|
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `Adapter failed to add: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteAdapter(i) {
|
deleteAdapter(i) {
|
||||||
AdapterBackend.deleteAdapter(this.state.data[i])
|
AdapterBackend.deleteAdapter(this.state.data[i])
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
Setting.showMessage("success", "Adapter deleted successfully");
|
if (res.status === "ok") {
|
||||||
this.setState({
|
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
||||||
data: Setting.deleteRow(this.state.data, i),
|
this.setState({
|
||||||
pagination: {total: this.state.pagination.total - 1},
|
data: Setting.deleteRow(this.state.data, i),
|
||||||
});
|
pagination: {total: this.state.pagination.total - 1},
|
||||||
}
|
});
|
||||||
)
|
} else {
|
||||||
|
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `Adapter failed to delete: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +87,7 @@ class AdapterListPage extends BaseListPage {
|
|||||||
...this.getColumnSearchProps("name"),
|
...this.getColumnSearchProps("name"),
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
<Link to={`/adapters/${text}`}>
|
<Link to={`/adapters/${record.organization}/${text}`}>
|
||||||
{text}
|
{text}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
@ -201,7 +208,7 @@ class AdapterListPage extends BaseListPage {
|
|||||||
title={`Sure to delete adapter: ${record.name} ?`}
|
title={`Sure to delete adapter: ${record.name} ?`}
|
||||||
onConfirm={() => this.deleteAdapter(index)}
|
onConfirm={() => this.deleteAdapter(index)}
|
||||||
>
|
>
|
||||||
<Button style={{marginBottom: "10px"}} type="danger">{i18next.t("general:Delete")}</Button>
|
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
571
web/src/App.js
571
web/src/App.js
@ -17,7 +17,7 @@ import "./App.less";
|
|||||||
import {Helmet} from "react-helmet";
|
import {Helmet} from "react-helmet";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import {BarsOutlined, DownOutlined, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
import {BarsOutlined, DownOutlined, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
||||||
import {Avatar, BackTop, Button, Card, Drawer, Dropdown, Layout, Menu, Result} from "antd";
|
import {Avatar, Button, Card, ConfigProvider, Drawer, Dropdown, FloatButton, Layout, Menu, Result, theme} from "antd";
|
||||||
import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom";
|
import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom";
|
||||||
import OrganizationListPage from "./OrganizationListPage";
|
import OrganizationListPage from "./OrganizationListPage";
|
||||||
import OrganizationEditPage from "./OrganizationEditPage";
|
import OrganizationEditPage from "./OrganizationEditPage";
|
||||||
@ -55,28 +55,23 @@ import CustomGithubCorner from "./CustomGithubCorner";
|
|||||||
import * as Conf from "./Conf";
|
import * as Conf from "./Conf";
|
||||||
|
|
||||||
import * as Auth from "./auth/Auth";
|
import * as Auth from "./auth/Auth";
|
||||||
import SignupPage from "./auth/SignupPage";
|
import EntryPage from "./EntryPage";
|
||||||
import ResultPage from "./auth/ResultPage";
|
import ResultPage from "./auth/ResultPage";
|
||||||
import LoginPage from "./auth/LoginPage";
|
|
||||||
import SelfLoginPage from "./auth/SelfLoginPage";
|
|
||||||
import SelfForgetPage from "./auth/SelfForgetPage";
|
|
||||||
import ForgetPage from "./auth/ForgetPage";
|
|
||||||
import * as AuthBackend from "./auth/AuthBackend";
|
import * as AuthBackend from "./auth/AuthBackend";
|
||||||
import AuthCallback from "./auth/AuthCallback";
|
import AuthCallback from "./auth/AuthCallback";
|
||||||
import SelectLanguageBox from "./SelectLanguageBox";
|
import SelectLanguageBox from "./SelectLanguageBox";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import PromptPage from "./auth/PromptPage";
|
|
||||||
import OdicDiscoveryPage from "./auth/OidcDiscoveryPage";
|
import OdicDiscoveryPage from "./auth/OidcDiscoveryPage";
|
||||||
import SamlCallback from "./auth/SamlCallback";
|
import SamlCallback from "./auth/SamlCallback";
|
||||||
import CasLogout from "./auth/CasLogout";
|
|
||||||
import ModelListPage from "./ModelListPage";
|
import ModelListPage from "./ModelListPage";
|
||||||
import ModelEditPage from "./ModelEditPage";
|
import ModelEditPage from "./ModelEditPage";
|
||||||
import SystemInfo from "./SystemInfo";
|
import SystemInfo from "./SystemInfo";
|
||||||
import AdapterListPage from "./AdapterListPage";
|
import AdapterListPage from "./AdapterListPage";
|
||||||
import AdapterEditPage from "./AdapterEditPage";
|
import AdapterEditPage from "./AdapterEditPage";
|
||||||
import {withTranslation} from "react-i18next";
|
import {withTranslation} from "react-i18next";
|
||||||
|
import SelectThemeBox from "./SelectThemeBox";
|
||||||
|
|
||||||
const {Header, Footer} = Layout;
|
const {Header, Footer, Content} = Layout;
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -87,6 +82,8 @@ class App extends Component {
|
|||||||
account: undefined,
|
account: undefined,
|
||||||
uri: null,
|
uri: null,
|
||||||
menuVisible: false,
|
menuVisible: false,
|
||||||
|
themeAlgorithm: null,
|
||||||
|
logo: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
Setting.initServerUrl();
|
Setting.initServerUrl();
|
||||||
@ -101,6 +98,16 @@ class App extends Component {
|
|||||||
this.getAccount();
|
this.getAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
localStorage.getItem("theme") ?
|
||||||
|
this.setState({"themeAlgorithm": this.getTheme()}) : this.setState({"themeAlgorithm": theme.defaultAlgorithm});
|
||||||
|
this.setState({"logo": Setting.getLogo(localStorage.getItem("theme"))});
|
||||||
|
addEventListener("themeChange", (e) => {
|
||||||
|
this.setState({"themeAlgorithm": this.getTheme()});
|
||||||
|
this.setState({"logo": Setting.getLogo(localStorage.getItem("theme"))});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
// eslint-disable-next-line no-restricted-globals
|
// eslint-disable-next-line no-restricted-globals
|
||||||
const uri = location.pathname;
|
const uri = location.pathname;
|
||||||
@ -190,6 +197,10 @@ class App extends Component {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTheme() {
|
||||||
|
return Setting.Themes.find(t => t.key === localStorage.getItem("theme"))["style"];
|
||||||
|
}
|
||||||
|
|
||||||
setLanguage(account) {
|
setLanguage(account) {
|
||||||
const language = account?.language;
|
const language = account?.language;
|
||||||
if (language !== "" && language !== i18next.language) {
|
if (language !== "" && language !== i18next.language) {
|
||||||
@ -224,7 +235,7 @@ class App extends Component {
|
|||||||
this.setLanguage(account);
|
this.setLanguage(account);
|
||||||
} else {
|
} else {
|
||||||
if (res.data !== "Please login first") {
|
if (res.data !== "Please login first") {
|
||||||
Setting.showMessage("error", `Failed to sign in: ${res.msg}`);
|
Setting.showMessage("error", `${i18next.t("application:Failed to sign in")}: ${res.msg}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +260,7 @@ class App extends Component {
|
|||||||
account: null,
|
account: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
Setting.showMessage("success", "Logged out successfully");
|
Setting.showMessage("success", i18next.t("application:Logged out successfully"));
|
||||||
const redirectUri = res.data2;
|
const redirectUri = res.data2;
|
||||||
if (redirectUri !== null && redirectUri !== undefined && redirectUri !== "") {
|
if (redirectUri !== null && redirectUri !== undefined && redirectUri !== "") {
|
||||||
Setting.goToLink(redirectUri);
|
Setting.goToLink(redirectUri);
|
||||||
@ -295,23 +306,16 @@ class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderRightDropdown() {
|
renderRightDropdown() {
|
||||||
const menu = (
|
const items = [];
|
||||||
<Menu onClick={this.handleRightDropdownClick.bind(this)}>
|
items.push(Setting.getItem(<><SettingOutlined /> {i18next.t("account:My Account")}</>,
|
||||||
<Menu.Item key="/account">
|
"/account"
|
||||||
<SettingOutlined />
|
));
|
||||||
|
items.push(Setting.getItem(<><LogoutOutlined /> {i18next.t("account:Logout")}</>,
|
||||||
{i18next.t("account:My Account")}
|
"/logout"));
|
||||||
</Menu.Item>
|
const onClick = this.handleRightDropdownClick.bind(this);
|
||||||
<Menu.Item key="/logout">
|
|
||||||
<LogoutOutlined />
|
|
||||||
|
|
||||||
{i18next.t("account:Logout")}
|
|
||||||
</Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown key="/rightDropDown" overlay={menu} className="rightDropDown">
|
<Dropdown key="/rightDropDown" menu={{items, onClick}} className="rightDropDown">
|
||||||
<div className="ant-dropdown-link" style={{float: "right", cursor: "pointer"}}>
|
<div className="ant-dropdown-link" style={{float: "right", cursor: "pointer"}}>
|
||||||
|
|
||||||
|
|
||||||
@ -363,156 +367,89 @@ class App extends Component {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
res.push(
|
res.push(Setting.getItem(<Link to="/">{i18next.t("general:Home")}</Link>, "/"));
|
||||||
<Menu.Item key="/">
|
|
||||||
<Link to="/">
|
|
||||||
{i18next.t("general:Home")}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Setting.isAdminUser(this.state.account)) {
|
if (Setting.isAdminUser(this.state.account)) {
|
||||||
res.push(
|
res.push(Setting.getItem(<Link to="/organizations">{i18next.t("general:Organizations")}</Link>,
|
||||||
<Menu.Item key="/organizations">
|
"/organizations"));
|
||||||
<Link to="/organizations">
|
|
||||||
{i18next.t("general:Organizations")}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Setting.isLocalAdminUser(this.state.account)) {
|
if (Setting.isLocalAdminUser(this.state.account)) {
|
||||||
res.push(
|
res.push(Setting.getItem(<Link to="/users">{i18next.t("general:Users")}</Link>,
|
||||||
<Menu.Item key="/users">
|
"/users"
|
||||||
<Link to="/users">
|
));
|
||||||
{i18next.t("general:Users")}
|
|
||||||
</Link>
|
res.push(Setting.getItem(<Link to="/roles">{i18next.t("general:Roles")}</Link>,
|
||||||
</Menu.Item>
|
"/roles"
|
||||||
);
|
));
|
||||||
res.push(
|
|
||||||
<Menu.Item key="/roles">
|
res.push(Setting.getItem(<Link to="/permissions">{i18next.t("general:Permissions")}</Link>,
|
||||||
<Link to="/roles">
|
"/permissions"
|
||||||
{i18next.t("general:Roles")}
|
));
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
res.push(
|
|
||||||
<Menu.Item key="/permissions">
|
|
||||||
<Link to="/permissions">
|
|
||||||
{i18next.t("general:Permissions")}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Setting.isAdminUser(this.state.account)) {
|
if (Setting.isAdminUser(this.state.account)) {
|
||||||
res.push(
|
res.push(Setting.getItem(<Link to="/models">{i18next.t("general:Models")}</Link>,
|
||||||
<Menu.Item key="/models">
|
"/models"
|
||||||
<Link to="/models">
|
));
|
||||||
{i18next.t("general:Models")}
|
|
||||||
</Link>
|
res.push(Setting.getItem(<Link to="/adapters">{i18next.t("general:Adapters")}</Link>,
|
||||||
</Menu.Item>
|
"/adapters"
|
||||||
);
|
));
|
||||||
res.push(
|
|
||||||
<Menu.Item key="/adapters">
|
|
||||||
<Link to="/adapters">
|
|
||||||
{i18next.t("general:Adapters")}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
res.push(
|
|
||||||
<Menu.Item key="/applications">
|
|
||||||
<Link to="/applications">
|
|
||||||
{i18next.t("general:Applications")}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Setting.isLocalAdminUser(this.state.account)) {
|
if (Setting.isLocalAdminUser(this.state.account)) {
|
||||||
res.push(
|
res.push(Setting.getItem(<Link to="/applications">{i18next.t("general:Applications")}</Link>,
|
||||||
<Menu.Item key="/providers">
|
"/applications"
|
||||||
<Link to="/providers">
|
));
|
||||||
{i18next.t("general:Providers")}
|
|
||||||
</Link>
|
res.push(Setting.getItem(<Link to="/providers">{i18next.t("general:Providers")}</Link>,
|
||||||
</Menu.Item>
|
"/providers"
|
||||||
);
|
));
|
||||||
res.push(
|
|
||||||
<Menu.Item key="/resources">
|
res.push(Setting.getItem(<Link to="/resources">{i18next.t("general:Resources")}</Link>,
|
||||||
<Link to="/resources">
|
"/resources"
|
||||||
{i18next.t("general:Resources")}
|
));
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
res.push(Setting.getItem(<Link to="/records">{i18next.t("general:Records")}</Link>,
|
||||||
);
|
"/records"
|
||||||
res.push(
|
));
|
||||||
<Menu.Item key="/records">
|
|
||||||
<Link to="/records">
|
|
||||||
{i18next.t("general:Records")}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Setting.isAdminUser(this.state.account)) {
|
if (Setting.isAdminUser(this.state.account)) {
|
||||||
res.push(
|
res.push(Setting.getItem(<Link to="/tokens">{i18next.t("general:Tokens")}</Link>,
|
||||||
<Menu.Item key="/tokens">
|
"/tokens"
|
||||||
<Link to="/tokens">
|
));
|
||||||
{i18next.t("general:Tokens")}
|
|
||||||
</Link>
|
res.push(Setting.getItem(<Link to="/webhooks">{i18next.t("general:Webhooks")}</Link>,
|
||||||
</Menu.Item>
|
"/webhooks"
|
||||||
);
|
));
|
||||||
res.push(
|
|
||||||
<Menu.Item key="/webhooks">
|
res.push(Setting.getItem(<Link to="/syncers">{i18next.t("general:Syncers")}</Link>,
|
||||||
<Link to="/webhooks">
|
"/syncers"
|
||||||
{i18next.t("general:Webhooks")}
|
));
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
res.push(Setting.getItem(<Link to="/certs">{i18next.t("general:Certs")}</Link>,
|
||||||
);
|
"/certs"
|
||||||
res.push(
|
));
|
||||||
<Menu.Item key="/syncers">
|
|
||||||
<Link to="/syncers">
|
|
||||||
{i18next.t("general:Syncers")}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
res.push(
|
|
||||||
<Menu.Item key="/certs">
|
|
||||||
<Link to="/certs">
|
|
||||||
{i18next.t("general:Certs")}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Conf.EnableExtraPages) {
|
if (Conf.EnableExtraPages) {
|
||||||
res.push(
|
res.push(Setting.getItem(<Link to="/products">{i18next.t("general:Products")}</Link>,
|
||||||
<Menu.Item key="/products">
|
"/products"
|
||||||
<Link to="/products">
|
));
|
||||||
{i18next.t("general:Products")}
|
|
||||||
</Link>
|
res.push(Setting.getItem(<Link to="/payments">{i18next.t("general:Payments")}</Link>,
|
||||||
</Menu.Item>
|
"/payments"
|
||||||
);
|
));
|
||||||
res.push(
|
|
||||||
<Menu.Item key="/payments">
|
res.push(Setting.getItem(<Link to="/sysinfo">{i18next.t("general:SysInfo")}</Link>,
|
||||||
<Link to="/payments">
|
"/sysinfo"
|
||||||
{i18next.t("general:Payments")}
|
));
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
res.push(
|
|
||||||
<Menu.Item key="/sysinfo">
|
|
||||||
<Link to="/sysinfo">
|
|
||||||
{i18next.t("general:SysInfo")}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
res.push(
|
res.push(Setting.getItem(<a target="_blank" rel="noreferrer"
|
||||||
<Menu.Item key="/swagger">
|
href={Setting.isLocalhost() ? `${Setting.ServerUrl}/swagger` : "/swagger"}>{i18next.t("general:Swagger")}</a>,
|
||||||
<a target="_blank" rel="noreferrer" href={Setting.isLocalhost() ? `${Setting.ServerUrl}/swagger` : "/swagger"}>
|
"/swagger"
|
||||||
{i18next.t("general:Swagger")}
|
));
|
||||||
</a>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@ -545,55 +482,62 @@ class App extends Component {
|
|||||||
|
|
||||||
renderRouter() {
|
renderRouter() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<ConfigProvider theme={{
|
||||||
<Switch>
|
token: {
|
||||||
<Route exact path="/result" render={(props) => this.renderHomeIfLoggedIn(<ResultPage {...props} />)} />
|
colorPrimary: "rgb(89,54,213)",
|
||||||
<Route exact path="/result/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<ResultPage {...props} />)} />
|
colorInfo: "rgb(89,54,213)",
|
||||||
<Route exact path="/" render={(props) => this.renderLoginIfNotLoggedIn(<HomePage account={this.state.account} {...props} />)} />
|
},
|
||||||
<Route exact path="/account" render={(props) => this.renderLoginIfNotLoggedIn(<AccountPage account={this.state.account} {...props} />)} />
|
algorithm: this.state.themeAlgorithm,
|
||||||
<Route exact path="/organizations" render={(props) => this.renderLoginIfNotLoggedIn(<OrganizationListPage account={this.state.account} {...props} />)} />
|
}}>
|
||||||
<Route exact path="/organizations/:organizationName" render={(props) => this.renderLoginIfNotLoggedIn(<OrganizationEditPage account={this.state.account} {...props} />)} />
|
<div>
|
||||||
<Route exact path="/organizations/:organizationName/users" render={(props) => this.renderLoginIfNotLoggedIn(<UserListPage account={this.state.account} {...props} />)} />
|
<Switch>
|
||||||
<Route exact path="/users" render={(props) => this.renderLoginIfNotLoggedIn(<UserListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/result" render={(props) => this.renderHomeIfLoggedIn(<ResultPage {...props} />)} />
|
||||||
<Route exact path="/users/:organizationName/:userName" render={(props) => <UserEditPage account={this.state.account} {...props} />} />
|
<Route exact path="/result/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<ResultPage {...props} />)} />
|
||||||
<Route exact path="/roles" render={(props) => this.renderLoginIfNotLoggedIn(<RoleListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/" render={(props) => this.renderLoginIfNotLoggedIn(<HomePage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/roles/:organizationName/:roleName" render={(props) => this.renderLoginIfNotLoggedIn(<RoleEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/account" render={(props) => this.renderLoginIfNotLoggedIn(<AccountPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/permissions" render={(props) => this.renderLoginIfNotLoggedIn(<PermissionListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/organizations" render={(props) => this.renderLoginIfNotLoggedIn(<OrganizationListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/permissions/:organizationName/:permissionName" render={(props) => this.renderLoginIfNotLoggedIn(<PermissionEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/organizations/:organizationName" render={(props) => this.renderLoginIfNotLoggedIn(<OrganizationEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/models" render={(props) => this.renderLoginIfNotLoggedIn(<ModelListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/organizations/:organizationName/users" render={(props) => this.renderLoginIfNotLoggedIn(<UserListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/models/:organizationName/:modelName" render={(props) => this.renderLoginIfNotLoggedIn(<ModelEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/users" render={(props) => this.renderLoginIfNotLoggedIn(<UserListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/adapters" render={(props) => this.renderLoginIfNotLoggedIn(<AdapterListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/users/:organizationName/:userName" render={(props) => <UserEditPage account={this.state.account} {...props} />} />
|
||||||
<Route exact path="/adapters/:organizationName/:adapterName" render={(props) => this.renderLoginIfNotLoggedIn(<AdapterEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/roles" render={(props) => this.renderLoginIfNotLoggedIn(<RoleListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/providers" render={(props) => this.renderLoginIfNotLoggedIn(<ProviderListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/roles/:organizationName/:roleName" render={(props) => this.renderLoginIfNotLoggedIn(<RoleEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/providers/:providerName" render={(props) => this.renderLoginIfNotLoggedIn(<ProviderEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/permissions" render={(props) => this.renderLoginIfNotLoggedIn(<PermissionListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/providers/:organizationName/:providerName" render={(props) => this.renderLoginIfNotLoggedIn(<ProviderEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/permissions/:organizationName/:permissionName" render={(props) => this.renderLoginIfNotLoggedIn(<PermissionEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/applications" render={(props) => this.renderLoginIfNotLoggedIn(<ApplicationListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/models" render={(props) => this.renderLoginIfNotLoggedIn(<ModelListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/applications/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<ApplicationEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/models/:organizationName/:modelName" render={(props) => this.renderLoginIfNotLoggedIn(<ModelEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/resources" render={(props) => this.renderLoginIfNotLoggedIn(<ResourceListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/adapters" render={(props) => this.renderLoginIfNotLoggedIn(<AdapterListPage account={this.state.account} {...props} />)} />
|
||||||
{/* <Route exact path="/resources/:resourceName" render={(props) => this.renderLoginIfNotLoggedIn(<ResourceEditPage account={this.state.account} {...props} />)}/>*/}
|
<Route exact path="/adapters/:organizationName/:adapterName" render={(props) => this.renderLoginIfNotLoggedIn(<AdapterEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/ldap/:ldapId" render={(props) => this.renderLoginIfNotLoggedIn(<LdapEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/providers" render={(props) => this.renderLoginIfNotLoggedIn(<ProviderListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/ldap/sync/:ldapId" render={(props) => this.renderLoginIfNotLoggedIn(<LdapSyncPage account={this.state.account} {...props} />)} />
|
<Route exact path="/providers/:organizationName/:providerName" render={(props) => this.renderLoginIfNotLoggedIn(<ProviderEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/tokens" render={(props) => this.renderLoginIfNotLoggedIn(<TokenListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/applications" render={(props) => this.renderLoginIfNotLoggedIn(<ApplicationListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/tokens/:tokenName" render={(props) => this.renderLoginIfNotLoggedIn(<TokenEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/applications/:organizationName/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<ApplicationEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/webhooks" render={(props) => this.renderLoginIfNotLoggedIn(<WebhookListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/resources" render={(props) => this.renderLoginIfNotLoggedIn(<ResourceListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/webhooks/:webhookName" render={(props) => this.renderLoginIfNotLoggedIn(<WebhookEditPage account={this.state.account} {...props} />)} />
|
{/* <Route exact path="/resources/:resourceName" render={(props) => this.renderLoginIfNotLoggedIn(<ResourceEditPage account={this.state.account} {...props} />)}/>*/}
|
||||||
<Route exact path="/syncers" render={(props) => this.renderLoginIfNotLoggedIn(<SyncerListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/ldap/:ldapId" render={(props) => this.renderLoginIfNotLoggedIn(<LdapEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/syncers/:syncerName" render={(props) => this.renderLoginIfNotLoggedIn(<SyncerEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/ldap/sync/:ldapId" render={(props) => this.renderLoginIfNotLoggedIn(<LdapSyncPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/certs" render={(props) => this.renderLoginIfNotLoggedIn(<CertListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/tokens" render={(props) => this.renderLoginIfNotLoggedIn(<TokenListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/certs/:certName" render={(props) => this.renderLoginIfNotLoggedIn(<CertEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/tokens/:tokenName" render={(props) => this.renderLoginIfNotLoggedIn(<TokenEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/products" render={(props) => this.renderLoginIfNotLoggedIn(<ProductListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/webhooks" render={(props) => this.renderLoginIfNotLoggedIn(<WebhookListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/products/:productName" render={(props) => this.renderLoginIfNotLoggedIn(<ProductEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/webhooks/:webhookName" render={(props) => this.renderLoginIfNotLoggedIn(<WebhookEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/products/:productName/buy" render={(props) => this.renderLoginIfNotLoggedIn(<ProductBuyPage account={this.state.account} {...props} />)} />
|
<Route exact path="/syncers" render={(props) => this.renderLoginIfNotLoggedIn(<SyncerListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/payments" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/syncers/:syncerName" render={(props) => this.renderLoginIfNotLoggedIn(<SyncerEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/payments/:paymentName" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/certs" render={(props) => this.renderLoginIfNotLoggedIn(<CertListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/payments/:paymentName/result" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentResultPage account={this.state.account} {...props} />)} />
|
<Route exact path="/certs/:certName" render={(props) => this.renderLoginIfNotLoggedIn(<CertEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/products" render={(props) => this.renderLoginIfNotLoggedIn(<ProductListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/.well-known/openid-configuration" render={(props) => <OdicDiscoveryPage />} />
|
<Route exact path="/products/:productName" render={(props) => this.renderLoginIfNotLoggedIn(<ProductEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/sysinfo" render={(props) => this.renderLoginIfNotLoggedIn(<SystemInfo account={this.state.account} {...props} />)} />
|
<Route exact path="/products/:productName/buy" render={(props) => this.renderLoginIfNotLoggedIn(<ProductBuyPage account={this.state.account} {...props} />)} />
|
||||||
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
<Route exact path="/payments" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentListPage account={this.state.account} {...props} />)} />
|
||||||
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
|
<Route exact path="/payments/:paymentName" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentEditPage account={this.state.account} {...props} />)} />
|
||||||
</Switch>
|
<Route exact path="/payments/:paymentName/result" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentResultPage account={this.state.account} {...props} />)} />
|
||||||
</div>
|
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)} />
|
||||||
|
<Route exact path="/.well-known/openid-configuration" render={(props) => <OdicDiscoveryPage />} />
|
||||||
|
<Route exact path="/sysinfo" render={(props) => this.renderLoginIfNotLoggedIn(<SystemInfo account={this.state.account} {...props} />)} />
|
||||||
|
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
||||||
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
|
||||||
|
</Switch>
|
||||||
|
</div>
|
||||||
|
</ConfigProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,81 +556,75 @@ class App extends Component {
|
|||||||
renderContent() {
|
renderContent() {
|
||||||
if (!Setting.isMobile()) {
|
if (!Setting.isMobile()) {
|
||||||
return (
|
return (
|
||||||
<div style={{display: "flex", flex: "auto", width: "100%", flexDirection: "column"}}>
|
<Layout id="parent-area">
|
||||||
<Layout style={{display: "flex", alignItems: "stretch"}}>
|
<Header style={{marginBottom: "3px", paddingInline: 0, backgroundColor: this.state.themeAlgorithm === theme.darkAlgorithm ? "black" : "white"}}>
|
||||||
<Header style={{padding: "0", marginBottom: "3px"}}>
|
|
||||||
{
|
|
||||||
Setting.isMobile() ? null : (
|
|
||||||
<Link to={"/"}>
|
|
||||||
<div className="logo" />
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
<div>
|
|
||||||
<Menu
|
|
||||||
// theme="dark"
|
|
||||||
mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"}
|
|
||||||
selectedKeys={[`${this.state.selectedMenuKey}`]}
|
|
||||||
style={{lineHeight: "64px", position: "absolute", left: "145px", right: "200px"}}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
this.renderMenu()
|
|
||||||
}
|
|
||||||
</Menu>
|
|
||||||
{
|
|
||||||
this.renderAccount()
|
|
||||||
}
|
|
||||||
<SelectLanguageBox />
|
|
||||||
</div>
|
|
||||||
</Header>
|
|
||||||
<Layout style={{backgroundColor: "#f5f5f5", alignItems: "stretch"}}>
|
|
||||||
<Card className="content-warp-card">
|
|
||||||
{
|
|
||||||
this.renderRouter()
|
|
||||||
}
|
|
||||||
</Card>
|
|
||||||
</Layout>
|
|
||||||
</Layout>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Header style={{padding: "0", marginBottom: "3px"}}>
|
|
||||||
{
|
{
|
||||||
Setting.isMobile() ? null : (
|
Setting.isMobile() ? null : (
|
||||||
<Link to={"/"}>
|
<Link to={"/"}>
|
||||||
<div className="logo" />
|
<div className="logo" style={{background: `url(${this.state.logo})`}} />
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<Menu
|
||||||
|
items={this.renderMenu()}
|
||||||
|
mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"}
|
||||||
|
selectedKeys={[`${this.state.selectedMenuKey}`]}
|
||||||
|
style={{position: "absolute", left: "145px", backgroundColor: this.state.themeAlgorithm === theme.darkAlgorithm ? "black" : "white"}}
|
||||||
|
/>
|
||||||
|
{
|
||||||
|
this.renderAccount()
|
||||||
|
}
|
||||||
|
{this.state.account && <SelectThemeBox themes={this.state.account.organization.themes} />}
|
||||||
|
{this.state.account && <SelectLanguageBox languages={this.state.account.organization.languages} />}
|
||||||
|
</Header>
|
||||||
|
<Content style={{alignItems: "stretch", display: "flex", flexDirection: "column"}}>
|
||||||
|
<Card className="content-warp-card">
|
||||||
|
{
|
||||||
|
this.renderRouter()
|
||||||
|
}
|
||||||
|
</Card>
|
||||||
|
</Content>
|
||||||
|
{
|
||||||
|
this.renderFooter()
|
||||||
|
}
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<Header style={{padding: "0", marginBottom: "3px", backgroundColor: this.state.themeAlgorithm === theme.darkAlgorithm ? "black" : "white"}}>
|
||||||
|
{
|
||||||
|
Setting.isMobile() ? null : (
|
||||||
|
<Link to={"/"}>
|
||||||
|
<div className="logo" style={{background: `url(${this.state.logo})`}} />
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
<Drawer title={i18next.t("general:Close")} placement="left" visible={this.state.menuVisible} onClose={this.onClose}>
|
<Drawer title={i18next.t("general:Close")} placement="left" visible={this.state.menuVisible} onClose={this.onClose}>
|
||||||
<Menu
|
<Menu
|
||||||
// theme="dark"
|
// theme="dark"
|
||||||
|
items={this.renderMenu()}
|
||||||
mode={(Setting.isMobile()) ? "inline" : "horizontal"}
|
mode={(Setting.isMobile()) ? "inline" : "horizontal"}
|
||||||
selectedKeys={[`${this.state.selectedMenuKey}`]}
|
selectedKeys={[`${this.state.selectedMenuKey}`]}
|
||||||
style={{lineHeight: "64px"}}
|
style={{lineHeight: "64px"}}
|
||||||
onClick={this.onClose}
|
onClick={this.onClose}
|
||||||
>
|
>
|
||||||
{
|
|
||||||
this.renderMenu()
|
|
||||||
}
|
|
||||||
</Menu>
|
</Menu>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
<Button icon={<BarsOutlined />} onClick={this.showMenu} type="text">
|
<Button icon={<BarsOutlined />} onClick={this.showMenu} type="text">
|
||||||
{i18next.t("general:Menu")}
|
{i18next.t("general:Menu")}
|
||||||
</Button>
|
</Button>
|
||||||
<div style = {{float: "right"}}>
|
{
|
||||||
{
|
this.renderAccount()
|
||||||
this.renderAccount()
|
}
|
||||||
}
|
{this.state.account && <SelectThemeBox themes={this.state.account.organization.themes} />}
|
||||||
<SelectLanguageBox />
|
{this.state.account && <SelectLanguageBox languages={this.state.account.organization.languages} />}
|
||||||
</div>
|
|
||||||
</Header>
|
</Header>
|
||||||
{
|
<Content style={{display: "flex", flexDirection: "column"}} >{
|
||||||
this.renderRouter()
|
this.renderRouter()}
|
||||||
}
|
</Content>
|
||||||
</div>
|
{this.renderFooter()}
|
||||||
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -696,77 +634,66 @@ class App extends Component {
|
|||||||
// https://www.freecodecamp.org/neyarnws/how-to-keep-your-footer-where-it-belongs-59c6aa05c59c/
|
// https://www.freecodecamp.org/neyarnws/how-to-keep-your-footer-where-it-belongs-59c6aa05c59c/
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<React.Fragment>
|
||||||
{!this.state.account ? null : <div style={{display: "none"}} id="CasdoorApplicationName" value={this.state.account.signupApplication} />}
|
{!this.state.account ? null : <div style={{display: "none"}} id="CasdoorApplicationName" value={this.state.account.signupApplication} />}
|
||||||
<Footer id="footer" style={
|
<Footer id="footer" style={
|
||||||
{
|
{
|
||||||
borderTop: "1px solid #e8e8e8",
|
|
||||||
backgroundColor: "white",
|
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
Powered by <a target="_blank" href="https://casdoor.org" rel="noreferrer"><img style={{paddingBottom: "3px"}} height={"20px"} alt={"Casdoor"} src={`${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png`} /></a>
|
Powered by <a target="_blank" href="https://casdoor.org" rel="noreferrer"><img style={{paddingBottom: "3px"}} height={"20px"} alt={"Casdoor"} src={this.state.logo} /></a>
|
||||||
</Footer>
|
</Footer>
|
||||||
</>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
isDoorPages() {
|
isDoorPages() {
|
||||||
|
return this.isEntryPages() || window.location.pathname.startsWith("/callback");
|
||||||
|
}
|
||||||
|
|
||||||
|
isEntryPages() {
|
||||||
return window.location.pathname.startsWith("/signup") ||
|
return window.location.pathname.startsWith("/signup") ||
|
||||||
window.location.pathname.startsWith("/login") ||
|
window.location.pathname.startsWith("/login") ||
|
||||||
window.location.pathname.startsWith("/callback") ||
|
|
||||||
window.location.pathname.startsWith("/prompt") ||
|
|
||||||
window.location.pathname.startsWith("/forget") ||
|
window.location.pathname.startsWith("/forget") ||
|
||||||
window.location.pathname.startsWith("/cas");
|
window.location.pathname.startsWith("/prompt") ||
|
||||||
|
window.location.pathname.startsWith("/cas") ||
|
||||||
|
window.location.pathname.startsWith("/auto-signup");
|
||||||
}
|
}
|
||||||
|
|
||||||
renderPage() {
|
renderPage() {
|
||||||
if (this.isDoorPages()) {
|
if (this.isDoorPages()) {
|
||||||
return (
|
return (
|
||||||
<div style={{display: "flex", flexDirection: "column", height: "100%"}}>
|
<React.Fragment>
|
||||||
<div id="login-content-wrap" style={{flexDirection: "column"}}>
|
<Layout id="parent-area">
|
||||||
<Switch>
|
<Content style={{display: "flex", justifyContent: "center"}}>
|
||||||
<Route exact path="/signup" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} />)} />
|
{
|
||||||
<Route exact path="/signup/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />)} />
|
this.isEntryPages() ?
|
||||||
<Route exact path="/login" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage account={this.state.account} {...props} />)} />
|
<EntryPage account={this.state.account} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />
|
||||||
<Route exact path="/login/:owner" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage account={this.state.account} {...props} />)} />
|
:
|
||||||
<Route exact path="/auto-signup/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signup"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
<Switch>
|
||||||
<Route exact path="/signup/oauth/authorize" render={(props) => <SignupPage account={this.state.account} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
<Route exact path="/callback" component={AuthCallback} />
|
||||||
<Route exact path="/login/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
<Route exact path="/callback/saml" component={SamlCallback} />
|
||||||
<Route exact path="/login/saml/authorize/:owner/:applicationName" render={(props) => <LoginPage account={this.state.account} type={"saml"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
||||||
<Route exact path="/cas/:owner/:casApplicationName/logout" render={(props) => this.renderHomeIfLoggedIn(<CasLogout clearAccount={() => this.setState({account: null})} {...props} />)} />
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
|
||||||
<Route exact path="/cas/:owner/:casApplicationName/login" render={(props) => {return (<LoginPage type={"cas"} mode={"signup"} account={this.state.account} {...props} />);}} />
|
</Switch>
|
||||||
<Route exact path="/callback" component={AuthCallback} />
|
}
|
||||||
<Route exact path="/callback/saml" component={SamlCallback} />
|
</Content>
|
||||||
<Route exact path="/forget" render={(props) => this.renderHomeIfLoggedIn(<SelfForgetPage {...props} />)} />
|
{
|
||||||
<Route exact path="/forget/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<ForgetPage {...props} />)} />
|
this.renderFooter()
|
||||||
<Route exact path="/prompt" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage account={this.state.account} {...props} />)} />
|
}
|
||||||
<Route exact path="/prompt/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage account={this.state.account} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} {...props} />)} />
|
</Layout>
|
||||||
<Route exact path="/sysinfo" render={(props) => this.renderLoginIfNotLoggedIn(<SystemInfo {...props} />)} />
|
</React.Fragment>
|
||||||
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
|
||||||
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
|
|
||||||
</Switch>
|
|
||||||
</div>
|
|
||||||
{
|
|
||||||
this.renderFooter()
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="parent-area">
|
<React.Fragment>
|
||||||
<BackTop />
|
<FloatButton.BackTop />
|
||||||
<CustomGithubCorner />
|
<CustomGithubCorner />
|
||||||
<div id="content-wrap" style={{flexDirection: "column"}}>
|
|
||||||
{
|
|
||||||
this.renderContent()
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{
|
{
|
||||||
this.renderFooter()
|
this.renderContent()
|
||||||
}
|
}
|
||||||
</div>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,9 +704,17 @@ class App extends Component {
|
|||||||
<Helmet>
|
<Helmet>
|
||||||
<link rel="icon" href={"https://cdn.casdoor.com/static/favicon.png"} />
|
<link rel="icon" href={"https://cdn.casdoor.com/static/favicon.png"} />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
{
|
<ConfigProvider theme={{
|
||||||
this.renderPage()
|
token: {
|
||||||
}
|
colorPrimary: "rgb(89,54,213)",
|
||||||
|
colorInfo: "rgb(89,54,213)",
|
||||||
|
},
|
||||||
|
algorithm: this.state.themeAlgorithm,
|
||||||
|
}}>
|
||||||
|
{
|
||||||
|
this.renderPage()
|
||||||
|
}
|
||||||
|
</ConfigProvider>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -791,9 +726,17 @@ class App extends Component {
|
|||||||
<title>{organization.displayName}</title>
|
<title>{organization.displayName}</title>
|
||||||
<link rel="icon" href={organization.favicon} />
|
<link rel="icon" href={organization.favicon} />
|
||||||
</Helmet>
|
</Helmet>
|
||||||
{
|
<ConfigProvider theme={{
|
||||||
this.renderPage()
|
token: {
|
||||||
}
|
colorPrimary: "rgb(89,54,213)",
|
||||||
|
colorInfo: "rgb(89,54,213)",
|
||||||
|
},
|
||||||
|
algorithm: this.state.themeAlgorithm,
|
||||||
|
}}>
|
||||||
|
{
|
||||||
|
this.renderPage()
|
||||||
|
}
|
||||||
|
</ConfigProvider>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
/* stylelint-disable at-rule-name-case */
|
/* stylelint-disable at-rule-name-case */
|
||||||
/* stylelint-disable selector-class-pattern */
|
/* stylelint-disable selector-class-pattern */
|
||||||
@import "~antd/dist/antd.less";
|
|
||||||
|
|
||||||
@StaticBaseUrl: "https://cdn.casbin.org";
|
@StaticBaseUrl: "https://cdn.casbin.org";
|
||||||
|
|
||||||
@ -14,20 +13,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.App-header {
|
.App-header {
|
||||||
background-color: #282c34;
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: calc(10px + 2vmin);
|
font-size: calc(10px + 2vmin);
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.App-link {
|
.App-link {
|
||||||
color: #61dafb;
|
color: #61dafb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-style: none;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
#root {
|
#root {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
@ -37,32 +39,10 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#content-wrap {
|
.panel-logo {
|
||||||
display: flex;
|
margin-bottom: 30px;
|
||||||
flex: 1 1 0;
|
|
||||||
align-items: stretch;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#login-content-wrap {
|
|
||||||
display: flex;
|
|
||||||
flex: 1 1 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#footer {
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 70px; /* Footer height */
|
|
||||||
}
|
|
||||||
|
|
||||||
#language-box-corner {
|
|
||||||
position: absolute;
|
|
||||||
top: 75px;
|
|
||||||
right: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.language-box {
|
.language-box {
|
||||||
@ -72,7 +52,7 @@
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
width: 45px;
|
width: 45px;
|
||||||
height: 65px;
|
height: 100%;
|
||||||
float: right;
|
float: right;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
@ -81,9 +61,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.login-form .language-box {
|
||||||
|
height: 65px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-box {
|
||||||
|
background: url("@{StaticBaseUrl}/img/muti_language.svg");
|
||||||
|
background-size: 25px, 25px;
|
||||||
|
background-position: center !important;
|
||||||
|
background-repeat: no-repeat !important;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 45px;
|
||||||
|
height: 100%;
|
||||||
|
float: right;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f5f5f5 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.rightDropDown {
|
.rightDropDown {
|
||||||
|
border-radius: 7px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
|
color: black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +110,7 @@
|
|||||||
|
|
||||||
.forget-content {
|
.forget-content {
|
||||||
padding: 10px 100px 20px;
|
padding: 10px 100px 20px;
|
||||||
|
margin: 30px auto;
|
||||||
border: 2px solid #fff;
|
border: 2px solid #fff;
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
background-color: rgb(255 255 255);
|
background-color: rgb(255 255 255);
|
||||||
@ -123,7 +127,7 @@
|
|||||||
|
|
||||||
.login-form {
|
.login-form {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 10px;
|
padding: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-content {
|
.login-content {
|
||||||
@ -137,10 +141,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.loginBackground {
|
.loginBackground {
|
||||||
|
flex: auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 1 1 0;
|
|
||||||
background: #fff no-repeat;
|
background: #fff no-repeat;
|
||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-menu-horizontal {
|
||||||
|
border-bottom: none !important;
|
||||||
|
margin-right: 30px;
|
||||||
|
right: 230px;
|
||||||
|
}
|
||||||
|
@ -49,6 +49,9 @@ const template = `<style>
|
|||||||
}
|
}
|
||||||
</style>`;
|
</style>`;
|
||||||
|
|
||||||
|
const previewGrid = Setting.isMobile() ? 22 : 11;
|
||||||
|
const previewWidth = Setting.isMobile() ? "110%" : "90%";
|
||||||
|
|
||||||
const sideTemplate = `<style>
|
const sideTemplate = `<style>
|
||||||
.left-model{
|
.left-model{
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -91,7 +94,7 @@ class ApplicationEditPage extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
classes: props,
|
classes: props,
|
||||||
owner: props.account.owner,
|
owner: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
|
||||||
applicationName: props.match.params.applicationName,
|
applicationName: props.match.params.applicationName,
|
||||||
application: null,
|
application: null,
|
||||||
organizations: [],
|
organizations: [],
|
||||||
@ -142,21 +145,11 @@ class ApplicationEditPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getProviders() {
|
getProviders() {
|
||||||
if (Setting.isAdminUser(this.props.account)) {
|
ProviderBackend.getProviders(this.state.owner).then((res => {
|
||||||
ProviderBackend.getGlobalProviders()
|
this.setState({
|
||||||
.then((res) => {
|
providers: res,
|
||||||
this.setState({
|
});
|
||||||
providers: res,
|
}));
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
ProviderBackend.getProviders(this.state.owner)
|
|
||||||
.then((res) => {
|
|
||||||
this.setState({
|
|
||||||
providers: res,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSamlMetadata() {
|
getSamlMetadata() {
|
||||||
@ -198,7 +191,7 @@ class ApplicationEditPage extends React.Component {
|
|||||||
Setting.showMessage("success", i18next.t("application:File uploaded successfully"));
|
Setting.showMessage("success", i18next.t("application:File uploaded successfully"));
|
||||||
this.updateApplicationField("termsOfUse", res.data);
|
this.updateApplicationField("termsOfUse", res.data);
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", res.msg);
|
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||||
}
|
}
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.setState({uploading: false});
|
this.setState({uploading: false});
|
||||||
@ -287,7 +280,7 @@ class ApplicationEditPage extends React.Component {
|
|||||||
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Select virtual={false} style={{width: "100%"}} value={this.state.application.organization} onChange={(value => {this.updateApplicationField("organization", value);})}>
|
<Select virtual={false} style={{width: "100%"}} disabled={!Setting.isAdminUser(this.props.account)} value={this.state.application.organization} onChange={(value => {this.updateApplicationField("organization", value);})}>
|
||||||
{
|
{
|
||||||
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
this.state.organizations.map((organization, index) => <Option key={index} value={organization.name}>{organization.name}</Option>)
|
||||||
}
|
}
|
||||||
@ -552,6 +545,16 @@ class ApplicationEditPage extends React.Component {
|
|||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("application:SAML Reply URL"), i18next.t("application:Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Input prefix={<LinkOutlined />} value={this.state.application.samlReplyUrl} onChange={e => {
|
||||||
|
this.updateApplicationField("samlReplyUrl", e.target.value);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||||
{Setting.getLabel(i18next.t("application:Enable SAML compress"), i18next.t("application:Enable SAML compress - Tooltip"))} :
|
{Setting.getLabel(i18next.t("application:Enable SAML compress"), i18next.t("application:Enable SAML compress - Tooltip"))} :
|
||||||
@ -723,14 +726,14 @@ class ApplicationEditPage extends React.Component {
|
|||||||
renderSignupSigninPreview() {
|
renderSignupSigninPreview() {
|
||||||
let signUpUrl = `/signup/${this.state.application.name}`;
|
let signUpUrl = `/signup/${this.state.application.name}`;
|
||||||
const signInUrl = `/login/oauth/authorize?client_id=${this.state.application.clientId}&response_type=code&redirect_uri=${this.state.application.redirectUris[0]}&scope=read&state=casdoor`;
|
const signInUrl = `/login/oauth/authorize?client_id=${this.state.application.clientId}&response_type=code&redirect_uri=${this.state.application.redirectUris[0]}&scope=read&state=casdoor`;
|
||||||
const maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "100%", width: "100%", background: "rgba(0,0,0,0.4)"};
|
const maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "97%", width: "100%", background: "rgba(0,0,0,0.4)"};
|
||||||
if (!this.state.application.enablePassword) {
|
if (!this.state.application.enablePassword) {
|
||||||
signUpUrl = signInUrl.replace("/login/oauth/authorize", "/signup/oauth/authorize");
|
signUpUrl = signInUrl.replace("/login/oauth/authorize", "/signup/oauth/authorize");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Col span={11}>
|
<Col span={previewGrid}>
|
||||||
<Button style={{marginBottom: "10px"}} type="primary" shape="round" icon={<CopyOutlined />} onClick={() => {
|
<Button style={{marginBottom: "10px"}} type="primary" shape="round" icon={<CopyOutlined />} onClick={() => {
|
||||||
copy(`${window.location.origin}${signUpUrl}`);
|
copy(`${window.location.origin}${signUpUrl}`);
|
||||||
Setting.showMessage("success", i18next.t("application:Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser"));
|
Setting.showMessage("success", i18next.t("application:Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser"));
|
||||||
@ -739,19 +742,23 @@ class ApplicationEditPage extends React.Component {
|
|||||||
{i18next.t("application:Copy signup page URL")}
|
{i18next.t("application:Copy signup page URL")}
|
||||||
</Button>
|
</Button>
|
||||||
<br />
|
<br />
|
||||||
<div style={{position: "relative", width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", alignItems: "center", overflow: "auto", flexDirection: "column", flex: "auto"}}>
|
<div style={{position: "relative", width: previewWidth, border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", overflow: "auto"}}>
|
||||||
{
|
{
|
||||||
this.state.application.enablePassword ? (
|
this.state.application.enablePassword ? (
|
||||||
<SignupPage application={this.state.application} />
|
<div className="loginBackground" style={{backgroundImage: `url(${this.state.application?.formBackgroundUrl})`, overflow: "auto"}}>
|
||||||
|
<SignupPage application={this.state.application} preview = "auto" />
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<LoginPage type={"login"} mode={"signup"} application={this.state.application} />
|
<div className="loginBackground" style={{backgroundImage: `url(${this.state.application?.formBackgroundUrl})`, overflow: "auto"}}>
|
||||||
|
<LoginPage type={"login"} mode={"signup"} application={this.state.application} preview = "auto" />
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
<div style={maskStyle} />
|
<div style={{overflow: "auto", ...maskStyle}} />
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={11}>
|
<Col span={previewGrid}>
|
||||||
<Button style={{marginBottom: "10px"}} type="primary" shape="round" icon={<CopyOutlined />} onClick={() => {
|
<Button style={{marginBottom: "10px", marginTop: Setting.isMobile() ? "15px" : "0"}} type="primary" shape="round" icon={<CopyOutlined />} onClick={() => {
|
||||||
copy(`${window.location.origin}${signInUrl}`);
|
copy(`${window.location.origin}${signInUrl}`);
|
||||||
Setting.showMessage("success", i18next.t("application:Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser"));
|
Setting.showMessage("success", i18next.t("application:Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser"));
|
||||||
}}
|
}}
|
||||||
@ -759,9 +766,11 @@ class ApplicationEditPage extends React.Component {
|
|||||||
{i18next.t("application:Copy signin page URL")}
|
{i18next.t("application:Copy signin page URL")}
|
||||||
</Button>
|
</Button>
|
||||||
<br />
|
<br />
|
||||||
<div style={{position: "relative", width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", alignItems: "center", overflow: "auto", flexDirection: "column", flex: "auto"}}>
|
<div style={{position: "relative", width: previewWidth, border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", overflow: "auto"}}>
|
||||||
<LoginPage type={"login"} mode={"signin"} application={this.state.application} />
|
<div className="loginBackground" style={{backgroundImage: `url(${this.state.application?.formBackgroundUrl})`, overflow: "auto"}}>
|
||||||
<div style={maskStyle} />
|
<LoginPage type={"login"} mode={"signin"} application={this.state.application} preview = "auto" />
|
||||||
|
</div>
|
||||||
|
<div style={{overflow: "auto", ...maskStyle}} />
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
@ -772,7 +781,7 @@ class ApplicationEditPage extends React.Component {
|
|||||||
const promptUrl = `/prompt/${this.state.application.name}`;
|
const promptUrl = `/prompt/${this.state.application.name}`;
|
||||||
const maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "100%", width: "100%", background: "rgba(0,0,0,0.4)"};
|
const maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "100%", width: "100%", background: "rgba(0,0,0,0.4)"};
|
||||||
return (
|
return (
|
||||||
<Col span={11}>
|
<Col span={previewGrid}>
|
||||||
<Button style={{marginBottom: "10px"}} type="primary" shape="round" icon={<CopyOutlined />} onClick={() => {
|
<Button style={{marginBottom: "10px"}} type="primary" shape="round" icon={<CopyOutlined />} onClick={() => {
|
||||||
copy(`${window.location.origin}${promptUrl}`);
|
copy(`${window.location.origin}${promptUrl}`);
|
||||||
Setting.showMessage("success", i18next.t("application:Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser"));
|
Setting.showMessage("success", i18next.t("application:Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser"));
|
||||||
@ -781,7 +790,7 @@ class ApplicationEditPage extends React.Component {
|
|||||||
{i18next.t("application:Copy prompt page URL")}
|
{i18next.t("application:Copy prompt page URL")}
|
||||||
</Button>
|
</Button>
|
||||||
<br />
|
<br />
|
||||||
<div style={{position: "relative", width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", flexDirection: "column", flex: "auto"}}>
|
<div style={{position: "relative", width: previewWidth, border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", flexDirection: "column", flex: "auto"}}>
|
||||||
<PromptPage application={this.state.application} account={this.props.account} />
|
<PromptPage application={this.state.application} account={this.props.account} />
|
||||||
<div style={maskStyle} />
|
<div style={maskStyle} />
|
||||||
</div>
|
</div>
|
||||||
@ -791,10 +800,10 @@ class ApplicationEditPage extends React.Component {
|
|||||||
|
|
||||||
submitApplicationEdit(willExist) {
|
submitApplicationEdit(willExist) {
|
||||||
const application = Setting.deepCopy(this.state.application);
|
const application = Setting.deepCopy(this.state.application);
|
||||||
ApplicationBackend.updateApplication(this.state.application.owner, this.state.applicationName, application)
|
ApplicationBackend.updateApplication("admin", this.state.applicationName, application)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.msg === "") {
|
if (res.status === "ok") {
|
||||||
Setting.showMessage("success", "Successfully saved");
|
Setting.showMessage("success", i18next.t("general:Successfully saved"));
|
||||||
this.setState({
|
this.setState({
|
||||||
applicationName: this.state.application.name,
|
applicationName: this.state.application.name,
|
||||||
});
|
});
|
||||||
@ -802,25 +811,29 @@ class ApplicationEditPage extends React.Component {
|
|||||||
if (willExist) {
|
if (willExist) {
|
||||||
this.props.history.push("/applications");
|
this.props.history.push("/applications");
|
||||||
} else {
|
} else {
|
||||||
this.props.history.push(`/applications/${this.state.application.name}`);
|
this.props.history.push(`/applications/${this.state.application.organization}/${this.state.application.name}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", res.msg);
|
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||||
this.updateApplicationField("name", this.state.applicationName);
|
this.updateApplicationField("name", this.state.applicationName);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `Failed to connect to server: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteApplication() {
|
deleteApplication() {
|
||||||
ApplicationBackend.deleteApplication(this.state.application)
|
ApplicationBackend.deleteApplication(this.state.application)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
this.props.history.push("/applications");
|
if (res.status === "ok") {
|
||||||
|
this.props.history.push("/applications");
|
||||||
|
} else {
|
||||||
|
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `Application failed to delete: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,11 +23,28 @@ import i18next from "i18next";
|
|||||||
import BaseListPage from "./BaseListPage";
|
import BaseListPage from "./BaseListPage";
|
||||||
|
|
||||||
class ApplicationListPage extends BaseListPage {
|
class ApplicationListPage extends BaseListPage {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
classes: props,
|
||||||
|
organizationName: props.account.owner,
|
||||||
|
data: [],
|
||||||
|
pagination: {
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
},
|
||||||
|
loading: false,
|
||||||
|
searchText: "",
|
||||||
|
searchedColumn: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
newApplication() {
|
newApplication() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
return {
|
return {
|
||||||
owner: "admin", // this.props.account.applicationname,
|
owner: "admin", // this.props.account.applicationName,
|
||||||
name: `application_${randomName}`,
|
name: `application_${randomName}`,
|
||||||
|
organization: this.state.organizationName,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
displayName: `New Application - ${randomName}`,
|
displayName: `New Application - ${randomName}`,
|
||||||
logo: `${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png`,
|
logo: `${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png`,
|
||||||
@ -53,7 +70,7 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
redirectUris: ["http://localhost:9000/callback"],
|
redirectUris: ["http://localhost:9000/callback"],
|
||||||
tokenFormat: "JWT",
|
tokenFormat: "JWT",
|
||||||
expireInHours: 24 * 7,
|
expireInHours: 24 * 7,
|
||||||
formOffset: 8,
|
formOffset: 2,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,26 +78,33 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
const newApplication = this.newApplication();
|
const newApplication = this.newApplication();
|
||||||
ApplicationBackend.addApplication(newApplication)
|
ApplicationBackend.addApplication(newApplication)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.props.history.push({pathname: `/applications/${newApplication.name}`, mode: "add"});
|
if (res.status === "ok") {
|
||||||
}
|
this.props.history.push({pathname: `/applications/${newApplication.organization}/${newApplication.name}`, mode: "add"});
|
||||||
)
|
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
||||||
|
} else {
|
||||||
|
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `Application failed to add: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteApplication(i) {
|
deleteApplication(i) {
|
||||||
ApplicationBackend.deleteApplication(this.state.data[i])
|
ApplicationBackend.deleteApplication(this.state.data[i])
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
Setting.showMessage("success", "Application deleted successfully");
|
if (res.status === "ok") {
|
||||||
this.setState({
|
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
||||||
data: Setting.deleteRow(this.state.data, i),
|
this.setState({
|
||||||
pagination: {total: this.state.pagination.total - 1},
|
data: Setting.deleteRow(this.state.data, i),
|
||||||
});
|
pagination: {total: this.state.pagination.total - 1},
|
||||||
}
|
});
|
||||||
)
|
} else {
|
||||||
|
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `Application failed to delete: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +120,7 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
...this.getColumnSearchProps("name"),
|
...this.getColumnSearchProps("name"),
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
<Link to={`/applications/${text}`}>
|
<Link to={`/applications/${record.organization}/${text}`}>
|
||||||
{text}
|
{text}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
@ -173,9 +197,9 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
<List.Item>
|
<List.Item>
|
||||||
<div style={{display: "inline"}}>
|
<div style={{display: "inline"}}>
|
||||||
<Tooltip placement="topLeft" title="Edit">
|
<Tooltip placement="topLeft" title="Edit">
|
||||||
<Button style={{marginRight: "5px"}} icon={<EditOutlined />} size="small" onClick={() => Setting.goToLinkSoft(this, `/providers/${providerItem.name}`)} />
|
<Button style={{marginRight: "5px"}} icon={<EditOutlined />} size="small" onClick={() => Setting.goToLinkSoft(this, `/providers/${record.organization}/${providerItem.name}`)} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Link to={`/providers/${providerItem.name}`}>
|
<Link to={`/providers/${record.organization}/${providerItem.name}`}>
|
||||||
{providerItem.name}
|
{providerItem.name}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
@ -213,13 +237,13 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/applications/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/applications/${record.organization}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title={`Sure to delete application: ${record.name} ?`}
|
title={`Sure to delete application: ${record.name} ?`}
|
||||||
onConfirm={() => this.deleteApplication(index)}
|
onConfirm={() => this.deleteApplication(index)}
|
||||||
disabled={record.name === "app-built-in"}
|
disabled={record.name === "app-built-in"}
|
||||||
>
|
>
|
||||||
<Button style={{marginBottom: "10px"}} disabled={record.name === "app-built-in"} type="danger">{i18next.t("general:Delete")}</Button>
|
<Button style={{marginBottom: "10px"}} disabled={record.name === "app-built-in"} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -254,7 +278,8 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
const field = params.searchedColumn, value = params.searchText;
|
const field = params.searchedColumn, value = params.searchText;
|
||||||
const sortField = params.sortField, sortOrder = params.sortOrder;
|
const sortField = params.sortField, sortOrder = params.sortOrder;
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
ApplicationBackend.getApplications("admin", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
(Setting.isAdminUser(this.props.account) ? ApplicationBackend.getApplications("admin", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder) :
|
||||||
|
ApplicationBackend.getApplicationsByOrganization("admin", this.state.organizationName, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder))
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -87,7 +87,7 @@ class BaseListPage extends React.Component {
|
|||||||
record[dataIndex]
|
record[dataIndex]
|
||||||
? record[dataIndex].toString().toLowerCase().includes(value.toLowerCase())
|
? record[dataIndex].toString().toLowerCase().includes(value.toLowerCase())
|
||||||
: "",
|
: "",
|
||||||
onFilterDropdownVisibleChange: visible => {
|
onFilterDropdownOpenChange: visible => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
setTimeout(() => this.searchInput.select(), 100);
|
setTimeout(() => this.searchInput.select(), 100);
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,7 @@ class CertEditPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderCert() {
|
renderCert() {
|
||||||
|
const editorWidth = Setting.isMobile() ? 22 : 9;
|
||||||
return (
|
return (
|
||||||
<Card size="small" title={
|
<Card size="small" title={
|
||||||
<div>
|
<div>
|
||||||
@ -166,7 +167,7 @@ class CertEditPage extends React.Component {
|
|||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("cert:Certificate"), i18next.t("cert:Certificate - Tooltip"))} :
|
{Setting.getLabel(i18next.t("cert:Certificate"), i18next.t("cert:Certificate - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={9} >
|
<Col span={editorWidth} >
|
||||||
<Button style={{marginRight: "10px", marginBottom: "10px"}} onClick={() => {
|
<Button style={{marginRight: "10px", marginBottom: "10px"}} onClick={() => {
|
||||||
copy(this.state.cert.certificate);
|
copy(this.state.cert.certificate);
|
||||||
Setting.showMessage("success", i18next.t("cert:Certificate copied to clipboard successfully"));
|
Setting.showMessage("success", i18next.t("cert:Certificate copied to clipboard successfully"));
|
||||||
@ -189,7 +190,7 @@ class CertEditPage extends React.Component {
|
|||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("cert:Private key"), i18next.t("cert:Private key - Tooltip"))} :
|
{Setting.getLabel(i18next.t("cert:Private key"), i18next.t("cert:Private key - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={9} >
|
<Col span={editorWidth} >
|
||||||
<Button style={{marginRight: "10px", marginBottom: "10px"}} onClick={() => {
|
<Button style={{marginRight: "10px", marginBottom: "10px"}} onClick={() => {
|
||||||
copy(this.state.cert.privateKey);
|
copy(this.state.cert.privateKey);
|
||||||
Setting.showMessage("success", i18next.t("cert:Private key copied to clipboard successfully"));
|
Setting.showMessage("success", i18next.t("cert:Private key copied to clipboard successfully"));
|
||||||
@ -217,8 +218,8 @@ class CertEditPage extends React.Component {
|
|||||||
const cert = Setting.deepCopy(this.state.cert);
|
const cert = Setting.deepCopy(this.state.cert);
|
||||||
CertBackend.updateCert(this.state.cert.owner, this.state.certName, cert)
|
CertBackend.updateCert(this.state.cert.owner, this.state.certName, cert)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.msg === "") {
|
if (res.status === "ok") {
|
||||||
Setting.showMessage("success", "Successfully saved");
|
Setting.showMessage("success", i18next.t("general:Successfully saved"));
|
||||||
this.setState({
|
this.setState({
|
||||||
certName: this.state.cert.name,
|
certName: this.state.cert.name,
|
||||||
});
|
});
|
||||||
@ -229,22 +230,26 @@ class CertEditPage extends React.Component {
|
|||||||
this.props.history.push(`/certs/${this.state.cert.name}`);
|
this.props.history.push(`/certs/${this.state.cert.name}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", res.msg);
|
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||||
this.updateCertField("name", this.state.certName);
|
this.updateCertField("name", this.state.certName);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `Failed to connect to server: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteCert() {
|
deleteCert() {
|
||||||
CertBackend.deleteCert(this.state.cert)
|
CertBackend.deleteCert(this.state.cert)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
this.props.history.push("/certs");
|
if (res.status === "ok") {
|
||||||
|
this.props.history.push("/certs");
|
||||||
|
} else {
|
||||||
|
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `Cert failed to delete: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,26 +43,33 @@ class CertListPage extends BaseListPage {
|
|||||||
const newCert = this.newCert();
|
const newCert = this.newCert();
|
||||||
CertBackend.addCert(newCert)
|
CertBackend.addCert(newCert)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.props.history.push({pathname: `/certs/${newCert.name}`, mode: "add"});
|
if (res.status === "ok") {
|
||||||
}
|
this.props.history.push({pathname: `/certs/${newCert.name}`, mode: "add"});
|
||||||
)
|
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
||||||
|
} else {
|
||||||
|
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `Cert failed to add: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteCert(i) {
|
deleteCert(i) {
|
||||||
CertBackend.deleteCert(this.state.data[i])
|
CertBackend.deleteCert(this.state.data[i])
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
Setting.showMessage("success", "Cert deleted successfully");
|
if (res.status === "ok") {
|
||||||
this.setState({
|
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
||||||
data: Setting.deleteRow(this.state.data, i),
|
this.setState({
|
||||||
pagination: {total: this.state.pagination.total - 1},
|
data: Setting.deleteRow(this.state.data, i),
|
||||||
});
|
pagination: {total: this.state.pagination.total - 1},
|
||||||
}
|
});
|
||||||
)
|
} else {
|
||||||
|
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
Setting.showMessage("error", `Cert failed to delete: ${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +172,7 @@ class CertListPage extends BaseListPage {
|
|||||||
title={`Sure to delete cert: ${record.name} ?`}
|
title={`Sure to delete cert: ${record.name} ?`}
|
||||||
onConfirm={() => this.deleteCert(index)}
|
onConfirm={() => this.deleteCert(index)}
|
||||||
>
|
>
|
||||||
<Button style={{marginBottom: "10px"}} type="danger">{i18next.t("general:Delete")}</Button>
|
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -30,6 +30,7 @@ export const CropperDiv = (props) => {
|
|||||||
const {title} = props;
|
const {title} = props;
|
||||||
const {user} = props;
|
const {user} = props;
|
||||||
const {buttonText} = props;
|
const {buttonText} = props;
|
||||||
|
const {organization} = props;
|
||||||
let uploadButton;
|
let uploadButton;
|
||||||
|
|
||||||
const onChange = (e) => {
|
const onChange = (e) => {
|
||||||
@ -92,9 +93,8 @@ export const CropperDiv = (props) => {
|
|||||||
|
|
||||||
const getOptions = (data) => {
|
const getOptions = (data) => {
|
||||||
const options = [];
|
const options = [];
|
||||||
if (props.account.organization.defaultAvatar !== null) {
|
options.push({value: organization?.defaultAvatar});
|
||||||
options.push({value: props.account.organization.defaultAvatar});
|
|
||||||
}
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
if (data[i].fileType === "image") {
|
if (data[i].fileType === "image") {
|
||||||
const url = `${data[i].url}`;
|
const url = `${data[i].url}`;
|
||||||
@ -125,7 +125,7 @@ export const CropperDiv = (props) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
ResourceBackend.getResources(props.account.owner, props.account.name, "", "", "", "", "", "")
|
ResourceBackend.getResources(user.owner, user.name, "", "", "", "", "", "")
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setOptions(getOptions(res));
|
setOptions(getOptions(res));
|
||||||
@ -140,7 +140,7 @@ export const CropperDiv = (props) => {
|
|||||||
<Modal
|
<Modal
|
||||||
maskClosable={false}
|
maskClosable={false}
|
||||||
title={title}
|
title={title}
|
||||||
visible={visible}
|
open={visible}
|
||||||
okText={i18next.t("user:Upload a photo")}
|
okText={i18next.t("user:Upload a photo")}
|
||||||
confirmLoading={confirmLoading}
|
confirmLoading={confirmLoading}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user