mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-14 08:03:23 +08:00
Compare commits
110 Commits
Author | SHA1 | Date | |
---|---|---|---|
3b2820cbe3 | |||
764e88f603 | |||
7f298efebc | |||
0fc48bb6cd | |||
c3b3840994 | |||
eacc3fae5a | |||
ce7a2e924b | |||
ece060d03d | |||
1276da4daa | |||
616629ef99 | |||
b633ecdcf2 | |||
a12ba7fb85 | |||
08a0092974 | |||
bb04b10e8b | |||
ea1414dfd0 | |||
32a8a028d5 | |||
0fe34c2f53 | |||
dc57c476b7 | |||
a7cb202ee9 | |||
e5e264628e | |||
8d4127f744 | |||
1305899060 | |||
411a85c7ab | |||
f39358e122 | |||
a84752bbb5 | |||
e9d8ab8cdb | |||
d12088e8e7 | |||
c62588f9bc | |||
16cd09d175 | |||
7318ee6e3a | |||
3459ef1479 | |||
ca6b27f922 | |||
e528e8883b | |||
b7cd604e56 | |||
3c2fd574a6 | |||
a9de7d3aef | |||
9820801634 | |||
c6e422c3a8 | |||
bc8e9cfd64 | |||
c1eae9fcd8 | |||
6dae6e4954 | |||
559a91e8ee | |||
b0aaf09ef1 | |||
7e2f67c49a | |||
e584a6a111 | |||
6700d2e244 | |||
0c5c308071 | |||
0b859197da | |||
3078409343 | |||
bbf2db2e00 | |||
0c7b911ce7 | |||
2cc55715ac | |||
c829bf1769 | |||
ec956c12ca | |||
d3d4646c56 | |||
669ac7c618 | |||
6715efd781 | |||
953be4a7b6 | |||
943cc43427 | |||
1e5ce7a045 | |||
7a85b74573 | |||
7e349c1768 | |||
b19be2df88 | |||
fc3866db1c | |||
bf2bb31e41 | |||
ec8bd6f01d | |||
98722fd681 | |||
221c55aa93 | |||
988b26b3c2 | |||
7e3c361ce7 | |||
a637707e77 | |||
7970edeaa7 | |||
9da2f0775f | |||
739a9bcd0d | |||
fb0949b9ed | |||
27ed901167 | |||
ceab662b88 | |||
05b2f00057 | |||
8073dfa88c | |||
1eeeb64a0c | |||
f5e0461cae | |||
a0c5eb241f | |||
4d8edcc446 | |||
2b23c04f49 | |||
e60ee52d91 | |||
c54b54ca19 | |||
f0e097e138 | |||
25ec1bdfa8 | |||
ea7718d7b7 | |||
463fa8b636 | |||
11895902f4 | |||
15269d3315 | |||
4468859795 | |||
914128a78a | |||
e5a189e0f4 | |||
a07216d0e1 | |||
fec54944dd | |||
a2db61cc1a | |||
134541acde | |||
59fca0342e | |||
abfc464155 | |||
a41f6880a2 | |||
d12117324c | |||
1a6c9fbf69 | |||
dd60d79af9 | |||
73d314c7fe | |||
27959e0f6f | |||
47f40c5b24 | |||
2ff9020884 | |||
abaf4ca8d9 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -110,7 +110,7 @@ jobs:
|
||||
with:
|
||||
start: yarn start
|
||||
wait-on: 'http://localhost:7001'
|
||||
wait-on-timeout: 180
|
||||
wait-on-timeout: 210
|
||||
working-directory: ./web
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
|
@ -64,7 +64,6 @@ COPY --from=BACK /go/src/casdoor/docker-entrypoint.sh /docker-entrypoint.sh
|
||||
COPY --from=BACK /go/src/casdoor/conf/app.conf ./conf/app.conf
|
||||
COPY --from=BACK /go/src/casdoor/version_info.txt ./go/src/casdoor/version_info.txt
|
||||
COPY --from=FRONT /web/build ./web/build
|
||||
RUN mkdir tempFiles
|
||||
|
||||
ENTRYPOINT ["/bin/bash"]
|
||||
CMD ["/docker-entrypoint.sh"]
|
||||
|
10
README.md
10
README.md
@ -11,7 +11,7 @@
|
||||
<img alt="GitHub Workflow Status (branch)" src="https://github.com/casdoor/casdoor/workflows/Build/badge.svg?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/releases/latest">
|
||||
<img alt="GitHub Release" src="https://img.shields.io/github/v/release/casbin/casdoor.svg">
|
||||
<img alt="GitHub Release" src="https://img.shields.io/github/v/release/casdoor/casdoor.svg">
|
||||
</a>
|
||||
<a href="https://hub.docker.com/repository/docker/casbin/casdoor">
|
||||
<img alt="Docker Image Version (latest semver)" src="https://img.shields.io/badge/Docker%20Hub-latest-brightgreen">
|
||||
@ -23,16 +23,16 @@
|
||||
<img alt="Go Report Card" src="https://goreportcard.com/badge/github.com/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/casbin/casdoor?style=flat-square" alt="license">
|
||||
<img src="https://img.shields.io/github/license/casdoor/casdoor?style=flat-square" alt="license">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/issues">
|
||||
<img alt="GitHub issues" src="https://img.shields.io/github/issues/casbin/casdoor?style=flat-square">
|
||||
<img alt="GitHub issues" src="https://img.shields.io/github/issues/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="#">
|
||||
<img alt="GitHub stars" src="https://img.shields.io/github/stars/casbin/casdoor?style=flat-square">
|
||||
<img alt="GitHub stars" src="https://img.shields.io/github/stars/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/network">
|
||||
<img alt="GitHub forks" src="https://img.shields.io/github/forks/casbin/casdoor?style=flat-square">
|
||||
<img alt="GitHub forks" src="https://img.shields.io/github/forks/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="https://crowdin.com/project/casdoor-site">
|
||||
<img alt="Crowdin" src="https://badges.crowdin.net/casdoor-site/localized.svg">
|
||||
|
@ -46,6 +46,7 @@ p, *, *, POST, /api/login, *, *
|
||||
p, *, *, GET, /api/get-app-login, *, *
|
||||
p, *, *, POST, /api/logout, *, *
|
||||
p, *, *, GET, /api/logout, *, *
|
||||
p, *, *, POST, /api/callback, *, *
|
||||
p, *, *, GET, /api/get-account, *, *
|
||||
p, *, *, GET, /api/userinfo, *, *
|
||||
p, *, *, GET, /api/user, *, *
|
||||
@ -87,6 +88,8 @@ p, *, *, GET, /api/get-prometheus-info, *, *
|
||||
p, *, *, *, /api/metrics, *, *
|
||||
p, *, *, GET, /api/get-pricing, *, *
|
||||
p, *, *, GET, /api/get-plan, *, *
|
||||
p, *, *, GET, /api/get-subscription, *, *
|
||||
p, *, *, GET, /api/get-provider, *, *
|
||||
p, *, *, GET, /api/get-organization-names, *, *
|
||||
`
|
||||
|
||||
@ -119,6 +122,10 @@ func IsAllowed(subOwner string, subName string, method string, urlPath string, o
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if subOwner == "app" {
|
||||
return true
|
||||
}
|
||||
|
||||
if user != nil && user.IsAdmin && (subOwner == objOwner || (objOwner == "admin")) {
|
||||
return true
|
||||
}
|
||||
|
28
conf/conf.go
28
conf/conf.go
@ -15,7 +15,7 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
@ -24,15 +24,6 @@ import (
|
||||
"github.com/beego/beego"
|
||||
)
|
||||
|
||||
type Quota struct {
|
||||
Organization int `json:"organization"`
|
||||
User int `json:"user"`
|
||||
Application int `json:"application"`
|
||||
Provider int `json:"provider"`
|
||||
}
|
||||
|
||||
var quota = &Quota{-1, -1, -1, -1}
|
||||
|
||||
func init() {
|
||||
// this array contains the beego configuration items that may be modified via env
|
||||
presetConfigItems := []string{"httpport", "appname"}
|
||||
@ -44,17 +35,6 @@ 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 {
|
||||
@ -67,7 +47,7 @@ func GetConfigString(key string) string {
|
||||
if key == "staticBaseUrl" {
|
||||
res = "https://cdn.casbin.org"
|
||||
} else if key == "logConfig" {
|
||||
res = "{\"filename\": \"logs/casdoor.log\", \"maxdays\":99999, \"perm\":\"0770\"}"
|
||||
res = fmt.Sprintf("{\"filename\": \"logs/%s.log\", \"maxdays\":99999, \"perm\":\"0770\"}", beego.AppConfig.String("appname"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,10 +109,6 @@ func GetConfigBatchSize() int {
|
||||
return res
|
||||
}
|
||||
|
||||
func GetConfigQuota() *Quota {
|
||||
return quota
|
||||
}
|
||||
|
||||
func GetConfigRealDataSourceName(driverName string) string {
|
||||
var dataSourceName string
|
||||
if driverName != "mysql" {
|
||||
|
48
conf/conf_quota.go
Normal file
48
conf/conf_quota.go
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package conf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/beego/beego"
|
||||
)
|
||||
|
||||
type Quota struct {
|
||||
Organization int `json:"organization"`
|
||||
User int `json:"user"`
|
||||
Application int `json:"application"`
|
||||
Provider int `json:"provider"`
|
||||
}
|
||||
|
||||
var quota = &Quota{-1, -1, -1, -1}
|
||||
|
||||
func init() {
|
||||
initQuota()
|
||||
}
|
||||
|
||||
func initQuota() {
|
||||
res := beego.AppConfig.String("quota")
|
||||
if res != "" {
|
||||
err := json.Unmarshal([]byte(res), quota)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetConfigQuota() *Quota {
|
||||
return quota
|
||||
}
|
@ -140,25 +140,28 @@ func (c *ApiController) Signup() {
|
||||
username = id
|
||||
}
|
||||
|
||||
password := authForm.Password
|
||||
msg = object.CheckPasswordComplexityByOrg(organization, password)
|
||||
if msg != "" {
|
||||
c.ResponseError(msg)
|
||||
return
|
||||
}
|
||||
|
||||
initScore, err := organization.GetInitScore()
|
||||
if err != nil {
|
||||
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
||||
return
|
||||
}
|
||||
|
||||
userType := "normal-user"
|
||||
if authForm.Plan != "" && authForm.Pricing != "" {
|
||||
err = object.CheckPricingAndPlan(authForm.Organization, authForm.Pricing, authForm.Plan)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
userType = "paid-user"
|
||||
}
|
||||
|
||||
user := &object.User{
|
||||
Owner: authForm.Organization,
|
||||
Name: username,
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
Id: id,
|
||||
Type: "normal-user",
|
||||
Type: userType,
|
||||
Password: authForm.Password,
|
||||
DisplayName: authForm.Name,
|
||||
Avatar: organization.DefaultAvatar,
|
||||
@ -171,7 +174,6 @@ func (c *ApiController) Signup() {
|
||||
Region: authForm.Region,
|
||||
Score: initScore,
|
||||
IsAdmin: false,
|
||||
IsGlobalAdmin: false,
|
||||
IsForbidden: false,
|
||||
IsDeleted: false,
|
||||
SignupApplication: application.Name,
|
||||
@ -211,7 +213,7 @@ func (c *ApiController) Signup() {
|
||||
return
|
||||
}
|
||||
|
||||
if application.HasPromptPage() {
|
||||
if application.HasPromptPage() && user.Type == "normal-user" {
|
||||
// The prompt page needs the user to be signed in
|
||||
c.SetSessionUsername(user.GetId())
|
||||
}
|
||||
@ -228,15 +230,6 @@ func (c *ApiController) Signup() {
|
||||
return
|
||||
}
|
||||
|
||||
isSignupFromPricing := authForm.Plan != "" && authForm.Pricing != ""
|
||||
if isSignupFromPricing {
|
||||
_, err = object.Subscribe(organization.Name, user.Name, authForm.Plan, authForm.Pricing)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
record := object.NewRecord(c.Ctx)
|
||||
record.Organization = application.Organization
|
||||
record.User = user.Name
|
||||
@ -316,27 +309,32 @@ func (c *ApiController) Logout() {
|
||||
return
|
||||
}
|
||||
|
||||
if application.IsRedirectUriValid(redirectUri) {
|
||||
if user == "" {
|
||||
user = util.GetId(token.Organization, token.User)
|
||||
}
|
||||
if user == "" {
|
||||
user = util.GetId(token.Organization, token.User)
|
||||
}
|
||||
|
||||
c.ClearUserSession()
|
||||
// TODO https://github.com/casdoor/casdoor/pull/1494#discussion_r1095675265
|
||||
owner, username := util.GetOwnerAndNameFromId(user)
|
||||
c.ClearUserSession()
|
||||
// TODO https://github.com/casdoor/casdoor/pull/1494#discussion_r1095675265
|
||||
owner, username := util.GetOwnerAndNameFromId(user)
|
||||
|
||||
_, err := object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID())
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
_, err = object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID())
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
||||
|
||||
if redirectUri == "" {
|
||||
c.ResponseOk()
|
||||
return
|
||||
} else {
|
||||
if application.IsRedirectUriValid(redirectUri) {
|
||||
c.Ctx.Redirect(http.StatusFound, fmt.Sprintf("%s?state=%s", strings.TrimRight(redirectUri, "/"), state))
|
||||
} else {
|
||||
c.ResponseError(fmt.Sprintf(c.T("token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), redirectUri))
|
||||
return
|
||||
}
|
||||
|
||||
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
||||
|
||||
c.Ctx.Redirect(http.StatusFound, fmt.Sprintf("%s?state=%s", strings.TrimRight(redirectUri, "/"), state))
|
||||
} else {
|
||||
c.ResponseError(fmt.Sprintf(c.T("token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), redirectUri))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
)
|
||||
|
||||
// GetAdapters
|
||||
@ -144,92 +143,3 @@ func (c *ApiController) DeleteAdapter() {
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteAdapter(&adapter))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) GetPolicies() {
|
||||
id := c.Input().Get("id")
|
||||
adapter, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
policies, err := object.GetPolicies(adapter)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(policies)
|
||||
}
|
||||
|
||||
func (c *ApiController) UpdatePolicy() {
|
||||
id := c.Input().Get("id")
|
||||
adapter, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
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, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
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, err := object.GetAdapter(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
@ -62,13 +62,13 @@ func (c *ApiController) GetApplications() {
|
||||
}
|
||||
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||
app, err := object.GetPaginationApplications(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
application, err := object.GetPaginationApplications(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
applications := object.GetMaskedApplications(app, userId)
|
||||
applications := object.GetMaskedApplications(application, userId)
|
||||
c.ResponseOk(applications, paginator.Nums())
|
||||
}
|
||||
}
|
||||
@ -84,13 +84,33 @@ func (c *ApiController) GetApplication() {
|
||||
userId := c.GetSessionUsername()
|
||||
id := c.Input().Get("id")
|
||||
|
||||
app, err := object.GetApplication(id)
|
||||
application, err := object.GetApplication(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(object.GetMaskedApplication(app, userId))
|
||||
if c.Input().Get("withKey") != "" && application != nil && application.Cert != "" {
|
||||
cert, err := object.GetCert(util.GetId(application.Owner, application.Cert))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if cert == nil {
|
||||
cert, err = object.GetCert(util.GetId(application.Organization, application.Cert))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if cert != nil {
|
||||
application.CertPublicKey = cert.Certificate
|
||||
}
|
||||
}
|
||||
|
||||
c.ResponseOk(object.GetMaskedApplication(application, userId))
|
||||
}
|
||||
|
||||
// GetUserApplication
|
||||
@ -164,13 +184,13 @@ func (c *ApiController) GetOrganizationApplications() {
|
||||
}
|
||||
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||
app, err := object.GetPaginationOrganizationApplications(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
application, err := object.GetPaginationOrganizationApplications(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
applications := object.GetMaskedApplications(app, userId)
|
||||
applications := object.GetMaskedApplications(application, userId)
|
||||
c.ResponseOk(applications, paginator.Nums())
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -59,7 +60,7 @@ func tokenToResponse(token *object.Token) *Response {
|
||||
func (c *ApiController) HandleLoggedIn(application *object.Application, user *object.User, form *form.AuthForm) (resp *Response) {
|
||||
userId := user.GetId()
|
||||
|
||||
allowed, err := object.CheckAccessPermission(userId, application)
|
||||
allowed, err := object.CheckLoginPermission(userId, application)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error(), nil)
|
||||
return
|
||||
@ -70,7 +71,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
||||
}
|
||||
|
||||
// check user's tag
|
||||
if !user.IsGlobalAdmin && !user.IsAdmin && len(application.Tags) > 0 {
|
||||
if !user.IsGlobalAdmin() && !user.IsAdmin && len(application.Tags) > 0 {
|
||||
// only users with the tag that is listed in the application tags can login
|
||||
if !util.InSlice(application.Tags, user.Tag) {
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:User's tag: %s is not listed in the application's tags"), user.Tag))
|
||||
@ -78,6 +79,46 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
||||
}
|
||||
}
|
||||
|
||||
// check whether paid-user have active subscription
|
||||
if user.Type == "paid-user" {
|
||||
subscriptions, err := object.GetSubscriptionsByUser(user.Owner, user.Name)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
existActiveSubscription := false
|
||||
for _, subscription := range subscriptions {
|
||||
if subscription.State == object.SubStateActive {
|
||||
existActiveSubscription = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !existActiveSubscription {
|
||||
// check pending subscription
|
||||
for _, sub := range subscriptions {
|
||||
if sub.State == object.SubStatePending {
|
||||
c.ResponseOk("BuyPlanResult", sub)
|
||||
return
|
||||
}
|
||||
}
|
||||
// paid-user does not have active or pending subscription, find the default pricing of application
|
||||
pricing, err := object.GetApplicationDefaultPricing(application.Organization, application.Name)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
if pricing == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"), user.Name, application.Name))
|
||||
return
|
||||
} else {
|
||||
// let the paid-user select plan
|
||||
c.ResponseOk("SelectPlan", pricing)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if form.Type == ResponseTypeLogin {
|
||||
c.SetSessionUsername(userId)
|
||||
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
|
||||
@ -187,11 +228,34 @@ func (c *ApiController) GetApplicationLogin() {
|
||||
redirectUri := c.Input().Get("redirectUri")
|
||||
scope := c.Input().Get("scope")
|
||||
state := c.Input().Get("state")
|
||||
id := c.Input().Get("id")
|
||||
loginType := c.Input().Get("type")
|
||||
|
||||
msg, application, err := object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state, c.GetAcceptLanguage())
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
var application *object.Application
|
||||
var msg string
|
||||
var err error
|
||||
if loginType == "code" {
|
||||
msg, application, err = object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state, c.GetAcceptLanguage())
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
} else if loginType == "cas" {
|
||||
application, err = object.GetApplication(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
if application == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), id))
|
||||
return
|
||||
}
|
||||
|
||||
err = object.CheckCasLogin(application, c.GetAcceptLanguage(), redirectUri)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
application = object.GetMaskedApplication(application, "")
|
||||
@ -566,7 +630,6 @@ func (c *ApiController) Login() {
|
||||
Region: userInfo.CountryCode,
|
||||
Score: initScore,
|
||||
IsAdmin: false,
|
||||
IsGlobalAdmin: false,
|
||||
IsForbidden: false,
|
||||
IsDeleted: false,
|
||||
SignupApplication: application.Name,
|
||||
@ -834,3 +897,16 @@ func (c *ApiController) GetCaptchaStatus() {
|
||||
}
|
||||
c.ResponseOk(captchaEnabled)
|
||||
}
|
||||
|
||||
// Callback
|
||||
// @Title Callback
|
||||
// @Tag Callback API
|
||||
// @Description Get Login Error Counts
|
||||
// @router /api/Callback [post]
|
||||
func (c *ApiController) Callback() {
|
||||
code := c.GetString("code")
|
||||
state := c.GetString("state")
|
||||
|
||||
frontendCallbackUrl := fmt.Sprintf("/callback?code=%s&state=%s", code, state)
|
||||
c.Ctx.Redirect(http.StatusFound, frontendCallbackUrl)
|
||||
}
|
||||
|
@ -61,6 +61,10 @@ func (c *ApiController) IsAdminOrSelf(user2 *object.User) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
if user == nil || user2 == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if user.Owner == user2.Owner && user.Name == user2.Name {
|
||||
return true
|
||||
}
|
||||
@ -79,7 +83,7 @@ func (c *ApiController) isGlobalAdmin() (bool, *object.User) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return user.Owner == "built-in" || user.IsGlobalAdmin, user
|
||||
return user.IsGlobalAdmin(), user
|
||||
}
|
||||
|
||||
func (c *ApiController) getCurrentUser() *object.User {
|
||||
|
@ -35,6 +35,11 @@ const (
|
||||
UnauthorizedService string = "UNAUTHORIZED_SERVICE"
|
||||
)
|
||||
|
||||
func queryUnescape(service string) string {
|
||||
s, _ := url.QueryUnescape(service)
|
||||
return s
|
||||
}
|
||||
|
||||
func (c *RootController) CasValidate() {
|
||||
ticket := c.Input().Get("ticket")
|
||||
service := c.Input().Get("service")
|
||||
@ -60,24 +65,25 @@ func (c *RootController) CasServiceValidate() {
|
||||
if !strings.HasPrefix(ticket, "ST") {
|
||||
c.sendCasAuthenticationResponseErr(InvalidTicket, fmt.Sprintf("Ticket %s not recognized", ticket), format)
|
||||
}
|
||||
c.CasP3ServiceAndProxyValidate()
|
||||
c.CasP3ProxyValidate()
|
||||
}
|
||||
|
||||
func (c *RootController) CasProxyValidate() {
|
||||
// https://apereo.github.io/cas/6.6.x/protocol/CAS-Protocol-Specification.html#26-proxyvalidate-cas-20
|
||||
// "/proxyValidate" should accept both service tickets and proxy tickets.
|
||||
c.CasP3ProxyValidate()
|
||||
}
|
||||
|
||||
func (c *RootController) CasP3ServiceValidate() {
|
||||
ticket := c.Input().Get("ticket")
|
||||
format := c.Input().Get("format")
|
||||
if !strings.HasPrefix(ticket, "PT") {
|
||||
if !strings.HasPrefix(ticket, "ST") {
|
||||
c.sendCasAuthenticationResponseErr(InvalidTicket, fmt.Sprintf("Ticket %s not recognized", ticket), format)
|
||||
}
|
||||
c.CasP3ServiceAndProxyValidate()
|
||||
c.CasP3ProxyValidate()
|
||||
}
|
||||
|
||||
func queryUnescape(service string) string {
|
||||
s, _ := url.QueryUnescape(service)
|
||||
return s
|
||||
}
|
||||
|
||||
func (c *RootController) CasP3ServiceAndProxyValidate() {
|
||||
func (c *RootController) CasP3ProxyValidate() {
|
||||
ticket := c.Input().Get("ticket")
|
||||
format := c.Input().Get("format")
|
||||
service := c.Input().Get("service")
|
||||
@ -115,15 +121,17 @@ func (c *RootController) CasP3ServiceAndProxyValidate() {
|
||||
pgtiou := serviceResponse.Success.ProxyGrantingTicket
|
||||
// todo: check whether it is https
|
||||
pgtUrlObj, err := url.Parse(pgtUrl)
|
||||
if err != nil {
|
||||
c.sendCasAuthenticationResponseErr(InvalidProxyCallback, err.Error(), format)
|
||||
return
|
||||
}
|
||||
|
||||
if pgtUrlObj.Scheme != "https" {
|
||||
c.sendCasAuthenticationResponseErr(InvalidProxyCallback, "callback is not https", format)
|
||||
return
|
||||
}
|
||||
|
||||
// make a request to pgturl passing pgt and pgtiou
|
||||
if err != nil {
|
||||
c.sendCasAuthenticationResponseErr(InternalError, err.Error(), format)
|
||||
return
|
||||
}
|
||||
param := pgtUrlObj.Query()
|
||||
param.Add("pgtId", pgt)
|
||||
param.Add("pgtIou", pgtiou)
|
||||
@ -263,7 +271,6 @@ func (c *RootController) sendCasAuthenticationResponseErr(code, msg, format stri
|
||||
Message: msg,
|
||||
},
|
||||
}
|
||||
|
||||
if format == "json" {
|
||||
c.Data["json"] = serviceResponse
|
||||
c.ServeJSON()
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
)
|
||||
|
||||
// GetEnforcers
|
||||
@ -74,6 +75,7 @@ func (c *ApiController) GetEnforcers() {
|
||||
// @router /get-enforcer [get]
|
||||
func (c *ApiController) GetEnforcer() {
|
||||
id := c.Input().Get("id")
|
||||
loadModelCfg := c.Input().Get("loadModelCfg")
|
||||
|
||||
enforcer, err := object.GetEnforcer(id)
|
||||
if err != nil {
|
||||
@ -81,6 +83,13 @@ func (c *ApiController) GetEnforcer() {
|
||||
return
|
||||
}
|
||||
|
||||
if loadModelCfg == "true" && enforcer.Model != "" {
|
||||
err := enforcer.LoadModelCfg()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.ResponseOk(enforcer)
|
||||
}
|
||||
|
||||
@ -143,3 +152,88 @@ func (c *ApiController) DeleteEnforcer() {
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteEnforcer(&enforcer))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) GetPolicies() {
|
||||
id := c.Input().Get("id")
|
||||
adapterId := c.Input().Get("adapterId")
|
||||
|
||||
if adapterId != "" {
|
||||
adapter, err := object.GetAdapter(adapterId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
err = adapter.InitAdapter()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.ResponseOk()
|
||||
return
|
||||
}
|
||||
|
||||
policies, err := object.GetPolicies(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(policies)
|
||||
}
|
||||
|
||||
func (c *ApiController) UpdatePolicy() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var policies []xormadapter.CasbinRule
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policies)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.UpdatePolicy(id, util.CasbinToSlice(policies[0]), util.CasbinToSlice(policies[1]))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) AddPolicy() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var policy xormadapter.CasbinRule
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.AddPolicy(id, util.CasbinToSlice(policy))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) RemovePolicy() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var policy xormadapter.CasbinRule
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.RemovePolicy(id, util.CasbinToSlice(policy))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -23,7 +23,9 @@ import "github.com/casdoor/casdoor/object"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /get-dashboard [get]
|
||||
func (c *ApiController) GetDashboard() {
|
||||
data, err := object.GetDashboard()
|
||||
owner := c.Input().Get("owner")
|
||||
|
||||
data, err := object.GetDashboard(owner)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
|
@ -45,13 +45,13 @@ func (c *ApiController) Unlink() {
|
||||
// the user will be unlinked from the provider
|
||||
unlinkedUser := form.User
|
||||
|
||||
if user.Id != unlinkedUser.Id && !user.IsGlobalAdmin {
|
||||
if user.Id != unlinkedUser.Id && !user.IsGlobalAdmin() {
|
||||
// if the user is not the same as the one we are unlinking, we need to make sure the user is the global admin.
|
||||
c.ResponseError(c.T("link:You are not the global admin, you can't unlink other users"))
|
||||
return
|
||||
}
|
||||
|
||||
if user.Id == unlinkedUser.Id && !user.IsGlobalAdmin {
|
||||
if user.Id == unlinkedUser.Id && !user.IsGlobalAdmin() {
|
||||
// if the user is unlinking themselves, should check the provider can be unlinked, if not, we should return an error.
|
||||
application, err := object.GetApplicationByUser(user)
|
||||
if err != nil {
|
||||
|
@ -183,8 +183,6 @@ func (c *ApiController) DeleteOrganization() {
|
||||
func (c *ApiController) GetDefaultApplication() {
|
||||
userId := c.GetSessionUsername()
|
||||
id := c.Input().Get("id")
|
||||
redirectUri := c.Input().Get("redirectUri")
|
||||
typ := c.Input().Get("type")
|
||||
|
||||
application, err := object.GetDefaultApplication(id)
|
||||
if err != nil {
|
||||
@ -192,14 +190,6 @@ func (c *ApiController) GetDefaultApplication() {
|
||||
return
|
||||
}
|
||||
|
||||
if typ == "cas" {
|
||||
err = object.CheckCasRestrict(application, c.GetAcceptLanguage(), redirectUri)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
maskedApplication := object.GetMaskedApplication(application, userId)
|
||||
c.ResponseOk(maskedApplication)
|
||||
}
|
||||
|
@ -176,11 +176,10 @@ func (c *ApiController) DeletePayment() {
|
||||
func (c *ApiController) NotifyPayment() {
|
||||
owner := c.Ctx.Input.Param(":owner")
|
||||
paymentName := c.Ctx.Input.Param(":payment")
|
||||
orderId := c.Ctx.Input.Param("order")
|
||||
|
||||
body := c.Ctx.Input.RequestBody
|
||||
|
||||
payment, err := object.NotifyPayment(c.Ctx.Request, body, owner, paymentName, orderId)
|
||||
payment, err := object.NotifyPayment(body, owner, paymentName)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
|
@ -16,6 +16,7 @@ package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
@ -32,16 +33,15 @@ func (c *ApiController) UploadPermissions() {
|
||||
}
|
||||
|
||||
fileId := fmt.Sprintf("%s_%s_%s", owner, user, util.RemoveExt(header.Filename))
|
||||
|
||||
path := util.GetUploadXlsxPath(fileId)
|
||||
util.EnsureFileFolderExists(path)
|
||||
defer os.Remove(path)
|
||||
err = saveFile(path, &file)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.UploadPermissions(owner, fileId)
|
||||
affected, err := object.UploadPermissions(owner, path)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
@ -82,7 +83,10 @@ func (c *ApiController) GetPlan() {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if plan == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("plan:The plan: %s does not exist"), id))
|
||||
return
|
||||
}
|
||||
if includeOption {
|
||||
options, err := object.GetPermissionsByRole(plan.Role)
|
||||
if err != nil {
|
||||
@ -110,14 +114,29 @@ func (c *ApiController) GetPlan() {
|
||||
// @router /update-plan [post]
|
||||
func (c *ApiController) UpdatePlan() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
owner := util.GetOwnerFromId(id)
|
||||
var plan object.Plan
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &plan)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if plan.Product != "" {
|
||||
productId := util.GetId(owner, plan.Product)
|
||||
product, err := object.GetProduct(productId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
if product != nil {
|
||||
object.UpdateProductForPlan(&plan, product)
|
||||
_, err = object.UpdateProduct(productId, product)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(object.UpdatePlan(id, &plan))
|
||||
c.ServeJSON()
|
||||
}
|
||||
@ -136,7 +155,14 @@ func (c *ApiController) AddPlan() {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Create a related product for plan
|
||||
product := object.CreateProductForPlan(&plan)
|
||||
_, err = object.AddProduct(product)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
plan.Product = product.Name
|
||||
c.Data["json"] = wrapActionResponse(object.AddPlan(&plan))
|
||||
c.ServeJSON()
|
||||
}
|
||||
@ -155,7 +181,13 @@ func (c *ApiController) DeletePlan() {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if plan.Product != "" {
|
||||
_, err = object.DeleteProduct(&object.Product{Owner: plan.Owner, Name: plan.Product})
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
c.Data["json"] = wrapActionResponse(object.DeletePlan(&plan))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
@ -80,7 +81,10 @@ func (c *ApiController) GetPricing() {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if pricing == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("pricing:The pricing: %s does not exist"), id))
|
||||
return
|
||||
}
|
||||
c.ResponseOk(pricing)
|
||||
}
|
||||
|
||||
|
@ -161,10 +161,17 @@ func (c *ApiController) DeleteProduct() {
|
||||
// @router /buy-product [post]
|
||||
func (c *ApiController) BuyProduct() {
|
||||
id := c.Input().Get("id")
|
||||
providerName := c.Input().Get("providerName")
|
||||
host := c.Ctx.Request.Host
|
||||
|
||||
userId := c.GetSessionUsername()
|
||||
providerName := c.Input().Get("providerName")
|
||||
// buy `pricingName/planName` for `paidUserName`
|
||||
pricingName := c.Input().Get("pricingName")
|
||||
planName := c.Input().Get("planName")
|
||||
paidUserName := c.Input().Get("userName")
|
||||
owner, _ := util.GetOwnerAndNameFromId(id)
|
||||
userId := util.GetId(owner, paidUserName)
|
||||
if paidUserName == "" {
|
||||
userId = c.GetSessionUsername()
|
||||
}
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
return
|
||||
@ -175,17 +182,16 @@ func (c *ApiController) BuyProduct() {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId))
|
||||
return
|
||||
}
|
||||
|
||||
payUrl, orderId, err := object.BuyProduct(id, providerName, user, host)
|
||||
payment, err := object.BuyProduct(id, user, providerName, pricingName, planName, host)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(payUrl, orderId)
|
||||
c.ResponseOk(payment)
|
||||
}
|
||||
|
@ -1,121 +0,0 @@
|
||||
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
// GetRecords
|
||||
// @Title GetRecords
|
||||
// @Tag Record API
|
||||
// @Description get all records
|
||||
// @Param pageSize query string true "The size of each page"
|
||||
// @Param p query string true "The number of the page"
|
||||
// @Success 200 {object} object.Record The Response object
|
||||
// @router /get-records [get]
|
||||
func (c *ApiController) GetRecords() {
|
||||
organization, ok := c.RequireAdmin()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
limit := c.Input().Get("pageSize")
|
||||
page := c.Input().Get("p")
|
||||
field := c.Input().Get("field")
|
||||
value := c.Input().Get("value")
|
||||
sortField := c.Input().Get("sortField")
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
organizationName := c.Input().Get("organizationName")
|
||||
|
||||
if limit == "" || page == "" {
|
||||
records, err := object.GetRecords()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(records)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
if c.IsGlobalAdmin() && organizationName != "" {
|
||||
organization = organizationName
|
||||
}
|
||||
filterRecord := &object.Record{Organization: organization}
|
||||
count, err := object.GetRecordCount(field, value, filterRecord)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||
records, err := object.GetPaginationRecords(paginator.Offset(), limit, field, value, sortField, sortOrder, filterRecord)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(records, paginator.Nums())
|
||||
}
|
||||
}
|
||||
|
||||
// GetRecordsByFilter
|
||||
// @Tag Record API
|
||||
// @Title GetRecordsByFilter
|
||||
// @Description get records by filter
|
||||
// @Param filter body string true "filter Record message"
|
||||
// @Success 200 {object} object.Record The Response object
|
||||
// @router /get-records-filter [post]
|
||||
func (c *ApiController) GetRecordsByFilter() {
|
||||
body := string(c.Ctx.Input.RequestBody)
|
||||
|
||||
record := &object.Record{}
|
||||
err := util.JsonToStruct(body, record)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
records, err := object.GetRecordsByField(record)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(records)
|
||||
}
|
||||
|
||||
// AddRecord
|
||||
// @Title AddRecord
|
||||
// @Tag Record API
|
||||
// @Description add a record
|
||||
// @Param body body object.Record true "The details of the record"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /add-record [post]
|
||||
func (c *ApiController) AddRecord() {
|
||||
var record object.Record
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &record)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = wrapActionResponse(object.AddRecord(&record))
|
||||
c.ServeJSON()
|
||||
}
|
@ -16,6 +16,7 @@ package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
@ -32,16 +33,15 @@ func (c *ApiController) UploadRoles() {
|
||||
}
|
||||
|
||||
fileId := fmt.Sprintf("%s_%s_%s", owner, user, util.RemoveExt(header.Filename))
|
||||
|
||||
path := util.GetUploadXlsxPath(fileId)
|
||||
util.EnsureFileFolderExists(path)
|
||||
defer os.Remove(path)
|
||||
err = saveFile(path, &file)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.UploadRoles(owner, fileId)
|
||||
affected, err := object.UploadRoles(owner, path)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
}
|
||||
|
@ -40,6 +40,10 @@ type SmsForm struct {
|
||||
OrgId string `json:"organizationId"` // e.g. "admin/built-in"
|
||||
}
|
||||
|
||||
type NotificationForm struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
// SendEmail
|
||||
// @Title SendEmail
|
||||
// @Tag Service API
|
||||
@ -156,3 +160,33 @@ func (c *ApiController) SendSms() {
|
||||
|
||||
c.ResponseOk()
|
||||
}
|
||||
|
||||
// SendNotification
|
||||
// @Title SendNotification
|
||||
// @Tag Service API
|
||||
// @Description This API is not for Casdoor frontend to call, it is for Casdoor SDKs.
|
||||
// @Param from body controllers.NotificationForm true "Details of the notification request"
|
||||
// @Success 200 {object} Response object
|
||||
// @router /api/send-notification [post]
|
||||
func (c *ApiController) SendNotification() {
|
||||
provider, err := c.GetProviderFromContext("Notification")
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var notificationForm NotificationForm
|
||||
err = json.Unmarshal(c.Ctx.Input.RequestBody, ¬ificationForm)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = object.SendNotification(provider, notificationForm.Content)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk()
|
||||
}
|
||||
|
@ -160,7 +160,11 @@ func (c *ApiController) RunSyncer() {
|
||||
return
|
||||
}
|
||||
|
||||
object.RunSyncer(syncer)
|
||||
err = object.RunSyncer(syncer)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk()
|
||||
}
|
||||
|
@ -47,16 +47,16 @@ func (c *ApiController) GetSystemInfo() {
|
||||
// @router /get-version-info [get]
|
||||
func (c *ApiController) GetVersionInfo() {
|
||||
versionInfo, err := util.GetVersionInfo()
|
||||
|
||||
if versionInfo.Version == "" {
|
||||
versionInfo, err = util.GetVersionInfoFromFile()
|
||||
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
if versionInfo.Version != "" {
|
||||
c.ResponseOk(versionInfo)
|
||||
return
|
||||
}
|
||||
|
||||
versionInfo, err = util.GetVersionInfoFromFile()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.ResponseOk(versionInfo)
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ func (c *ApiController) DeleteToken() {
|
||||
// @Success 200 {object} object.TokenWrapper The Response object
|
||||
// @Success 400 {object} object.TokenError The Response object
|
||||
// @Success 401 {object} object.TokenError The Response object
|
||||
// @router /login/oauth/access_token [post]
|
||||
// @router api/login/oauth/access_token [post]
|
||||
func (c *ApiController) GetOAuthToken() {
|
||||
grantType := c.Input().Get("grant_type")
|
||||
refreshToken := c.Input().Get("refresh_token")
|
||||
|
@ -258,6 +258,13 @@ func (c *ApiController) UpdateUser() {
|
||||
return
|
||||
}
|
||||
|
||||
if c.Input().Get("allowEmpty") == "" {
|
||||
if user.DisplayName == "" {
|
||||
c.ResponseError(c.T("user:Display name cannot be empty"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if msg := object.CheckUpdateUser(oldUser, &user, c.GetAcceptLanguage()); msg != "" {
|
||||
c.ResponseError(msg)
|
||||
return
|
||||
@ -441,12 +448,25 @@ func (c *ApiController) SetPassword() {
|
||||
}
|
||||
|
||||
targetUser, err := object.GetUser(userId)
|
||||
if targetUser == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId))
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if oldPassword != "" {
|
||||
isAdmin := c.IsAdmin()
|
||||
if isAdmin {
|
||||
if oldPassword != "" {
|
||||
msg := object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
|
||||
if msg != "" {
|
||||
c.ResponseError(msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
msg := object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
|
||||
if msg != "" {
|
||||
c.ResponseError(msg)
|
||||
|
@ -48,17 +48,17 @@ func (c *ApiController) UploadUsers() {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
fileId := fmt.Sprintf("%s_%s_%s", owner, user, util.RemoveExt(header.Filename))
|
||||
|
||||
fileId := fmt.Sprintf("%s_%s_%s", owner, user, util.RemoveExt(header.Filename))
|
||||
path := util.GetUploadXlsxPath(fileId)
|
||||
util.EnsureFileFolderExists(path)
|
||||
defer os.Remove(path)
|
||||
err = saveFile(path, &file)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
affected, err := object.UploadUsers(owner, fileId)
|
||||
affected, err := object.UploadUsers(owner, path)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
|
227
email/azure_acs.go
Normal file
227
email/azure_acs.go
Normal file
@ -0,0 +1,227 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package email
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
importanceNormal = "normal"
|
||||
sendEmailEndpoint = "/emails:send"
|
||||
apiVersion = "2023-03-31"
|
||||
)
|
||||
|
||||
type Email struct {
|
||||
Recipients Recipients `json:"recipients"`
|
||||
SenderAddress string `json:"senderAddress"`
|
||||
Content Content `json:"content"`
|
||||
Headers []CustomHeader `json:"headers"`
|
||||
Tracking bool `json:"disableUserEngagementTracking"`
|
||||
Importance string `json:"importance"`
|
||||
ReplyTo []EmailAddress `json:"replyTo"`
|
||||
Attachments []Attachment `json:"attachments"`
|
||||
}
|
||||
|
||||
type Recipients struct {
|
||||
To []EmailAddress `json:"to"`
|
||||
CC []EmailAddress `json:"cc"`
|
||||
BCC []EmailAddress `json:"bcc"`
|
||||
}
|
||||
|
||||
type EmailAddress struct {
|
||||
DisplayName string `json:"displayName"`
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
type Content struct {
|
||||
Subject string `json:"subject"`
|
||||
HTML string `json:"html"`
|
||||
PlainText string `json:"plainText"`
|
||||
}
|
||||
|
||||
type CustomHeader struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type Attachment struct {
|
||||
Content string `json:"contentBytesBase64"`
|
||||
AttachmentType string `json:"attachmentType"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ErrorResponse struct {
|
||||
Error CommunicationError `json:"error"`
|
||||
}
|
||||
|
||||
// CommunicationError contains the error code and message
|
||||
type CommunicationError struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type AzureACSEmailProvider struct {
|
||||
AccessKey string
|
||||
Endpoint string
|
||||
}
|
||||
|
||||
func NewAzureACSEmailProvider(accessKey string, endpoint string) *AzureACSEmailProvider {
|
||||
return &AzureACSEmailProvider{
|
||||
AccessKey: accessKey,
|
||||
Endpoint: endpoint,
|
||||
}
|
||||
}
|
||||
|
||||
func newEmail(fromAddress string, toAddress string, subject string, content string) *Email {
|
||||
return &Email{
|
||||
Recipients: Recipients{
|
||||
To: []EmailAddress{
|
||||
{
|
||||
DisplayName: toAddress,
|
||||
Address: toAddress,
|
||||
},
|
||||
},
|
||||
},
|
||||
SenderAddress: fromAddress,
|
||||
Content: Content{
|
||||
Subject: subject,
|
||||
HTML: content,
|
||||
},
|
||||
Importance: importanceNormal,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AzureACSEmailProvider) sendEmail(e *Email) error {
|
||||
postBody, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
return fmt.Errorf("email JSON marshall failed: %s", err)
|
||||
}
|
||||
|
||||
bodyBuffer := bytes.NewBuffer(postBody)
|
||||
|
||||
req, err := http.NewRequest("POST", a.Endpoint+sendEmailEndpoint+"?api-version="+apiVersion, bodyBuffer)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating AzureACS API request: %s", err)
|
||||
}
|
||||
|
||||
// Sign the request using the AzureACS access key and HMAC-SHA256
|
||||
err = signRequestHMAC(a.AccessKey, req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error signing AzureACS API request: %s", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
// Some important header
|
||||
req.Header.Set("repeatability-request-id", uuid.New().String())
|
||||
req.Header.Set("repeatability-first-sent", time.Now().UTC().Format(http.TimeFormat))
|
||||
|
||||
// Send request
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error sending AzureACS API request: %s", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Response error Handling
|
||||
if resp.StatusCode == http.StatusBadRequest {
|
||||
commError := ErrorResponse{}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&commError)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fmt.Errorf("error sending email: %s", commError.Error.Message)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusAccepted {
|
||||
return fmt.Errorf("error sending email: status: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func signRequestHMAC(secret string, req *http.Request) error {
|
||||
method := req.Method
|
||||
host := req.URL.Host
|
||||
pathAndQuery := req.URL.Path
|
||||
|
||||
if req.URL.RawQuery != "" {
|
||||
pathAndQuery = pathAndQuery + "?" + req.URL.RawQuery
|
||||
}
|
||||
|
||||
var content []byte
|
||||
var err error
|
||||
if req.Body != nil {
|
||||
content, err = io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
// return err
|
||||
content = []byte{}
|
||||
}
|
||||
}
|
||||
|
||||
req.Body = io.NopCloser(bytes.NewBuffer(content))
|
||||
|
||||
key, err := base64.StdEncoding.DecodeString(secret)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decoding secret: %s", err)
|
||||
}
|
||||
|
||||
timestamp := time.Now().UTC().Format(http.TimeFormat)
|
||||
contentHash := GetContentHashBase64(content)
|
||||
stringToSign := fmt.Sprintf("%s\n%s\n%s;%s;%s", strings.ToUpper(method), pathAndQuery, timestamp, host, contentHash)
|
||||
signature := GetHmac(stringToSign, key)
|
||||
|
||||
req.Header.Set("x-ms-content-sha256", contentHash)
|
||||
req.Header.Set("x-ms-date", timestamp)
|
||||
|
||||
req.Header.Set("Authorization", "HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature="+signature)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetContentHashBase64(content []byte) string {
|
||||
hasher := sha256.New()
|
||||
hasher.Write(content)
|
||||
|
||||
return base64.StdEncoding.EncodeToString(hasher.Sum(nil))
|
||||
}
|
||||
|
||||
func GetHmac(content string, key []byte) string {
|
||||
hmac := hmac.New(sha256.New, key)
|
||||
hmac.Write([]byte(content))
|
||||
|
||||
return base64.StdEncoding.EncodeToString(hmac.Sum(nil))
|
||||
}
|
||||
|
||||
func (a *AzureACSEmailProvider) Send(fromAddress string, fromName string, toAddress string, subject string, content string) error {
|
||||
e := newEmail(fromAddress, toAddress, subject, content)
|
||||
|
||||
return a.sendEmail(e)
|
||||
}
|
27
email/provider.go
Normal file
27
email/provider.go
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package email
|
||||
|
||||
type EmailProvider interface {
|
||||
Send(fromAddress string, fromName, toAddress string, subject string, content string) error
|
||||
}
|
||||
|
||||
func GetEmailProvider(typ string, clientId string, clientSecret string, appId string, host string, port int, disableSsl bool) EmailProvider {
|
||||
if typ == "Azure ACS" {
|
||||
return NewAzureACSEmailProvider(appId, host)
|
||||
} else {
|
||||
return NewSmtpEmailProvider(clientId, clientSecret, host, port, typ, disableSsl)
|
||||
}
|
||||
}
|
49
email/smtp.go
Normal file
49
email/smtp.go
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package email
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/casdoor/gomail/v2"
|
||||
)
|
||||
|
||||
type SmtpEmailProvider struct {
|
||||
Dialer *gomail.Dialer
|
||||
}
|
||||
|
||||
func NewSmtpEmailProvider(userName string, password string, host string, port int, typ string, disableSsl bool) *SmtpEmailProvider {
|
||||
dialer := &gomail.Dialer{}
|
||||
dialer = gomail.NewDialer(host, port, userName, password)
|
||||
if typ == "SUBMAIL" {
|
||||
dialer.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
}
|
||||
|
||||
dialer.SSL = !disableSsl
|
||||
|
||||
return &SmtpEmailProvider{Dialer: dialer}
|
||||
}
|
||||
|
||||
func (s *SmtpEmailProvider) Send(fromAddress string, fromName string, toAddress string, subject string, content string) error {
|
||||
message := gomail.NewMessage()
|
||||
|
||||
message.SetAddressHeader("From", fromAddress, fromName)
|
||||
message.SetHeader("To", toAddress)
|
||||
message.SetHeader("Subject", subject)
|
||||
message.SetBody("text/html", content)
|
||||
|
||||
message.SkipUsernameCheck = true
|
||||
return s.Dialer.DialAndSend(message)
|
||||
}
|
23
form/auth.go
23
form/auth.go
@ -17,17 +17,18 @@ package form
|
||||
type AuthForm struct {
|
||||
Type string `json:"type"`
|
||||
|
||||
Organization string `json:"organization"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Name string `json:"name"`
|
||||
FirstName string `json:"firstName"`
|
||||
LastName string `json:"lastName"`
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
Affiliation string `json:"affiliation"`
|
||||
IdCard string `json:"idCard"`
|
||||
Region string `json:"region"`
|
||||
Organization string `json:"organization"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Name string `json:"name"`
|
||||
FirstName string `json:"firstName"`
|
||||
LastName string `json:"lastName"`
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
Affiliation string `json:"affiliation"`
|
||||
IdCard string `json:"idCard"`
|
||||
Region string `json:"region"`
|
||||
InvitationCode string `json:"invitationCode"`
|
||||
|
||||
Application string `json:"application"`
|
||||
ClientId string `json:"clientId"`
|
||||
|
28
go.mod
28
go.mod
@ -6,16 +6,17 @@ require (
|
||||
github.com/Masterminds/squirrel v1.5.3
|
||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b
|
||||
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.62.188 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.4
|
||||
github.com/aws/aws-sdk-go v1.45.5
|
||||
github.com/beego/beego v1.12.12
|
||||
github.com/beevik/etree v1.1.0
|
||||
github.com/casbin/casbin v1.9.1 // indirect
|
||||
github.com/casbin/casbin/v2 v2.30.1
|
||||
github.com/casdoor/go-sms-sender v0.12.0
|
||||
github.com/casbin/casbin/v2 v2.37.0
|
||||
github.com/casdoor/go-sms-sender v0.14.0
|
||||
github.com/casdoor/gomail/v2 v2.0.1
|
||||
github.com/casdoor/notify v0.43.0
|
||||
github.com/casdoor/oss v1.3.0
|
||||
github.com/casdoor/xorm-adapter/v3 v3.0.4
|
||||
github.com/casvisor/casvisor-go-sdk v1.0.3
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
||||
github.com/denisenkom/go-mssqldb v0.9.0
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect
|
||||
@ -26,13 +27,13 @@ require (
|
||||
github.com/go-mysql-org/go-mysql v1.7.0
|
||||
github.com/go-pay/gopay v1.5.72
|
||||
github.com/go-sql-driver/mysql v1.6.0
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
|
||||
github.com/go-webauthn/webauthn v0.6.0
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/mux v1.7.3 // indirect
|
||||
github.com/google/uuid v1.3.1
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||
github.com/lestrrat-go/jwx v1.2.21
|
||||
github.com/lib/pq v1.10.2
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
|
||||
github.com/markbates/goth v1.75.2
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
@ -45,12 +46,12 @@ require (
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/russellhaering/gosaml2 v0.9.0
|
||||
github.com/russellhaering/goxmldsig v1.2.0
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
github.com/stretchr/testify v1.8.3
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/stripe/stripe-go/v74 v74.29.0
|
||||
github.com/tealeg/xlsx v1.0.5
|
||||
github.com/thanhpk/randstr v1.0.4
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
@ -58,11 +59,12 @@ require (
|
||||
github.com/xorm-io/core v0.7.4
|
||||
github.com/xorm-io/xorm v1.1.6
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.11.0
|
||||
golang.org/x/net v0.13.0
|
||||
golang.org/x/oauth2 v0.10.0
|
||||
golang.org/x/crypto v0.12.0
|
||||
golang.org/x/net v0.14.0
|
||||
golang.org/x/oauth2 v0.11.0
|
||||
google.golang.org/api v0.138.0
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
maunium.net/go/mautrix v0.16.0
|
||||
modernc.org/sqlite v1.18.2
|
||||
)
|
||||
|
@ -36,6 +36,15 @@ func TestGenerateI18nFrontend(t *testing.T) {
|
||||
applyToOtherLanguage("frontend", "it", data)
|
||||
applyToOtherLanguage("frontend", "ms", data)
|
||||
applyToOtherLanguage("frontend", "tr", data)
|
||||
applyToOtherLanguage("frontend", "ar", data)
|
||||
applyToOtherLanguage("frontend", "he", data)
|
||||
applyToOtherLanguage("frontend", "nl", data)
|
||||
applyToOtherLanguage("frontend", "pl", data)
|
||||
applyToOtherLanguage("frontend", "fi", data)
|
||||
applyToOtherLanguage("frontend", "sv", data)
|
||||
applyToOtherLanguage("frontend", "uk", data)
|
||||
applyToOtherLanguage("frontend", "kk", data)
|
||||
applyToOtherLanguage("frontend", "fa", data)
|
||||
}
|
||||
|
||||
func TestGenerateI18nBackend(t *testing.T) {
|
||||
@ -55,4 +64,13 @@ func TestGenerateI18nBackend(t *testing.T) {
|
||||
applyToOtherLanguage("backend", "it", data)
|
||||
applyToOtherLanguage("backend", "ms", data)
|
||||
applyToOtherLanguage("backend", "tr", data)
|
||||
applyToOtherLanguage("backend", "ar", data)
|
||||
applyToOtherLanguage("backend", "he", data)
|
||||
applyToOtherLanguage("backend", "nl", data)
|
||||
applyToOtherLanguage("backend", "pl", data)
|
||||
applyToOtherLanguage("backend", "fi", data)
|
||||
applyToOtherLanguage("backend", "sv", data)
|
||||
applyToOtherLanguage("backend", "uk", data)
|
||||
applyToOtherLanguage("backend", "kk", data)
|
||||
applyToOtherLanguage("backend", "fa", data)
|
||||
}
|
||||
|
142
i18n/locales/ar/data.json
Normal file
142
i18n/locales/ar/data.json
Normal file
@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"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",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"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",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/fa/data.json
Normal file
142
i18n/locales/fa/data.json
Normal file
@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"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",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"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",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/fi/data.json
Normal file
142
i18n/locales/fi/data.json
Normal file
@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"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",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"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",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/he/data.json
Normal file
142
i18n/locales/he/data.json
Normal file
@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"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",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"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",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/kk/data.json
Normal file
142
i18n/locales/kk/data.json
Normal file
@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"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",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"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",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/nl/data.json
Normal file
142
i18n/locales/nl/data.json
Normal file
@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"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",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"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",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/pl/data.json
Normal file
142
i18n/locales/pl/data.json
Normal file
@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"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",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"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",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/sv/data.json
Normal file
142
i18n/locales/sv/data.json
Normal file
@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"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",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"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",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/uk/data.json
Normal file
142
i18n/locales/uk/data.json
Normal file
@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"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",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"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",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
@ -72,13 +72,13 @@ type FacebookCheckToken struct {
|
||||
}
|
||||
|
||||
// FacebookCheckTokenData
|
||||
// Get more detail via: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#checktoken
|
||||
// Get more detail via: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow#checktoken
|
||||
type FacebookCheckTokenData struct {
|
||||
UserId string `json:"user_id"`
|
||||
}
|
||||
|
||||
// GetToken use code get access_token (*operation of getting code ought to be done in front)
|
||||
// get more detail via: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#confirm
|
||||
// get more detail via: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow#confirm
|
||||
func (idp *FacebookIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
params := url.Values{}
|
||||
params.Add("client_id", idp.Config.ClientID)
|
||||
|
10
idp/goth.go
10
idp/goth.go
@ -19,6 +19,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
@ -97,6 +98,9 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
|
||||
Session: &amazon.Session{},
|
||||
}
|
||||
case "Apple":
|
||||
if !strings.Contains(redirectUrl, "/api/callback") {
|
||||
redirectUrl = strings.Replace(redirectUrl, "/callback", "/api/callback", 1)
|
||||
}
|
||||
idp = GothIdProvider{
|
||||
Provider: apple.New(clientId, clientSecret, redirectUrl, nil),
|
||||
Session: &apple.Session{},
|
||||
@ -392,7 +396,9 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
|
||||
// Goth's idp all implement the Client method, but since the goth.Provider interface does not provide to modify idp's client method, reflection is required
|
||||
func (idp *GothIdProvider) SetHttpClient(client *http.Client) {
|
||||
idpClient := reflect.ValueOf(idp.Provider).Elem().FieldByName("HTTPClient")
|
||||
idpClient.Set(reflect.ValueOf(client))
|
||||
if idpClient.IsValid() {
|
||||
idpClient.Set(reflect.ValueOf(client))
|
||||
}
|
||||
}
|
||||
|
||||
func (idp *GothIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
@ -468,6 +474,8 @@ func getUser(gothUser goth.User, provider string) *UserInfo {
|
||||
if provider == "steam" {
|
||||
user.Username = user.Id
|
||||
user.Email = ""
|
||||
} else if provider == "apple" {
|
||||
user.Username = util.GetUsernameFromEmail(user.Email)
|
||||
}
|
||||
return &user
|
||||
}
|
||||
|
@ -9,11 +9,11 @@
|
||||
"passwordType": "plain",
|
||||
"passwordSalt": "",
|
||||
"passwordOptions": ["AtLeast6"],
|
||||
"countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN", "IT", "MY", "TR"],
|
||||
"countryCodes": ["US", "GB", "ES", "FR", "DE", "CN", "JP", "KR", "VN", "ID", "SG", "IN", "IT", "MY", "TR", "DZ", "IL", "PH", "NL", "PL", "FI", "SE", "UA", "KZ"],
|
||||
"defaultAvatar": "",
|
||||
"defaultApplication": "",
|
||||
"tags": [],
|
||||
"languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "it", "ms", "tr"],
|
||||
"languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "it", "ms", "tr","ar", "he", "nl", "pl", "fi", "sv", "uk", "kk", "fa"],
|
||||
"masterPassword": "",
|
||||
"initScore": 2000,
|
||||
"enableSoftDeletion": false,
|
||||
@ -123,7 +123,6 @@
|
||||
"score": 2000,
|
||||
"ranking": 1,
|
||||
"isAdmin": true,
|
||||
"isGlobalAdmin": true,
|
||||
"isForbidden": false,
|
||||
"isDeleted": false,
|
||||
"signupApplication": "",
|
||||
|
@ -62,7 +62,7 @@ func handleBind(w ldap.ResponseWriter, m *ldap.Message) {
|
||||
return
|
||||
}
|
||||
|
||||
if bindOrg == "built-in" || bindUser.IsGlobalAdmin {
|
||||
if bindOrg == "built-in" || bindUser.IsGlobalAdmin() {
|
||||
m.Client.IsGlobalAdmin, m.Client.IsOrgAdmin = true, true
|
||||
} else if bindUser.IsAdmin {
|
||||
m.Client.IsOrgAdmin = true
|
||||
|
15
main.go
15
main.go
@ -15,7 +15,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/beego/beego"
|
||||
@ -30,17 +29,10 @@ import (
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
func getCreateDatabaseFlag() bool {
|
||||
res := flag.Bool("createDatabase", false, "true if you need Casdoor to create database")
|
||||
flag.Parse()
|
||||
return *res
|
||||
}
|
||||
|
||||
func main() {
|
||||
createDatabase := getCreateDatabaseFlag()
|
||||
|
||||
object.InitAdapter(createDatabase)
|
||||
object.CreateTables(createDatabase)
|
||||
object.InitFlag()
|
||||
object.InitAdapter()
|
||||
object.CreateTables()
|
||||
object.DoMigration()
|
||||
|
||||
object.InitDb()
|
||||
@ -50,6 +42,7 @@ func main() {
|
||||
proxy.InitHttpClient()
|
||||
authz.InitApi()
|
||||
object.InitUserManager()
|
||||
object.InitCasvisorConfig()
|
||||
|
||||
util.SafeGoroutine(func() { object.RunSyncUsersJob() })
|
||||
|
||||
|
29
notification/bark.go
Normal file
29
notification/bark.go
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/bark"
|
||||
)
|
||||
|
||||
func NewBarkProvider(deviceKey string) (notify.Notifier, error) {
|
||||
barkSrv := bark.New(deviceKey)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(barkSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
@ -12,37 +12,35 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
package notification
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/casdoor/casdoor/proxy"
|
||||
)
|
||||
|
||||
type HttpSmsClient struct {
|
||||
type HttpNotificationClient struct {
|
||||
endpoint string
|
||||
method string
|
||||
paramName string
|
||||
text string
|
||||
}
|
||||
|
||||
func newHttpSmsClient(endpoint string, method string, paramName string, text string) (*HttpSmsClient, error) {
|
||||
client := &HttpSmsClient{
|
||||
func NewCustomHttpProvider(endpoint string, method string, paramName string) (*HttpNotificationClient, error) {
|
||||
client := &HttpNotificationClient{
|
||||
endpoint: endpoint,
|
||||
method: method,
|
||||
paramName: paramName,
|
||||
text: text,
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (c *HttpSmsClient) SendMessage(param map[string]string, targetPhoneNumber ...string) error {
|
||||
func (c *HttpNotificationClient) Send(ctx context.Context, subject string, content string) error {
|
||||
var err error
|
||||
|
||||
content := param["code"]
|
||||
httpClient := proxy.DefaultHttpClient
|
||||
|
||||
req, err := http.NewRequest(c.method, c.endpoint, bytes.NewBufferString(content))
|
||||
@ -68,7 +66,7 @@ func (c *HttpSmsClient) SendMessage(param map[string]string, targetPhoneNumber .
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("SendMessage() error, custom HTTP SMS request failed with status: %s", resp.Status)
|
||||
return fmt.Errorf("SendMessage() error, custom HTTP Notification request failed with status: %s", resp.Status)
|
||||
}
|
||||
|
||||
return err
|
33
notification/dingtalk.go
Normal file
33
notification/dingtalk.go
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/dingding"
|
||||
)
|
||||
|
||||
func NewDingTalkProvider(token string, secret string) (notify.Notifier, error) {
|
||||
cfg := dingding.Config{
|
||||
Token: token,
|
||||
Secret: secret,
|
||||
}
|
||||
dingtalkSrv := dingding.New(&cfg)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(dingtalkSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
37
notification/discord.go
Normal file
37
notification/discord.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/casdoor/proxy"
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/discord"
|
||||
)
|
||||
|
||||
func NewDiscordProvider(token string, channelId string) (*notify.Notify, error) {
|
||||
discordSrv := discord.New()
|
||||
|
||||
err := discordSrv.AuthenticateWithBotToken(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
discordSrv.SetHttpClient(proxy.ProxyHttpClient)
|
||||
discordSrv.AddReceivers(channelId)
|
||||
|
||||
notifier := notify.NewWithServices(discordSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
53
notification/google_chat.go
Normal file
53
notification/google_chat.go
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/googlechat"
|
||||
"google.golang.org/api/chat/v1"
|
||||
"google.golang.org/api/option"
|
||||
)
|
||||
|
||||
func NewGoogleChatProvider(credentials string) (*notify.Notify, error) {
|
||||
withCred := option.WithCredentialsJSON([]byte(credentials))
|
||||
withSpacesScope := option.WithScopes("https://www.googleapis.com/auth/chat.spaces")
|
||||
|
||||
listSvc, err := chat.NewService(context.Background(), withCred, withSpacesScope)
|
||||
spaces, err := listSvc.Spaces.List().Do()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
receivers := make([]string, 0)
|
||||
for _, space := range spaces.Spaces {
|
||||
name := strings.Replace(space.Name, "spaces/", "", 1)
|
||||
receivers = append(receivers, name)
|
||||
}
|
||||
|
||||
googleChatSrv, err := googlechat.New(withCred)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
googleChatSrv.AddReceivers(receivers...)
|
||||
|
||||
notifier := notify.NewWithServices(googleChatSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
29
notification/lark.go
Normal file
29
notification/lark.go
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/lark"
|
||||
)
|
||||
|
||||
func NewLarkProvider(webhookURL string) (notify.Notifier, error) {
|
||||
larkSrv := lark.NewWebhookService(webhookURL)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(larkSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
32
notification/line.go
Normal file
32
notification/line.go
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/casdoor/proxy"
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/line"
|
||||
)
|
||||
|
||||
func NewLineProvider(channelSecret string, accessToken string, receiver string) (*notify.Notify, error) {
|
||||
lineSrv, _ := line.NewWithHttpClient(channelSecret, accessToken, proxy.ProxyHttpClient)
|
||||
|
||||
lineSrv.AddReceivers(receiver)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(lineSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
36
notification/matrix.go
Normal file
36
notification/matrix.go
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/casdoor/proxy"
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/matrix"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
func NewMatrixProvider(userId string, roomId string, accessToken string, homeServer string) (*notify.Notify, error) {
|
||||
matrixSrv, err := matrix.New(id.UserID(userId), id.RoomID(roomId), homeServer, accessToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
matrixSrv.SetHttpClient(proxy.ProxyHttpClient)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(matrixSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
31
notification/microsoft_teams.go
Normal file
31
notification/microsoft_teams.go
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/msteams"
|
||||
)
|
||||
|
||||
func NewMicrosoftTeamsProvider(webhookURL string) (notify.Notifier, error) {
|
||||
msTeamsSrv := msteams.New()
|
||||
|
||||
msTeamsSrv.AddReceivers(webhookURL)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(msTeamsSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
59
notification/provider.go
Normal file
59
notification/provider.go
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import "github.com/casdoor/notify"
|
||||
|
||||
func GetNotificationProvider(typ string, clientId string, clientSecret string, clientId2 string, clientSecret2 string, appId string, receiver string, method string, title string, metaData string) (notify.Notifier, error) {
|
||||
if typ == "Telegram" {
|
||||
return NewTelegramProvider(appId, receiver)
|
||||
} else if typ == "Custom HTTP" {
|
||||
return NewCustomHttpProvider(receiver, method, title)
|
||||
} else if typ == "DingTalk" {
|
||||
return NewDingTalkProvider(appId, receiver)
|
||||
} else if typ == "Lark" {
|
||||
return NewLarkProvider(receiver)
|
||||
} else if typ == "Microsoft Teams" {
|
||||
return NewMicrosoftTeamsProvider(receiver)
|
||||
} else if typ == "Bark" {
|
||||
return NewBarkProvider(receiver)
|
||||
} else if typ == "Pushover" {
|
||||
return NewPushoverProvider(appId, receiver)
|
||||
} else if typ == "Pushbullet" {
|
||||
return NewPushbulletProvider(appId, receiver)
|
||||
} else if typ == "Slack" {
|
||||
return NewSlackProvider(appId, receiver)
|
||||
} else if typ == "Webpush" {
|
||||
return NewWebpushProvider(clientId, clientSecret, receiver)
|
||||
} else if typ == "Discord" {
|
||||
return NewDiscordProvider(appId, receiver)
|
||||
} else if typ == "Google Chat" {
|
||||
return NewGoogleChatProvider(metaData)
|
||||
} else if typ == "Line" {
|
||||
return NewLineProvider(clientSecret, appId, receiver)
|
||||
} else if typ == "Matrix" {
|
||||
return NewMatrixProvider(clientId, clientSecret, appId, receiver)
|
||||
} else if typ == "Twitter" {
|
||||
return NewTwitterProvider(clientId, clientSecret, clientId2, clientSecret2, receiver)
|
||||
} else if typ == "Reddit" {
|
||||
return NewRedditProvider(clientId, clientSecret, clientId2, clientSecret2, receiver)
|
||||
} else if typ == "Rocket Chat" {
|
||||
return NewRocketChatProvider(clientId, clientSecret, appId, receiver)
|
||||
} else if typ == "Viber" {
|
||||
return NewViberProvider(clientId, clientSecret, appId, receiver)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
31
notification/pushbullet.go
Normal file
31
notification/pushbullet.go
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/pushbullet"
|
||||
)
|
||||
|
||||
func NewPushbulletProvider(apiToken string, deviceNickname string) (notify.Notifier, error) {
|
||||
pushbulletSrv := pushbullet.New(apiToken)
|
||||
|
||||
pushbulletSrv.AddReceivers(deviceNickname)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(pushbulletSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
31
notification/pushover.go
Normal file
31
notification/pushover.go
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/pushover"
|
||||
)
|
||||
|
||||
func NewPushoverProvider(appToken string, recipientID string) (notify.Notifier, error) {
|
||||
pushoverSrv := pushover.New(appToken)
|
||||
|
||||
pushoverSrv.AddReceivers(recipientID)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(pushoverSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
34
notification/reddit.go
Normal file
34
notification/reddit.go
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/reddit"
|
||||
)
|
||||
|
||||
func NewRedditProvider(clientId string, clientSecret string, username string, password string, recipient string) (notify.Notifier, error) {
|
||||
redditSrv, err := reddit.New(clientId, clientSecret, username, password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
redditSrv.AddReceivers(recipient)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(redditSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
47
notification/rocket_chat.go
Normal file
47
notification/rocket_chat.go
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/rocketchat"
|
||||
)
|
||||
|
||||
func NewRocketChatProvider(clientId string, clientSecret string, endpoint string, channelName string) (notify.Notifier, error) {
|
||||
parts := strings.Split(endpoint, "://")
|
||||
|
||||
var scheme, serverURL string
|
||||
if len(parts) >= 2 {
|
||||
scheme = parts[0]
|
||||
serverURL = parts[1]
|
||||
} else {
|
||||
return nil, fmt.Errorf("parse endpoint error")
|
||||
}
|
||||
|
||||
rocketChatSrv, err := rocketchat.New(serverURL, scheme, clientId, clientSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rocketChatSrv.AddReceivers(channelName)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(rocketChatSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
30
notification/slack.go
Normal file
30
notification/slack.go
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/slack"
|
||||
)
|
||||
|
||||
func NewSlackProvider(apiToken string, channelID string) (*notify.Notify, error) {
|
||||
slackSrv := slack.New(apiToken)
|
||||
slackSrv.AddReceivers(channelID)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(slackSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
45
notification/telegram.go
Normal file
45
notification/telegram.go
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/casdoor/casdoor/proxy"
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/telegram"
|
||||
api "github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
)
|
||||
|
||||
func NewTelegramProvider(apiToken string, chatIdStr string) (notify.Notifier, error) {
|
||||
client, err := api.NewBotAPIWithClient(apiToken, proxy.ProxyHttpClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
telegramSrv := &telegram.Telegram{}
|
||||
telegramSrv.SetClient(client)
|
||||
|
||||
chatId, err := strconv.ParseInt(chatIdStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
telegramSrv.AddReceivers(chatId)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(telegramSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
41
notification/twitter.go
Normal file
41
notification/twitter.go
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/casdoor/proxy"
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/twitter"
|
||||
)
|
||||
|
||||
func NewTwitterProvider(consumerKey string, consumerSecret string, accessToken string, accessTokenSecret string, twitterId string) (*notify.Notify, error) {
|
||||
credentials := twitter.Credentials{
|
||||
ConsumerKey: consumerKey,
|
||||
ConsumerSecret: consumerSecret,
|
||||
AccessToken: accessToken,
|
||||
AccessTokenSecret: accessTokenSecret,
|
||||
}
|
||||
twitterSrv, err := twitter.NewWithHttpClient(credentials, proxy.ProxyHttpClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
twitterSrv.AddReceivers(twitterId)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(twitterSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
36
notification/viber.go
Normal file
36
notification/viber.go
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/viber"
|
||||
)
|
||||
|
||||
func NewViberProvider(senderName string, appKey string, webhookURL string, receiverId string) (notify.Notifier, error) {
|
||||
viberSrv := viber.New(appKey, senderName, "")
|
||||
|
||||
err := viberSrv.SetWebhook(webhookURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
viberSrv.AddReceivers(receiverId)
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(viberSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
33
notification/webpush.go
Normal file
33
notification/webpush.go
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package notification
|
||||
|
||||
import (
|
||||
"github.com/casdoor/notify"
|
||||
"github.com/casdoor/notify/service/webpush"
|
||||
)
|
||||
|
||||
func NewWebpushProvider(publicKey string, privateKey string, endpoint string) (*notify.Notify, error) {
|
||||
webpushSrv := webpush.New(publicKey, privateKey)
|
||||
|
||||
subscription := webpush.Subscription{
|
||||
Endpoint: endpoint,
|
||||
}
|
||||
webpushSrv.AddReceivers(subscription)
|
||||
|
||||
notifier := notify.NewWithServices(webpushSrv)
|
||||
|
||||
return notifier, nil
|
||||
}
|
@ -18,7 +18,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
@ -41,8 +40,6 @@ type Adapter struct {
|
||||
Table string `xorm:"varchar(100)" json:"table"`
|
||||
TableNamePrefix string `xorm:"varchar(100)" json:"tableNamePrefix"`
|
||||
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
*xormadapter.Adapter `xorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
@ -150,11 +147,11 @@ func (adapter *Adapter) getTable() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (adapter *Adapter) initAdapter() error {
|
||||
func (adapter *Adapter) InitAdapter() error {
|
||||
if adapter.Adapter == nil {
|
||||
var dataSourceName string
|
||||
|
||||
if adapter.builtInAdapter() {
|
||||
if adapter.isBuiltIn() {
|
||||
dataSourceName = conf.GetConfigString("dataSourceName")
|
||||
if adapter.DatabaseType == "mysql" {
|
||||
dataSourceName = dataSourceName + adapter.Database
|
||||
@ -186,6 +183,14 @@ func (adapter *Adapter) initAdapter() error {
|
||||
|
||||
var err error
|
||||
engine, err := xorm.NewEngine(adapter.DatabaseType, dataSourceName)
|
||||
|
||||
if adapter.isBuiltIn() && adapter.DatabaseType == "postgres" {
|
||||
schema := util.GetValueFromDataSourceName("search_path", dataSourceName)
|
||||
if schema != "" {
|
||||
engine.SetSchema(schema)
|
||||
}
|
||||
}
|
||||
|
||||
adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(engine, adapter.getTable(), adapter.TableNamePrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -214,130 +219,10 @@ func adapterChangeTrigger(oldName string, newName string) error {
|
||||
return session.Commit()
|
||||
}
|
||||
|
||||
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 GetPolicies(adapter *Adapter) ([]*xormadapter.CasbinRule, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
policies := matrixToCasbinRules("p", casbinModel.GetPolicy("p", "p"))
|
||||
policies = append(policies, matrixToCasbinRules("g", casbinModel.GetPolicy("g", "g"))...)
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
func UpdatePolicy(oldPolicy, newPolicy []string, adapter *Adapter) (bool, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
affected := casbinModel.UpdatePolicy("p", "p", oldPolicy, newPolicy)
|
||||
if err != nil {
|
||||
return affected, err
|
||||
}
|
||||
err = adapter.SavePolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
func AddPolicy(policy []string, adapter *Adapter) (bool, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel.AddPolicy("p", "p", policy)
|
||||
err = adapter.SavePolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func RemovePolicy(policy []string, adapter *Adapter) (bool, error) {
|
||||
err := adapter.initAdapter()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
casbinModel := getModelDef()
|
||||
err = adapter.LoadPolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
affected := casbinModel.RemovePolicy("p", "p", policy)
|
||||
if err != nil {
|
||||
return affected, err
|
||||
}
|
||||
err = adapter.SavePolicy(casbinModel)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
func (adapter *Adapter) builtInAdapter() bool {
|
||||
func (adapter *Adapter) isBuiltIn() bool {
|
||||
if adapter.Owner != "built-in" {
|
||||
return false
|
||||
}
|
||||
|
||||
return adapter.Name == "user-adapter-built-in" || adapter.Name == "api-adapter-built-in"
|
||||
}
|
||||
|
||||
func getModelDef() model.Model {
|
||||
casbinModel := model.NewModel()
|
||||
casbinModel.AddDef("p", "p", "_, _, _, _, _, _")
|
||||
casbinModel.AddDef("g", "g", "_, _, _, _, _, _")
|
||||
return casbinModel
|
||||
}
|
||||
|
@ -57,7 +57,9 @@ type Application struct {
|
||||
SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
|
||||
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`
|
||||
OrganizationObj *Organization `xorm:"-" json:"organizationObj"`
|
||||
CertPublicKey string `xorm:"-" json:"certPublicKey"`
|
||||
Tags []string `xorm:"mediumtext" json:"tags"`
|
||||
InvitationCodes []string `xorm:"varchar(200)" json:"invitationCodes"`
|
||||
|
||||
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
||||
ClientSecret string `xorm:"varchar(100)" json:"clientSecret"`
|
||||
@ -311,6 +313,11 @@ func GetMaskedApplication(application *Application, userId string) *Application
|
||||
application.OrganizationObj.PasswordSalt = "***"
|
||||
}
|
||||
}
|
||||
|
||||
if application.InvitationCodes != nil {
|
||||
application.InvitationCodes = []string{"***"}
|
||||
}
|
||||
|
||||
return application
|
||||
}
|
||||
|
||||
@ -421,15 +428,14 @@ func (application *Application) GetId() string {
|
||||
}
|
||||
|
||||
func (application *Application) IsRedirectUriValid(redirectUri string) bool {
|
||||
isValid := false
|
||||
for _, targetUri := range application.RedirectUris {
|
||||
redirectUris := append([]string{"http://localhost:"}, application.RedirectUris...)
|
||||
for _, targetUri := range redirectUris {
|
||||
targetUriRegex := regexp.MustCompile(targetUri)
|
||||
if targetUriRegex.MatchString(redirectUri) || strings.Contains(redirectUri, targetUri) {
|
||||
isValid = true
|
||||
break
|
||||
return true
|
||||
}
|
||||
}
|
||||
return isValid
|
||||
return false
|
||||
}
|
||||
|
||||
func IsOriginAllowed(origin string) (bool, error) {
|
||||
|
@ -33,10 +33,8 @@ type Cert struct {
|
||||
BitSize int `json:"bitSize"`
|
||||
ExpireInYears int `json:"expireInYears"`
|
||||
|
||||
Certificate string `xorm:"mediumtext" json:"certificate"`
|
||||
PrivateKey string `xorm:"mediumtext" json:"privateKey"`
|
||||
AuthorityPublicKey string `xorm:"mediumtext" json:"authorityPublicKey"`
|
||||
AuthorityRootPublicKey string `xorm:"mediumtext" json:"authorityRootPublicKey"`
|
||||
Certificate string `xorm:"mediumtext" json:"certificate"`
|
||||
PrivateKey string `xorm:"mediumtext" json:"privateKey"`
|
||||
}
|
||||
|
||||
func GetMaskedCert(cert *Cert) *Cert {
|
||||
|
BIN
object/cert.go~
Normal file
BIN
object/cert.go~
Normal file
Binary file not shown.
@ -66,8 +66,11 @@ func CheckUserSignup(application *Application, organization *Organization, form
|
||||
}
|
||||
}
|
||||
|
||||
if len(form.Password) <= 5 {
|
||||
return i18n.Translate(lang, "check:Password must have at least 6 characters")
|
||||
if application.IsSignupItemVisible("Password") {
|
||||
msg := CheckPasswordComplexityByOrg(organization, form.Password)
|
||||
if msg != "" {
|
||||
return msg
|
||||
}
|
||||
}
|
||||
|
||||
if application.IsSignupItemVisible("Email") {
|
||||
@ -124,6 +127,18 @@ func CheckUserSignup(application *Application, organization *Organization, form
|
||||
}
|
||||
}
|
||||
|
||||
if len(application.InvitationCodes) > 0 {
|
||||
if form.InvitationCode == "" {
|
||||
if application.IsSignupItemRequired("Invitation code") {
|
||||
return i18n.Translate(lang, "check:Invitation code cannot be blank")
|
||||
}
|
||||
} else {
|
||||
if !util.InSlice(application.InvitationCodes, form.InvitationCode) {
|
||||
return i18n.Translate(lang, "check:Invitation code is invalid")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -141,7 +156,7 @@ func checkSigninErrorTimes(user *User, lang string) string {
|
||||
// reset the error times
|
||||
user.SigninWrongTimes = 0
|
||||
|
||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times"}, user.IsGlobalAdmin)
|
||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times"}, false)
|
||||
}
|
||||
|
||||
return ""
|
||||
@ -319,7 +334,7 @@ func CheckUserPermission(requestUserId, userId string, strict bool, lang string)
|
||||
if requestUser == nil {
|
||||
return false, fmt.Errorf(i18n.Translate(lang, "check:Session outdated, please login again"))
|
||||
}
|
||||
if requestUser.IsGlobalAdmin {
|
||||
if requestUser.IsGlobalAdmin() {
|
||||
hasPermission = true
|
||||
} else if requestUserId == userId {
|
||||
hasPermission = true
|
||||
@ -335,7 +350,7 @@ func CheckUserPermission(requestUserId, userId string, strict bool, lang string)
|
||||
return hasPermission, fmt.Errorf(i18n.Translate(lang, "auth:Unauthorized operation"))
|
||||
}
|
||||
|
||||
func CheckAccessPermission(userId string, application *Application) (bool, error) {
|
||||
func CheckLoginPermission(userId string, application *Application) (bool, error) {
|
||||
var err error
|
||||
if userId == "built-in/admin" {
|
||||
return true, nil
|
||||
@ -346,32 +361,40 @@ func CheckAccessPermission(userId string, application *Application) (bool, error
|
||||
return false, err
|
||||
}
|
||||
|
||||
allowed := true
|
||||
allowCount := 0
|
||||
denyCount := 0
|
||||
for _, permission := range permissions {
|
||||
if !permission.IsEnabled {
|
||||
if !permission.IsEnabled || permission.ResourceType != "Application" || !permission.isResourceHit(application.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
isHit := false
|
||||
for _, resource := range permission.Resources {
|
||||
if application.Name == resource {
|
||||
isHit = true
|
||||
break
|
||||
}
|
||||
if permission.isUserHit(userId) {
|
||||
allowCount += 1
|
||||
}
|
||||
|
||||
if isHit {
|
||||
containsAsterisk := ContainsAsterisk(userId, permission.Users)
|
||||
if containsAsterisk {
|
||||
return true, err
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
|
||||
var isAllowed bool
|
||||
isAllowed, err = enforcer.Enforce(userId, application.Name, "Read")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if isAllowed {
|
||||
if permission.Effect == "Allow" {
|
||||
allowCount += 1
|
||||
}
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
if allowed, err = enforcer.Enforce(userId, application.Name, "read"); allowed {
|
||||
return allowed, err
|
||||
} else {
|
||||
if permission.Effect == "Deny" {
|
||||
denyCount += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return allowed, err
|
||||
|
||||
if denyCount > 0 {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func CheckUsername(username string, lang string) string {
|
||||
@ -391,10 +414,6 @@ func CheckUsername(username string, lang string) string {
|
||||
}
|
||||
|
||||
func CheckUpdateUser(oldUser, user *User, lang string) string {
|
||||
if user.DisplayName == "" {
|
||||
return i18n.Translate(lang, "user:Display name cannot be empty")
|
||||
}
|
||||
|
||||
if oldUser.Name != user.Name {
|
||||
if msg := CheckUsername(user.Name, lang); msg != "" {
|
||||
return msg
|
||||
@ -404,7 +423,7 @@ func CheckUpdateUser(oldUser, user *User, lang string) string {
|
||||
}
|
||||
}
|
||||
if oldUser.Email != user.Email {
|
||||
if HasUserByField(user.Name, "email", user.Email) {
|
||||
if HasUserByField(user.Owner, "email", user.Email) {
|
||||
return i18n.Translate(lang, "check:Email already exists")
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func resetUserSigninErrorTimes(user *User) {
|
||||
return
|
||||
}
|
||||
user.SigninWrongTimes = 0
|
||||
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"}, false)
|
||||
}
|
||||
|
||||
func recordSigninErrorInfo(user *User, lang string, options ...bool) string {
|
||||
@ -61,7 +61,7 @@ func recordSigninErrorInfo(user *User, lang string, options ...bool) string {
|
||||
}
|
||||
|
||||
// update 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"}, false)
|
||||
leftChances := SigninWrongTimesLimit - user.SigninWrongTimes
|
||||
if leftChances == 0 && enableCaptcha {
|
||||
return fmt.Sprint(i18n.Translate(lang, "check:password or code is incorrect"))
|
||||
|
@ -19,6 +19,7 @@ package object
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/casdoor/casdoor/email"
|
||||
"github.com/casdoor/gomail/v2"
|
||||
)
|
||||
|
||||
@ -35,9 +36,7 @@ func getDialer(provider *Provider) *gomail.Dialer {
|
||||
}
|
||||
|
||||
func SendEmail(provider *Provider, title string, content string, dest string, sender string) error {
|
||||
dialer := getDialer(provider)
|
||||
|
||||
message := gomail.NewMessage()
|
||||
emailProvider := email.GetEmailProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.AppId, provider.Host, provider.Port, provider.DisableSsl)
|
||||
|
||||
fromAddress := provider.ClientId2
|
||||
if fromAddress == "" {
|
||||
@ -49,14 +48,7 @@ func SendEmail(provider *Provider, title string, content string, dest string, se
|
||||
fromName = sender
|
||||
}
|
||||
|
||||
message.SetAddressHeader("From", fromAddress, fromName)
|
||||
message.SetHeader("To", dest)
|
||||
message.SetHeader("Subject", title)
|
||||
message.SetBody("text/html", content)
|
||||
|
||||
message.SkipUsernameCheck = true
|
||||
|
||||
return dialer.DialAndSend(message)
|
||||
return emailProvider.Send(fromAddress, fromName, dest, title, content)
|
||||
}
|
||||
|
||||
// DailSmtpServer Dail Smtp server
|
||||
|
@ -18,7 +18,9 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/config"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
@ -30,10 +32,10 @@ type Enforcer struct {
|
||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||
Description string `xorm:"varchar(100)" json:"description"`
|
||||
|
||||
Model string `xorm:"varchar(100)" json:"model"`
|
||||
Adapter string `xorm:"varchar(100)" json:"adapter"`
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
Model string `xorm:"varchar(100)" json:"model"`
|
||||
Adapter string `xorm:"varchar(100)" json:"adapter"`
|
||||
|
||||
ModelCfg map[string]string `xorm:"-" json:"modelCfg"`
|
||||
*casbin.Enforcer
|
||||
}
|
||||
|
||||
@ -120,8 +122,8 @@ func DeleteEnforcer(enforcer *Enforcer) (bool, error) {
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (p *Enforcer) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
|
||||
func (enforcer *Enforcer) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", enforcer.Owner, enforcer.Name)
|
||||
}
|
||||
|
||||
func (enforcer *Enforcer) InitEnforcer() error {
|
||||
@ -154,7 +156,7 @@ func (enforcer *Enforcer) InitEnforcer() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = a.initAdapter()
|
||||
err = a.InitAdapter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -182,3 +184,70 @@ func GetInitializedEnforcer(enforcerId string) (*Enforcer, error) {
|
||||
}
|
||||
return enforcer, nil
|
||||
}
|
||||
|
||||
func GetPolicies(id string) ([]*xormadapter.CasbinRule, error) {
|
||||
enforcer, err := GetInitializedEnforcer(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
policies := util.MatrixToCasbinRules("p", enforcer.GetPolicy())
|
||||
if enforcer.GetModel()["g"] != nil {
|
||||
policies = append(policies, util.MatrixToCasbinRules("g", enforcer.GetGroupingPolicy())...)
|
||||
}
|
||||
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
func UpdatePolicy(id string, oldPolicy, newPolicy []string) (bool, error) {
|
||||
enforcer, err := GetInitializedEnforcer(id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return enforcer.UpdatePolicy(oldPolicy, newPolicy)
|
||||
}
|
||||
|
||||
func AddPolicy(id string, policy []string) (bool, error) {
|
||||
enforcer, err := GetInitializedEnforcer(id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return enforcer.AddPolicy(policy)
|
||||
}
|
||||
|
||||
func RemovePolicy(id string, policy []string) (bool, error) {
|
||||
enforcer, err := GetInitializedEnforcer(id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return enforcer.RemovePolicy(policy)
|
||||
}
|
||||
|
||||
func (enforcer *Enforcer) LoadModelCfg() error {
|
||||
if enforcer.ModelCfg != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
model, err := GetModel(enforcer.Model)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if model == nil {
|
||||
return fmt.Errorf("the model: %s for enforcer: %s is not found", enforcer.Model, enforcer.GetId())
|
||||
}
|
||||
|
||||
cfg, err := config.NewConfigFromText(model.ModelText)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enforcer.ModelCfg = make(map[string]string)
|
||||
enforcer.ModelCfg["p"] = cfg.String("policy_definition::p")
|
||||
if cfg.String("role_definition::g") != "" {
|
||||
enforcer.ModelCfg["g"] = cfg.String("role_definition::g")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -14,7 +14,10 @@
|
||||
|
||||
package object
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Dashboard struct {
|
||||
OrganizationCounts []int `json:"organizationCounts"`
|
||||
@ -24,7 +27,7 @@ type Dashboard struct {
|
||||
SubscriptionCounts []int `json:"subscriptionCounts"`
|
||||
}
|
||||
|
||||
func GetDashboard() (*Dashboard, error) {
|
||||
func GetDashboard(owner string) (*Dashboard, error) {
|
||||
dashboard := &Dashboard{
|
||||
OrganizationCounts: make([]int, 31),
|
||||
UserCounts: make([]int, 31),
|
||||
@ -33,29 +36,56 @@ func GetDashboard() (*Dashboard, error) {
|
||||
SubscriptionCounts: make([]int, 31),
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
organizations := []Organization{}
|
||||
users := []User{}
|
||||
providers := []Provider{}
|
||||
applications := []Application{}
|
||||
subscriptions := []Subscription{}
|
||||
|
||||
wg.Add(5)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := ormer.Engine.Find(&organizations, &Organization{Owner: owner}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&users, &User{Owner: owner}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&providers, &Provider{Owner: owner}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&applications, &Application{Owner: owner}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&subscriptions, &Subscription{Owner: owner}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
wg.Wait()
|
||||
|
||||
nowTime := time.Now()
|
||||
|
||||
organizations := make([]Organization, 0)
|
||||
if err := ormer.Engine.Find(&organizations); err != nil {
|
||||
return dashboard, err
|
||||
}
|
||||
users := make([]User, 0)
|
||||
if err := ormer.Engine.Find(&users); err != nil {
|
||||
return dashboard, err
|
||||
}
|
||||
providers := make([]Provider, 0)
|
||||
if err := ormer.Engine.Find(&providers); err != nil {
|
||||
return dashboard, err
|
||||
}
|
||||
applications := make([]Application, 0)
|
||||
if err := ormer.Engine.Find(&applications); err != nil {
|
||||
return dashboard, err
|
||||
}
|
||||
subscriptions := make([]Subscription, 0)
|
||||
if err := ormer.Engine.Find(&subscriptions); err != nil {
|
||||
return dashboard, err
|
||||
}
|
||||
|
||||
for i := 30; i >= 0; i-- {
|
||||
cutTime := nowTime.AddDate(0, 0, -i)
|
||||
dashboard.OrganizationCounts[30-i] = countCreatedBefore(organizations, cutTime)
|
||||
@ -64,7 +94,6 @@ func GetDashboard() (*Dashboard, error) {
|
||||
dashboard.ApplicationCounts[30-i] = countCreatedBefore(applications, cutTime)
|
||||
dashboard.SubscriptionCounts[30-i] = countCreatedBefore(subscriptions, cutTime)
|
||||
}
|
||||
|
||||
return dashboard, nil
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,6 @@ func getBuiltInAccountItems() []*AccountItem {
|
||||
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Is global admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Is forbidden", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Is deleted", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Multi-factor authentication", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
@ -145,7 +144,6 @@ func initBuiltInUser() {
|
||||
Score: 2000,
|
||||
Ranking: 1,
|
||||
IsAdmin: true,
|
||||
IsGlobalAdmin: true,
|
||||
IsForbidden: false,
|
||||
IsDeleted: false,
|
||||
SignupApplication: "app-built-in",
|
||||
@ -318,7 +316,6 @@ func initBuiltInUserModel() {
|
||||
Name: "user-model-built-in",
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: "Built-in Model",
|
||||
IsEnabled: true,
|
||||
ModelText: `[request_definition]
|
||||
r = sub, obj, act
|
||||
|
||||
@ -376,7 +373,6 @@ m = (r.subOwner == p.subOwner || p.subOwner == "*") && \
|
||||
Name: "api-model-built-in",
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: "API Model",
|
||||
IsEnabled: true,
|
||||
ModelText: modelText,
|
||||
}
|
||||
_, err = AddModel(model)
|
||||
@ -435,7 +431,6 @@ func initBuiltInUserAdapter() {
|
||||
TableNamePrefix: conf.GetConfigString("tableNamePrefix"),
|
||||
Database: conf.GetConfigString("dbName"),
|
||||
Table: "casbin_user_rule",
|
||||
IsEnabled: true,
|
||||
}
|
||||
_, err = AddAdapter(adapter)
|
||||
if err != nil {
|
||||
@ -462,7 +457,6 @@ func initBuiltInApiAdapter() {
|
||||
TableNamePrefix: conf.GetConfigString("tableNamePrefix"),
|
||||
Database: conf.GetConfigString("dbName"),
|
||||
Table: "casbin_api_rule",
|
||||
IsEnabled: true,
|
||||
}
|
||||
_, err = AddAdapter(adapter)
|
||||
if err != nil {
|
||||
@ -487,7 +481,6 @@ func initBuiltInUserEnforcer() {
|
||||
DisplayName: "User Enforcer",
|
||||
Model: "built-in/user-model-built-in",
|
||||
Adapter: "built-in/user-adapter-built-in",
|
||||
IsEnabled: true,
|
||||
}
|
||||
|
||||
_, err = AddEnforcer(enforcer)
|
||||
@ -513,7 +506,6 @@ func initBuiltInApiEnforcer() {
|
||||
DisplayName: "API Enforcer",
|
||||
Model: "built-in/api-model-built-in",
|
||||
Adapter: "built-in/api-adapter-built-in",
|
||||
IsEnabled: true,
|
||||
}
|
||||
|
||||
_, err = AddEnforcer(enforcer)
|
||||
|
@ -311,18 +311,20 @@ func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUser
|
||||
}
|
||||
|
||||
newUser := &User{
|
||||
Owner: owner,
|
||||
Name: name,
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: syncUser.buildLdapDisplayName(),
|
||||
Avatar: organization.DefaultAvatar,
|
||||
Email: syncUser.Email,
|
||||
Phone: syncUser.Mobile,
|
||||
Address: []string{syncUser.Address},
|
||||
Affiliation: affiliation,
|
||||
Tag: tag,
|
||||
Score: score,
|
||||
Ldap: syncUser.Uuid,
|
||||
Owner: owner,
|
||||
Name: name,
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
DisplayName: syncUser.buildLdapDisplayName(),
|
||||
SignupApplication: organization.DefaultApplication,
|
||||
Type: "normal-user",
|
||||
Avatar: organization.DefaultAvatar,
|
||||
Email: syncUser.Email,
|
||||
Phone: syncUser.Mobile,
|
||||
Address: []string{syncUser.Address},
|
||||
Affiliation: affiliation,
|
||||
Tag: tag,
|
||||
Score: score,
|
||||
Ldap: syncUser.Uuid,
|
||||
}
|
||||
|
||||
affected, err := AddUser(newUser)
|
||||
|
@ -84,7 +84,7 @@ func MfaRecover(user *User, recoveryCode string) error {
|
||||
return fmt.Errorf("recovery code not found")
|
||||
}
|
||||
|
||||
_, err := UpdateUser(user.GetId(), user, []string{"recovery_codes"}, user.IsAdminUser())
|
||||
_, err := UpdateUser(user.GetId(), user, []string{"recovery_codes"}, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -181,7 +181,7 @@ func DisabledMultiFactorAuth(user *User) error {
|
||||
func SetPreferredMultiFactorAuth(user *User, mfaType string) error {
|
||||
user.PreferredMfaType = mfaType
|
||||
|
||||
_, err := UpdateUser(user.GetId(), user, []string{"preferred_mfa_type"}, user.IsAdminUser())
|
||||
_, err := UpdateUser(user.GetId(), user, []string{"preferred_mfa_type"}, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -17,15 +17,18 @@ package object
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/beego/beego"
|
||||
"github.com/beego/beego/context"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pquerna/otp"
|
||||
"github.com/pquerna/otp/totp"
|
||||
)
|
||||
|
||||
const MfaTotpSecretSession = "mfa_totp_secret"
|
||||
const (
|
||||
MfaTotpSecretSession = "mfa_totp_secret"
|
||||
MfaTotpPeriodInSeconds = 30
|
||||
)
|
||||
|
||||
type TotpMfa struct {
|
||||
Config *MfaProps
|
||||
@ -35,10 +38,11 @@ type TotpMfa struct {
|
||||
}
|
||||
|
||||
func (mfa *TotpMfa) Initiate(ctx *context.Context, userId string) (*MfaProps, error) {
|
||||
issuer := beego.AppConfig.String("appname")
|
||||
if issuer == "" {
|
||||
issuer = "casdoor"
|
||||
}
|
||||
//issuer := beego.AppConfig.String("appname")
|
||||
//if issuer == "" {
|
||||
// issuer = "casdoor"
|
||||
//}
|
||||
issuer := "Casdoor"
|
||||
|
||||
key, err := totp.Generate(totp.GenerateOpts{
|
||||
Issuer: issuer,
|
||||
@ -76,7 +80,16 @@ func (mfa *TotpMfa) SetupVerify(ctx *context.Context, passcode string) error {
|
||||
if secret == nil {
|
||||
return errors.New("totp secret is missing")
|
||||
}
|
||||
result := totp.Validate(passcode, secret.(string))
|
||||
|
||||
result, err := totp.ValidateCustom(passcode, secret.(string), time.Now().UTC(), totp.ValidateOpts{
|
||||
Period: MfaTotpPeriodInSeconds,
|
||||
Skew: 1,
|
||||
Digits: otp.DigitsSix,
|
||||
Algorithm: otp.AlgorithmSHA1,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if result {
|
||||
return nil
|
||||
@ -115,7 +128,15 @@ func (mfa *TotpMfa) Enable(ctx *context.Context, user *User) error {
|
||||
}
|
||||
|
||||
func (mfa *TotpMfa) Verify(passcode string) error {
|
||||
result := totp.Validate(passcode, mfa.Config.Secret)
|
||||
result, err := totp.ValidateCustom(passcode, mfa.Config.Secret, time.Now().UTC(), totp.ValidateOpts{
|
||||
Period: MfaTotpPeriodInSeconds,
|
||||
Skew: 1,
|
||||
Digits: otp.DigitsSix,
|
||||
Algorithm: otp.AlgorithmSHA1,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if result {
|
||||
return nil
|
||||
@ -133,7 +154,7 @@ func NewTotpMfaUtil(config *MfaProps) *TotpMfa {
|
||||
|
||||
return &TotpMfa{
|
||||
Config: config,
|
||||
period: 30,
|
||||
period: MfaTotpPeriodInSeconds,
|
||||
secretSize: 20,
|
||||
digits: otp.DigitsSix,
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ type Model struct {
|
||||
Description string `xorm:"varchar(100)" json:"description"`
|
||||
|
||||
ModelText string `xorm:"mediumtext" json:"modelText"`
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
model.Model `xorm:"-" json:"-"`
|
||||
}
|
||||
|
42
object/notification.go
Normal file
42
object/notification.go
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/casdoor/casdoor/notification"
|
||||
"github.com/casdoor/notify"
|
||||
)
|
||||
|
||||
func getNotificationClient(provider *Provider) (notify.Notifier, error) {
|
||||
var client notify.Notifier
|
||||
client, err := notification.GetNotificationProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.ClientId2, provider.ClientSecret2, provider.AppId, provider.Receiver, provider.Method, provider.Title, provider.Metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func SendNotification(provider *Provider, content string) error {
|
||||
client, err := getNotificationClient(provider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.Send(context.Background(), "", content)
|
||||
return err
|
||||
}
|
@ -103,7 +103,7 @@ func GetOidcDiscovery(host string) OidcDiscovery {
|
||||
SubjectTypesSupported: []string{"public"},
|
||||
IdTokenSigningAlgValuesSupported: []string{"RS256"},
|
||||
ScopesSupported: []string{"openid", "email", "profile", "address", "phone", "offline_access"},
|
||||
ClaimsSupported: []string{"iss", "ver", "sub", "aud", "iat", "exp", "id", "type", "displayName", "avatar", "permanentAvatar", "email", "phone", "location", "affiliation", "title", "homepage", "bio", "tag", "region", "language", "score", "ranking", "isOnline", "isAdmin", "isGlobalAdmin", "isForbidden", "signupApplication", "ldap"},
|
||||
ClaimsSupported: []string{"iss", "ver", "sub", "aud", "iat", "exp", "id", "type", "displayName", "avatar", "permanentAvatar", "email", "phone", "location", "affiliation", "title", "homepage", "bio", "tag", "region", "language", "score", "ranking", "isOnline", "isAdmin", "isForbidden", "signupApplication", "ldap"},
|
||||
RequestParameterSupported: true,
|
||||
RequestObjectSigningAlgValuesSupported: []string{"HS256", "HS384", "HS512"},
|
||||
EndSessionEndpoint: fmt.Sprintf("%s/api/logout", originBackend),
|
||||
|
@ -437,14 +437,6 @@ func organizationChangeTrigger(oldName string, newName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
record := new(Record)
|
||||
record.Owner = newName
|
||||
record.Organization = newName
|
||||
_, err = session.Where("organization=?", oldName).Update(record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resource := new(Resource)
|
||||
resource.Owner = newName
|
||||
_, err = session.Where("owner=?", oldName).Update(resource)
|
||||
|
147
object/ormer.go
147
object/ormer.go
@ -16,7 +16,10 @@ package object
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@ -32,7 +35,24 @@ import (
|
||||
_ "modernc.org/sqlite" // db = sqlite
|
||||
)
|
||||
|
||||
var ormer *Ormer
|
||||
var (
|
||||
ormer *Ormer = nil
|
||||
isCreateDatabaseDefined = false
|
||||
createDatabase = true
|
||||
)
|
||||
|
||||
func InitFlag() {
|
||||
if !isCreateDatabaseDefined {
|
||||
isCreateDatabaseDefined = true
|
||||
createDatabase = getCreateDatabaseFlag()
|
||||
}
|
||||
}
|
||||
|
||||
func getCreateDatabaseFlag() bool {
|
||||
res := flag.Bool("createDatabase", false, "true if you need to create database")
|
||||
flag.Parse()
|
||||
return *res
|
||||
}
|
||||
|
||||
func InitConfig() {
|
||||
err := beego.LoadAppConfig("ini", "../conf/app.conf")
|
||||
@ -42,12 +62,23 @@ func InitConfig() {
|
||||
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
|
||||
InitAdapter(true)
|
||||
CreateTables(true)
|
||||
InitAdapter()
|
||||
CreateTables()
|
||||
DoMigration()
|
||||
}
|
||||
|
||||
func InitAdapter(createDatabase bool) {
|
||||
func InitAdapter() {
|
||||
if conf.GetConfigString("driverName") == "" {
|
||||
if !util.FileExist("conf/app.conf") {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
dir = strings.ReplaceAll(dir, "\\", "/")
|
||||
panic(fmt.Sprintf("The Casdoor config file: \"app.conf\" was not found, it should be placed at: \"%s/conf/app.conf\"", dir))
|
||||
}
|
||||
}
|
||||
|
||||
if createDatabase {
|
||||
err := createDatabaseForPostgres(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName"))
|
||||
if err != nil {
|
||||
@ -62,7 +93,7 @@ func InitAdapter(createDatabase bool) {
|
||||
ormer.Engine.SetTableMapper(tbMapper)
|
||||
}
|
||||
|
||||
func CreateTables(createDatabase bool) {
|
||||
func CreateTables() {
|
||||
if createDatabase {
|
||||
err := ormer.CreateDatabase()
|
||||
if err != nil {
|
||||
@ -105,9 +136,14 @@ func NewAdapter(driverName string, dataSourceName string, dbName string) *Ormer
|
||||
return a
|
||||
}
|
||||
|
||||
func refineDataSourceNameForPostgres(dataSourceName string) string {
|
||||
reg := regexp.MustCompile(`dbname=[^ ]+\s*`)
|
||||
return reg.ReplaceAllString(dataSourceName, "")
|
||||
}
|
||||
|
||||
func createDatabaseForPostgres(driverName string, dataSourceName string, dbName string) error {
|
||||
if driverName == "postgres" {
|
||||
db, err := sql.Open(driverName, dataSourceName)
|
||||
db, err := sql.Open(driverName, refineDataSourceNameForPostgres(dataSourceName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -119,6 +155,21 @@ func createDatabaseForPostgres(driverName string, dataSourceName string, dbName
|
||||
return err
|
||||
}
|
||||
}
|
||||
schema := util.GetValueFromDataSourceName("search_path", dataSourceName)
|
||||
if schema != "" {
|
||||
db, err = sql.Open(driverName, dataSourceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.Exec(fmt.Sprintf("CREATE SCHEMA %s;", schema))
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "already exists") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
} else {
|
||||
@ -151,6 +202,12 @@ func (a *Ormer) open() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if a.driverName == "postgres" {
|
||||
schema := util.GetValueFromDataSourceName("search_path", dataSourceName)
|
||||
if schema != "" {
|
||||
engine.SetSchema(schema)
|
||||
}
|
||||
}
|
||||
|
||||
a.Engine = engine
|
||||
}
|
||||
@ -229,11 +286,6 @@ func (a *Ormer) createTable() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Record))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Webhook))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -294,76 +346,3 @@ func (a *Ormer) createTable() {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
||||
session := ormer.Engine.Prepare()
|
||||
if offset != -1 && limit != -1 {
|
||||
session.Limit(limit, offset)
|
||||
}
|
||||
if owner != "" {
|
||||
session = session.And("owner=?", owner)
|
||||
}
|
||||
if field != "" && value != "" {
|
||||
if util.FilterField(field) {
|
||||
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
|
||||
}
|
||||
}
|
||||
if sortField == "" || sortOrder == "" {
|
||||
sortField = "created_time"
|
||||
}
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Asc(util.SnakeString(sortField))
|
||||
} else {
|
||||
session = session.Desc(util.SnakeString(sortField))
|
||||
}
|
||||
return session
|
||||
}
|
||||
|
||||
func GetSessionForUser(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
||||
session := ormer.Engine.Prepare()
|
||||
if offset != -1 && limit != -1 {
|
||||
session.Limit(limit, offset)
|
||||
}
|
||||
if owner != "" {
|
||||
if offset == -1 {
|
||||
session = session.And("owner=?", owner)
|
||||
} else {
|
||||
session = session.And("a.owner=?", owner)
|
||||
}
|
||||
}
|
||||
if field != "" && value != "" {
|
||||
if util.FilterField(field) {
|
||||
if offset != -1 {
|
||||
field = fmt.Sprintf("a.%s", field)
|
||||
}
|
||||
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
|
||||
}
|
||||
}
|
||||
if sortField == "" || sortOrder == "" {
|
||||
sortField = "created_time"
|
||||
}
|
||||
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
tableName := tableNamePrefix + "user"
|
||||
if offset == -1 {
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Asc(util.SnakeString(sortField))
|
||||
} else {
|
||||
session = session.Desc(util.SnakeString(sortField))
|
||||
}
|
||||
} else {
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Alias("a").
|
||||
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name").
|
||||
Select("b.*").
|
||||
Asc("a." + util.SnakeString(sortField))
|
||||
} else {
|
||||
session = session.Alias("a").
|
||||
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name").
|
||||
Select("b.*").
|
||||
Desc("a." + util.SnakeString(sortField))
|
||||
}
|
||||
}
|
||||
|
||||
return session
|
||||
}
|
||||
|
96
object/ormer_session.go
Normal file
96
object/ormer_session.go
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/xorm-io/xorm"
|
||||
)
|
||||
|
||||
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
||||
session := ormer.Engine.Prepare()
|
||||
if offset != -1 && limit != -1 {
|
||||
session.Limit(limit, offset)
|
||||
}
|
||||
if owner != "" {
|
||||
session = session.And("owner=?", owner)
|
||||
}
|
||||
if field != "" && value != "" {
|
||||
if util.FilterField(field) {
|
||||
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
|
||||
}
|
||||
}
|
||||
if sortField == "" || sortOrder == "" {
|
||||
sortField = "created_time"
|
||||
}
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Asc(util.SnakeString(sortField))
|
||||
} else {
|
||||
session = session.Desc(util.SnakeString(sortField))
|
||||
}
|
||||
return session
|
||||
}
|
||||
|
||||
func GetSessionForUser(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
||||
session := ormer.Engine.Prepare()
|
||||
if offset != -1 && limit != -1 {
|
||||
session.Limit(limit, offset)
|
||||
}
|
||||
if owner != "" {
|
||||
if offset == -1 {
|
||||
session = session.And("owner=?", owner)
|
||||
} else {
|
||||
session = session.And("a.owner=?", owner)
|
||||
}
|
||||
}
|
||||
if field != "" && value != "" {
|
||||
if util.FilterField(field) {
|
||||
if offset != -1 {
|
||||
field = fmt.Sprintf("a.%s", field)
|
||||
}
|
||||
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
|
||||
}
|
||||
}
|
||||
if sortField == "" || sortOrder == "" {
|
||||
sortField = "created_time"
|
||||
}
|
||||
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
tableName := tableNamePrefix + "user"
|
||||
if offset == -1 {
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Asc(util.SnakeString(sortField))
|
||||
} else {
|
||||
session = session.Desc(util.SnakeString(sortField))
|
||||
}
|
||||
} else {
|
||||
if sortOrder == "ascend" {
|
||||
session = session.Alias("a").
|
||||
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name").
|
||||
Select("b.*").
|
||||
Asc("a." + util.SnakeString(sortField))
|
||||
} else {
|
||||
session = session.Alias("a").
|
||||
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name").
|
||||
Select("b.*").
|
||||
Desc("a." + util.SnakeString(sortField))
|
||||
}
|
||||
}
|
||||
|
||||
return session
|
||||
}
|
@ -16,7 +16,6 @@ package object
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/casdoor/casdoor/pp"
|
||||
|
||||
@ -55,6 +54,7 @@ type Payment struct {
|
||||
// Order Info
|
||||
OutOrderId string `xorm:"varchar(100)" json:"outOrderId"`
|
||||
PayUrl string `xorm:"varchar(2000)" json:"payUrl"`
|
||||
SuccessUrl string `xorm:"varchar(2000)" json:"successUrl""` // `successUrl` is redirected from `payUrl` after pay success
|
||||
State pp.PaymentState `xorm:"varchar(100)" json:"state"`
|
||||
Message string `xorm:"varchar(2000)" json:"message"`
|
||||
}
|
||||
@ -152,7 +152,7 @@ func DeletePayment(payment *Payment) (bool, error) {
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func notifyPayment(request *http.Request, body []byte, owner string, paymentName string, orderId string) (*Payment, *pp.NotifyResult, error) {
|
||||
func notifyPayment(body []byte, owner string, paymentName string) (*Payment, *pp.NotifyResult, error) {
|
||||
payment, err := getPayment(owner, paymentName)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -166,7 +166,7 @@ func notifyPayment(request *http.Request, body []byte, owner string, paymentName
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pProvider, cert, err := provider.getPaymentProvider()
|
||||
pProvider, err := GetPaymentProvider(provider)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -180,11 +180,7 @@ func notifyPayment(request *http.Request, body []byte, owner string, paymentName
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if orderId == "" {
|
||||
orderId = payment.OutOrderId
|
||||
}
|
||||
|
||||
notifyResult, err := pProvider.Notify(request, body, cert.AuthorityPublicKey, orderId)
|
||||
notifyResult, err := pProvider.Notify(body, payment.OutOrderId)
|
||||
if err != nil {
|
||||
return payment, nil, err
|
||||
}
|
||||
@ -205,8 +201,8 @@ func notifyPayment(request *http.Request, body []byte, owner string, paymentName
|
||||
return payment, notifyResult, nil
|
||||
}
|
||||
|
||||
func NotifyPayment(request *http.Request, body []byte, owner string, paymentName string, orderId string) (*Payment, error) {
|
||||
payment, notifyResult, err := notifyPayment(request, body, owner, paymentName, orderId)
|
||||
func NotifyPayment(body []byte, owner string, paymentName string) (*Payment, error) {
|
||||
payment, notifyResult, err := notifyPayment(body, owner, paymentName)
|
||||
if payment != nil {
|
||||
if err != nil {
|
||||
payment.State = pp.PaymentStateError
|
||||
@ -234,7 +230,7 @@ func invoicePayment(payment *Payment) (string, error) {
|
||||
return "", fmt.Errorf("the payment provider: %s does not exist", payment.Provider)
|
||||
}
|
||||
|
||||
pProvider, _, err := provider.getPaymentProvider()
|
||||
pProvider, err := GetPaymentProvider(provider)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ type Permission struct {
|
||||
Description string `xorm:"varchar(100)" json:"description"`
|
||||
|
||||
Users []string `xorm:"mediumtext" json:"users"`
|
||||
Groups []string `xorm:"mediumtext" json:"groups"`
|
||||
Roles []string `xorm:"mediumtext" json:"roles"`
|
||||
Domains []string `xorm:"mediumtext" json:"domains"`
|
||||
|
||||
@ -60,10 +61,6 @@ type PermissionRule struct {
|
||||
|
||||
const builtInAvailableField = 5 // Casdoor built-in adapter, use V5 to filter permission, so has 5 available field
|
||||
|
||||
func (p *Permission) GetId() string {
|
||||
return util.GetId(p.Owner, p.Name)
|
||||
}
|
||||
|
||||
func GetPermissionCount(owner, field, value string) (int64, error) {
|
||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||
return session.Count(&Permission{})
|
||||
@ -345,20 +342,6 @@ func GetPermissionsByModel(owner string, model string) ([]*Permission, error) {
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
func ContainsAsterisk(userId string, users []string) bool {
|
||||
containsAsterisk := false
|
||||
group, _ := util.GetOwnerAndNameFromId(userId)
|
||||
for _, user := range users {
|
||||
permissionGroup, permissionUserName := util.GetOwnerAndNameFromId(user)
|
||||
if permissionGroup == group && permissionUserName == "*" {
|
||||
containsAsterisk = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return containsAsterisk
|
||||
}
|
||||
|
||||
func GetMaskedPermissions(permissions []*Permission) []*Permission {
|
||||
for _, permission := range permissions {
|
||||
permission.Users = nil
|
||||
@ -388,3 +371,27 @@ func GroupPermissionsByModelAdapter(permissions []*Permission) map[string][]stri
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (p *Permission) GetId() string {
|
||||
return util.GetId(p.Owner, p.Name)
|
||||
}
|
||||
|
||||
func (p *Permission) isUserHit(name string) bool {
|
||||
targetOrg, _ := util.GetOwnerAndNameFromId(name)
|
||||
for _, user := range p.Users {
|
||||
userOrg, userName := util.GetOwnerAndNameFromId(user)
|
||||
if userOrg == targetOrg && userName == "*" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Permission) isResourceHit(name string) bool {
|
||||
for _, resource := range p.Resources {
|
||||
if name == resource {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -79,9 +79,7 @@ func (p *Permission) setEnforcerAdapter(enforcer *casbin.Enforcer) error {
|
||||
}
|
||||
}
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
driverName := conf.GetConfigString("driverName")
|
||||
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
|
||||
adapter, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, tableName, tableNamePrefix, true)
|
||||
adapter, err := xormadapter.NewAdapterByEngineWithTableName(ormer.Engine, tableName, tableNamePrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -33,8 +33,8 @@ func getPermissionMap(owner string) (map[string]*Permission, error) {
|
||||
return m, err
|
||||
}
|
||||
|
||||
func UploadPermissions(owner string, fileId string) (bool, error) {
|
||||
table := xlsx.ReadXlsxFile(fileId)
|
||||
func UploadPermissions(owner string, path string) (bool, error) {
|
||||
table := xlsx.ReadXlsxFile(path)
|
||||
|
||||
oldUserMap, err := getPermissionMap(owner)
|
||||
if err != nil {
|
||||
|
@ -16,6 +16,7 @@ package object
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/xorm-io/core"
|
||||
@ -28,15 +29,39 @@ type Plan struct {
|
||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||
Description string `xorm:"varchar(100)" json:"description"`
|
||||
|
||||
PricePerMonth float64 `json:"pricePerMonth"`
|
||||
PricePerYear float64 `json:"pricePerYear"`
|
||||
Currency string `xorm:"varchar(100)" json:"currency"`
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
Price float64 `json:"price"`
|
||||
Currency string `xorm:"varchar(100)" json:"currency"`
|
||||
Period string `xorm:"varchar(100)" json:"period"`
|
||||
Product string `xorm:"varchar(100)" json:"product"`
|
||||
PaymentProviders []string `xorm:"varchar(100)" json:"paymentProviders"` // payment providers for related product
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
Role string `xorm:"varchar(100)" json:"role"`
|
||||
Options []string `xorm:"-" json:"options"`
|
||||
}
|
||||
|
||||
const (
|
||||
PeriodMonthly = "Monthly"
|
||||
PeriodYearly = "Yearly"
|
||||
)
|
||||
|
||||
func (plan *Plan) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", plan.Owner, plan.Name)
|
||||
}
|
||||
|
||||
func GetDuration(period string) (startTime time.Time, endTime time.Time) {
|
||||
if period == PeriodYearly {
|
||||
startTime = time.Now()
|
||||
endTime = startTime.AddDate(1, 0, 0)
|
||||
} else if period == PeriodMonthly {
|
||||
startTime = time.Now()
|
||||
endTime = startTime.AddDate(0, 1, 0)
|
||||
} else {
|
||||
panic(fmt.Sprintf("invalid period: %s", period))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetPlanCount(owner, field, value string) (int64, error) {
|
||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||
return session.Count(&Plan{})
|
||||
@ -114,38 +139,3 @@ func DeletePlan(plan *Plan) (bool, error) {
|
||||
}
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (plan *Plan) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", plan.Owner, plan.Name)
|
||||
}
|
||||
|
||||
func Subscribe(owner string, user string, plan string, pricing string) (*Subscription, error) {
|
||||
selectedPricing, err := GetPricing(fmt.Sprintf("%s/%s", owner, pricing))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
valid := selectedPricing != nil && selectedPricing.IsEnabled
|
||||
|
||||
if !valid {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
planBelongToPricing, err := selectedPricing.HasPlan(owner, plan)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if planBelongToPricing {
|
||||
newSubscription := NewSubscription(owner, user, plan, selectedPricing.TrialDuration)
|
||||
affected, err := AddSubscription(newSubscription)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if affected {
|
||||
return newSubscription, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ package object
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/xorm-io/core"
|
||||
@ -33,12 +32,26 @@ type Pricing struct {
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
TrialDuration int `json:"trialDuration"`
|
||||
Application string `xorm:"varchar(100)" json:"application"`
|
||||
}
|
||||
|
||||
Submitter string `xorm:"varchar(100)" json:"submitter"`
|
||||
Approver string `xorm:"varchar(100)" json:"approver"`
|
||||
ApproveTime string `xorm:"varchar(100)" json:"approveTime"`
|
||||
func (pricing *Pricing) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", pricing.Owner, pricing.Name)
|
||||
}
|
||||
|
||||
State string `xorm:"varchar(100)" json:"state"`
|
||||
func (pricing *Pricing) HasPlan(planName string) (bool, error) {
|
||||
planId := util.GetId(pricing.Owner, planName)
|
||||
plan, err := GetPlan(planId)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if plan == nil {
|
||||
return false, fmt.Errorf("plan: %s does not exist", planId)
|
||||
}
|
||||
|
||||
if util.InSlice(pricing.Plans, plan.Name) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func GetPricingCount(owner, field, value string) (int64, error) {
|
||||
@ -74,7 +87,7 @@ func getPricing(owner, name string) (*Pricing, error) {
|
||||
pricing := Pricing{Owner: owner, Name: name}
|
||||
existed, err := ormer.Engine.Get(&pricing)
|
||||
if err != nil {
|
||||
return &pricing, err
|
||||
return nil, err
|
||||
}
|
||||
if existed {
|
||||
return &pricing, nil
|
||||
@ -88,6 +101,20 @@ func GetPricing(id string) (*Pricing, error) {
|
||||
return getPricing(owner, name)
|
||||
}
|
||||
|
||||
func GetApplicationDefaultPricing(owner, appName string) (*Pricing, error) {
|
||||
pricings := make([]*Pricing, 0, 1)
|
||||
err := ormer.Engine.Asc("created_time").Find(&pricings, &Pricing{Owner: owner, Application: appName})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, pricing := range pricings {
|
||||
if pricing.IsEnabled {
|
||||
return pricing, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func UpdatePricing(id string, pricing *Pricing) (bool, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
if p, err := getPricing(owner, name); err != nil {
|
||||
@ -120,28 +147,21 @@ func DeletePricing(pricing *Pricing) (bool, error) {
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (pricing *Pricing) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", pricing.Owner, pricing.Name)
|
||||
}
|
||||
|
||||
func (pricing *Pricing) HasPlan(owner string, plan string) (bool, error) {
|
||||
selectedPlan, err := GetPlan(fmt.Sprintf("%s/%s", owner, plan))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if selectedPlan == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
result := false
|
||||
|
||||
for _, pricingPlan := range pricing.Plans {
|
||||
if strings.Contains(pricingPlan, selectedPlan.Name) {
|
||||
result = true
|
||||
break
|
||||
func CheckPricingAndPlan(owner, pricingName, planName string) error {
|
||||
pricingId := util.GetId(owner, pricingName)
|
||||
pricing, err := GetPricing(pricingId)
|
||||
if pricing == nil || err != nil {
|
||||
if pricing == nil && err == nil {
|
||||
err = fmt.Errorf("pricing: %s does not exist", pricingName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
ok, err := pricing.HasPlan(planName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("pricing: %s does not have plan: %s", pricingName, planName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ type Product struct {
|
||||
Price float64 `json:"price"`
|
||||
Quantity int `json:"quantity"`
|
||||
Sold int `json:"sold"`
|
||||
Providers []string `xorm:"varchar(100)" json:"providers"`
|
||||
Providers []string `xorm:"varchar(255)" json:"providers"`
|
||||
ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"`
|
||||
|
||||
State string `xorm:"varchar(100)" json:"state"`
|
||||
@ -141,59 +141,76 @@ func (product *Product) isValidProvider(provider *Provider) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (product *Product) getProvider(providerId string) (*Provider, error) {
|
||||
provider, err := getProvider(product.Owner, providerId)
|
||||
func (product *Product) getProvider(providerName string) (*Provider, error) {
|
||||
provider, err := getProvider(product.Owner, providerName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if provider == nil {
|
||||
return nil, fmt.Errorf("the payment provider: %s does not exist", providerId)
|
||||
return nil, fmt.Errorf("the payment provider: %s does not exist", providerName)
|
||||
}
|
||||
|
||||
if !product.isValidProvider(provider) {
|
||||
return nil, fmt.Errorf("the payment provider: %s is not valid for the product: %s", providerId, product.Name)
|
||||
return nil, fmt.Errorf("the payment provider: %s is not valid for the product: %s", providerName, product.Name)
|
||||
}
|
||||
|
||||
return provider, nil
|
||||
}
|
||||
|
||||
func BuyProduct(id string, providerName string, user *User, host string) (string, string, error) {
|
||||
func BuyProduct(id string, user *User, providerName, pricingName, planName, host string) (*Payment, error) {
|
||||
product, err := GetProduct(id)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if product == nil {
|
||||
return "", "", fmt.Errorf("the product: %s does not exist", id)
|
||||
return nil, fmt.Errorf("the product: %s does not exist", id)
|
||||
}
|
||||
|
||||
provider, err := product.getProvider(providerName)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pProvider, _, err := provider.getPaymentProvider()
|
||||
pProvider, err := GetPaymentProvider(provider)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
owner := product.Owner
|
||||
productName := product.Name
|
||||
payerName := fmt.Sprintf("%s | %s", user.Name, user.DisplayName)
|
||||
paymentName := util.GenerateTimeId()
|
||||
paymentName := fmt.Sprintf("payment_%v", util.GenerateTimeId())
|
||||
productDisplayName := product.DisplayName
|
||||
|
||||
originFrontend, originBackend := getOriginFromHost(host)
|
||||
returnUrl := fmt.Sprintf("%s/payments/%s/%s/result", originFrontend, owner, paymentName)
|
||||
notifyUrl := fmt.Sprintf("%s/api/notify-payment/%s/%s", originBackend, owner, paymentName)
|
||||
// Create an Order and get the payUrl
|
||||
if user.Type == "paid-user" {
|
||||
// Create a subscription for `paid-user`
|
||||
if pricingName != "" && planName != "" {
|
||||
plan, err := GetPlan(util.GetId(owner, planName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if plan == nil {
|
||||
return nil, fmt.Errorf("the plan: %s does not exist", planName)
|
||||
}
|
||||
sub := NewSubscription(owner, user.Name, plan.Name, paymentName, plan.Period)
|
||||
_, err = AddSubscription(sub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
returnUrl = fmt.Sprintf("%s/buy-plan/%s/%s/result?subscription=%s", originFrontend, owner, pricingName, sub.Name)
|
||||
}
|
||||
}
|
||||
// Create an OrderId and get the payUrl
|
||||
payUrl, orderId, err := pProvider.Pay(providerName, productName, payerName, paymentName, productDisplayName, product.Price, product.Currency, returnUrl, notifyUrl)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return nil, err
|
||||
}
|
||||
// Create a Payment linked with Product and Order
|
||||
payment := Payment{
|
||||
payment := &Payment{
|
||||
Owner: product.Owner,
|
||||
Name: paymentName,
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
@ -212,6 +229,7 @@ func BuyProduct(id string, providerName string, user *User, host string) (string
|
||||
|
||||
User: user.Name,
|
||||
PayUrl: payUrl,
|
||||
SuccessUrl: returnUrl,
|
||||
State: pp.PaymentStateCreated,
|
||||
OutOrderId: orderId,
|
||||
}
|
||||
@ -220,16 +238,15 @@ func BuyProduct(id string, providerName string, user *User, host string) (string
|
||||
payment.State = pp.PaymentStatePaid
|
||||
}
|
||||
|
||||
affected, err := AddPayment(&payment)
|
||||
affected, err := AddPayment(payment)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !affected {
|
||||
return "", "", fmt.Errorf("failed to add payment: %s", util.StructToJson(payment))
|
||||
return nil, fmt.Errorf("failed to add payment: %s", util.StructToJson(payment))
|
||||
}
|
||||
|
||||
return payUrl, orderId, err
|
||||
return payment, err
|
||||
}
|
||||
|
||||
func ExtendProductWithProviders(product *Product) error {
|
||||
@ -252,3 +269,38 @@ func ExtendProductWithProviders(product *Product) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateProductForPlan(plan *Plan) *Product {
|
||||
product := &Product{
|
||||
Owner: plan.Owner,
|
||||
Name: fmt.Sprintf("product_%v", util.GetRandomName()),
|
||||
DisplayName: fmt.Sprintf("Product for Plan %v/%v/%v", plan.Name, plan.DisplayName, plan.Period),
|
||||
CreatedTime: plan.CreatedTime,
|
||||
|
||||
Image: "https://cdn.casbin.org/img/casdoor-logo_1185x256.png", // TODO
|
||||
Detail: fmt.Sprintf("This product was auto created for plan %v(%v), subscription period is %v", plan.Name, plan.DisplayName, plan.Period),
|
||||
Description: plan.Description,
|
||||
Tag: "auto_created_product_for_plan",
|
||||
Price: plan.Price,
|
||||
Currency: plan.Currency,
|
||||
|
||||
Quantity: 999,
|
||||
Sold: 0,
|
||||
|
||||
Providers: plan.PaymentProviders,
|
||||
State: "Published",
|
||||
}
|
||||
if product.Providers == nil {
|
||||
product.Providers = []string{}
|
||||
}
|
||||
return product
|
||||
}
|
||||
|
||||
func UpdateProductForPlan(plan *Plan, product *Product) {
|
||||
product.Owner = plan.Owner
|
||||
product.DisplayName = fmt.Sprintf("Product for Plan %v/%v/%v", plan.Name, plan.DisplayName, plan.Period)
|
||||
product.Detail = fmt.Sprintf("This product was auto created for plan %v(%v), subscription period is %v", plan.Name, plan.DisplayName, plan.Period)
|
||||
product.Price = plan.Price
|
||||
product.Currency = plan.Currency
|
||||
product.Providers = plan.PaymentProviders
|
||||
}
|
||||
|
@ -17,31 +17,24 @@
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/casdoor/casdoor/pp"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
func TestProduct(t *testing.T) {
|
||||
InitConfig()
|
||||
|
||||
product, _ := GetProduct("admin/product_123")
|
||||
provider, _ := getProvider(product.Owner, "provider_pay_alipay")
|
||||
cert, _ := getCert(product.Owner, "cert-pay-alipay")
|
||||
pProvider, err := pp.GetPaymentProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, cert.Certificate, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey, provider.ClientId2)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
paymentName := util.GenerateTimeId()
|
||||
returnUrl := ""
|
||||
notifyUrl := ""
|
||||
payUrl, _, err := pProvider.Pay(provider.Name, product.Name, "alice", paymentName, product.DisplayName, product.Price, product.Currency, returnUrl, notifyUrl)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
println(payUrl)
|
||||
}
|
||||
//func TestProduct(t *testing.T) {
|
||||
// InitConfig()
|
||||
//
|
||||
// product, _ := GetProduct("admin/product_123")
|
||||
// provider, _ := getProvider(product.Owner, "provider_pay_alipay")
|
||||
// cert, _ := getCert(product.Owner, "cert-pay-alipay")
|
||||
// pProvider, err := pp.GetPaymentProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, cert.Certificate, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey, provider.ClientId2)
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//
|
||||
// paymentName := util.GenerateTimeId()
|
||||
// returnUrl := ""
|
||||
// notifyUrl := ""
|
||||
// payUrl, _, err := pProvider.Pay(provider.Name, product.Name, "alice", paymentName, product.DisplayName, product.Price, product.Currency, returnUrl, notifyUrl)
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//
|
||||
// println(payUrl)
|
||||
//}
|
||||
|
@ -36,7 +36,7 @@ type Provider struct {
|
||||
Type string `xorm:"varchar(100)" json:"type"`
|
||||
SubType string `xorm:"varchar(100)" json:"subType"`
|
||||
Method string `xorm:"varchar(100)" json:"method"`
|
||||
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
||||
ClientId string `xorm:"varchar(200)" json:"clientId"`
|
||||
ClientSecret string `xorm:"varchar(2000)" json:"clientSecret"`
|
||||
ClientId2 string `xorm:"varchar(100)" json:"clientId2"`
|
||||
ClientSecret2 string `xorm:"varchar(100)" json:"clientSecret2"`
|
||||
@ -251,30 +251,69 @@ func DeleteProvider(provider *Provider) (bool, error) {
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func (p *Provider) getPaymentProvider() (pp.PaymentProvider, *Cert, error) {
|
||||
func GetPaymentProvider(p *Provider) (pp.PaymentProvider, error) {
|
||||
cert := &Cert{}
|
||||
if p.Cert != "" {
|
||||
var err error
|
||||
cert, err = getCert(p.Owner, p.Cert)
|
||||
cert, err = GetCert(util.GetId(p.Owner, p.Cert))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cert == nil {
|
||||
return nil, nil, fmt.Errorf("the cert: %s does not exist", p.Cert)
|
||||
return nil, fmt.Errorf("the cert: %s does not exist", p.Cert)
|
||||
}
|
||||
}
|
||||
|
||||
pProvider, err := pp.GetPaymentProvider(p.Type, p.ClientId, p.ClientSecret, p.Host, cert.Certificate, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey, p.ClientId2)
|
||||
if err != nil {
|
||||
return nil, cert, err
|
||||
typ := p.Type
|
||||
if typ == "Dummy" {
|
||||
pp, err := pp.NewDummyPaymentProvider()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pp, nil
|
||||
} else if typ == "Alipay" {
|
||||
if p.Metadata != "" {
|
||||
// alipay provider store rootCert's name in metadata
|
||||
rootCert, err := GetCert(util.GetId(p.Owner, p.Metadata))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rootCert == nil {
|
||||
return nil, fmt.Errorf("the cert: %s does not exist", p.Metadata)
|
||||
}
|
||||
pp, err := pp.NewAlipayPaymentProvider(p.ClientId, cert.Certificate, cert.PrivateKey, rootCert.Certificate, rootCert.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pp, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("the metadata of alipay provider is empty")
|
||||
}
|
||||
} else if typ == "GC" {
|
||||
return pp.NewGcPaymentProvider(p.ClientId, p.ClientSecret, p.Host), nil
|
||||
} else if typ == "WeChat Pay" {
|
||||
pp, err := pp.NewWechatPaymentProvider(p.ClientId, p.ClientSecret, p.ClientId2, cert.Certificate, cert.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pp, nil
|
||||
} else if typ == "PayPal" {
|
||||
pp, err := pp.NewPaypalPaymentProvider(p.ClientId, p.ClientSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pp, nil
|
||||
} else if typ == "Stripe" {
|
||||
pp, err := pp.NewStripePaymentProvider(p.ClientId, p.ClientSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pp, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("the payment provider type: %s is not supported", p.Type)
|
||||
}
|
||||
|
||||
if pProvider == nil {
|
||||
return nil, cert, fmt.Errorf("the payment provider type: %s is not supported", p.Type)
|
||||
}
|
||||
|
||||
return pProvider, cert, nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *Provider) GetId() string {
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"github.com/beego/beego/context"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/casvisor/casvisor-go-sdk/casvisorsdk"
|
||||
)
|
||||
|
||||
var logPostOnly bool
|
||||
@ -30,26 +31,10 @@ func init() {
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
Id int `xorm:"int notnull pk autoincr" json:"id"`
|
||||
|
||||
Owner string `xorm:"varchar(100) index" json:"owner"`
|
||||
Name string `xorm:"varchar(100) index" json:"name"`
|
||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||
|
||||
Organization string `xorm:"varchar(100)" json:"organization"`
|
||||
ClientIp string `xorm:"varchar(100)" json:"clientIp"`
|
||||
User string `xorm:"varchar(100)" json:"user"`
|
||||
Method string `xorm:"varchar(100)" json:"method"`
|
||||
RequestUri string `xorm:"varchar(1000)" json:"requestUri"`
|
||||
Action string `xorm:"varchar(1000)" json:"action"`
|
||||
|
||||
Object string `xorm:"-" json:"object"`
|
||||
ExtendedUser *User `xorm:"-" json:"extendedUser"`
|
||||
|
||||
IsTriggered bool `json:"isTriggered"`
|
||||
casvisorsdk.Record
|
||||
}
|
||||
|
||||
func NewRecord(ctx *context.Context) *Record {
|
||||
func NewRecord(ctx *context.Context) *casvisorsdk.Record {
|
||||
ip := strings.Replace(util.GetIPFromRequest(ctx.Request), ": ", "", -1)
|
||||
action := strings.Replace(ctx.Request.URL.Path, "/api/", "", -1)
|
||||
requestUri := util.FilterQuery(ctx.Request.RequestURI, []string{"accessToken"})
|
||||
@ -62,7 +47,7 @@ func NewRecord(ctx *context.Context) *Record {
|
||||
object = string(ctx.Input.RequestBody)
|
||||
}
|
||||
|
||||
record := Record{
|
||||
record := casvisorsdk.Record{
|
||||
Name: util.GenerateId(),
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
ClientIp: ip,
|
||||
@ -76,7 +61,7 @@ func NewRecord(ctx *context.Context) *Record {
|
||||
return &record
|
||||
}
|
||||
|
||||
func AddRecord(record *Record) bool {
|
||||
func AddRecord(record *casvisorsdk.Record) bool {
|
||||
if logPostOnly {
|
||||
if record.Method == "GET" {
|
||||
return false
|
||||
@ -96,51 +81,19 @@ func AddRecord(record *Record) bool {
|
||||
fmt.Println(errWebhook)
|
||||
}
|
||||
|
||||
affected, err := ormer.Engine.Insert(record)
|
||||
if casvisorsdk.GetClient() == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
affected, err := casvisorsdk.AddRecord(record)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return affected != 0
|
||||
return affected
|
||||
}
|
||||
|
||||
func GetRecordCount(field, value string, filterRecord *Record) (int64, error) {
|
||||
session := GetSession("", -1, -1, field, value, "", "")
|
||||
return session.Count(filterRecord)
|
||||
}
|
||||
|
||||
func GetRecords() ([]*Record, error) {
|
||||
records := []*Record{}
|
||||
err := ormer.Engine.Desc("id").Find(&records)
|
||||
if err != nil {
|
||||
return records, err
|
||||
}
|
||||
|
||||
return records, nil
|
||||
}
|
||||
|
||||
func GetPaginationRecords(offset, limit int, field, value, sortField, sortOrder string, filterRecord *Record) ([]*Record, error) {
|
||||
records := []*Record{}
|
||||
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
|
||||
err := session.Find(&records, filterRecord)
|
||||
if err != nil {
|
||||
return records, err
|
||||
}
|
||||
|
||||
return records, nil
|
||||
}
|
||||
|
||||
func GetRecordsByField(record *Record) ([]*Record, error) {
|
||||
records := []*Record{}
|
||||
err := ormer.Engine.Find(&records, record)
|
||||
if err != nil {
|
||||
return records, err
|
||||
}
|
||||
|
||||
return records, nil
|
||||
}
|
||||
|
||||
func SendWebhooks(record *Record) error {
|
||||
func SendWebhooks(record *casvisorsdk.Record) error {
|
||||
webhooks, err := getWebhooksByOrganization(record.Organization)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -160,17 +113,16 @@ func SendWebhooks(record *Record) error {
|
||||
}
|
||||
|
||||
if matched {
|
||||
var user *User
|
||||
if webhook.IsUserExtended {
|
||||
user, err := getUser(record.Organization, record.User)
|
||||
user, err = getUser(record.Organization, record.User)
|
||||
user, err = GetMaskedUser(user, false, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record.ExtendedUser = user
|
||||
}
|
||||
|
||||
err := sendWebhook(webhook, record)
|
||||
err = sendWebhook(webhook, record, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
50
object/record_casvisor.go
Normal file
50
object/record_casvisor.go
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/casvisor/casvisor-go-sdk/casvisorsdk"
|
||||
)
|
||||
|
||||
func getCasvisorApplication() *Application {
|
||||
applications, err := GetApplications("admin")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, application := range applications {
|
||||
if strings.Contains(strings.ToLower(application.Name), "casvisor") {
|
||||
return application
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func InitCasvisorConfig() {
|
||||
application := getCasvisorApplication()
|
||||
if application == nil {
|
||||
return
|
||||
}
|
||||
|
||||
casvisorEndpoint := application.HomepageUrl
|
||||
clientId := application.ClientId
|
||||
clientSecret := application.ClientSecret
|
||||
casdoorOrganization := application.Organization
|
||||
casdoorApplication := application.Name
|
||||
|
||||
casvisorsdk.InitConfig(casvisorEndpoint, clientId, clientSecret, casdoorOrganization, casdoorApplication)
|
||||
}
|
@ -33,8 +33,8 @@ func getRoleMap(owner string) (map[string]*Role, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func UploadRoles(owner string, fileId string) (bool, error) {
|
||||
table := xlsx.ReadXlsxFile(fileId)
|
||||
func UploadRoles(owner string, path string) (bool, error) {
|
||||
table := xlsx.ReadXlsxFile(path)
|
||||
|
||||
oldUserMap, err := getRoleMap(owner)
|
||||
if err != nil {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user