Compare commits

...

108 Commits

Author SHA1 Message Date
891e8e21d8 feat: support Web3-Onboard provider (#2209)
* feat: add Web3-Onboard idp

* feat: update Web3-Onboard logo

* feat: update package.json

* feat: remove unused package

* feat: add yarn build param --max_old_space_size=4096

* feat: remove log

* feat: add Wallet configure

* feat: remove hardware wallets
2023-08-13 23:58:57 +08:00
80b0d26813 fix: synchronize update the syncers (#2201)
Signed-off-by: baihhh <2542274498@qq.com>
2023-08-13 22:30:57 +08:00
db4ac60bb6 feat: fix LDAP mobile field incorrect mapped (#2206) 2023-08-12 13:45:26 +08:00
33a922f026 Add custom HTTP SMS provider 2023-08-12 12:52:53 +08:00
9f65053d04 Improve i18n 2023-08-12 02:44:38 +08:00
be969e5efa Fix typo 2023-08-11 22:18:35 +08:00
9156bd426b ci: Show provider.displayName in signin button 2023-08-11 16:29:52 +08:00
fe4a4328aa feat: refactor code in InitApi() 2023-08-11 16:17:29 +08:00
9899022bcd fix: check enforcer should not be nil (#2199)
* fix: check enforcer should not be nil

* fix: check enforcer should not be nil

* Update user.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-08-11 12:31:49 +08:00
1a9d02be46 feat: use the casbin model to store relationships between users and groups (#2178)
* fix:reslove conflict

* fix: remove interface
2023-08-11 10:59:18 +08:00
eafaa135b4 Change builtInAvailableField back to 5 2023-08-11 02:45:11 +08:00
6746551447 Improve error message in InitEnforcer() 2023-08-11 02:36:29 +08:00
3cb46c3628 Add isKey to syncer's table 2023-08-09 00:33:04 +08:00
558bcf95d6 feat: save policy in adapter edit page (#2190)
* fix: save policy in adapter

* fix: disable edit for builtin adapter
2023-08-09 00:12:53 +08:00
bb937c30c1 Fix empty cert in getPaymentProvider() 2023-08-08 22:37:48 +08:00
8dfdf7f767 ci: add GoogleCloud and QiNiu in Storage (#2188)
* feat: add GoogleCloud and QiNiu in Storage

Signed-off-by: baihhh <2542274498@qq.com>

* Update qiniu_cloud.go

* Update storage.go

---------

Signed-off-by: baihhh <2542274498@qq.com>
Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-08-08 22:34:55 +08:00
62b2082e82 Add getUserOrganization() to user edit page 2023-08-08 21:58:27 +08:00
a1806439f8 Add UserPrincipalName and MemberOf to get-ldap-users API 2023-08-08 20:18:47 +08:00
01e58158b7 feat: Remove useless code 2023-08-08 19:16:55 +08:00
15427ad9d6 fix: fix add provider error (#2184) 2023-08-07 17:22:32 +08:00
d058f78dc6 fix: fix broken links (#2181) 2023-08-07 01:02:03 +08:00
fd9dbf8251 feat: add multiple SMS providers (#2182)
* feat: add amazon sns and azure acs provider

* feat: add msg91 sms provider

* feat: add infobip sms provider

* feat: add ucloud sms provider

* feat: add baidu cloud sms provider

* fix: fix logo and azure acs
2023-08-07 00:59:17 +08:00
3220a04fa9 fix: use org/groupName replace groupName (#2180) 2023-08-06 20:16:44 +08:00
f06a4990bd fix: rename in init.go (#2179)
* fix: rename in init.go

* fix: remove blank line

* fix: remove blank line

* Update init.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-08-06 13:07:30 +08:00
9df7de5f27 Improve menu icons 2023-08-05 18:00:24 +08:00
56c808c091 Improve menu 2023-08-05 17:41:35 +08:00
9fd2421564 Update @ant-design/cssinjs dependency to avoid build error 2023-08-04 01:22:57 +08:00
689d45c7fa feat: fix org name cannot be changed bug 2023-08-03 18:48:37 +08:00
c24343bd53 Fix XxxChangeTrigger() doesn't return error bug 2023-08-03 18:45:49 +08:00
979f43638d Change builtInAvailableField to 10 2023-08-03 18:17:15 +08:00
685a4514cd fix: revert adapter port vartype to int (#2174) 2023-08-03 09:35:16 +08:00
a05ca3af24 feat: use role ID to search in GetPermissionsAndRolesByUser() (#2170) 2023-08-02 20:58:06 +08:00
c6f301ff9e Support svg in downloadImage() 2023-07-31 20:23:28 +08:00
d7b2bcf288 feat: support payment cancel state (#2165) 2023-07-31 15:24:13 +08:00
67ac3d6d21 Fix typo 2023-07-31 15:23:44 +08:00
912d5c6a7f fix: support enforcerId parameter in Enforce API (#2164) 2023-07-31 00:20:53 +08:00
32fbb5b534 Support custom provider for storage API 2023-07-30 23:19:45 +08:00
21004f3009 Fix GetResources() missing items bug 2023-07-30 22:47:14 +08:00
463bacd53b Add GetDirectResources() 2023-07-30 22:01:10 +08:00
78dc660041 feat: support 3 more language (#2163)
Signed-off-by: baihhh <2542274498@qq.com>
2023-07-30 20:45:47 +08:00
2fb9674171 Fix file not exist panic in StaticFilter() 2023-07-30 19:03:21 +08:00
55c522d3b7 Improve provider type input box 2023-07-30 17:31:36 +08:00
f879170663 Remove AI related code 2023-07-30 14:39:27 +08:00
12e5d9b583 Remove adapter.file 2023-07-30 12:08:05 +08:00
eefa1e6df4 fix: fix paypal payment provider and refactor payment code (#2159)
* feat: support paypal payment provider

* feat: support paypal flow

* feat: use owner replace org for payment

* feat: update paypal logic

* feat: gofumpt

* feat: update payment

* fix: fix notify

* feat: delete log
2023-07-30 11:54:42 +08:00
026fb207b3 fix: remove model in adapter page (#2161) 2023-07-29 23:42:08 +08:00
ea10f8e615 feat: make hard-coded authz adapter editable, rename adapter to ormer (#2149)
* refactor: rename casbinAdapter to casdoorAdapter

* feat: add initEnforcer

* fix: router

* refactor: make hard-coded code configurable

* fix: data type

* feat: support sqlite3

* feat: disable delete and edit name for built in resources

* feat: optimize code

* fix: init

* fix: e2e

* fix: remove datasourcename

* fix: revert rename

* refactor: change all ORM's Adatper to Ormer

* refactor: name
2023-07-29 15:07:04 +08:00
74b058aa3f Fix sync-ldap-users() bug, brought by: 666ff48837 2023-07-29 13:14:55 +08:00
6c628d7893 Fix static path not changed bug in makeGzipResponse() 2023-07-29 12:23:48 +08:00
a38896e4d8 Improve swagger docs 2023-07-29 11:35:03 +08:00
5f054c4989 Fix product links 2023-07-28 15:08:45 +08:00
fb16d8cee6 fix: not set count of enforcers to the response (#2155) 2023-07-28 14:46:11 +08:00
5e4ba4f338 feat: add authorize button and defaultValue (#2152)
Signed-off-by: baihhh <2542274498@qq.com>
2023-07-27 23:55:35 +08:00
ca47af2ee1 Make post_logout_redirect_uri optional for logout 2023-07-27 23:26:30 +08:00
59da104463 fix: update ldap admin pwd only if changed (#2146)
* fix ldap pwd update

* fix: linter

* fix: simplify check
2023-07-27 17:49:15 +08:00
c5bb916651 fix: fix response data in PricingPage.js (#2143) 2023-07-27 10:46:31 +08:00
e98264f957 fix: application fails to call /api/get-resources (#2139)
just like other apis, resource.go.GetResources() no longer calls ApiController.RequireSignedInUser() to auth or check
2023-07-26 17:19:00 +08:00
6a952952a8 fix: unmask application for org admin (#2138)
* feat: unmask application with user admin

* Update application.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-07-26 17:17:49 +08:00
ba8a0f36be Support custom actions in permission edit page 2023-07-26 14:49:45 +08:00
b5e9084e5d feat: en/decodeURI in permission/role name (#2137) 2023-07-26 13:08:35 +08:00
55d5ae10f2 fix: fix infinite loop in containsRole() (#2136) 2023-07-25 20:53:08 +08:00
6986dad295 Use arg to control createDatabaseForPostgres() 2023-07-25 18:36:15 +08:00
949feb18af feat: add basic enforcer manager (#2130)
* feat: add basic enforcer manager

* chore: generate swagger
2023-07-25 17:17:59 +08:00
d1f88ca9b8 feat: support google one tap signin (#2131)
* feat: add google one tap support

* feat: gofumpt

* feat: add google provider rule conf

* feat: update i18n
2023-07-25 15:49:15 +08:00
bfe8e5f3e7 fix: fix response data assignment error (#2129) 2023-07-25 13:52:31 +08:00
702ee6acd0 Print log for StartLdapServer()'s error 2023-07-25 01:49:43 +08:00
0a9587901a fix: fix response data assignment error in ApplicationEditPage.js (#2126) 2023-07-24 20:09:09 +08:00
577bd6ce58 feat: fix response data assignment error (#2123) 2023-07-24 14:52:30 +08:00
3c4112dd44 refactor: optimize the code to getEnforcer (#2120) 2023-07-24 14:02:34 +08:00
b7a37126ad feat: restrict redirectUrls for CAS login (#2118)
* feat: support cas restricted login

* feat: add cas login i18n

* feat: add CheckCasService for all cas api

* feat: gofumpt

* feat: replace 404

* feat: reuse i18n

* feat: delete CheckCasService

* Update token_cas.go

* Update LoginPage.js

* Update token_cas.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-07-24 11:47:31 +08:00
8669d5bb0d chore: hide field of IntranetEndpoint in Tencent COS storage provider (#2117) 2023-07-23 19:02:42 +08:00
aee3ea4981 feat: improve TermsOfUse UI in mobile (#2106)
* style: Mobile interface adaptation

Signed-off-by: baihhh <2542274498@qq.com>

* Update index.css

---------

Signed-off-by: baihhh <2542274498@qq.com>
Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-07-23 15:28:13 +08:00
516f4b7569 Fix response of /api/get-sorted-users and /api/get-user-count 2023-07-23 14:46:38 +08:00
7d7ca10481 fix: hide fields of minio storage provider (#2115)
* feat: hide field of minio storage provider

* feat: hide field of domain in minio storage provider
2023-07-23 14:40:30 +08:00
a9d4978a0f chore: hide fields of local file system storage provider (#2109)
* style: adjust local file system storage

* style: disable domain when use local file system
2023-07-23 11:48:15 +08:00
09f40bb5ce Fix id of "/api/get-resource" API 2023-07-23 11:33:48 +08:00
a6f803aff1 feat: refactor code to use responseOK everywhere (#2111)
* refactor: use responseOK return frontend format json data

* revert handle error

* revert handle error
2023-07-23 09:49:16 +08:00
fc9528be43 Add createDatabaseForPostgres() 2023-07-22 16:19:13 +08:00
58e8f9f90b feat: fix Effect in Casbin rule (#2103)
* fix: Add `Effect` to Casbin rule of role

fix: https://github.com/casdoor/casdoor/issues/2102

* Update permission_enforcer.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-07-21 18:01:37 +08:00
e850e33f37 Fix error message of missing cert when login 2023-07-20 19:45:22 +08:00
d7110ff8bf feat: support MetaMask provider (#2084)
* feat: add metamask provider

* feat: add eth login

* feat: check eth sign

* feat: finish metamask signin/signup

* feat: support MetaMask provider link/unlink

* feat: update web/craco.config.js to handle polyfill

* feat: gofumpt idp/metamask.go

* feat: update MetaMask logo path

* feat: support MetaMask avatar
2023-07-20 17:51:36 +08:00
f923a8f0d7 fix: provide detailed description of ldap in swagger (#2094)
* provide detailed description of ldap in swagger

* modify the directory of swagger

fix: provide detailed description of ldap in swagger
2023-07-20 12:32:48 +08:00
7bfb74ba18 Fix typo 2023-07-19 19:34:43 +08:00
38f031bc86 Show access secret if isAdminOrSelf is true in get-user and get-account APIs 2023-07-19 19:14:53 +08:00
5c441d195c Add Effect to Casbin rule of add-permission 2023-07-19 18:52:22 +08:00
0639564d27 fix: check group name cannot be same as organization name (#2090) 2023-07-19 11:37:28 +08:00
6c647818ca feat: add "Sender number" input for Twilio SMS provider 2023-07-18 22:46:56 +08:00
8bc73d17aa feat: fix bug that themeEditor can not load saved theme data (#2085) 2023-07-17 22:57:55 +08:00
1f37c80177 feat: refactor code to add getStorageProvider() 2023-07-17 15:59:37 +08:00
7924fca403 fix: hidden bug of "like" query (#2082) 2023-07-16 17:11:32 +08:00
bd06996bab Improve CorsFilter for login API 2023-07-15 19:29:48 +08:00
19ab168b12 Fix panic in func (c *ApiController) GetUser() if no user exists in DB 2023-07-14 20:57:59 +08:00
854a74b73e feat: fix the error when user uploads avatar to minio (https) (#2078)
* fix: Error reported when user uploads avatar to minio (https)

* Update provider.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-07-14 15:58:30 +08:00
beefb0b432 fix: fix event-stream streaming output in prod mode (#2076) 2023-07-14 11:59:26 +08:00
d8969e6652 Support EnableSigninSession after SAML login 2023-07-14 11:27:18 +08:00
666ff48837 Use id param in /sync-ldap-users API 2023-07-13 00:14:18 +08:00
0a0c1b4788 Fix "Groups is immutable" bug when updating a user 2023-07-13 00:03:18 +08:00
438c999e11 Add password mask to /get-ldaps and /get-ldap APIs 2023-07-12 23:21:47 +08:00
a193ceb33d Fix bug in TestDeployStaticFiles() 2023-07-12 23:11:02 +08:00
caec1d1bac Only consider x509 certs in /.well-known/jwks API 2023-07-12 22:39:39 +08:00
0d48da24dc feat: fix wrong rowKey for tables (#2070) 2023-07-12 21:12:36 +08:00
de9eeaa1ef fix: init groups modify rule with admin (#2054) 2023-07-11 09:49:49 +08:00
ae6e35ee73 feat: fix bug that the password input disappears in login window (#2051)
Signed-off-by: baihhh <2542274498@qq.com>
2023-07-08 23:46:31 +08:00
a58df645bf fix: fix state after mfa is enabled (#2050) 2023-07-08 22:35:31 +08:00
68417a2d7a fix: /api/upload-resource panics when parsing file_type (#2046) 2023-07-07 16:18:25 +08:00
9511fae9d9 docs: add swagger docs for Resource-API (#2044)
swagger files are all auto generated.
2023-07-07 14:28:10 +08:00
347d3d2b53 feat: fix bugs in MFA (#2033)
* fix: prompt mfa binding

* fix: clean session when leave promptpage

* fix: css

* fix: force enable mfa

* fix: add prompt rule

* fix: refactor directory structure

* fix: prompt notification

* fix: fix some bug and clean code

* fix: rebase

* fix: improve notification

* fix: i18n

* fix: router

* fix: prompt

* fix: remove localStorage
2023-07-07 12:30:07 +08:00
6edfc08b28 Refactor the code 2023-07-07 00:13:05 +08:00
236 changed files with 14829 additions and 6084 deletions

141
ai/ai.go
View File

@ -1,141 +0,0 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ai
import (
"context"
"fmt"
"io"
"net/http"
"strings"
"time"
"github.com/sashabaranov/go-openai"
)
func queryAnswer(authToken string, question string, timeout int) (string, error) {
// fmt.Printf("Question: %s\n", question)
client := getProxyClientFromToken(authToken)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(2+timeout*2)*time.Second)
defer cancel()
resp, err := client.CreateChatCompletion(
ctx,
openai.ChatCompletionRequest{
Model: openai.GPT3Dot5Turbo,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: question,
},
},
},
)
if err != nil {
return "", err
}
res := resp.Choices[0].Message.Content
res = strings.Trim(res, "\n")
// fmt.Printf("Answer: %s\n\n", res)
return res, nil
}
func QueryAnswerSafe(authToken string, question string) string {
var res string
var err error
for i := 0; i < 10; i++ {
res, err = queryAnswer(authToken, question, i)
if err != nil {
if i > 0 {
fmt.Printf("\tFailed (%d): %s\n", i+1, err.Error())
}
} else {
break
}
}
if err != nil {
panic(err)
}
return res
}
func QueryAnswerStream(authToken string, question string, writer io.Writer, builder *strings.Builder) error {
client := getProxyClientFromToken(authToken)
ctx := context.Background()
flusher, ok := writer.(http.Flusher)
if !ok {
return fmt.Errorf("writer does not implement http.Flusher")
}
// https://platform.openai.com/tokenizer
// https://github.com/pkoukk/tiktoken-go#available-encodings
promptTokens, err := getTokenSize(openai.GPT3TextDavinci003, question)
if err != nil {
return err
}
// https://platform.openai.com/docs/models/gpt-3-5
maxTokens := 4097 - promptTokens
respStream, err := client.CreateCompletionStream(
ctx,
openai.CompletionRequest{
Model: openai.GPT3TextDavinci003,
Prompt: question,
MaxTokens: maxTokens,
Stream: true,
},
)
if err != nil {
return err
}
defer respStream.Close()
isLeadingReturn := true
for {
completion, streamErr := respStream.Recv()
if streamErr != nil {
if streamErr == io.EOF {
break
}
return streamErr
}
data := completion.Choices[0].Text
if isLeadingReturn && len(data) != 0 {
if strings.Count(data, "\n") == len(data) {
continue
} else {
isLeadingReturn = false
}
}
fmt.Printf("%s", data)
// Write the streamed data as Server-Sent Events
if _, err = fmt.Fprintf(writer, "data: %s\n\n", data); err != nil {
return err
}
flusher.Flush()
// Append the response to the strings.Builder
builder.WriteString(data)
}
return nil
}

View File

@ -1,42 +0,0 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !skipCi
// +build !skipCi
package ai
import (
"testing"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/proxy"
"github.com/sashabaranov/go-openai"
)
func TestRun(t *testing.T) {
object.InitConfig()
proxy.InitHttpClient()
text, err := queryAnswer("", "hi", 5)
if err != nil {
panic(err)
}
println(text)
}
func TestToken(t *testing.T) {
println(getTokenSize(openai.GPT3TextDavinci003, ""))
}

View File

@ -18,60 +18,21 @@ import (
"strings" "strings"
"github.com/casbin/casbin/v2" "github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
"github.com/casdoor/casdoor/conf" "github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
xormadapter "github.com/casdoor/xorm-adapter/v3"
stringadapter "github.com/qiangmzsx/string-adapter/v2" stringadapter "github.com/qiangmzsx/string-adapter/v2"
) )
var Enforcer *casbin.Enforcer var Enforcer *casbin.Enforcer
func InitAuthz() { func InitApi() {
var err error e, err := object.GetInitializedEnforcer(util.GetId("built-in", "api-enforcer-built-in"))
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
driverName := conf.GetConfigString("driverName")
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
a, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, "casbin_rule", tableNamePrefix, true)
if err != nil {
panic(err)
}
modelText := `
[request_definition]
r = subOwner, subName, method, urlPath, objOwner, objName
[policy_definition]
p = subOwner, subName, method, urlPath, objOwner, objName
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = (r.subOwner == p.subOwner || p.subOwner == "*") && \
(r.subName == p.subName || p.subName == "*" || r.subName != "anonymous" && p.subName == "!anonymous") && \
(r.method == p.method || p.method == "*") && \
(r.urlPath == p.urlPath || p.urlPath == "*") && \
(r.objOwner == p.objOwner || p.objOwner == "*") && \
(r.objName == p.objName || p.objName == "*") || \
(r.subOwner == r.objOwner && r.subName == r.objName)
`
m, err := model.NewModelFromString(modelText)
if err != nil {
panic(err)
}
Enforcer, err = casbin.NewEnforcer(m, a)
if err != nil { if err != nil {
panic(err) panic(err)
} }
Enforcer = e.Enforcer
Enforcer.ClearPolicy() Enforcer.ClearPolicy()
// if len(Enforcer.GetPolicy()) == 0 { // if len(Enforcer.GetPolicy()) == 0 {

View File

@ -290,10 +290,11 @@ func (c *ApiController) Logout() {
c.ResponseOk(user, application.HomepageUrl) c.ResponseOk(user, application.HomepageUrl)
return return
} else { } else {
if redirectUri == "" { // "post_logout_redirect_uri" has been made optional, see: https://github.com/casdoor/casdoor/issues/2151
c.ResponseError(c.T("general:Missing parameter") + ": post_logout_redirect_uri") // if redirectUri == "" {
return // c.ResponseError(c.T("general:Missing parameter") + ": post_logout_redirect_uri")
} // return
// }
if accessToken == "" { if accessToken == "" {
c.ResponseError(c.T("general:Missing parameter") + ": id_token_hint") c.ResponseError(c.T("general:Missing parameter") + ": id_token_hint")
return return
@ -368,9 +369,11 @@ func (c *ApiController) GetAccount() {
return return
} }
user.Permissions = object.GetMaskedPermissions(user.Permissions) if user != nil {
user.Roles = object.GetMaskedRoles(user.Roles) user.Permissions = object.GetMaskedPermissions(user.Permissions)
user.MultiFactorAuths = object.GetAllMfaProps(user, true) user.Roles = object.GetMaskedRoles(user.Roles)
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
}
organization, err := object.GetMaskedOrganization(object.GetOrganizationByUser(user)) organization, err := object.GetMaskedOrganization(object.GetOrganizationByUser(user))
if err != nil { if err != nil {
@ -378,7 +381,8 @@ func (c *ApiController) GetAccount() {
return return
} }
u, err := object.GetMaskedUser(user) isAdminOrSelf := c.IsAdminOrSelf(user)
u, err := object.GetMaskedUser(user, isAdminOrSelf)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return

View File

@ -23,14 +23,14 @@ import (
xormadapter "github.com/casdoor/xorm-adapter/v3" xormadapter "github.com/casdoor/xorm-adapter/v3"
) )
// GetCasbinAdapters // GetAdapters
// @Title GetCasbinAdapters // @Title GetAdapters
// @Tag Adapter API // @Tag Adapter API
// @Description get adapters // @Description get adapters
// @Param owner query string true "The owner of adapters" // @Param owner query string true "The owner of adapters"
// @Success 200 {array} object.Adapter The Response object // @Success 200 {array} object.Adapter The Response object
// @router /get-adapters [get] // @router /get-adapters [get]
func (c *ApiController) GetCasbinAdapters() { func (c *ApiController) GetAdapters() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
limit := c.Input().Get("pageSize") limit := c.Input().Get("pageSize")
page := c.Input().Get("p") page := c.Input().Get("p")
@ -40,7 +40,7 @@ func (c *ApiController) GetCasbinAdapters() {
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
adapters, err := object.GetCasbinAdapters(owner) adapters, err := object.GetAdapters(owner)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -49,14 +49,14 @@ func (c *ApiController) GetCasbinAdapters() {
c.ResponseOk(adapters) c.ResponseOk(adapters)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetCasbinAdapterCount(owner, field, value) count, err := object.GetAdapterCount(owner, field, value)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
paginator := pagination.SetPaginator(c.Ctx, limit, count) paginator := pagination.SetPaginator(c.Ctx, limit, count)
adapters, err := object.GetPaginationCasbinAdapters(owner, paginator.Offset(), limit, field, value, sortField, sortOrder) adapters, err := object.GetPaginationAdapters(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -66,17 +66,17 @@ func (c *ApiController) GetCasbinAdapters() {
} }
} }
// GetCasbinAdapter // GetAdapter
// @Title GetCasbinAdapter // @Title GetAdapter
// @Tag Adapter API // @Tag Adapter API
// @Description get adapter // @Description get adapter
// @Param id query string true "The id ( owner/name ) of the adapter" // @Param id query string true "The id ( owner/name ) of the adapter"
// @Success 200 {object} object.Adapter The Response object // @Success 200 {object} object.Adapter The Response object
// @router /get-adapter [get] // @router /get-adapter [get]
func (c *ApiController) GetCasbinAdapter() { func (c *ApiController) GetAdapter() {
id := c.Input().Get("id") id := c.Input().Get("id")
adapter, err := object.GetCasbinAdapter(id) adapter, err := object.GetAdapter(id)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -85,75 +85,75 @@ func (c *ApiController) GetCasbinAdapter() {
c.ResponseOk(adapter) c.ResponseOk(adapter)
} }
// UpdateCasbinAdapter // UpdateAdapter
// @Title UpdateCasbinAdapter // @Title UpdateAdapter
// @Tag Adapter API // @Tag Adapter API
// @Description update adapter // @Description update adapter
// @Param id query string true "The id ( owner/name ) of the adapter" // @Param id query string true "The id ( owner/name ) of the adapter"
// @Param body body object.Adapter true "The details of the adapter" // @Param body body object.Adapter true "The details of the adapter"
// @Success 200 {object} controllers.Response The Response object // @Success 200 {object} controllers.Response The Response object
// @router /update-adapter [post] // @router /update-adapter [post]
func (c *ApiController) UpdateCasbinAdapter() { func (c *ApiController) UpdateAdapter() {
id := c.Input().Get("id") id := c.Input().Get("id")
var casbinAdapter object.CasbinAdapter var adapter object.Adapter
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter) err := json.Unmarshal(c.Ctx.Input.RequestBody, &adapter)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.Data["json"] = wrapActionResponse(object.UpdateCasbinAdapter(id, &casbinAdapter)) c.Data["json"] = wrapActionResponse(object.UpdateAdapter(id, &adapter))
c.ServeJSON() c.ServeJSON()
} }
// AddCasbinAdapter // AddAdapter
// @Title AddCasbinAdapter // @Title AddAdapter
// @Tag Adapter API // @Tag Adapter API
// @Description add adapter // @Description add adapter
// @Param body body object.Adapter true "The details of the adapter" // @Param body body object.Adapter true "The details of the adapter"
// @Success 200 {object} controllers.Response The Response object // @Success 200 {object} controllers.Response The Response object
// @router /add-adapter [post] // @router /add-adapter [post]
func (c *ApiController) AddCasbinAdapter() { func (c *ApiController) AddAdapter() {
var casbinAdapter object.CasbinAdapter var adapter object.Adapter
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter) err := json.Unmarshal(c.Ctx.Input.RequestBody, &adapter)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.Data["json"] = wrapActionResponse(object.AddCasbinAdapter(&casbinAdapter)) c.Data["json"] = wrapActionResponse(object.AddAdapter(&adapter))
c.ServeJSON() c.ServeJSON()
} }
// DeleteCasbinAdapter // DeleteAdapter
// @Title DeleteCasbinAdapter // @Title DeleteAdapter
// @Tag Adapter API // @Tag Adapter API
// @Description delete adapter // @Description delete adapter
// @Param body body object.Adapter true "The details of the adapter" // @Param body body object.Adapter true "The details of the adapter"
// @Success 200 {object} controllers.Response The Response object // @Success 200 {object} controllers.Response The Response object
// @router /delete-adapter [post] // @router /delete-adapter [post]
func (c *ApiController) DeleteCasbinAdapter() { func (c *ApiController) DeleteAdapter() {
var casbinAdapter object.CasbinAdapter var adapter object.Adapter
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter) err := json.Unmarshal(c.Ctx.Input.RequestBody, &adapter)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.Data["json"] = wrapActionResponse(object.DeleteCasbinAdapter(&casbinAdapter)) c.Data["json"] = wrapActionResponse(object.DeleteAdapter(&adapter))
c.ServeJSON() c.ServeJSON()
} }
func (c *ApiController) SyncPolicies() { func (c *ApiController) GetPolicies() {
id := c.Input().Get("id") id := c.Input().Get("id")
adapter, err := object.GetCasbinAdapter(id) adapter, err := object.GetAdapter(id)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
policies, err := object.SyncPolicies(adapter) policies, err := object.GetPolicies(adapter)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -164,7 +164,7 @@ func (c *ApiController) SyncPolicies() {
func (c *ApiController) UpdatePolicy() { func (c *ApiController) UpdatePolicy() {
id := c.Input().Get("id") id := c.Input().Get("id")
adapter, err := object.GetCasbinAdapter(id) adapter, err := object.GetAdapter(id)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -188,7 +188,7 @@ func (c *ApiController) UpdatePolicy() {
func (c *ApiController) AddPolicy() { func (c *ApiController) AddPolicy() {
id := c.Input().Get("id") id := c.Input().Get("id")
adapter, err := object.GetCasbinAdapter(id) adapter, err := object.GetAdapter(id)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -212,7 +212,7 @@ func (c *ApiController) AddPolicy() {
func (c *ApiController) RemovePolicy() { func (c *ApiController) RemovePolicy() {
id := c.Input().Get("id") id := c.Input().Get("id")
adapter, err := object.GetCasbinAdapter(id) adapter, err := object.GetAdapter(id)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return

View File

@ -48,14 +48,11 @@ func (c *ApiController) GetApplications() {
} else { } else {
applications, err = object.GetOrganizationApplications(owner, organization) applications, err = object.GetOrganizationApplications(owner, organization)
} }
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.ResponseOk(object.GetMaskedApplications(applications, userId))
c.Data["json"] = object.GetMaskedApplications(applications, userId)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetApplicationCount(owner, field, value) count, err := object.GetApplicationCount(owner, field, value)
@ -86,14 +83,14 @@ func (c *ApiController) GetApplications() {
func (c *ApiController) GetApplication() { func (c *ApiController) GetApplication() {
userId := c.GetSessionUsername() userId := c.GetSessionUsername()
id := c.Input().Get("id") id := c.Input().Get("id")
app, err := object.GetApplication(id) app, err := object.GetApplication(id)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.Data["json"] = object.GetMaskedApplication(app, userId) c.ResponseOk(object.GetMaskedApplication(app, userId))
c.ServeJSON()
} }
// GetUserApplication // GetUserApplication
@ -106,25 +103,24 @@ func (c *ApiController) GetApplication() {
func (c *ApiController) GetUserApplication() { func (c *ApiController) GetUserApplication() {
userId := c.GetSessionUsername() userId := c.GetSessionUsername()
id := c.Input().Get("id") id := c.Input().Get("id")
user, err := object.GetUser(id) user, err := object.GetUser(id)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
if user == nil { if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), id)) c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), id))
return return
} }
app, err := object.GetApplicationByUser(user) application, err := object.GetApplicationByUser(user)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.Data["json"] = object.GetMaskedApplication(app, userId) c.ResponseOk(object.GetMaskedApplication(application, userId))
c.ServeJSON()
} }
// GetOrganizationApplications // GetOrganizationApplications
@ -157,8 +153,7 @@ func (c *ApiController) GetOrganizationApplications() {
return return
} }
c.Data["json"] = object.GetMaskedApplications(applications, userId) c.ResponseOk(object.GetMaskedApplications(applications, userId))
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)

View File

@ -78,12 +78,6 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
} }
} }
if form.Password != "" && user.IsMfaEnabled() {
c.setMfaSessionData(&object.MfaSessionData{UserId: userId})
resp = &Response{Status: object.NextMfa, Data: user.GetPreferredMfaProps(true)}
return
}
if form.Type == ResponseTypeLogin { if form.Type == ResponseTypeLogin {
c.SetSessionUsername(userId) c.SetSessionUsername(userId)
util.LogInfo(c.Ctx, "API: [%s] signed in", userId) util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
@ -129,6 +123,11 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
return return
} }
resp = &Response{Status: "ok", Msg: "", Data: res, Data2: map[string]string{"redirectUrl": redirectUrl, "method": method}} resp = &Response{Status: "ok", Msg: "", Data: res, Data2: map[string]string{"redirectUrl": redirectUrl, "method": method}}
if application.EnableSigninSession || application.HasPromptPage() {
// The prompt page needs the user to be signed in
c.SetSessionUsername(userId)
}
} else if form.Type == ResponseTypeCas { } else if form.Type == ResponseTypeCas {
// not oauth but CAS SSO protocol // not oauth but CAS SSO protocol
service := c.Input().Get("service") service := c.Input().Get("service")
@ -141,11 +140,11 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
resp.Data = st resp.Data = st
} }
} }
if application.EnableSigninSession || application.HasPromptPage() { if application.EnableSigninSession || application.HasPromptPage() {
// The prompt page needs the user to be signed in // The prompt page needs the user to be signed in
c.SetSessionUsername(userId) c.SetSessionUsername(userId)
} }
} else { } else {
resp = wrapErrorResponse(fmt.Errorf("unknown response type: %s", form.Type)) resp = wrapErrorResponse(fmt.Errorf("unknown response type: %s", form.Type))
} }
@ -353,17 +352,26 @@ func (c *ApiController) Login() {
return return
} }
resp = c.HandleLoggedIn(application, user, &authForm)
organization, err := object.GetOrganizationByUser(user) organization, err := object.GetOrganizationByUser(user)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
} }
if user != nil && organization.HasRequiredMfa() && !user.IsMfaEnabled() { if object.IsNeedPromptMfa(organization, user) {
resp.Msg = object.RequiredMfa // The prompt page needs the user to be signed in
c.SetSessionUsername(user.GetId())
c.ResponseOk(object.RequiredMfa)
return
} }
if user.IsMfaEnabled() {
c.setMfaUserSession(user.GetId())
c.ResponseOk(object.NextMfa, user.GetPreferredMfaProps(true))
return
}
resp = c.HandleLoggedIn(application, user, &authForm)
record := object.NewRecord(c.Ctx) record := object.NewRecord(c.Ctx)
record.Organization = application.Organization record.Organization = application.Organization
record.User = user.Name record.User = user.Name
@ -414,7 +422,7 @@ func (c *ApiController) Login() {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
} else if provider.Category == "OAuth" { } else if provider.Category == "OAuth" || provider.Category == "Web3" {
// OAuth // OAuth
idpInfo := object.FromProviderToIdpInfo(c.Ctx, provider) idpInfo := object.FromProviderToIdpInfo(c.Ctx, provider)
idProvider := idp.GetIdProvider(idpInfo, authForm.RedirectUri) idProvider := idp.GetIdProvider(idpInfo, authForm.RedirectUri)
@ -457,7 +465,7 @@ func (c *ApiController) Login() {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
} else if provider.Category == "OAuth" { } else if provider.Category == "OAuth" || provider.Category == "Web3" {
user, err = object.GetUserByField(application.Organization, provider.Type, userInfo.Id) user, err = object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
@ -478,7 +486,7 @@ func (c *ApiController) Login() {
record.Organization = application.Organization record.Organization = application.Organization
record.User = user.Name record.User = user.Name
util.SafeGoroutine(func() { object.AddRecord(record) }) util.SafeGoroutine(func() { object.AddRecord(record) })
} else if provider.Category == "OAuth" { } else if provider.Category == "OAuth" || provider.Category == "Web3" {
// Sign up via OAuth // Sign up via OAuth
if application.EnableLinkWithEmail { if application.EnableLinkWithEmail {
if userInfo.Email != "" { if userInfo.Email != "" {
@ -649,13 +657,16 @@ func (c *ApiController) Login() {
resp = &Response{Status: "error", Msg: "Failed to link user account", Data: isLinked} resp = &Response{Status: "error", Msg: "Failed to link user account", Data: isLinked}
} }
} }
} else if c.getMfaSessionData() != nil { } else if c.getMfaUserSession() != "" {
mfaSession := c.getMfaSessionData() user, err := object.GetUser(c.getMfaUserSession())
user, err := object.GetUser(mfaSession.UserId)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
if user == nil {
c.ResponseError("expired user session")
return
}
if authForm.Passcode != "" { if authForm.Passcode != "" {
mfaUtil := object.GetMfaUtil(authForm.MfaType, user.GetPreferredMfaProps(false)) mfaUtil := object.GetMfaUtil(authForm.MfaType, user.GetPreferredMfaProps(false))
@ -669,13 +680,15 @@ func (c *ApiController) Login() {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
} } else if authForm.RecoveryCode != "" {
if authForm.RecoveryCode != "" {
err = object.MfaRecover(user, authForm.RecoveryCode) err = object.MfaRecover(user, authForm.RecoveryCode)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
} else {
c.ResponseError("missing passcode or recovery code")
return
} }
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application)) application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
@ -690,6 +703,7 @@ func (c *ApiController) Login() {
} }
resp = c.HandleLoggedIn(application, user, &authForm) resp = c.HandleLoggedIn(application, user, &authForm)
c.setMfaUserSession("")
record := object.NewRecord(c.Ctx) record := object.NewRecord(c.Ctx)
record.Organization = application.Organization record.Organization = application.Organization

View File

@ -55,6 +55,18 @@ func (c *ApiController) IsAdmin() bool {
return isGlobalAdmin || user.IsAdmin return isGlobalAdmin || user.IsAdmin
} }
func (c *ApiController) IsAdminOrSelf(user2 *object.User) bool {
isGlobalAdmin, user := c.isGlobalAdmin()
if isGlobalAdmin || (user != nil && user.IsAdmin) {
return true
}
if user.Owner == user2.Owner && user.Name == user2.Name {
return true
}
return false
}
func (c *ApiController) isGlobalAdmin() (bool, *object.User) { func (c *ApiController) isGlobalAdmin() (bool, *object.User) {
username := c.GetSessionUsername() username := c.GetSessionUsername()
if strings.HasPrefix(username, "app/") { if strings.HasPrefix(username, "app/") {
@ -178,24 +190,16 @@ func (c *ApiController) SetSessionData(s *SessionData) {
c.SetSession("SessionData", util.StructToJson(s)) c.SetSession("SessionData", util.StructToJson(s))
} }
func (c *ApiController) setMfaSessionData(data *object.MfaSessionData) { func (c *ApiController) setMfaUserSession(userId string) {
if data == nil { c.SetSession(object.MfaSessionUserId, userId)
c.SetSession(object.MfaSessionUserId, nil)
return
}
c.SetSession(object.MfaSessionUserId, data.UserId)
} }
func (c *ApiController) getMfaSessionData() *object.MfaSessionData { func (c *ApiController) getMfaUserSession() string {
userId := c.GetSession(object.MfaSessionUserId) userId := c.Ctx.Input.CruSession.Get(object.MfaSessionUserId)
if userId == nil { if userId == nil {
return nil return ""
} }
return userId.(string)
data := &object.MfaSessionData{
UserId: userId.(string),
}
return data
} }
func (c *ApiController) setExpireForSession() { func (c *ApiController) setExpireForSession() {

262
controllers/casbin_api.go Normal file
View File

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

View File

@ -45,8 +45,7 @@ func (c *ApiController) GetCerts() {
return return
} }
c.Data["json"] = maskedCerts c.ResponseOk(maskedCerts)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetCertCount(owner, field, value) count, err := object.GetCertCount(owner, field, value)
@ -87,8 +86,7 @@ func (c *ApiController) GetGlobleCerts() {
return return
} }
c.Data["json"] = maskedCerts c.ResponseOk(maskedCerts)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetGlobalCertsCount(field, value) count, err := object.GetGlobalCertsCount(field, value)
@ -123,8 +121,7 @@ func (c *ApiController) GetCert() {
return return
} }
c.Data["json"] = object.GetMaskedCert(cert) c.ResponseOk(object.GetMaskedCert(cert))
c.ServeJSON()
} }
// UpdateCert // UpdateCert

View File

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

View File

@ -1,4 +1,4 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved. // Copyright 2023 The Casdoor Authors. All Rights Reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -17,210 +17,129 @@ package controllers
import ( import (
"encoding/json" "encoding/json"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
) )
// Enforce // GetEnforcers
// @Title Enforce // @Title GetEnforcers
// @Tag Enforce API // @Tag Enforcer API
// @Description Call Casbin Enforce API // @Description get enforcers
// @Param body body object.CasbinRequest true "Casbin request" // @Param owner query string true "The owner of enforcers"
// @Param permissionId query string false "permission id" // @Success 200 {array} object.Enforcer
// @Param modelId query string false "model id" // @router /get-enforcers [get]
// @Param resourceId query string false "resource id" func (c *ApiController) GetEnforcers() {
// @Success 200 {object} controllers.Response The Response object owner := c.Input().Get("owner")
// @router /enforce [post] limit := c.Input().Get("pageSize")
func (c *ApiController) Enforce() { page := c.Input().Get("p")
permissionId := c.Input().Get("permissionId") field := c.Input().Get("field")
modelId := c.Input().Get("modelId") value := c.Input().Get("value")
resourceId := c.Input().Get("resourceId") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
var request object.CasbinRequest if limit == "" || page == "" {
err := json.Unmarshal(c.Ctx.Input.RequestBody, &request) enforcers, err := object.GetEnforcers(owner)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(enforcers)
} else {
limit := util.ParseInt(limit)
count, err := object.GetEnforcerCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
enforcers, err := object.GetPaginationEnforcers(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(enforcers, paginator.Nums())
}
}
// GetEnforcer
// @Title GetEnforcer
// @Tag Enforcer API
// @Description get enforcer
// @Param id query string true "The id ( owner/name ) of enforcer"
// @Success 200 {object} object
// @router /get-enforcer [get]
func (c *ApiController) GetEnforcer() {
id := c.Input().Get("id")
enforcer, err := object.GetEnforcer(id)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
if permissionId != "" { c.ResponseOk(enforcer)
permission, err := object.GetPermission(permissionId)
if err != nil {
c.ResponseError(err.Error())
return
}
res := []bool{}
if permission == nil {
res = append(res, false)
} else {
enforceResult, err := object.Enforce(permission, &request)
if err != nil {
c.ResponseError(err.Error())
return
}
res = append(res, enforceResult)
}
c.ResponseOk(res)
return
}
permissions := []*object.Permission{}
if modelId != "" {
owner, modelName := util.GetOwnerAndNameFromId(modelId)
permissions, err = object.GetPermissionsByModel(owner, modelName)
if err != nil {
c.ResponseError(err.Error())
return
}
} else if resourceId != "" {
permissions, err = object.GetPermissionsByResource(resourceId)
if err != nil {
c.ResponseError(err.Error())
return
}
} else {
c.ResponseError(c.T("general:Missing parameter"))
return
}
res := []bool{}
listPermissionIdMap := object.GroupPermissionsByModelAdapter(permissions)
for _, permissionIds := range listPermissionIdMap {
firstPermission, err := object.GetPermission(permissionIds[0])
if err != nil {
c.ResponseError(err.Error())
return
}
enforceResult, err := object.Enforce(firstPermission, &request, permissionIds...)
if err != nil {
c.ResponseError(err.Error())
return
}
res = append(res, enforceResult)
}
c.ResponseOk(res)
} }
// BatchEnforce // UpdateEnforcer
// @Title BatchEnforce // @Title UpdateEnforcer
// @Tag Enforce API // @Tag Enforcer API
// @Description Call Casbin BatchEnforce API // @Description update enforcer
// @Param body body object.CasbinRequest true "array of casbin requests" // @Param id query string true "The id ( owner/name ) of enforcer"
// @Param permissionId query string false "permission id" // @Param enforcer body object true "The enforcer object"
// @Param modelId query string false "model id" // @Success 200 {object} object
// @Success 200 {object} controllers.Response The Response object // @router /update-enforcer [post]
// @router /batch-enforce [post] func (c *ApiController) UpdateEnforcer() {
func (c *ApiController) BatchEnforce() { id := c.Input().Get("id")
permissionId := c.Input().Get("permissionId")
modelId := c.Input().Get("modelId")
var requests []object.CasbinRequest enforcer := object.Enforcer{}
err := json.Unmarshal(c.Ctx.Input.RequestBody, &requests) err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
if permissionId != "" { c.Data["json"] = wrapActionResponse(object.UpdateEnforcer(id, &enforcer))
permission, err := object.GetPermission(permissionId) c.ServeJSON()
if err != nil {
c.ResponseError(err.Error())
return
}
res := [][]bool{}
if permission == nil {
l := len(requests)
resRequest := make([]bool, l)
for i := 0; i < l; i++ {
resRequest[i] = false
}
res = append(res, resRequest)
} else {
enforceResult, err := object.BatchEnforce(permission, &requests)
if err != nil {
c.ResponseError(err.Error())
return
}
res = append(res, enforceResult)
}
c.ResponseOk(res)
return
}
permissions := []*object.Permission{}
if modelId != "" {
owner, modelName := util.GetOwnerAndNameFromId(modelId)
permissions, err = object.GetPermissionsByModel(owner, modelName)
if err != nil {
c.ResponseError(err.Error())
return
}
} else {
c.ResponseError(c.T("general:Missing parameter"))
return
}
res := [][]bool{}
listPermissionIdMap := object.GroupPermissionsByModelAdapter(permissions)
for _, permissionIds := range listPermissionIdMap {
firstPermission, err := object.GetPermission(permissionIds[0])
if err != nil {
c.ResponseError(err.Error())
return
}
enforceResult, err := object.BatchEnforce(firstPermission, &requests, permissionIds...)
if err != nil {
c.ResponseError(err.Error())
return
}
res = append(res, enforceResult)
}
c.ResponseOk(res)
} }
func (c *ApiController) GetAllObjects() { // AddEnforcer
userId := c.GetSessionUsername() // @Title AddEnforcer
if userId == "" { // @Tag Enforcer API
c.ResponseError(c.T("general:Please login first")) // @Description add enforcer
// @Param enforcer body object true "The enforcer object"
// @Success 200 {object} object
// @router /add-enforcer [post]
func (c *ApiController) AddEnforcer() {
enforcer := object.Enforcer{}
err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
if err != nil {
c.ResponseError(err.Error())
return return
} }
c.ResponseOk(object.GetAllObjects(userId)) c.Data["json"] = wrapActionResponse(object.AddEnforcer(&enforcer))
c.ServeJSON()
} }
func (c *ApiController) GetAllActions() { // DeleteEnforcer
userId := c.GetSessionUsername() // @Title DeleteEnforcer
if userId == "" { // @Tag Enforcer API
c.ResponseError(c.T("general:Please login first")) // @Description delete enforcer
// @Param body body object.Enforce true "The enforcer object"
// @Success 200 {object} object
// @router /delete-enforcer [post]
func (c *ApiController) DeleteEnforcer() {
var enforcer object.Enforcer
err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
if err != nil {
c.ResponseError(err.Error())
return return
} }
c.ResponseOk(object.GetAllActions(userId)) c.Data["json"] = wrapActionResponse(object.DeleteEnforcer(&enforcer))
} c.ServeJSON()
func (c *ApiController) GetAllRoles() {
userId := c.GetSessionUsername()
if userId == "" {
c.ResponseError(c.T("general:Please login first"))
return
}
c.ResponseOk(object.GetAllRoles(userId))
} }

View File

@ -82,9 +82,9 @@ func (c *ApiController) GetGroup() {
group, err := object.GetGroup(id) group, err := object.GetGroup(id)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
} else { return
c.ResponseOk(group)
} }
c.ResponseOk(group)
} }
// UpdateGroup // UpdateGroup

View File

@ -38,8 +38,11 @@ type LdapSyncResp struct {
} }
// GetLdapUsers // GetLdapUsers
// @Tag Account API
// @Title GetLdapser // @Title GetLdapser
// @Tag Account API
// @Description get ldap users
// Param id string true "id"
// @Success 200 {object} LdapResp The Response object
// @router /get-ldap-users [get] // @router /get-ldap-users [get]
func (c *ApiController) GetLdapUsers() { func (c *ApiController) GetLdapUsers() {
id := c.Input().Get("id") id := c.Input().Get("id")
@ -94,18 +97,24 @@ func (c *ApiController) GetLdapUsers() {
} }
// GetLdaps // GetLdaps
// @Tag Account API
// @Title GetLdaps // @Title GetLdaps
// @Tag Account API
// @Description get ldaps
// @Param owner query string false "owner"
// @Success 200 {array} object.Ldap The Response object
// @router /get-ldaps [get] // @router /get-ldaps [get]
func (c *ApiController) GetLdaps() { func (c *ApiController) GetLdaps() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
c.ResponseOk(object.GetLdaps(owner)) c.ResponseOk(object.GetMaskedLdaps(object.GetLdaps(owner)))
} }
// GetLdap // GetLdap
// @Tag Account API
// @Title GetLdap // @Title GetLdap
// @Tag Account API
// @Description get ldap
// @Param id query string true "id"
// @Success 200 {object} object.Ldap The Response object
// @router /get-ldap [get] // @router /get-ldap [get]
func (c *ApiController) GetLdap() { func (c *ApiController) GetLdap() {
id := c.Input().Get("id") id := c.Input().Get("id")
@ -116,12 +125,20 @@ func (c *ApiController) GetLdap() {
} }
_, name := util.GetOwnerAndNameFromId(id) _, name := util.GetOwnerAndNameFromId(id)
c.ResponseOk(object.GetLdap(name)) ldap, err := object.GetLdap(name)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(object.GetMaskedLdap(ldap))
} }
// AddLdap // AddLdap
// @Tag Account API
// @Title AddLdap // @Title AddLdap
// @Tag Account API
// @Description add ldap
// @Param body body object.Ldap true "The details of the ldap"
// @Success 200 {object} controllers.Response The Response object
// @router /add-ldap [post] // @router /add-ldap [post]
func (c *ApiController) AddLdap() { func (c *ApiController) AddLdap() {
var ldap object.Ldap var ldap object.Ldap
@ -160,8 +177,11 @@ func (c *ApiController) AddLdap() {
} }
// UpdateLdap // UpdateLdap
// @Tag Account API
// @Title UpdateLdap // @Title UpdateLdap
// @Tag Account API
// @Description update ldap
// @Param body body object.Ldap true "The details of the ldap"
// @Success 200 {object} controllers.Response The Response object
// @router /update-ldap [post] // @router /update-ldap [post]
func (c *ApiController) UpdateLdap() { func (c *ApiController) UpdateLdap() {
var ldap object.Ldap var ldap object.Ldap
@ -198,8 +218,11 @@ func (c *ApiController) UpdateLdap() {
} }
// DeleteLdap // DeleteLdap
// @Tag Account API
// @Title DeleteLdap // @Title DeleteLdap
// @Tag Account API
// @Description delete ldap
// @Param body body object.Ldap true "The details of the ldap"
// @Success 200 {object} controllers.Response The Response object
// @router /delete-ldap [post] // @router /delete-ldap [post]
func (c *ApiController) DeleteLdap() { func (c *ApiController) DeleteLdap() {
var ldap object.Ldap var ldap object.Ldap
@ -222,12 +245,16 @@ func (c *ApiController) DeleteLdap() {
} }
// SyncLdapUsers // SyncLdapUsers
// @Tag Account API
// @Title SyncLdapUsers // @Title SyncLdapUsers
// @Tag Account API
// @Description sync ldap users
// @Param id query string true "id"
// @Success 200 {object} LdapSyncResp The Response object
// @router /sync-ldap-users [post] // @router /sync-ldap-users [post]
func (c *ApiController) SyncLdapUsers() { func (c *ApiController) SyncLdapUsers() {
owner := c.Input().Get("owner") id := c.Input().Get("id")
ldapId := c.Input().Get("ldapId")
owner, ldapId := util.GetOwnerAndNameFromId(id)
var users []object.LdapUser var users []object.LdapUser
err := json.Unmarshal(c.Ctx.Input.RequestBody, &users) err := json.Unmarshal(c.Ctx.Input.RequestBody, &users)
if err != nil { if err != nil {

View File

@ -1,315 +0,0 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package controllers
import (
"encoding/json"
"fmt"
"strings"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/ai"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
// GetMessages
// @Title GetMessages
// @Tag Message API
// @Description get messages
// @Param owner query string true "The owner of messages"
// @Success 200 {array} object.Message The Response object
// @router /get-messages [get]
func (c *ApiController) GetMessages() {
owner := c.Input().Get("owner")
organization := c.Input().Get("organization")
limit := c.Input().Get("pageSize")
page := c.Input().Get("p")
field := c.Input().Get("field")
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
chat := c.Input().Get("chat")
if limit == "" || page == "" {
var messages []*object.Message
var err error
if chat == "" {
messages, err = object.GetMessages(owner)
} else {
messages, err = object.GetChatMessages(chat)
}
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = object.GetMaskedMessages(messages)
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
count, err := object.GetMessageCount(owner, organization, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
paginationMessages, err := object.GetPaginationMessages(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
messages := object.GetMaskedMessages(paginationMessages)
c.ResponseOk(messages, paginator.Nums())
}
}
// GetMessage
// @Title GetMessage
// @Tag Message API
// @Description get message
// @Param id query string true "The id ( owner/name ) of the message"
// @Success 200 {object} object.Message The Response object
// @router /get-message [get]
func (c *ApiController) GetMessage() {
id := c.Input().Get("id")
message, err := object.GetMessage(id)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = object.GetMaskedMessage(message)
c.ServeJSON()
}
func (c *ApiController) ResponseErrorStream(errorText string) {
event := fmt.Sprintf("event: myerror\ndata: %s\n\n", errorText)
_, err := c.Ctx.ResponseWriter.Write([]byte(event))
if err != nil {
c.ResponseError(err.Error())
return
}
}
// GetMessageAnswer
// @Title GetMessageAnswer
// @Tag Message API
// @Description get message answer
// @Param id query string true "The id ( owner/name ) of the message"
// @Success 200 {object} object.Message The Response object
// @router /get-message-answer [get]
func (c *ApiController) GetMessageAnswer() {
id := c.Input().Get("id")
c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
message, err := object.GetMessage(id)
if err != nil {
c.ResponseError(err.Error())
return
}
if message == nil {
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The message: %s is not found"), id))
return
}
if message.Author != "AI" || message.ReplyTo == "" || message.Text != "" {
c.ResponseErrorStream(c.T("chat:The message is invalid"))
return
}
chatId := util.GetId("admin", message.Chat)
chat, err := object.GetChat(chatId)
if err != nil {
c.ResponseError(err.Error())
return
}
if chat == nil || chat.Organization != message.Organization {
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The chat: %s is not found"), chatId))
return
}
if chat.Type != "AI" {
c.ResponseErrorStream(c.T("chat:The chat type must be \"AI\""))
return
}
questionMessage, err := object.GetMessage(message.ReplyTo)
if questionMessage == nil {
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The message: %s is not found"), id))
return
}
providerId := util.GetId(chat.Owner, chat.User2)
provider, err := object.GetProvider(providerId)
if err != nil {
c.ResponseError(err.Error())
return
}
if provider == nil {
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The provider: %s is not found"), providerId))
return
}
if provider.Category != "AI" || provider.ClientSecret == "" {
c.ResponseErrorStream(fmt.Sprintf(c.T("chat:The provider: %s is invalid"), providerId))
return
}
c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream")
c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
authToken := provider.ClientSecret
question := questionMessage.Text
var stringBuilder strings.Builder
fmt.Printf("Question: [%s]\n", questionMessage.Text)
fmt.Printf("Answer: [")
err = ai.QueryAnswerStream(authToken, question, c.Ctx.ResponseWriter, &stringBuilder)
if err != nil {
c.ResponseErrorStream(err.Error())
return
}
fmt.Printf("]\n")
event := fmt.Sprintf("event: end\ndata: %s\n\n", "end")
_, err = c.Ctx.ResponseWriter.Write([]byte(event))
if err != nil {
c.ResponseError(err.Error())
return
}
answer := stringBuilder.String()
message.Text = answer
_, err = object.UpdateMessage(message.GetId(), message)
if err != nil {
c.ResponseError(err.Error())
return
}
}
// UpdateMessage
// @Title UpdateMessage
// @Tag Message API
// @Description update message
// @Param id query string true "The id ( owner/name ) of the message"
// @Param body body object.Message true "The details of the message"
// @Success 200 {object} controllers.Response The Response object
// @router /update-message [post]
func (c *ApiController) UpdateMessage() {
id := c.Input().Get("id")
var message object.Message
err := json.Unmarshal(c.Ctx.Input.RequestBody, &message)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.UpdateMessage(id, &message))
c.ServeJSON()
}
// AddMessage
// @Title AddMessage
// @Tag Message API
// @Description add message
// @Param body body object.Message true "The details of the message"
// @Success 200 {object} controllers.Response The Response object
// @router /add-message [post]
func (c *ApiController) AddMessage() {
var message object.Message
err := json.Unmarshal(c.Ctx.Input.RequestBody, &message)
if err != nil {
c.ResponseError(err.Error())
return
}
var chat *object.Chat
if message.Chat != "" {
chatId := util.GetId("admin", message.Chat)
chat, err = object.GetChat(chatId)
if err != nil {
c.ResponseError(err.Error())
return
}
if chat == nil || chat.Organization != message.Organization {
c.ResponseError(fmt.Sprintf(c.T("chat:The chat: %s is not found"), chatId))
return
}
}
affected, err := object.AddMessage(&message)
if err != nil {
c.ResponseError(err.Error())
return
}
if affected {
if chat != nil && chat.Type == "AI" {
answerMessage := &object.Message{
Owner: message.Owner,
Name: fmt.Sprintf("message_%s", util.GetRandomName()),
CreatedTime: util.GetCurrentTimeEx(message.CreatedTime),
Organization: message.Organization,
Chat: message.Chat,
ReplyTo: message.GetId(),
Author: "AI",
Text: "",
}
_, err = object.AddMessage(answerMessage)
if err != nil {
c.ResponseError(err.Error())
return
}
}
}
c.Data["json"] = wrapActionResponse(affected)
c.ServeJSON()
}
// DeleteMessage
// @Title DeleteMessage
// @Tag Message API
// @Description delete message
// @Param body body object.Message true "The details of the message"
// @Success 200 {object} controllers.Response The Response object
// @router /delete-message [post]
func (c *ApiController) DeleteMessage() {
var message object.Message
err := json.Unmarshal(c.Ctx.Input.RequestBody, &message)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = wrapActionResponse(object.DeleteMessage(&message))
c.ServeJSON()
}

View File

@ -45,8 +45,7 @@ func (c *ApiController) GetModels() {
return return
} }
c.Data["json"] = models c.ResponseOk(models)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetModelCount(owner, field, value) count, err := object.GetModelCount(owner, field, value)
@ -82,8 +81,7 @@ func (c *ApiController) GetModel() {
return return
} }
c.Data["json"] = model c.ResponseOk(model)
c.ServeJSON()
} }
// UpdateModel // UpdateModel

View File

@ -55,8 +55,7 @@ func (c *ApiController) GetOrganizations() {
return return
} }
c.Data["json"] = maskedOrganizations c.ResponseOk(maskedOrganizations)
c.ServeJSON()
} else { } else {
if !isGlobalAdmin { if !isGlobalAdmin {
maskedOrganizations, err := object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner)) maskedOrganizations, err := object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner))
@ -184,6 +183,8 @@ func (c *ApiController) DeleteOrganization() {
func (c *ApiController) GetDefaultApplication() { func (c *ApiController) GetDefaultApplication() {
userId := c.GetSessionUsername() userId := c.GetSessionUsername()
id := c.Input().Get("id") id := c.Input().Get("id")
redirectUri := c.Input().Get("redirectUri")
typ := c.Input().Get("type")
application, err := object.GetDefaultApplication(id) application, err := object.GetDefaultApplication(id)
if err != nil { if err != nil {
@ -191,6 +192,14 @@ func (c *ApiController) GetDefaultApplication() {
return return
} }
if typ == "cas" {
err = object.CheckCasRestrict(application, c.GetAcceptLanguage(), redirectUri)
if err != nil {
c.ResponseError(err.Error())
return
}
}
maskedApplication := object.GetMaskedApplication(application, userId) maskedApplication := object.GetMaskedApplication(application, userId)
c.ResponseOk(maskedApplication) c.ResponseOk(maskedApplication)
} }

View File

@ -31,7 +31,6 @@ import (
// @router /get-payments [get] // @router /get-payments [get]
func (c *ApiController) GetPayments() { func (c *ApiController) GetPayments() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
organization := c.Input().Get("organization")
limit := c.Input().Get("pageSize") limit := c.Input().Get("pageSize")
page := c.Input().Get("p") page := c.Input().Get("p")
field := c.Input().Get("field") field := c.Input().Get("field")
@ -46,18 +45,17 @@ func (c *ApiController) GetPayments() {
return return
} }
c.Data["json"] = payments c.ResponseOk(payments)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetPaymentCount(owner, organization, field, value) count, err := object.GetPaymentCount(owner, field, value)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
paginator := pagination.SetPaginator(c.Ctx, limit, count) paginator := pagination.SetPaginator(c.Ctx, limit, count)
payments, err := object.GetPaginationPayments(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder) payments, err := object.GetPaginationPayments(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -78,10 +76,9 @@ func (c *ApiController) GetPayments() {
// @router /get-user-payments [get] // @router /get-user-payments [get]
func (c *ApiController) GetUserPayments() { func (c *ApiController) GetUserPayments() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
organization := c.Input().Get("organization")
user := c.Input().Get("user") user := c.Input().Get("user")
payments, err := object.GetUserPayments(owner, organization, user) payments, err := object.GetUserPayments(owner, user)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -106,8 +103,7 @@ func (c *ApiController) GetPayment() {
return return
} }
c.Data["json"] = payment c.ResponseOk(payment)
c.ServeJSON()
} }
// UpdatePayment // UpdatePayment
@ -179,24 +175,18 @@ func (c *ApiController) DeletePayment() {
// @router /notify-payment [post] // @router /notify-payment [post]
func (c *ApiController) NotifyPayment() { func (c *ApiController) NotifyPayment() {
owner := c.Ctx.Input.Param(":owner") owner := c.Ctx.Input.Param(":owner")
providerName := c.Ctx.Input.Param(":provider")
productName := c.Ctx.Input.Param(":product")
paymentName := c.Ctx.Input.Param(":payment") paymentName := c.Ctx.Input.Param(":payment")
orderId := c.Ctx.Input.Param("order") orderId := c.Ctx.Input.Param("order")
body := c.Ctx.Input.RequestBody body := c.Ctx.Input.RequestBody
err, errorResponse := object.NotifyPayment(c.Ctx.Request, body, owner, providerName, productName, paymentName, orderId) payment, err := object.NotifyPayment(c.Ctx.Request, body, owner, paymentName, orderId)
_, err2 := c.Ctx.ResponseWriter.Write([]byte(errorResponse))
if err2 != nil {
panic(err2)
}
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.ResponseOk(payment)
} }
// InvoicePayment // InvoicePayment

View File

@ -45,8 +45,7 @@ func (c *ApiController) GetPermissions() {
return return
} }
c.Data["json"] = permissions c.ResponseOk(permissions)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetPermissionCount(owner, field, value) count, err := object.GetPermissionCount(owner, field, value)
@ -85,7 +84,6 @@ func (c *ApiController) GetPermissionsBySubmitter() {
} }
c.ResponseOk(permissions, len(permissions)) c.ResponseOk(permissions, len(permissions))
return
} }
// GetPermissionsByRole // GetPermissionsByRole
@ -104,7 +102,6 @@ func (c *ApiController) GetPermissionsByRole() {
} }
c.ResponseOk(permissions, len(permissions)) c.ResponseOk(permissions, len(permissions))
return
} }
// GetPermission // GetPermission
@ -123,8 +120,7 @@ func (c *ApiController) GetPermission() {
return return
} }
c.Data["json"] = permission c.ResponseOk(permission)
c.ServeJSON()
} }
// UpdatePermission // UpdatePermission

View File

@ -45,8 +45,7 @@ func (c *ApiController) GetPlans() {
return return
} }
c.Data["json"] = plans c.ResponseOk(plans)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetPlanCount(owner, field, value) count, err := object.GetPlanCount(owner, field, value)
@ -95,11 +94,10 @@ func (c *ApiController) GetPlan() {
plan.Options = append(plan.Options, option.DisplayName) plan.Options = append(plan.Options, option.DisplayName)
} }
c.Data["json"] = plan c.ResponseOk(plan)
} else { } else {
c.Data["json"] = plan c.ResponseOk(plan)
} }
c.ServeJSON()
} }
// UpdatePlan // UpdatePlan

View File

@ -45,8 +45,7 @@ func (c *ApiController) GetPricings() {
return return
} }
c.Data["json"] = pricings c.ResponseOk(pricings)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetPricingCount(owner, field, value) count, err := object.GetPricingCount(owner, field, value)
@ -82,8 +81,7 @@ func (c *ApiController) GetPricing() {
return return
} }
c.Data["json"] = pricing c.ResponseOk(pricing)
c.ServeJSON()
} }
// UpdatePricing // UpdatePricing

View File

@ -46,8 +46,7 @@ func (c *ApiController) GetProducts() {
return return
} }
c.Data["json"] = products c.ResponseOk(products)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetProductCount(owner, field, value) count, err := object.GetProductCount(owner, field, value)
@ -89,8 +88,7 @@ func (c *ApiController) GetProduct() {
return return
} }
c.Data["json"] = product c.ResponseOk(product)
c.ServeJSON()
} }
// UpdateProduct // UpdateProduct

View File

@ -51,8 +51,7 @@ func (c *ApiController) GetRecords() {
return return
} }
c.Data["json"] = records c.ResponseOk(records)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
if c.IsGlobalAdmin() && organizationName != "" { if c.IsGlobalAdmin() && organizationName != "" {
@ -99,8 +98,7 @@ func (c *ApiController) GetRecordsByFilter() {
return return
} }
c.Data["json"] = records c.ResponseOk(records)
c.ServeJSON()
} }
// AddRecord // AddRecord

View File

@ -29,9 +29,19 @@ import (
) )
// GetResources // GetResources
// @router /get-resources [get]
// @Tag Resource API // @Tag Resource API
// @Title GetResources // @Title GetResources
// @Description get resources
// @Param owner query string true "Owner"
// @Param user query string true "User"
// @Param pageSize query integer false "Page Size"
// @Param p query integer false "Page Number"
// @Param field query string false "Field"
// @Param value query string false "Value"
// @Param sortField query string false "Sort Field"
// @Param sortOrder query string false "Sort Order"
// @Success 200 {array} object.Resource The Response object
// @router /get-resources [get]
func (c *ApiController) GetResources() { func (c *ApiController) GetResources() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
user := c.Input().Get("user") user := c.Input().Get("user")
@ -42,23 +52,29 @@ func (c *ApiController) GetResources() {
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
userObj, ok := c.RequireSignedInUser() if sortField == "Direct" {
if !ok { provider, err := c.GetProviderFromContext("Storage")
return if err != nil {
} c.ResponseError(err.Error())
if userObj.IsAdmin { return
user = "" }
}
if limit == "" || page == "" { prefix := sortOrder
resources, err := object.GetDirectResources(owner, user, provider, prefix, c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(resources)
} else if limit == "" || page == "" {
resources, err := object.GetResources(owner, user) resources, err := object.GetResources(owner, user)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.Data["json"] = resources c.ResponseOk(resources)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetResourceCount(owner, user, field, value) count, err := object.GetResourceCount(owner, user, field, value)
@ -81,6 +97,9 @@ func (c *ApiController) GetResources() {
// GetResource // GetResource
// @Tag Resource API // @Tag Resource API
// @Title GetResource // @Title GetResource
// @Description get resource
// @Param id query string true "The id ( owner/name ) of resource"
// @Success 200 {object} object.Resource The Response object
// @router /get-resource [get] // @router /get-resource [get]
func (c *ApiController) GetResource() { func (c *ApiController) GetResource() {
id := c.Input().Get("id") id := c.Input().Get("id")
@ -91,13 +110,16 @@ func (c *ApiController) GetResource() {
return return
} }
c.Data["json"] = resource c.ResponseOk(resource)
c.ServeJSON()
} }
// UpdateResource // UpdateResource
// @Tag Resource API // @Tag Resource API
// @Title UpdateResource // @Title UpdateResource
// @Description get resource
// @Param id query string true "The id ( owner/name ) of resource"
// @Param resource body object.Resource true "The resource object"
// @Success 200 {object} controllers.Response Success or error
// @router /update-resource [post] // @router /update-resource [post]
func (c *ApiController) UpdateResource() { func (c *ApiController) UpdateResource() {
id := c.Input().Get("id") id := c.Input().Get("id")
@ -116,6 +138,8 @@ func (c *ApiController) UpdateResource() {
// AddResource // AddResource
// @Tag Resource API // @Tag Resource API
// @Title AddResource // @Title AddResource
// @Param resource body object.Resource true "Resource object"
// @Success 200 {object} controllers.Response Success or error
// @router /add-resource [post] // @router /add-resource [post]
func (c *ApiController) AddResource() { func (c *ApiController) AddResource() {
var resource object.Resource var resource object.Resource
@ -132,6 +156,8 @@ func (c *ApiController) AddResource() {
// DeleteResource // DeleteResource
// @Tag Resource API // @Tag Resource API
// @Title DeleteResource // @Title DeleteResource
// @Param resource body object.Resource true "Resource object"
// @Success 200 {object} controllers.Response Success or error
// @router /delete-resource [post] // @router /delete-resource [post]
func (c *ApiController) DeleteResource() { func (c *ApiController) DeleteResource() {
var resource object.Resource var resource object.Resource
@ -141,11 +167,16 @@ func (c *ApiController) DeleteResource() {
return return
} }
if resource.Provider != "" {
c.Input().Set("provider", resource.Provider)
}
c.Input().Set("fullFilePath", resource.Name)
provider, err := c.GetProviderFromContext("Storage") provider, err := c.GetProviderFromContext("Storage")
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
_, resource.Name = refineFullFilePath(resource.Name)
err = object.DeleteFile(provider, resource.Name, c.GetAcceptLanguage()) err = object.DeleteFile(provider, resource.Name, c.GetAcceptLanguage())
if err != nil { if err != nil {
@ -160,6 +191,16 @@ func (c *ApiController) DeleteResource() {
// UploadResource // UploadResource
// @Tag Resource API // @Tag Resource API
// @Title UploadResource // @Title UploadResource
// @Param owner query string true "Owner"
// @Param user query string true "User"
// @Param application query string true "Application"
// @Param tag query string false "Tag"
// @Param parent query string false "Parent"
// @Param fullFilePath query string true "Full File Path"
// @Param createdTime query string false "Created Time"
// @Param description query string false "Description"
// @Param file formData file true "Resource file"
// @Success 200 {object} object.Resource FileUrl, objectKey
// @router /upload-resource [post] // @router /upload-resource [post]
func (c *ApiController) UploadResource() { func (c *ApiController) UploadResource() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
@ -195,15 +236,16 @@ func (c *ApiController) UploadResource() {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
_, fullFilePath = refineFullFilePath(fullFilePath)
fileType := "unknown" fileType := "unknown"
contentType := header.Header.Get("Content-Type") contentType := header.Header.Get("Content-Type")
fileType, _ = util.GetOwnerAndNameFromId(contentType) fileType, _ = util.GetOwnerAndNameFromIdNoCheck(contentType + "/")
if fileType != "image" && fileType != "video" { if fileType != "image" && fileType != "video" {
ext := filepath.Ext(filename) ext := filepath.Ext(filename)
mimeType := mime.TypeByExtension(ext) mimeType := mime.TypeByExtension(ext)
fileType, _ = util.GetOwnerAndNameFromId(mimeType) fileType, _ = util.GetOwnerAndNameFromIdNoCheck(mimeType + "/")
} }
fullFilePath = object.GetTruncatedPath(provider, fullFilePath, 175) fullFilePath = object.GetTruncatedPath(provider, fullFilePath, 175)

View File

@ -45,8 +45,7 @@ func (c *ApiController) GetRoles() {
return return
} }
c.Data["json"] = roles c.ResponseOk(roles)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetRoleCount(owner, field, value) count, err := object.GetRoleCount(owner, field, value)
@ -82,8 +81,7 @@ func (c *ApiController) GetRole() {
return return
} }
c.Data["json"] = role c.ResponseOk(role)
c.ServeJSON()
} }
// UpdateRole // UpdateRole

View File

@ -140,10 +140,12 @@ func (c *ApiController) SendSms() {
return return
} }
invalidReceivers := getInvalidSmsReceivers(smsForm) if provider.Type != "Custom HTTP SMS" {
if len(invalidReceivers) != 0 { invalidReceivers := getInvalidSmsReceivers(smsForm)
c.ResponseError(fmt.Sprintf(c.T("service:Invalid phone receivers: %s"), strings.Join(invalidReceivers, ", "))) if len(invalidReceivers) != 0 {
return c.ResponseError(fmt.Sprintf(c.T("service:Invalid phone receivers: %s"), strings.Join(invalidReceivers, ", ")))
return
}
} }
err = object.SendSms(provider, smsForm.Content, smsForm.Receivers...) err = object.SendSms(provider, smsForm.Content, smsForm.Receivers...)

View File

@ -45,8 +45,7 @@ func (c *ApiController) GetSessions() {
return return
} }
c.Data["json"] = sessions c.ResponseOk(sessions)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetSessionCount(owner, field, value) count, err := object.GetSessionCount(owner, field, value)
@ -81,8 +80,7 @@ func (c *ApiController) GetSingleSession() {
return return
} }
c.Data["json"] = session c.ResponseOk(session)
c.ServeJSON()
} }
// UpdateSession // UpdateSession
@ -161,7 +159,5 @@ func (c *ApiController) IsSessionDuplicated() {
return return
} }
c.Data["json"] = &Response{Status: "ok", Msg: "", Data: isUserSessionDuplicated} c.ResponseOk(isUserSessionDuplicated)
c.ServeJSON()
} }

View File

@ -45,8 +45,7 @@ func (c *ApiController) GetSubscriptions() {
return return
} }
c.Data["json"] = subscriptions c.ResponseOk(subscriptions)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetSubscriptionCount(owner, field, value) count, err := object.GetSubscriptionCount(owner, field, value)
@ -82,8 +81,7 @@ func (c *ApiController) GetSubscription() {
return return
} }
c.Data["json"] = subscription c.ResponseOk(subscription)
c.ServeJSON()
} }
// UpdateSubscription // UpdateSubscription

View File

@ -46,8 +46,7 @@ func (c *ApiController) GetSyncers() {
return return
} }
c.Data["json"] = organizationSyncers c.ResponseOk(organizationSyncers)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetSyncerCount(owner, organization, field, value) count, err := object.GetSyncerCount(owner, organization, field, value)
@ -83,8 +82,7 @@ func (c *ApiController) GetSyncer() {
return return
} }
c.Data["json"] = syncer c.ResponseOk(syncer)
c.ServeJSON()
} }
// UpdateSyncer // UpdateSyncer

View File

@ -47,8 +47,7 @@ func (c *ApiController) GetTokens() {
return return
} }
c.Data["json"] = token c.ResponseOk(token)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetTokenCount(owner, organization, field, value) count, err := object.GetTokenCount(owner, organization, field, value)
@ -83,8 +82,7 @@ func (c *ApiController) GetToken() {
return return
} }
c.Data["json"] = token c.ResponseOk(token)
c.ServeJSON()
} }
// UpdateToken // UpdateToken

View File

@ -45,8 +45,7 @@ func (c *ApiController) GetGlobalUsers() {
return return
} }
c.Data["json"] = maskedUsers c.ResponseOk(maskedUsers)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetGlobalUserCount(field, value) count, err := object.GetGlobalUserCount(field, value)
@ -91,7 +90,7 @@ func (c *ApiController) GetUsers() {
if limit == "" || page == "" { if limit == "" || page == "" {
if groupName != "" { if groupName != "" {
maskedUsers, err := object.GetMaskedUsers(object.GetGroupUsers(groupName)) maskedUsers, err := object.GetMaskedUsers(object.GetGroupUsers(util.GetId(owner, groupName)))
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -106,8 +105,7 @@ func (c *ApiController) GetUsers() {
return return
} }
c.Data["json"] = maskedUsers c.ResponseOk(maskedUsers)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetUserCount(owner, field, value, groupName) count, err := object.GetUserCount(owner, field, value, groupName)
@ -198,21 +196,24 @@ func (c *ApiController) GetUser() {
return return
} }
user.MultiFactorAuths = object.GetAllMfaProps(user, true) if user != nil {
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
}
err = object.ExtendUserWithRolesAndPermissions(user) err = object.ExtendUserWithRolesAndPermissions(user)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
maskedUser, err := object.GetMaskedUser(user) isAdminOrSelf := c.IsAdminOrSelf(user)
maskedUser, err := object.GetMaskedUser(user, isAdminOrSelf)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.Data["json"] = maskedUser c.ResponseOk(maskedUser)
c.ServeJSON()
} }
// UpdateUser // UpdateUser
@ -509,8 +510,7 @@ func (c *ApiController) GetSortedUsers() {
return return
} }
c.Data["json"] = maskedUsers c.ResponseOk(maskedUsers)
c.ServeJSON()
} }
// GetUserCount // GetUserCount
@ -537,8 +537,7 @@ func (c *ApiController) GetUserCount() {
return return
} }
c.Data["json"] = count c.ResponseOk(count)
c.ServeJSON()
} }
// AddUserkeys // AddUserkeys
@ -568,6 +567,22 @@ func (c *ApiController) RemoveUserFromGroup() {
name := c.Ctx.Request.Form.Get("name") name := c.Ctx.Request.Form.Get("name")
groupName := c.Ctx.Request.Form.Get("groupName") groupName := c.Ctx.Request.Form.Get("groupName")
c.Data["json"] = wrapActionResponse(object.RemoveUserFromGroup(owner, name, groupName)) organization, err := object.GetOrganization(util.GetId("admin", owner))
c.ServeJSON() if err != nil {
return
}
item := object.GetAccountItemByName("Groups", organization)
res, msg := object.CheckAccountItemModifyRule(item, c.IsAdmin(), c.GetAcceptLanguage())
if !res {
c.ResponseError(msg)
return
}
affected, err := object.DeleteGroupForUser(util.GetId(owner, name), groupName)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(affected)
} }

View File

@ -16,6 +16,7 @@ package controllers
import ( import (
"fmt" "fmt"
"strings"
"github.com/casdoor/casdoor/conf" "github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/i18n" "github.com/casdoor/casdoor/i18n"
@ -143,8 +144,30 @@ func (c *ApiController) IsMaskedEnabled() (bool, bool) {
return true, isMaskEnabled return true, isMaskEnabled
} }
func refineFullFilePath(fullFilePath string) (string, string) {
tokens := strings.Split(fullFilePath, "/")
if len(tokens) >= 2 && tokens[0] == "Direct" && tokens[1] != "" {
providerName := tokens[1]
res := strings.Join(tokens[2:], "/")
return providerName, "/" + res
} else {
return "", fullFilePath
}
}
func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, error) { func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, error) {
providerName := c.Input().Get("provider") providerName := c.Input().Get("provider")
if providerName == "" {
field := c.Input().Get("field")
value := c.Input().Get("value")
if field == "provider" && value != "" {
providerName = value
} else {
fullFilePath := c.Input().Get("fullFilePath")
providerName, _ = refineFullFilePath(fullFilePath)
}
}
if providerName != "" { if providerName != "" {
provider, err := object.GetProvider(util.GetId("admin", providerName)) provider, err := object.GetProvider(util.GetId("admin", providerName))
if err != nil { if err != nil {

View File

@ -93,10 +93,9 @@ func (c *ApiController) SendVerificationCode() {
} }
} }
// mfaSessionData != nil, means method is MfaAuthVerification // mfaUserSession != "", means method is MfaAuthVerification
if mfaSessionData := c.getMfaSessionData(); mfaSessionData != nil { if mfaUserSession := c.getMfaUserSession(); mfaUserSession != "" {
user, err = object.GetUser(mfaSessionData.UserId) user, err = object.GetUser(mfaUserSession)
c.setMfaSessionData(nil)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
@ -134,6 +133,8 @@ func (c *ApiController) SendVerificationCode() {
if user != nil && util.GetMaskedEmail(mfaProps.Secret) == vform.Dest { if user != nil && util.GetMaskedEmail(mfaProps.Secret) == vform.Dest {
vform.Dest = mfaProps.Secret vform.Dest = mfaProps.Secret
} }
} else if vform.Method == MfaSetupVerification {
c.SetSession(object.MfaDestSession, vform.Dest)
} }
provider, err := application.GetEmailProvider() provider, err := application.GetEmailProvider()
@ -164,6 +165,11 @@ func (c *ApiController) SendVerificationCode() {
vform.CountryCode = user.GetCountryCode(vform.CountryCode) vform.CountryCode = user.GetCountryCode(vform.CountryCode)
} }
} }
if vform.Method == MfaSetupVerification {
c.SetSession(object.MfaCountryCodeSession, vform.CountryCode)
c.SetSession(object.MfaDestSession, vform.Dest)
}
} else if vform.Method == MfaAuthVerification { } else if vform.Method == MfaAuthVerification {
mfaProps := user.GetPreferredMfaProps(false) mfaProps := user.GetPreferredMfaProps(false)
if user != nil && util.GetMaskedPhone(mfaProps.Secret) == vform.Dest { if user != nil && util.GetMaskedPhone(mfaProps.Secret) == vform.Dest {
@ -187,11 +193,6 @@ func (c *ApiController) SendVerificationCode() {
} }
} }
if vform.Method == MfaSetupVerification {
c.SetSession(object.MfaSmsCountryCodeSession, vform.CountryCode)
c.SetSession(object.MfaSmsDestSession, vform.Dest)
}
if sendResp != nil { if sendResp != nil {
c.ResponseError(sendResp.Error()) c.ResponseError(sendResp.Error())
} else { } else {

View File

@ -26,9 +26,10 @@ import (
// @Title GetWebhooks // @Title GetWebhooks
// @Tag Webhook API // @Tag Webhook API
// @Description get webhooks // @Description get webhooks
// @Param owner query string true "The owner of webhooks" // @Param owner query string built-in/admin true "The owner of webhooks"
// @Success 200 {array} object.Webhook The Response object // @Success 200 {array} object.Webhook The Response object
// @router /get-webhooks [get] // @router /get-webhooks [get]
// @Security test_apiKey
func (c *ApiController) GetWebhooks() { func (c *ApiController) GetWebhooks() {
owner := c.Input().Get("owner") owner := c.Input().Get("owner")
limit := c.Input().Get("pageSize") limit := c.Input().Get("pageSize")
@ -46,8 +47,7 @@ func (c *ApiController) GetWebhooks() {
return return
} }
c.Data["json"] = webhooks c.ResponseOk(webhooks)
c.ServeJSON()
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
count, err := object.GetWebhookCount(owner, organization, field, value) count, err := object.GetWebhookCount(owner, organization, field, value)
@ -72,7 +72,7 @@ func (c *ApiController) GetWebhooks() {
// @Title GetWebhook // @Title GetWebhook
// @Tag Webhook API // @Tag Webhook API
// @Description get webhook // @Description get webhook
// @Param id query string true "The id ( owner/name ) of the webhook" // @Param id query string built-in/admin true "The id ( owner/name ) of the webhook"
// @Success 200 {object} object.Webhook The Response object // @Success 200 {object} object.Webhook The Response object
// @router /get-webhook [get] // @router /get-webhook [get]
func (c *ApiController) GetWebhook() { func (c *ApiController) GetWebhook() {
@ -84,15 +84,14 @@ func (c *ApiController) GetWebhook() {
return return
} }
c.Data["json"] = webhook c.ResponseOk(webhook)
c.ServeJSON()
} }
// UpdateWebhook // UpdateWebhook
// @Title UpdateWebhook // @Title UpdateWebhook
// @Tag Webhook API // @Tag Webhook API
// @Description update webhook // @Description update webhook
// @Param id query string true "The id ( owner/name ) of the webhook" // @Param id query string built-in/admin true "The id ( owner/name ) of the webhook"
// @Param body body object.Webhook true "The details of the webhook" // @Param body body object.Webhook true "The details of the webhook"
// @Success 200 {object} controllers.Response The Response object // @Success 200 {object} controllers.Response The Response object
// @router /update-webhook [post] // @router /update-webhook [post]

View File

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

23
go.mod
View File

@ -12,13 +12,12 @@ require (
github.com/beevik/etree v1.1.0 github.com/beevik/etree v1.1.0
github.com/casbin/casbin v1.9.1 // indirect github.com/casbin/casbin v1.9.1 // indirect
github.com/casbin/casbin/v2 v2.30.1 github.com/casbin/casbin/v2 v2.30.1
github.com/casdoor/go-sms-sender v0.6.1 github.com/casdoor/go-sms-sender v0.12.0
github.com/casdoor/gomail/v2 v2.0.1 github.com/casdoor/gomail/v2 v2.0.1
github.com/casdoor/oss v1.2.0 github.com/casdoor/oss v1.3.0
github.com/casdoor/xorm-adapter/v3 v3.0.4 github.com/casdoor/xorm-adapter/v3 v3.0.4
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
github.com/denisenkom/go-mssqldb v0.9.0 github.com/denisenkom/go-mssqldb v0.9.0
github.com/dlclark/regexp2 v1.9.0 // indirect
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect
github.com/fogleman/gg v1.3.0 github.com/fogleman/gg v1.3.0
github.com/forestmgy/ldapserver v1.1.0 github.com/forestmgy/ldapserver v1.1.0
@ -29,9 +28,6 @@ require (
github.com/go-sql-driver/mysql v1.6.0 github.com/go-sql-driver/mysql v1.6.0
github.com/go-webauthn/webauthn v0.6.0 github.com/go-webauthn/webauthn v0.6.0
github.com/golang-jwt/jwt/v4 v4.5.0 github.com/golang-jwt/jwt/v4 v4.5.0
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.7.3 // indirect github.com/gorilla/mux v1.7.3 // indirect
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
@ -42,21 +38,19 @@ require (
github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/mapstructure v1.5.0
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
github.com/nyaruka/phonenumbers v1.1.5 github.com/nyaruka/phonenumbers v1.1.5
github.com/pkoukk/tiktoken-go v0.1.1
github.com/pquerna/otp v1.4.0 github.com/pquerna/otp v1.4.0
github.com/prometheus/client_golang v1.11.1 github.com/prometheus/client_golang v1.11.1
github.com/prometheus/client_model v0.2.0 github.com/prometheus/client_model v0.3.0
github.com/qiangmzsx/string-adapter/v2 v2.1.0 github.com/qiangmzsx/string-adapter/v2 v2.1.0
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/russellhaering/gosaml2 v0.9.0 github.com/russellhaering/gosaml2 v0.9.0
github.com/russellhaering/goxmldsig v1.2.0 github.com/russellhaering/goxmldsig v1.2.0
github.com/sashabaranov/go-openai v1.12.0
github.com/satori/go.uuid v1.2.0 github.com/satori/go.uuid v1.2.0
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible github.com/shirou/gopsutil v3.21.11+incompatible
github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.8.2 github.com/stretchr/testify v1.8.3
github.com/tealeg/xlsx v1.0.5 github.com/tealeg/xlsx v1.0.5
github.com/thanhpk/randstr v1.0.4 github.com/thanhpk/randstr v1.0.4
github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect
@ -64,12 +58,11 @@ require (
github.com/xorm-io/core v0.7.4 github.com/xorm-io/core v0.7.4
github.com/xorm-io/xorm v1.1.6 github.com/xorm-io/xorm v1.1.6
github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.6.0 golang.org/x/crypto v0.11.0
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect golang.org/x/net v0.13.0
golang.org/x/net v0.7.0 golang.org/x/oauth2 v0.10.0
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/square/go-jose.v2 v2.6.0
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84 modernc.org/sqlite v1.18.2
) )

1429
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -33,6 +33,9 @@ func TestGenerateI18nFrontend(t *testing.T) {
applyToOtherLanguage("frontend", "ru", data) applyToOtherLanguage("frontend", "ru", data)
applyToOtherLanguage("frontend", "vi", data) applyToOtherLanguage("frontend", "vi", data)
applyToOtherLanguage("frontend", "pt", data) applyToOtherLanguage("frontend", "pt", data)
applyToOtherLanguage("frontend", "it", data)
applyToOtherLanguage("frontend", "ms", data)
applyToOtherLanguage("frontend", "tr", data)
} }
func TestGenerateI18nBackend(t *testing.T) { func TestGenerateI18nBackend(t *testing.T) {
@ -49,4 +52,7 @@ func TestGenerateI18nBackend(t *testing.T) {
applyToOtherLanguage("backend", "ru", data) applyToOtherLanguage("backend", "ru", data)
applyToOtherLanguage("backend", "vi", data) applyToOtherLanguage("backend", "vi", data)
applyToOtherLanguage("backend", "pt", data) applyToOtherLanguage("backend", "pt", data)
applyToOtherLanguage("backend", "it", data)
applyToOtherLanguage("backend", "ms", data)
applyToOtherLanguage("backend", "tr", data)
} }

View File

@ -24,14 +24,6 @@
"cas": { "cas": {
"Service %s and %s do not match": "Service %s und %s stimmen nicht überein" "Service %s and %s do not match": "Service %s und %s stimmen nicht überein"
}, },
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": { "check": {
"Affiliation cannot be blank": "Zugehörigkeit darf nicht leer sein", "Affiliation cannot be blank": "Zugehörigkeit darf nicht leer sein",
"DisplayName cannot be blank": "Anzeigename kann nicht leer sein", "DisplayName cannot be blank": "Anzeigename kann nicht leer sein",

View File

@ -24,14 +24,6 @@
"cas": { "cas": {
"Service %s and %s do not match": "Service %s and %s do not match" "Service %s and %s do not match": "Service %s and %s do not match"
}, },
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": { "check": {
"Affiliation cannot be blank": "Affiliation cannot be blank", "Affiliation cannot be blank": "Affiliation cannot be blank",
"DisplayName cannot be blank": "DisplayName cannot be blank", "DisplayName cannot be blank": "DisplayName cannot be blank",

View File

@ -24,14 +24,6 @@
"cas": { "cas": {
"Service %s and %s do not match": "Los servicios %s y %s no coinciden" "Service %s and %s do not match": "Los servicios %s y %s no coinciden"
}, },
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": { "check": {
"Affiliation cannot be blank": "Afiliación no puede estar en blanco", "Affiliation cannot be blank": "Afiliación no puede estar en blanco",
"DisplayName cannot be blank": "El nombre de visualización no puede estar en blanco", "DisplayName cannot be blank": "El nombre de visualización no puede estar en blanco",

View File

@ -24,14 +24,6 @@
"cas": { "cas": {
"Service %s and %s do not match": "Les services %s et %s ne correspondent pas" "Service %s and %s do not match": "Les services %s et %s ne correspondent pas"
}, },
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": { "check": {
"Affiliation cannot be blank": "Affiliation ne peut pas être vide", "Affiliation cannot be blank": "Affiliation ne peut pas être vide",
"DisplayName cannot be blank": "Le nom d'affichage ne peut pas être vide", "DisplayName cannot be blank": "Le nom d'affichage ne peut pas être vide",

View File

@ -24,14 +24,6 @@
"cas": { "cas": {
"Service %s and %s do not match": "Layanan %s dan %s tidak cocok" "Service %s and %s do not match": "Layanan %s dan %s tidak cocok"
}, },
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": { "check": {
"Affiliation cannot be blank": "Keterkaitan tidak boleh kosong", "Affiliation cannot be blank": "Keterkaitan tidak boleh kosong",
"DisplayName cannot be blank": "Nama Pengguna tidak boleh kosong", "DisplayName cannot be blank": "Nama Pengguna tidak boleh kosong",

150
i18n/locales/it/data.json Normal file
View File

@ -0,0 +1,150 @@
{
"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"
},
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": {
"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"
}
}

View File

@ -24,14 +24,6 @@
"cas": { "cas": {
"Service %s and %s do not match": "サービス%sと%sは一致しません" "Service %s and %s do not match": "サービス%sと%sは一致しません"
}, },
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": { "check": {
"Affiliation cannot be blank": "所属は空白にできません", "Affiliation cannot be blank": "所属は空白にできません",
"DisplayName cannot be blank": "表示名は空白にできません", "DisplayName cannot be blank": "表示名は空白にできません",

View File

@ -24,14 +24,6 @@
"cas": { "cas": {
"Service %s and %s do not match": "서비스 %s와 %s는 일치하지 않습니다" "Service %s and %s do not match": "서비스 %s와 %s는 일치하지 않습니다"
}, },
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": { "check": {
"Affiliation cannot be blank": "소속은 비워 둘 수 없습니다", "Affiliation cannot be blank": "소속은 비워 둘 수 없습니다",
"DisplayName cannot be blank": "DisplayName는 비어 있을 수 없습니다", "DisplayName cannot be blank": "DisplayName는 비어 있을 수 없습니다",

150
i18n/locales/ms/data.json Normal file
View File

@ -0,0 +1,150 @@
{
"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"
},
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": {
"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"
}
}

View File

@ -24,14 +24,6 @@
"cas": { "cas": {
"Service %s and %s do not match": "Service %s and %s do not match" "Service %s and %s do not match": "Service %s and %s do not match"
}, },
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": { "check": {
"Affiliation cannot be blank": "Affiliation cannot be blank", "Affiliation cannot be blank": "Affiliation cannot be blank",
"DisplayName cannot be blank": "DisplayName cannot be blank", "DisplayName cannot be blank": "DisplayName cannot be blank",

View File

@ -24,14 +24,6 @@
"cas": { "cas": {
"Service %s and %s do not match": "Сервисы %s и %s не совпадают" "Service %s and %s do not match": "Сервисы %s и %s не совпадают"
}, },
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": { "check": {
"Affiliation cannot be blank": "Принадлежность не может быть пустым значением", "Affiliation cannot be blank": "Принадлежность не может быть пустым значением",
"DisplayName cannot be blank": "Имя отображения не может быть пустым", "DisplayName cannot be blank": "Имя отображения не может быть пустым",

150
i18n/locales/tr/data.json Normal file
View File

@ -0,0 +1,150 @@
{
"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"
},
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": {
"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"
}
}

View File

@ -24,14 +24,6 @@
"cas": { "cas": {
"Service %s and %s do not match": "Dịch sang tiếng Việt: Dịch vụ %s và %s không khớp" "Service %s and %s do not match": "Dịch sang tiếng Việt: Dịch vụ %s và %s không khớp"
}, },
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": { "check": {
"Affiliation cannot be blank": "Tình trạng liên kết không thể để trống", "Affiliation cannot be blank": "Tình trạng liên kết không thể để trống",
"DisplayName cannot be blank": "Tên hiển thị không thể để trống", "DisplayName cannot be blank": "Tên hiển thị không thể để trống",

View File

@ -24,14 +24,6 @@
"cas": { "cas": {
"Service %s and %s do not match": "服务%s与%s不匹配" "Service %s and %s do not match": "服务%s与%s不匹配"
}, },
"chat": {
"The chat type must be \\\"AI\\\"": "The chat type must be \\\"AI\\\"",
"The chat: %s is not found": "The chat: %s is not found",
"The message is invalid": "The message is invalid",
"The message: %s is not found": "The message: %s is not found",
"The provider: %s is invalid": "The provider: %s is invalid",
"The provider: %s is not found": "The provider: %s is not found"
},
"check": { "check": {
"Affiliation cannot be blank": "工作单位不可为空", "Affiliation cannot be blank": "工作单位不可为空",
"DisplayName cannot be blank": "显示名称不可为空", "DisplayName cannot be blank": "显示名称不可为空",

View File

@ -132,7 +132,7 @@ func (idp *GiteeIdProvider) GetToken(code string) (*oauth2.Token, error) {
"type": "User", "type": "User",
"blog": null, "blog": null,
"weibo": null, "weibo": null,
"bio": "个人博客https://gitee.com/xxx/xxx/pages", "bio": "bio",
"public_repos": 2, "public_repos": 2,
"public_gists": 0, "public_gists": 0,
"followers": 0, "followers": 0,

View File

@ -21,15 +21,39 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"strings"
"time"
"github.com/casdoor/casdoor/util"
"golang.org/x/oauth2" "golang.org/x/oauth2"
) )
const GoogleIdTokenKey = "GoogleIdToken"
type GoogleIdProvider struct { type GoogleIdProvider struct {
Client *http.Client Client *http.Client
Config *oauth2.Config Config *oauth2.Config
} }
// https://developers.google.com/identity/sign-in/web/backend-auth#calling-the-tokeninfo-endpoint
type GoogleIdToken struct {
// These six fields are included in all Google ID Tokens.
Iss string `json:"iss"` // The issuer, or signer, of the token. For Google-signed ID tokens, this value is https://accounts.google.com.
Sub string `json:"sub"` // The subject: the ID that represents the principal making the request.
Azp string `json:"azp"` // Optional. Who the token was issued to. Here is the ClientID
Aud string `json:"aud"` // The audience of the token. Here is the ClientID
Iat string `json:"iat"` // Unix epoch time when the token was issued.
Exp string `json:"exp"` // Unix epoch time when the token expires.
// These seven fields are only included when the user has granted the "profile" and "email" OAuth scopes to the application.
Email string `json:"email"`
EmailVerified string `json:"email_verified"`
Name string `json:"name"`
Picture string `json:"picture"`
GivenName string `json:"given_name"`
FamilyName string `json:"family_name"`
Locale string `json:"locale"`
}
func NewGoogleIdProvider(clientId string, clientSecret string, redirectUrl string) *GoogleIdProvider { func NewGoogleIdProvider(clientId string, clientSecret string, redirectUrl string) *GoogleIdProvider {
idp := &GoogleIdProvider{} idp := &GoogleIdProvider{}
@ -61,6 +85,25 @@ func (idp *GoogleIdProvider) getConfig() *oauth2.Config {
} }
func (idp *GoogleIdProvider) GetToken(code string) (*oauth2.Token, error) { func (idp *GoogleIdProvider) GetToken(code string) (*oauth2.Token, error) {
// Obtained the GoogleIdToken through Google OneTap authorization.
if strings.HasPrefix(code, GoogleIdTokenKey) {
code = strings.TrimPrefix(code, GoogleIdTokenKey+"-")
var googleIdToken GoogleIdToken
if err := json.Unmarshal([]byte(code), &googleIdToken); err != nil {
return nil, err
}
expiry := int64(util.ParseInt(googleIdToken.Exp))
token := &oauth2.Token{
AccessToken: fmt.Sprintf("%v-%v", GoogleIdTokenKey, googleIdToken.Sub),
TokenType: "Bearer",
Expiry: time.Unix(expiry, 0),
}
token = token.WithExtra(map[string]interface{}{
GoogleIdTokenKey: googleIdToken,
})
return token, nil
}
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, idp.Client) ctx := context.WithValue(context.Background(), oauth2.HTTPClient, idp.Client)
return idp.Config.Exchange(ctx, code) return idp.Config.Exchange(ctx, code)
} }
@ -88,6 +131,20 @@ type GoogleUserInfo struct {
} }
func (idp *GoogleIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) { func (idp *GoogleIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
if strings.HasPrefix(token.AccessToken, GoogleIdTokenKey) {
googleIdToken, ok := token.Extra(GoogleIdTokenKey).(GoogleIdToken)
if !ok {
return nil, errors.New("invalid googleIdToken")
}
userInfo := UserInfo{
Id: googleIdToken.Sub,
Username: googleIdToken.Email,
DisplayName: googleIdToken.Name,
Email: googleIdToken.Email,
AvatarUrl: googleIdToken.Picture,
}
return &userInfo, nil
}
url := fmt.Sprintf("https://www.googleapis.com/oauth2/v2/userinfo?alt=json&access_token=%s", token.AccessToken) url := fmt.Sprintf("https://www.googleapis.com/oauth2/v2/userinfo?alt=json&access_token=%s", token.AccessToken)
resp, err := idp.Client.Get(url) resp, err := idp.Client.Get(url)
if err != nil { if err != nil {

70
idp/metamask.go Normal file
View File

@ -0,0 +1,70 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package idp
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"time"
"golang.org/x/oauth2"
)
type MetaMaskIdProvider struct {
Client *http.Client
}
func NewMetaMaskIdProvider() *MetaMaskIdProvider {
idp := &MetaMaskIdProvider{}
return idp
}
func (idp *MetaMaskIdProvider) SetHttpClient(client *http.Client) {
idp.Client = client
}
func (idp *MetaMaskIdProvider) GetToken(code string) (*oauth2.Token, error) {
web3AuthToken := Web3AuthToken{}
if err := json.Unmarshal([]byte(code), &web3AuthToken); err != nil {
return nil, err
}
token := &oauth2.Token{
AccessToken: web3AuthToken.Signature,
TokenType: "Bearer",
Expiry: time.Now().AddDate(0, 1, 0),
}
token = token.WithExtra(map[string]interface{}{
Web3AuthTokenKey: web3AuthToken,
})
return token, nil
}
func (idp *MetaMaskIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
// TODO use "github.com/ethereum/go-ethereum" to check address's eth balance or transaction
web3AuthToken, ok := token.Extra(Web3AuthTokenKey).(Web3AuthToken)
if !ok {
return nil, errors.New("invalid web3AuthToken")
}
userInfo := &UserInfo{
Id: web3AuthToken.Address,
Username: web3AuthToken.Address,
DisplayName: web3AuthToken.Address,
AvatarUrl: fmt.Sprintf("metamask:%v", web3AuthToken.Address),
}
return userInfo, nil
}

View File

@ -109,6 +109,10 @@ func GetIdProvider(idpInfo *ProviderInfo, redirectUrl string) IdProvider {
return NewDouyinIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl) return NewDouyinIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
case "Bilibili": case "Bilibili":
return NewBilibiliIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl) return NewBilibiliIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
case "MetaMask":
return NewMetaMaskIdProvider()
case "Web3Onboard":
return NewWeb3OnboardIdProvider()
default: default:
if isGothSupport(idpInfo.Type) { if isGothSupport(idpInfo.Type) {
return NewGothIdProvider(idpInfo.Type, idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl) return NewGothIdProvider(idpInfo.Type, idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl)

103
idp/web3onboard.go Normal file
View File

@ -0,0 +1,103 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package idp
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"strings"
"time"
"golang.org/x/oauth2"
)
const Web3AuthTokenKey = "web3AuthToken"
type Web3AuthToken struct {
Address string `json:"address"`
Nonce string `json:"nonce"`
CreateAt uint64 `json:"createAt"`
TypedData string `json:"typedData"` // typed data use for application
Signature string `json:"signature"` // signature for typed data
WalletType string `json:"walletType"` // e.g."MetaMask", "Coinbase"
}
type Web3OnboardIdProvider struct {
Client *http.Client
}
func NewWeb3OnboardIdProvider() *Web3OnboardIdProvider {
idp := &Web3OnboardIdProvider{}
return idp
}
func (idp *Web3OnboardIdProvider) SetHttpClient(client *http.Client) {
idp.Client = client
}
func (idp *Web3OnboardIdProvider) GetToken(code string) (*oauth2.Token, error) {
web3AuthToken := Web3AuthToken{}
if err := json.Unmarshal([]byte(code), &web3AuthToken); err != nil {
return nil, err
}
token := &oauth2.Token{
AccessToken: fmt.Sprintf("%v:%v", Web3AuthTokenKey, web3AuthToken.Address),
TokenType: "Bearer",
Expiry: time.Now().AddDate(0, 1, 0),
}
token = token.WithExtra(map[string]interface{}{
Web3AuthTokenKey: web3AuthToken,
})
return token, nil
}
func (idp *Web3OnboardIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
web3AuthToken, ok := token.Extra(Web3AuthTokenKey).(Web3AuthToken)
if !ok {
return nil, errors.New("invalid web3AuthToken")
}
fmtAddress := fmt.Sprintf("%v_%v",
strings.ReplaceAll(strings.TrimSpace(web3AuthToken.WalletType), " ", "_"),
web3AuthToken.Address,
)
userInfo := &UserInfo{
Id: fmtAddress,
Username: fmtAddress,
DisplayName: fmtAddress,
AvatarUrl: fmt.Sprintf("metamask:%v", forceEthereumAddress(web3AuthToken.Address)),
}
return userInfo, nil
}
func forceEthereumAddress(address string) string {
// The required address to general MetaMask avatar is a string of length 42 that represents an Ethereum address.
// This function is used to force any address as an Ethereum address
address = strings.TrimSpace(address)
var builder strings.Builder
for _, ch := range address {
builder.WriteRune(ch)
}
for len(builder.String()) < 42 {
builder.WriteString("0")
}
if len(builder.String()) > 42 {
return builder.String()[:42]
}
return builder.String()
}

View File

@ -9,11 +9,11 @@
"passwordType": "plain", "passwordType": "plain",
"passwordSalt": "", "passwordSalt": "",
"passwordOptions": ["AtLeast6"], "passwordOptions": ["AtLeast6"],
"countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"], "countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN", "IT", "MY", "TR"],
"defaultAvatar": "", "defaultAvatar": "",
"defaultApplication": "", "defaultApplication": "",
"tags": [], "tags": [],
"languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi"], "languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "it", "ms", "tr"],
"masterPassword": "", "masterPassword": "",
"initScore": 2000, "initScore": 2000,
"enableSoftDeletion": false, "enableSoftDeletion": false,

View File

@ -34,7 +34,7 @@ func StartLdapServer() {
server.Handle(routes) server.Handle(routes)
err := server.ListenAndServe("0.0.0.0:" + conf.GetConfigString("ldapServerPort")) err := server.ListenAndServe("0.0.0.0:" + conf.GetConfigString("ldapServerPort"))
if err != nil { if err != nil {
return log.Printf("StartLdapServer() failed, ErrMsg = %s", err.Error())
} }
} }

View File

@ -39,7 +39,7 @@ func getCreateDatabaseFlag() bool {
func main() { func main() {
createDatabase := getCreateDatabaseFlag() createDatabase := getCreateDatabaseFlag()
object.InitAdapter() object.InitAdapter(createDatabase)
object.CreateTables(createDatabase) object.CreateTables(createDatabase)
object.DoMigration() object.DoMigration()
@ -48,7 +48,8 @@ func main() {
object.InitDefaultStorageProvider() object.InitDefaultStorageProvider()
object.InitLdapAutoSynchronizer() object.InitLdapAutoSynchronizer()
proxy.InitHttpClient() proxy.InitHttpClient()
authz.InitAuthz() authz.InitApi()
object.InitUserManager()
util.SafeGoroutine(func() { object.RunSyncUsersJob() }) util.SafeGoroutine(func() { object.RunSyncUsersJob() })
@ -62,7 +63,7 @@ func main() {
beego.InsertFilter("*", beego.BeforeRouter, routers.StaticFilter) beego.InsertFilter("*", beego.BeforeRouter, routers.StaticFilter)
beego.InsertFilter("*", beego.BeforeRouter, routers.AutoSigninFilter) beego.InsertFilter("*", beego.BeforeRouter, routers.AutoSigninFilter)
beego.InsertFilter("*", beego.BeforeRouter, routers.CorsFilter) beego.InsertFilter("*", beego.BeforeRouter, routers.CorsFilter)
beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter) beego.InsertFilter("*", beego.BeforeRouter, routers.ApiFilter)
beego.InsertFilter("*", beego.BeforeRouter, routers.PrometheusFilter) beego.InsertFilter("*", beego.BeforeRouter, routers.PrometheusFilter)
beego.InsertFilter("*", beego.BeforeRouter, routers.RecordMessage) beego.InsertFilter("*", beego.BeforeRouter, routers.RecordMessage)

View File

@ -1,4 +1,4 @@
// Copyright 2021 The Casdoor Authors. All Rights Reserved. // Copyright 2022 The Casdoor Authors. All Rights Reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -16,325 +16,328 @@ package object
import ( import (
"fmt" "fmt"
"runtime" "strings"
"github.com/beego/beego" "github.com/casbin/casbin/v2/model"
"github.com/casdoor/casdoor/conf" "github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
xormadapter "github.com/casdoor/xorm-adapter/v3" xormadapter "github.com/casdoor/xorm-adapter/v3"
_ "github.com/denisenkom/go-mssqldb" // db = mssql
_ "github.com/go-sql-driver/mysql" // db = mysql
_ "github.com/lib/pq" // db = postgres
"github.com/xorm-io/core" "github.com/xorm-io/core"
"github.com/xorm-io/xorm" "github.com/xorm-io/xorm"
_ "modernc.org/sqlite" // db = sqlite
) )
var adapter *Adapter type Adapter struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
func InitConfig() { Type string `xorm:"varchar(100)" json:"type"`
err := beego.LoadAppConfig("ini", "../conf/app.conf") DatabaseType string `xorm:"varchar(100)" json:"databaseType"`
Host string `xorm:"varchar(100)" json:"host"`
Port int `json:"port"`
User string `xorm:"varchar(100)" json:"user"`
Password string `xorm:"varchar(100)" json:"password"`
Database string `xorm:"varchar(100)" json:"database"`
Table string `xorm:"varchar(100)" json:"table"`
TableNamePrefix string `xorm:"varchar(100)" json:"tableNamePrefix"`
IsEnabled bool `json:"isEnabled"`
*xormadapter.Adapter `xorm:"-" json:"-"`
}
func GetAdapterCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
return session.Count(&Adapter{})
}
func GetAdapters(owner string) ([]*Adapter, error) {
adapters := []*Adapter{}
err := ormer.Engine.Desc("created_time").Find(&adapters, &Adapter{Owner: owner})
if err != nil { if err != nil {
panic(err) return adapters, err
} }
beego.BConfig.WebConfig.Session.SessionOn = true return adapters, nil
InitAdapter()
CreateTables(true)
DoMigration()
} }
func InitAdapter() { func GetPaginationAdapters(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Adapter, error) {
adapter = NewAdapter(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName")) adapters := []*Adapter{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&adapters)
if err != nil {
return adapters, err
}
tableNamePrefix := conf.GetConfigString("tableNamePrefix") return adapters, nil
tbMapper := core.NewPrefixMapper(core.SnakeMapper{}, tableNamePrefix)
adapter.Engine.SetTableMapper(tbMapper)
} }
func CreateTables(createDatabase bool) { func getAdapter(owner, name string) (*Adapter, error) {
if createDatabase { if owner == "" || name == "" {
err := adapter.CreateDatabase() return nil, nil
}
adapter := Adapter{Owner: owner, Name: name}
existed, err := ormer.Engine.Get(&adapter)
if err != nil {
return nil, err
}
if existed {
return &adapter, nil
} else {
return nil, nil
}
}
func GetAdapter(id string) (*Adapter, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getAdapter(owner, name)
}
func UpdateAdapter(id string, adapter *Adapter) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if adapter, err := getAdapter(owner, name); adapter == nil {
return false, err
}
if name != adapter.Name {
err := adapterChangeTrigger(name, adapter.Name)
if err != nil { if err != nil {
panic(err) return false, err
} }
} }
adapter.createTable() session := ormer.Engine.ID(core.PK{owner, name}).AllCols()
} if adapter.Password == "***" {
session.Omit("password")
// Adapter represents the MySQL adapter for policy storage. }
type Adapter struct { affected, err := session.Update(adapter)
driverName string
dataSourceName string
dbName string
Engine *xorm.Engine
}
// finalizer is the destructor for Adapter.
func finalizer(a *Adapter) {
err := a.Engine.Close()
if err != nil { if err != nil {
panic(err) return false, err
}
return affected != 0, nil
}
func AddAdapter(adapter *Adapter) (bool, error) {
affected, err := ormer.Engine.Insert(adapter)
if err != nil {
return false, err
}
return affected != 0, nil
}
func DeleteAdapter(adapter *Adapter) (bool, error) {
affected, err := ormer.Engine.ID(core.PK{adapter.Owner, adapter.Name}).Delete(&Adapter{})
if err != nil {
return false, err
}
return affected != 0, nil
}
func (adapter *Adapter) GetId() string {
return fmt.Sprintf("%s/%s", adapter.Owner, adapter.Name)
}
func (adapter *Adapter) getTable() string {
if adapter.DatabaseType == "mssql" {
return fmt.Sprintf("[%s]", adapter.Table)
} else {
return adapter.Table
} }
} }
// NewAdapter is the constructor for Adapter. func (adapter *Adapter) initAdapter() error {
func NewAdapter(driverName string, dataSourceName string, dbName string) *Adapter { if adapter.Adapter == nil {
a := &Adapter{} var dataSourceName string
a.driverName = driverName
a.dataSourceName = dataSourceName
a.dbName = dbName
// Open the DB, create it if not existed. if adapter.builtInAdapter() {
a.open() dataSourceName = conf.GetConfigString("dataSourceName")
if adapter.DatabaseType == "mysql" {
dataSourceName = dataSourceName + adapter.Database
}
} else {
switch adapter.DatabaseType {
case "mssql":
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", adapter.User,
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
case "mysql":
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", adapter.User,
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
case "postgres":
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s", adapter.User,
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
case "CockroachDB":
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s serial_normalization=virtual_sequence",
adapter.User, adapter.Password, adapter.Host, adapter.Port, adapter.Database)
case "sqlite3":
dataSourceName = fmt.Sprintf("file:%s", adapter.Host)
default:
return fmt.Errorf("unsupported database type: %s", adapter.DatabaseType)
}
}
// Call the destructor when the object is released. if !isCloudIntranet {
runtime.SetFinalizer(a, finalizer) dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
}
return a var err error
engine, err := xorm.NewEngine(adapter.DatabaseType, dataSourceName)
adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(engine, adapter.getTable(), adapter.TableNamePrefix)
if err != nil {
return err
}
}
return nil
} }
func (a *Adapter) CreateDatabase() error { func adapterChangeTrigger(oldName string, newName string) error {
engine, err := xorm.NewEngine(a.driverName, a.dataSourceName) session := ormer.Engine.NewSession()
defer session.Close()
err := session.Begin()
if err != nil { if err != nil {
return err return err
} }
defer engine.Close()
_, err = engine.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s default charset utf8mb4 COLLATE utf8mb4_general_ci", a.dbName)) enforcer := new(Enforcer)
return err enforcer.Adapter = newName
_, err = session.Where("adapter=?", oldName).Update(enforcer)
if err != nil {
session.Rollback()
return err
}
return session.Commit()
} }
func (a *Adapter) open() { func safeReturn(policy []string, i int) string {
dataSourceName := a.dataSourceName + a.dbName if len(policy) > i {
if a.driverName != "mysql" { return policy[i]
dataSourceName = a.dataSourceName
}
engine, err := xorm.NewEngine(a.driverName, dataSourceName)
if err != nil {
panic(err)
}
a.Engine = engine
}
func (a *Adapter) close() {
_ = a.Engine.Close()
a.Engine = nil
}
func (a *Adapter) createTable() {
showSql := conf.GetConfigBool("showSql")
a.Engine.ShowSQL(showSql)
err := a.Engine.Sync2(new(Organization))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(User))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Group))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Role))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Permission))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Model))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(CasbinAdapter))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Provider))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Application))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Resource))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Token))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(VerificationRecord))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Record))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Webhook))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Syncer))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Cert))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Chat))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Message))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Product))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Payment))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Ldap))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(PermissionRule))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(xormadapter.CasbinRule))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Session))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Subscription))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Plan))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Pricing))
if err != nil {
panic(err)
}
}
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
session := adapter.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 { } else {
session = session.Desc(util.SnakeString(sortField)) return ""
} }
return session
} }
func GetSessionForUser(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session { func matrixToCasbinRules(Ptype string, policies [][]string) []*xormadapter.CasbinRule {
session := adapter.Engine.Prepare() res := []*xormadapter.CasbinRule{}
if offset != -1 && limit != -1 {
session.Limit(limit, offset) for _, policy := range policies {
} line := xormadapter.CasbinRule{
if owner != "" { Ptype: Ptype,
if offset == -1 { V0: safeReturn(policy, 0),
session = session.And("owner=?", owner) V1: safeReturn(policy, 1),
} else { V2: safeReturn(policy, 2),
session = session.And("a.owner=?", owner) V3: safeReturn(policy, 3),
V4: safeReturn(policy, 4),
V5: safeReturn(policy, 5),
} }
} res = append(res, &line)
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") return res
tableName := tableNamePrefix + "user" }
if offset == -1 {
if sortOrder == "ascend" { func GetPolicies(adapter *Adapter) ([]*xormadapter.CasbinRule, error) {
session = session.Asc(util.SnakeString(sortField)) err := adapter.initAdapter()
} else { if err != nil {
session = session.Desc(util.SnakeString(sortField)) return nil, err
} }
} else {
if sortOrder == "ascend" { casbinModel := getModelDef()
session = session.Alias("a"). err = adapter.LoadPolicy(casbinModel)
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name"). if err != nil {
Select("b.*"). return nil, err
Asc("a." + util.SnakeString(sortField)) }
} else {
session = session.Alias("a"). policies := matrixToCasbinRules("p", casbinModel.GetPolicy("p", "p"))
Join("INNER", []string{tableName, "b"}, "a.owner = b.owner and a.name = b.name"). policies = append(policies, matrixToCasbinRules("g", casbinModel.GetPolicy("g", "g"))...)
Select("b.*"). return policies, nil
Desc("a." + util.SnakeString(sortField)) }
}
} func UpdatePolicy(oldPolicy, newPolicy []string, adapter *Adapter) (bool, error) {
err := adapter.initAdapter()
return session 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 {
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
} }

View File

@ -92,7 +92,7 @@ func GetOrganizationApplicationCount(owner, Organization, field, value string) (
func GetApplications(owner string) ([]*Application, error) { func GetApplications(owner string) ([]*Application, error) {
applications := []*Application{} applications := []*Application{}
err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Owner: owner}) err := ormer.Engine.Desc("created_time").Find(&applications, &Application{Owner: owner})
if err != nil { if err != nil {
return applications, err return applications, err
} }
@ -102,7 +102,7 @@ func GetApplications(owner string) ([]*Application, error) {
func GetOrganizationApplications(owner string, organization string) ([]*Application, error) { func GetOrganizationApplications(owner string, organization string) ([]*Application, error) {
applications := []*Application{} applications := []*Application{}
err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Organization: organization}) err := ormer.Engine.Desc("created_time").Find(&applications, &Application{Organization: organization})
if err != nil { if err != nil {
return applications, err return applications, err
} }
@ -182,7 +182,7 @@ func getApplication(owner string, name string) (*Application, error) {
} }
application := Application{Owner: owner, Name: name} application := Application{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&application) existed, err := ormer.Engine.Get(&application)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -206,7 +206,7 @@ func getApplication(owner string, name string) (*Application, error) {
func GetApplicationByOrganizationName(organization string) (*Application, error) { func GetApplicationByOrganizationName(organization string) (*Application, error) {
application := Application{} application := Application{}
existed, err := adapter.Engine.Where("organization=?", organization).Get(&application) existed, err := ormer.Engine.Where("organization=?", organization).Get(&application)
if err != nil { if err != nil {
return nil, nil return nil, nil
} }
@ -253,7 +253,7 @@ func GetApplicationByUserId(userId string) (application *Application, err error)
func GetApplicationByClientId(clientId string) (*Application, error) { func GetApplicationByClientId(clientId string) (*Application, error) {
application := Application{} application := Application{}
existed, err := adapter.Engine.Where("client_id=?", clientId).Get(&application) existed, err := ormer.Engine.Where("client_id=?", clientId).Get(&application)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -281,14 +281,21 @@ func GetApplication(id string) (*Application, error) {
} }
func GetMaskedApplication(application *Application, userId string) *Application { func GetMaskedApplication(application *Application, userId string) *Application {
if isUserIdGlobalAdmin(userId) {
return application
}
if application == nil { if application == nil {
return nil return nil
} }
if userId != "" {
if isUserIdGlobalAdmin(userId) {
return application
}
user, _ := GetUser(userId)
if user != nil && user.IsApplicationAdmin(application) {
return application
}
}
if application.ClientSecret != "" { if application.ClientSecret != "" {
application.ClientSecret = "***" application.ClientSecret = "***"
} }
@ -349,7 +356,7 @@ func UpdateApplication(id string, application *Application) (bool, error) {
providerItem.Provider = nil providerItem.Provider = nil
} }
session := adapter.Engine.ID(core.PK{owner, name}).AllCols() session := ormer.Engine.ID(core.PK{owner, name}).AllCols()
if application.ClientSecret == "***" { if application.ClientSecret == "***" {
session.Omit("client_secret") session.Omit("client_secret")
} }
@ -388,7 +395,7 @@ func AddApplication(application *Application) (bool, error) {
providerItem.Provider = nil providerItem.Provider = nil
} }
affected, err := adapter.Engine.Insert(application) affected, err := ormer.Engine.Insert(application)
if err != nil { if err != nil {
return false, nil return false, nil
} }
@ -401,7 +408,7 @@ func DeleteApplication(application *Application) (bool, error) {
return false, nil return false, nil
} }
affected, err := adapter.Engine.ID(core.PK{application.Owner, application.Name}).Delete(&Application{}) affected, err := ormer.Engine.ID(core.PK{application.Owner, application.Name}).Delete(&Application{})
if err != nil { if err != nil {
return false, err return false, err
} }
@ -477,7 +484,7 @@ func ExtendManagedAccountsWithUser(user *User) (*User, error) {
} }
func applicationChangeTrigger(oldName string, newName string) error { func applicationChangeTrigger(oldName string, newName string) error {
session := adapter.Engine.NewSession() session := ormer.Engine.NewSession()
defer session.Close() defer session.Close()
err := session.Begin() err := session.Begin()
@ -507,7 +514,7 @@ func applicationChangeTrigger(oldName string, newName string) error {
} }
var permissions []*Permission var permissions []*Permission
err = adapter.Engine.Find(&permissions) err = ormer.Engine.Find(&permissions)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,286 +0,0 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package object
import (
"fmt"
"strings"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
"github.com/casdoor/casdoor/util"
xormadapter "github.com/casdoor/xorm-adapter/v3"
"github.com/xorm-io/core"
)
type CasbinAdapter struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
Type string `xorm:"varchar(100)" json:"type"`
Model string `xorm:"varchar(100)" json:"model"`
Host string `xorm:"varchar(100)" json:"host"`
Port int `json:"port"`
User string `xorm:"varchar(100)" json:"user"`
Password string `xorm:"varchar(100)" json:"password"`
DatabaseType string `xorm:"varchar(100)" json:"databaseType"`
Database string `xorm:"varchar(100)" json:"database"`
Table string `xorm:"varchar(100)" json:"table"`
IsEnabled bool `json:"isEnabled"`
Adapter *xormadapter.Adapter `xorm:"-" json:"-"`
}
func GetCasbinAdapterCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
return session.Count(&CasbinAdapter{})
}
func GetCasbinAdapters(owner string) ([]*CasbinAdapter, error) {
adapters := []*CasbinAdapter{}
err := adapter.Engine.Desc("created_time").Find(&adapters, &CasbinAdapter{Owner: owner})
if err != nil {
return adapters, err
}
return adapters, nil
}
func GetPaginationCasbinAdapters(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*CasbinAdapter, error) {
adapters := []*CasbinAdapter{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&adapters)
if err != nil {
return adapters, err
}
return adapters, nil
}
func getCasbinAdapter(owner, name string) (*CasbinAdapter, error) {
if owner == "" || name == "" {
return nil, nil
}
casbinAdapter := CasbinAdapter{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&casbinAdapter)
if err != nil {
return nil, err
}
if existed {
return &casbinAdapter, nil
} else {
return nil, nil
}
}
func GetCasbinAdapter(id string) (*CasbinAdapter, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getCasbinAdapter(owner, name)
}
func UpdateCasbinAdapter(id string, casbinAdapter *CasbinAdapter) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if casbinAdapter, err := getCasbinAdapter(owner, name); casbinAdapter == nil {
return false, err
}
session := adapter.Engine.ID(core.PK{owner, name}).AllCols()
if casbinAdapter.Password == "***" {
session.Omit("password")
}
affected, err := session.Update(casbinAdapter)
if err != nil {
return false, err
}
return affected != 0, nil
}
func AddCasbinAdapter(casbinAdapter *CasbinAdapter) (bool, error) {
affected, err := adapter.Engine.Insert(casbinAdapter)
if err != nil {
return false, err
}
return affected != 0, nil
}
func DeleteCasbinAdapter(casbinAdapter *CasbinAdapter) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{casbinAdapter.Owner, casbinAdapter.Name}).Delete(&CasbinAdapter{})
if err != nil {
return false, err
}
return affected != 0, nil
}
func (casbinAdapter *CasbinAdapter) GetId() string {
return fmt.Sprintf("%s/%s", casbinAdapter.Owner, casbinAdapter.Name)
}
func (casbinAdapter *CasbinAdapter) getTable() string {
if casbinAdapter.DatabaseType == "mssql" {
return fmt.Sprintf("[%s]", casbinAdapter.Table)
} else {
return casbinAdapter.Table
}
}
func initEnforcer(modelObj *Model, casbinAdapter *CasbinAdapter) (*casbin.Enforcer, error) {
// init Adapter
if casbinAdapter.Adapter == nil {
var dataSourceName string
if casbinAdapter.DatabaseType == "mssql" {
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", casbinAdapter.User, casbinAdapter.Password, casbinAdapter.Host, casbinAdapter.Port, casbinAdapter.Database)
} else if casbinAdapter.DatabaseType == "postgres" {
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s", casbinAdapter.User, casbinAdapter.Password, casbinAdapter.Host, casbinAdapter.Port, casbinAdapter.Database)
} else {
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/", casbinAdapter.User, casbinAdapter.Password, casbinAdapter.Host, casbinAdapter.Port)
}
if !isCloudIntranet {
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
}
var err error
casbinAdapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(NewAdapter(casbinAdapter.DatabaseType, dataSourceName, casbinAdapter.Database).Engine, casbinAdapter.getTable(), "")
if err != nil {
return nil, err
}
}
// init Model
m, err := model.NewModelFromString(modelObj.ModelText)
if err != nil {
return nil, err
}
// init Enforcer
enforcer, err := casbin.NewEnforcer(m, casbinAdapter.Adapter)
if err != nil {
return nil, err
}
return enforcer, nil
}
func safeReturn(policy []string, i int) string {
if len(policy) > i {
return policy[i]
} else {
return ""
}
}
func matrixToCasbinRules(Ptype string, policies [][]string) []*xormadapter.CasbinRule {
res := []*xormadapter.CasbinRule{}
for _, policy := range policies {
line := xormadapter.CasbinRule{
Ptype: Ptype,
V0: safeReturn(policy, 0),
V1: safeReturn(policy, 1),
V2: safeReturn(policy, 2),
V3: safeReturn(policy, 3),
V4: safeReturn(policy, 4),
V5: safeReturn(policy, 5),
}
res = append(res, &line)
}
return res
}
func SyncPolicies(casbinAdapter *CasbinAdapter) ([]*xormadapter.CasbinRule, error) {
modelObj, err := getModel(casbinAdapter.Owner, casbinAdapter.Model)
if err != nil {
return nil, err
}
if modelObj == nil {
return nil, fmt.Errorf("The model: %s does not exist", util.GetId(casbinAdapter.Owner, casbinAdapter.Model))
}
enforcer, err := initEnforcer(modelObj, casbinAdapter)
if err != nil {
return nil, err
}
policies := matrixToCasbinRules("p", enforcer.GetPolicy())
if strings.Contains(modelObj.ModelText, "[role_definition]") {
policies = append(policies, matrixToCasbinRules("g", enforcer.GetGroupingPolicy())...)
}
return policies, nil
}
func UpdatePolicy(oldPolicy, newPolicy []string, casbinAdapter *CasbinAdapter) (bool, error) {
modelObj, err := getModel(casbinAdapter.Owner, casbinAdapter.Model)
if err != nil {
return false, err
}
enforcer, err := initEnforcer(modelObj, casbinAdapter)
if err != nil {
return false, err
}
affected, err := enforcer.UpdatePolicy(oldPolicy, newPolicy)
if err != nil {
return affected, err
}
return affected, nil
}
func AddPolicy(policy []string, casbinAdapter *CasbinAdapter) (bool, error) {
modelObj, err := getModel(casbinAdapter.Owner, casbinAdapter.Model)
if err != nil {
return false, err
}
enforcer, err := initEnforcer(modelObj, casbinAdapter)
if err != nil {
return false, err
}
affected, err := enforcer.AddPolicy(policy)
if err != nil {
return affected, err
}
return affected, nil
}
func RemovePolicy(policy []string, casbinAdapter *CasbinAdapter) (bool, error) {
modelObj, err := getModel(casbinAdapter.Owner, casbinAdapter.Model)
if err != nil {
return false, err
}
enforcer, err := initEnforcer(modelObj, casbinAdapter)
if err != nil {
return false, err
}
affected, err := enforcer.RemovePolicy(policy)
if err != nil {
return affected, err
}
return affected, nil
}

View File

@ -65,7 +65,7 @@ func GetCertCount(owner, field, value string) (int64, error) {
func GetCerts(owner string) ([]*Cert, error) { func GetCerts(owner string) ([]*Cert, error) {
certs := []*Cert{} certs := []*Cert{}
err := adapter.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&certs, &Cert{}) err := ormer.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&certs, &Cert{})
if err != nil { if err != nil {
return certs, err return certs, err
} }
@ -91,7 +91,7 @@ func GetGlobalCertsCount(field, value string) (int64, error) {
func GetGlobleCerts() ([]*Cert, error) { func GetGlobleCerts() ([]*Cert, error) {
certs := []*Cert{} certs := []*Cert{}
err := adapter.Engine.Desc("created_time").Find(&certs) err := ormer.Engine.Desc("created_time").Find(&certs)
if err != nil { if err != nil {
return certs, err return certs, err
} }
@ -116,7 +116,7 @@ func getCert(owner string, name string) (*Cert, error) {
} }
cert := Cert{Owner: owner, Name: name} cert := Cert{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&cert) existed, err := ormer.Engine.Get(&cert)
if err != nil { if err != nil {
return &cert, err return &cert, err
} }
@ -134,7 +134,7 @@ func getCertByName(name string) (*Cert, error) {
} }
cert := Cert{Name: name} cert := Cert{Name: name}
existed, err := adapter.Engine.Get(&cert) existed, err := ormer.Engine.Get(&cert)
if err != nil { if err != nil {
return &cert, nil return &cert, nil
} }
@ -162,10 +162,10 @@ func UpdateCert(id string, cert *Cert) (bool, error) {
if name != cert.Name { if name != cert.Name {
err := certChangeTrigger(name, cert.Name) err := certChangeTrigger(name, cert.Name)
if err != nil { if err != nil {
return false, nil return false, err
} }
} }
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(cert) affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(cert)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -180,7 +180,7 @@ func AddCert(cert *Cert) (bool, error) {
cert.PrivateKey = privateKey cert.PrivateKey = privateKey
} }
affected, err := adapter.Engine.Insert(cert) affected, err := ormer.Engine.Insert(cert)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -189,7 +189,7 @@ func AddCert(cert *Cert) (bool, error) {
} }
func DeleteCert(cert *Cert) (bool, error) { func DeleteCert(cert *Cert) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{cert.Owner, cert.Name}).Delete(&Cert{}) affected, err := ormer.Engine.ID(core.PK{cert.Owner, cert.Name}).Delete(&Cert{})
if err != nil { if err != nil {
return false, err return false, err
} }
@ -214,7 +214,7 @@ func GetDefaultCert() (*Cert, error) {
} }
func certChangeTrigger(oldName string, newName string) error { func certChangeTrigger(oldName string, newName string) error {
session := adapter.Engine.NewSession() session := ormer.Engine.NewSession()
defer session.Close() defer session.Close()
err := session.Begin() err := session.Begin()

View File

@ -1,166 +0,0 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package object
import (
"fmt"
"github.com/casdoor/casdoor/util"
"github.com/xorm-io/core"
)
type Chat struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
UpdatedTime string `xorm:"varchar(100)" json:"updatedTime"`
Organization string `xorm:"varchar(100)" json:"organization"`
DisplayName string `xorm:"varchar(100)" json:"displayName"`
Type string `xorm:"varchar(100)" json:"type"`
Category string `xorm:"varchar(100)" json:"category"`
User1 string `xorm:"varchar(100)" json:"user1"`
User2 string `xorm:"varchar(100)" json:"user2"`
Users []string `xorm:"varchar(100)" json:"users"`
MessageCount int `json:"messageCount"`
}
func GetMaskedChat(chat *Chat, err ...error) (*Chat, error) {
if len(err) > 0 && err[0] != nil {
return nil, err[0]
}
if chat == nil {
return nil, nil
}
return chat, nil
}
func GetMaskedChats(chats []*Chat, errs ...error) ([]*Chat, error) {
if len(errs) > 0 && errs[0] != nil {
return nil, errs[0]
}
var err error
for _, chat := range chats {
chat, err = GetMaskedChat(chat)
if err != nil {
return nil, err
}
}
return chats, nil
}
func GetChatCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
return session.Count(&Chat{})
}
func GetChats(owner string) ([]*Chat, error) {
chats := []*Chat{}
err := adapter.Engine.Desc("created_time").Find(&chats, &Chat{Owner: owner})
if err != nil {
return chats, err
}
return chats, nil
}
func GetPaginationChats(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Chat, error) {
chats := []*Chat{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&chats)
if err != nil {
return chats, err
}
return chats, nil
}
func getChat(owner string, name string) (*Chat, error) {
if owner == "" || name == "" {
return nil, nil
}
chat := Chat{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&chat)
if err != nil {
return &chat, err
}
if existed {
return &chat, nil
} else {
return nil, nil
}
}
func GetChat(id string) (*Chat, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getChat(owner, name)
}
func UpdateChat(id string, chat *Chat) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if c, err := getChat(owner, name); err != nil {
return false, err
} else if c == nil {
return false, nil
}
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(chat)
if err != nil {
return false, nil
}
return affected != 0, nil
}
func AddChat(chat *Chat) (bool, error) {
if chat.Type == "AI" && chat.User2 == "" {
provider, err := getDefaultAiProvider()
if err != nil {
return false, err
}
if provider != nil {
chat.User2 = provider.Name
}
}
affected, err := adapter.Engine.Insert(chat)
if err != nil {
return false, nil
}
return affected != 0, nil
}
func DeleteChat(chat *Chat) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{chat.Owner, chat.Name}).Delete(&Chat{})
if err != nil {
return false, err
}
if affected != 0 {
return DeleteChatMessages(chat.Name)
}
return affected != 0, nil
}
func (p *Chat) GetId() string {
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
}

View File

@ -365,7 +365,7 @@ func CheckAccessPermission(userId string, application *Application) (bool, error
if containsAsterisk { if containsAsterisk {
return true, err return true, err
} }
enforcer := getEnforcer(permission) enforcer := getPermissionEnforcer(permission)
if allowed, err = enforcer.Enforce(userId, application.Name, "read"); allowed { if allowed, err = enforcer.Enforce(userId, application.Name, "read"); allowed {
return allowed, err return allowed, err
} }

184
object/enforcer.go Normal file
View File

@ -0,0 +1,184 @@
// 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/casbin/casbin/v2"
"github.com/casdoor/casdoor/util"
"github.com/xorm-io/core"
)
type Enforcer struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
UpdatedTime string `xorm:"varchar(100) updated" json:"updatedTime"`
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"`
*casbin.Enforcer
}
func GetEnforcerCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
return session.Count(&Enforcer{})
}
func GetEnforcers(owner string) ([]*Enforcer, error) {
enforcers := []*Enforcer{}
err := ormer.Engine.Desc("created_time").Find(&enforcers, &Enforcer{Owner: owner})
if err != nil {
return enforcers, err
}
return enforcers, nil
}
func GetPaginationEnforcers(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Enforcer, error) {
enforcers := []*Enforcer{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&enforcers)
if err != nil {
return enforcers, err
}
return enforcers, nil
}
func getEnforcer(owner string, name string) (*Enforcer, error) {
if owner == "" || name == "" {
return nil, nil
}
enforcer := Enforcer{Owner: owner, Name: name}
existed, err := ormer.Engine.Get(&enforcer)
if err != nil {
return &enforcer, err
}
if existed {
return &enforcer, nil
} else {
return nil, nil
}
}
func GetEnforcer(id string) (*Enforcer, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getEnforcer(owner, name)
}
func UpdateEnforcer(id string, enforcer *Enforcer) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if oldEnforcer, err := getEnforcer(owner, name); err != nil {
return false, err
} else if oldEnforcer == nil {
return false, nil
}
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(enforcer)
if err != nil {
return false, err
}
return affected != 0, nil
}
func AddEnforcer(enforcer *Enforcer) (bool, error) {
affected, err := ormer.Engine.Insert(enforcer)
if err != nil {
return false, err
}
return affected != 0, nil
}
func DeleteEnforcer(enforcer *Enforcer) (bool, error) {
affected, err := ormer.Engine.ID(core.PK{enforcer.Owner, enforcer.Name}).Delete(&Enforcer{})
if err != nil {
return false, err
}
return affected != 0, nil
}
func (p *Enforcer) GetId() string {
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
}
func (enforcer *Enforcer) InitEnforcer() error {
if enforcer.Enforcer != nil {
return nil
}
if enforcer.Model == "" {
return fmt.Errorf("the model for enforcer: %s should not be empty", enforcer.GetId())
}
if enforcer.Adapter == "" {
return fmt.Errorf("the adapter for enforcer: %s should not be empty", enforcer.GetId())
}
m, err := GetModel(enforcer.Model)
if err != nil {
return err
} else if m == nil {
return fmt.Errorf("the model: %s for enforcer: %s is not found", enforcer.Model, enforcer.GetId())
}
a, err := GetAdapter(enforcer.Adapter)
if err != nil {
return err
} else if a == nil {
return fmt.Errorf("the adapter: %s for enforcer: %s is not found", enforcer.Adapter, enforcer.GetId())
}
err = m.initModel()
if err != nil {
return err
}
err = a.initAdapter()
if err != nil {
return err
}
casbinEnforcer, err := casbin.NewEnforcer(m.Model, a.Adapter)
if err != nil {
return err
}
enforcer.Enforcer = casbinEnforcer
return nil
}
func GetInitializedEnforcer(enforcerId string) (*Enforcer, error) {
enforcer, err := GetEnforcer(enforcerId)
if err != nil {
return nil, err
} else if enforcer == nil {
return nil, fmt.Errorf("the enforcer: %s is not found", enforcerId)
}
err = enforcer.InitEnforcer()
if err != nil {
return nil, err
}
return enforcer, nil
}

View File

@ -58,7 +58,7 @@ func GetGroupCount(owner, field, value string) (int64, error) {
func GetGroups(owner string) ([]*Group, error) { func GetGroups(owner string) ([]*Group, error) {
groups := []*Group{} groups := []*Group{}
err := adapter.Engine.Desc("created_time").Find(&groups, &Group{Owner: owner}) err := ormer.Engine.Desc("created_time").Find(&groups, &Group{Owner: owner})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -83,7 +83,7 @@ func getGroup(owner string, name string) (*Group, error) {
} }
group := Group{Owner: owner, Name: name} group := Group{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&group) existed, err := ormer.Engine.Get(&group)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -107,6 +107,11 @@ func UpdateGroup(id string, group *Group) (bool, error) {
return false, err return false, err
} }
err = checkGroupName(group.Name)
if err != nil {
return false, err
}
if name != group.Name { if name != group.Name {
err := GroupChangeTrigger(name, group.Name) err := GroupChangeTrigger(name, group.Name)
if err != nil { if err != nil {
@ -114,7 +119,7 @@ func UpdateGroup(id string, group *Group) (bool, error) {
} }
} }
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(group) affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(group)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -123,7 +128,12 @@ func UpdateGroup(id string, group *Group) (bool, error) {
} }
func AddGroup(group *Group) (bool, error) { func AddGroup(group *Group) (bool, error) {
affected, err := adapter.Engine.Insert(group) err := checkGroupName(group.Name)
if err != nil {
return false, err
}
affected, err := ormer.Engine.Insert(group)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -135,7 +145,7 @@ func AddGroups(groups []*Group) (bool, error) {
if len(groups) == 0 { if len(groups) == 0 {
return false, nil return false, nil
} }
affected, err := adapter.Engine.Insert(groups) affected, err := ormer.Engine.Insert(groups)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -143,24 +153,24 @@ func AddGroups(groups []*Group) (bool, error) {
} }
func DeleteGroup(group *Group) (bool, error) { func DeleteGroup(group *Group) (bool, error) {
_, err := adapter.Engine.Get(group) _, err := ormer.Engine.Get(group)
if err != nil { if err != nil {
return false, err return false, err
} }
if count, err := adapter.Engine.Where("parent_id = ?", group.Name).Count(&Group{}); err != nil { if count, err := ormer.Engine.Where("parent_id = ?", group.Name).Count(&Group{}); err != nil {
return false, err return false, err
} else if count > 0 { } else if count > 0 {
return false, errors.New("group has children group") return false, errors.New("group has children group")
} }
if count, err := GetGroupUserCount(group.Name, "", ""); err != nil { if count, err := GetGroupUserCount(group.GetId(), "", ""); err != nil {
return false, err return false, err
} else if count > 0 { } else if count > 0 {
return false, errors.New("group has users") return false, errors.New("group has users")
} }
affected, err := adapter.Engine.ID(core.PK{group.Owner, group.Name}).Delete(&Group{}) affected, err := ormer.Engine.ID(core.PK{group.Owner, group.Name}).Delete(&Group{})
if err != nil { if err != nil {
return false, err return false, err
} }
@ -168,6 +178,17 @@ func DeleteGroup(group *Group) (bool, error) {
return affected != 0, nil return affected != 0, nil
} }
func checkGroupName(name string) error {
exist, err := ormer.Engine.Exist(&Organization{Owner: "admin", Name: name})
if err != nil {
return err
}
if exist {
return errors.New("group name can't be same as the organization name")
}
return nil
}
func (group *Group) GetId() string { func (group *Group) GetId() string {
return fmt.Sprintf("%s/%s", group.Owner, group.Name) return fmt.Sprintf("%s/%s", group.Owner, group.Name)
} }
@ -193,39 +214,33 @@ func ConvertToTreeData(groups []*Group, parentId string) []*Group {
return treeData return treeData
} }
func RemoveUserFromGroup(owner, name, groupName string) (bool, error) { func GetGroupUserCount(groupId string, field, value string) (int64, error) {
user, err := getUser(owner, name) owner, _ := util.GetOwnerAndNameFromId(groupId)
names, err := userEnforcer.GetUserNamesByGroupName(groupId)
if err != nil { if err != nil {
return false, err return 0, err
}
if user == nil {
return false, errors.New("user not exist")
} }
user.Groups = util.DeleteVal(user.Groups, groupName)
affected, err := updateUser(user.GetId(), user, []string{"groups"})
if err != nil {
return false, err
}
return affected != 0, err
}
func GetGroupUserCount(groupName string, field, value string) (int64, error) {
if field == "" && value == "" { if field == "" && value == "" {
return adapter.Engine.Where(builder.Like{"`groups`", groupName}). return int64(len(names)), nil
Count(&User{})
} else { } else {
return adapter.Engine.Table("user"). return ormer.Engine.Table("user").
Where(builder.Like{"`groups`", groupName}). Where("owner = ?", owner).In("name", names).
And(fmt.Sprintf("user.%s LIKE ?", util.CamelToSnakeCase(field)), "%"+value+"%"). And(fmt.Sprintf("user.%s LIKE ?", util.CamelToSnakeCase(field)), "%"+value+"%").
Count() Count()
} }
} }
func GetPaginationGroupUsers(groupName string, offset, limit int, field, value, sortField, sortOrder string) ([]*User, error) { func GetPaginationGroupUsers(groupId string, offset, limit int, field, value, sortField, sortOrder string) ([]*User, error) {
users := []*User{} users := []*User{}
session := adapter.Engine.Table("user"). owner, _ := util.GetOwnerAndNameFromId(groupId)
Where(builder.Like{"`groups`", groupName}) names, err := userEnforcer.GetUserNamesByGroupName(groupId)
if err != nil {
return nil, err
}
session := ormer.Engine.Table("user").
Where("owner = ?", owner).In("name", names)
if offset != -1 && limit != -1 { if offset != -1 && limit != -1 {
session.Limit(limit, offset) session.Limit(limit, offset)
@ -244,7 +259,7 @@ func GetPaginationGroupUsers(groupName string, offset, limit int, field, value,
session = session.Desc(fmt.Sprintf("user.%s", util.SnakeString(sortField))) session = session.Desc(fmt.Sprintf("user.%s", util.SnakeString(sortField)))
} }
err := session.Find(&users) err = session.Find(&users)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -252,20 +267,20 @@ func GetPaginationGroupUsers(groupName string, offset, limit int, field, value,
return users, nil return users, nil
} }
func GetGroupUsers(groupName string) ([]*User, error) { func GetGroupUsers(groupId string) ([]*User, error) {
users := []*User{} users := []*User{}
err := adapter.Engine.Table("user"). owner, _ := util.GetOwnerAndNameFromId(groupId)
Where(builder.Like{"`groups`", groupName}). names, err := userEnforcer.GetUserNamesByGroupName(groupId)
Find(&users)
err = ormer.Engine.Where("owner = ?", owner).In("name", names).Find(&users)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return users, nil return users, nil
} }
func GroupChangeTrigger(oldName, newName string) error { func GroupChangeTrigger(oldName, newName string) error {
session := adapter.Engine.NewSession() session := ormer.Engine.NewSession()
defer session.Close() defer session.Close()
err := session.Begin() err := session.Begin()
if err != nil { if err != nil {

View File

@ -27,7 +27,6 @@ import (
func InitDb() { func InitDb() {
existed := initBuiltInOrganization() existed := initBuiltInOrganization()
if !existed { if !existed {
initBuiltInModel()
initBuiltInPermission() initBuiltInPermission()
initBuiltInProvider() initBuiltInProvider()
initBuiltInUser() initBuiltInUser()
@ -36,6 +35,15 @@ func InitDb() {
initBuiltInLdap() initBuiltInLdap()
} }
existed = initBuiltInApiModel()
if !existed {
initBuiltInApiAdapter()
initBuiltInApiEnforcer()
initBuiltInUserModel()
initBuiltInUserAdapter()
initBuiltInUserEnforcer()
}
initWebAuthn() initWebAuthn()
} }
@ -61,7 +69,7 @@ func getBuiltInAccountItems() []*AccountItem {
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"}, {Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"}, {Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"}, {Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
{Name: "Groups", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"}, {Name: "Groups", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"}, {Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"}, {Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"}, {Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
@ -93,7 +101,7 @@ func initBuiltInOrganization() bool {
Favicon: fmt.Sprintf("%s/img/casbin/favicon.ico", conf.GetConfigString("staticBaseUrl")), Favicon: fmt.Sprintf("%s/img/casbin/favicon.ico", conf.GetConfigString("staticBaseUrl")),
PasswordType: "plain", PasswordType: "plain",
PasswordOptions: []string{"AtLeast6"}, PasswordOptions: []string{"AtLeast6"},
CountryCodes: []string{"US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"}, CountryCodes: []string{"US", "ES", "FR", "DE", "GB", "CN", "JP", "KR", "VN", "ID", "SG", "IN"},
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")), DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
Tags: []string{}, Tags: []string{},
Languages: []string{"en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "pt"}, Languages: []string{"en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "pt"},
@ -130,7 +138,7 @@ func initBuiltInUser() {
Avatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")), Avatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
Email: "admin@example.com", Email: "admin@example.com",
Phone: "12345678910", Phone: "12345678910",
CountryCode: "CN", CountryCode: "US",
Address: []string{}, Address: []string{},
Affiliation: "Example Inc.", Affiliation: "Example Inc.",
Tag: "staff", Tag: "staff",
@ -295,8 +303,8 @@ func initWebAuthn() {
gob.Register(webauthn.SessionData{}) gob.Register(webauthn.SessionData{})
} }
func initBuiltInModel() { func initBuiltInUserModel() {
model, err := GetModel("built-in/model-built-in") model, err := GetModel("built-in/user-model-built-in")
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -307,7 +315,7 @@ func initBuiltInModel() {
model = &Model{ model = &Model{
Owner: "built-in", Owner: "built-in",
Name: "model-built-in", Name: "user-model-built-in",
CreatedTime: util.GetCurrentTime(), CreatedTime: util.GetCurrentTime(),
DisplayName: "Built-in Model", DisplayName: "Built-in Model",
IsEnabled: true, IsEnabled: true,
@ -317,11 +325,14 @@ r = sub, obj, act
[policy_definition] [policy_definition]
p = sub, obj, act p = sub, obj, act
[role_definition]
g = _, _
[policy_effect] [policy_effect]
e = some(where (p.eft == allow)) e = some(where (p.eft == allow))
[matchers] [matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`, m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`,
} }
_, err = AddModel(model) _, err = AddModel(model)
if err != nil { if err != nil {
@ -329,6 +340,52 @@ m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`,
} }
} }
func initBuiltInApiModel() bool {
model, err := GetModel("built-in/api-model-built-in")
if err != nil {
panic(err)
}
if model != nil {
return true
}
modelText := `[request_definition]
r = subOwner, subName, method, urlPath, objOwner, objName
[policy_definition]
p = subOwner, subName, method, urlPath, objOwner, objName
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = (r.subOwner == p.subOwner || p.subOwner == "*") && \
(r.subName == p.subName || p.subName == "*" || r.subName != "anonymous" && p.subName == "!anonymous") && \
(r.method == p.method || p.method == "*") && \
(r.urlPath == p.urlPath || p.urlPath == "*") && \
(r.objOwner == p.objOwner || p.objOwner == "*") && \
(r.objName == p.objName || p.objName == "*") || \
(r.subOwner == r.objOwner && r.subName == r.objName)`
model = &Model{
Owner: "built-in",
Name: "api-model-built-in",
CreatedTime: util.GetCurrentTime(),
DisplayName: "API Model",
IsEnabled: true,
ModelText: modelText,
}
_, err = AddModel(model)
if err != nil {
panic(err)
}
return false
}
func initBuiltInPermission() { func initBuiltInPermission() {
permission, err := GetPermission("built-in/permission-built-in") permission, err := GetPermission("built-in/permission-built-in")
if err != nil { if err != nil {
@ -358,3 +415,109 @@ func initBuiltInPermission() {
panic(err) panic(err)
} }
} }
func initBuiltInUserAdapter() {
adapter, err := GetAdapter("built-in/user-adapter-built-in")
if err != nil {
panic(err)
}
if adapter != nil {
return
}
adapter = &Adapter{
Owner: "built-in",
Name: "user-adapter-built-in",
CreatedTime: util.GetCurrentTime(),
Type: "Database",
DatabaseType: conf.GetConfigString("driverName"),
TableNamePrefix: conf.GetConfigString("tableNamePrefix"),
Database: conf.GetConfigString("dbName"),
Table: "casbin_user_rule",
IsEnabled: true,
}
_, err = AddAdapter(adapter)
if err != nil {
panic(err)
}
}
func initBuiltInApiAdapter() {
adapter, err := GetAdapter("built-in/api-adapter-built-in")
if err != nil {
panic(err)
}
if adapter != nil {
return
}
adapter = &Adapter{
Owner: "built-in",
Name: "api-adapter-built-in",
CreatedTime: util.GetCurrentTime(),
Type: "Database",
DatabaseType: conf.GetConfigString("driverName"),
TableNamePrefix: conf.GetConfigString("tableNamePrefix"),
Database: conf.GetConfigString("dbName"),
Table: "casbin_api_rule",
IsEnabled: true,
}
_, err = AddAdapter(adapter)
if err != nil {
panic(err)
}
}
func initBuiltInUserEnforcer() {
enforcer, err := GetEnforcer("built-in/user-enforcer-built-in")
if err != nil {
panic(err)
}
if enforcer != nil {
return
}
enforcer = &Enforcer{
Owner: "built-in",
Name: "user-enforcer-built-in",
CreatedTime: util.GetCurrentTime(),
DisplayName: "User Enforcer",
Model: "built-in/user-model-built-in",
Adapter: "built-in/user-adapter-built-in",
IsEnabled: true,
}
_, err = AddEnforcer(enforcer)
if err != nil {
panic(err)
}
}
func initBuiltInApiEnforcer() {
enforcer, err := GetEnforcer("built-in/api-enforcer-built-in")
if err != nil {
panic(err)
}
if enforcer != nil {
return
}
enforcer = &Enforcer{
Owner: "built-in",
Name: "api-enforcer-built-in",
CreatedTime: util.GetCurrentTime(),
DisplayName: "API Enforcer",
Model: "built-in/api-model-built-in",
Adapter: "built-in/api-adapter-built-in",
IsEnabled: true,
}
_, err = AddEnforcer(enforcer)
if err != nil {
panic(err)
}
}

View File

@ -46,7 +46,7 @@ func AddLdap(ldap *Ldap) (bool, error) {
ldap.CreatedTime = util.GetCurrentTime() ldap.CreatedTime = util.GetCurrentTime()
} }
affected, err := adapter.Engine.Insert(ldap) affected, err := ormer.Engine.Insert(ldap)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -56,7 +56,7 @@ func AddLdap(ldap *Ldap) (bool, error) {
func CheckLdapExist(ldap *Ldap) (bool, error) { func CheckLdapExist(ldap *Ldap) (bool, error) {
var result []*Ldap var result []*Ldap
err := adapter.Engine.Find(&result, &Ldap{ err := ormer.Engine.Find(&result, &Ldap{
Owner: ldap.Owner, Owner: ldap.Owner,
Host: ldap.Host, Host: ldap.Host,
Port: ldap.Port, Port: ldap.Port,
@ -77,7 +77,7 @@ func CheckLdapExist(ldap *Ldap) (bool, error) {
func GetLdaps(owner string) ([]*Ldap, error) { func GetLdaps(owner string) ([]*Ldap, error) {
var ldaps []*Ldap var ldaps []*Ldap
err := adapter.Engine.Desc("created_time").Find(&ldaps, &Ldap{Owner: owner}) err := ormer.Engine.Desc("created_time").Find(&ldaps, &Ldap{Owner: owner})
if err != nil { if err != nil {
return ldaps, err return ldaps, err
} }
@ -91,7 +91,7 @@ func GetLdap(id string) (*Ldap, error) {
} }
ldap := Ldap{Id: id} ldap := Ldap{Id: id}
existed, err := adapter.Engine.Get(&ldap) existed, err := ormer.Engine.Get(&ldap)
if err != nil { if err != nil {
return &ldap, nil return &ldap, nil
} }
@ -103,14 +103,51 @@ func GetLdap(id string) (*Ldap, error) {
} }
} }
func GetMaskedLdap(ldap *Ldap, errs ...error) (*Ldap, error) {
if len(errs) > 0 && errs[0] != nil {
return nil, errs[0]
}
if ldap == nil {
return nil, nil
}
if ldap.Password != "" {
ldap.Password = "***"
}
return ldap, nil
}
func GetMaskedLdaps(ldaps []*Ldap, errs ...error) ([]*Ldap, error) {
if len(errs) > 0 && errs[0] != nil {
return nil, errs[0]
}
var err error
for _, ldap := range ldaps {
ldap, err = GetMaskedLdap(ldap)
if err != nil {
return nil, err
}
}
return ldaps, nil
}
func UpdateLdap(ldap *Ldap) (bool, error) { func UpdateLdap(ldap *Ldap) (bool, error) {
if l, err := GetLdap(ldap.Id); err != nil { var l *Ldap
var err error
if l, err = GetLdap(ldap.Id); err != nil {
return false, nil return false, nil
} else if l == nil { } else if l == nil {
return false, nil return false, nil
} }
affected, err := adapter.Engine.ID(ldap.Id).Cols("owner", "server_name", "host", if ldap.Password == "***" {
ldap.Password = l.Password
}
affected, err := ormer.Engine.ID(ldap.Id).Cols("owner", "server_name", "host",
"port", "enable_ssl", "username", "password", "base_dn", "filter", "filter_fields", "auto_sync").Update(ldap) "port", "enable_ssl", "username", "password", "base_dn", "filter", "filter_fields", "auto_sync").Update(ldap)
if err != nil { if err != nil {
return false, nil return false, nil
@ -120,7 +157,7 @@ func UpdateLdap(ldap *Ldap) (bool, error) {
} }
func DeleteLdap(ldap *Ldap) (bool, error) { func DeleteLdap(ldap *Ldap) (bool, error) {
affected, err := adapter.Engine.ID(ldap.Id).Delete(&Ldap{}) affected, err := ormer.Engine.ID(ldap.Id).Delete(&Ldap{})
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -118,7 +118,7 @@ func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) e
// start all autosync goroutine for existing ldap servers in each organizations // start all autosync goroutine for existing ldap servers in each organizations
func (l *LdapAutoSynchronizer) LdapAutoSynchronizerStartUpAll() error { func (l *LdapAutoSynchronizer) LdapAutoSynchronizerStartUpAll() error {
organizations := []*Organization{} organizations := []*Organization{}
err := adapter.Engine.Desc("created_time").Find(&organizations) err := ormer.Engine.Desc("created_time").Find(&organizations)
if err != nil { if err != nil {
logs.Info("failed to Star up LdapAutoSynchronizer; ") logs.Info("failed to Star up LdapAutoSynchronizer; ")
} }
@ -141,7 +141,7 @@ func (l *LdapAutoSynchronizer) LdapAutoSynchronizerStartUpAll() error {
} }
func UpdateLdapSyncTime(ldapId string) error { func UpdateLdapSyncTime(ldapId string) error {
_, err := adapter.Engine.ID(ldapId).Update(&Ldap{LastSync: util.GetCurrentTime()}) _, err := ormer.Engine.ID(ldapId).Update(&Ldap{LastSync: util.GetCurrentTime()})
if err != nil { if err != nil {
return err return err
} }

View File

@ -41,19 +41,20 @@ type LdapUser struct {
GidNumber string `json:"gidNumber"` GidNumber string `json:"gidNumber"`
// Gcn string // Gcn string
Uuid string `json:"uuid"` Uuid string `json:"uuid"`
UserPrincipalName string `json:"userPrincipalName"`
DisplayName string `json:"displayName"` DisplayName string `json:"displayName"`
Mail string Mail string
Email string `json:"email"` Email string `json:"email"`
EmailAddress string EmailAddress string
TelephoneNumber string TelephoneNumber string
Mobile string Mobile string `json:"mobile"`
MobileTelephoneNumber string MobileTelephoneNumber string
RegisteredAddress string RegisteredAddress string
PostalAddress string PostalAddress string
GroupId string `json:"groupId"` GroupId string `json:"groupId"`
Phone string `json:"phone"` Address string `json:"address"`
Address string `json:"address"` MemberOf string `json:"memberOf"`
} }
func (ldap *Ldap) GetLdapConn() (c *LdapConn, err error) { func (ldap *Ldap) GetLdapConn() (c *LdapConn, err error) {
@ -168,6 +169,8 @@ func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]LdapUser, error) {
user.Uuid = attribute.Values[0] user.Uuid = attribute.Values[0]
case "objectGUID": case "objectGUID":
user.Uuid = attribute.Values[0] user.Uuid = attribute.Values[0]
case "userPrincipalName":
user.UserPrincipalName = attribute.Values[0]
case "displayName": case "displayName":
user.DisplayName = attribute.Values[0] user.DisplayName = attribute.Values[0]
case "mail": case "mail":
@ -186,6 +189,8 @@ func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]LdapUser, error) {
user.RegisteredAddress = attribute.Values[0] user.RegisteredAddress = attribute.Values[0]
case "postalAddress": case "postalAddress":
user.PostalAddress = attribute.Values[0] user.PostalAddress = attribute.Values[0]
case "memberOf":
user.MemberOf = attribute.Values[0]
} }
} }
ldapUsers = append(ldapUsers, user) ldapUsers = append(ldapUsers, user)
@ -312,7 +317,7 @@ func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUser
DisplayName: syncUser.buildLdapDisplayName(), DisplayName: syncUser.buildLdapDisplayName(),
Avatar: organization.DefaultAvatar, Avatar: organization.DefaultAvatar,
Email: syncUser.Email, Email: syncUser.Email,
Phone: syncUser.Phone, Phone: syncUser.Mobile,
Address: []string{syncUser.Address}, Address: []string{syncUser.Address},
Affiliation: affiliation, Affiliation: affiliation,
Tag: tag, Tag: tag,
@ -338,7 +343,7 @@ func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUser
func GetExistUuids(owner string, uuids []string) ([]string, error) { func GetExistUuids(owner string, uuids []string) ([]string, error) {
var existUuids []string var existUuids []string
err := adapter.Engine.Table("user").Where("owner = ?", owner).Cols("ldap"). err := ormer.Engine.Table("user").Where("owner = ?", owner).Cols("ldap").
In("ldap", uuids).Select("DISTINCT ldap").Find(&existUuids) In("ldap", uuids).Select("DISTINCT ldap").Find(&existUuids)
if err != nil { if err != nil {
return existUuids, err return existUuids, err
@ -350,7 +355,7 @@ func GetExistUuids(owner string, uuids []string) ([]string, error) {
func (ldapUser *LdapUser) buildLdapUserName() (string, error) { func (ldapUser *LdapUser) buildLdapUserName() (string, error) {
user := User{} user := User{}
uidWithNumber := fmt.Sprintf("%s_%s", ldapUser.Uid, ldapUser.UidNumber) uidWithNumber := fmt.Sprintf("%s_%s", ldapUser.Uid, ldapUser.UidNumber)
has, err := adapter.Engine.Where("name = ? or name = ?", ldapUser.Uid, uidWithNumber).Get(&user) has, err := ormer.Engine.Where("name = ? or name = ?", ldapUser.Uid, uidWithNumber).Get(&user)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -1,143 +0,0 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package object
import (
"fmt"
"github.com/casdoor/casdoor/util"
"github.com/xorm-io/core"
)
type Message struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
Organization string `xorm:"varchar(100)" json:"organization"`
Chat string `xorm:"varchar(100) index" json:"chat"`
ReplyTo string `xorm:"varchar(100) index" json:"replyTo"`
Author string `xorm:"varchar(100)" json:"author"`
Text string `xorm:"mediumtext" json:"text"`
}
func GetMaskedMessage(message *Message) *Message {
if message == nil {
return nil
}
return message
}
func GetMaskedMessages(messages []*Message) []*Message {
for _, message := range messages {
message = GetMaskedMessage(message)
}
return messages
}
func GetMessageCount(owner, organization, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
return session.Count(&Message{Organization: organization})
}
func GetMessages(owner string) ([]*Message, error) {
messages := []*Message{}
err := adapter.Engine.Desc("created_time").Find(&messages, &Message{Owner: owner})
return messages, err
}
func GetChatMessages(chat string) ([]*Message, error) {
messages := []*Message{}
err := adapter.Engine.Asc("created_time").Find(&messages, &Message{Chat: chat})
return messages, err
}
func GetPaginationMessages(owner, organization string, offset, limit int, field, value, sortField, sortOrder string) ([]*Message, error) {
messages := []*Message{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&messages, &Message{Organization: organization})
return messages, err
}
func getMessage(owner string, name string) (*Message, error) {
if owner == "" || name == "" {
return nil, nil
}
message := Message{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&message)
if err != nil {
return nil, err
}
if existed {
return &message, nil
} else {
return nil, nil
}
}
func GetMessage(id string) (*Message, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getMessage(owner, name)
}
func UpdateMessage(id string, message *Message) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if m, err := getMessage(owner, name); err != nil {
return false, err
} else if m == nil {
return false, nil
}
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(message)
if err != nil {
return false, err
}
return affected != 0, nil
}
func AddMessage(message *Message) (bool, error) {
affected, err := adapter.Engine.Insert(message)
if err != nil {
return false, err
}
return affected != 0, nil
}
func DeleteMessage(message *Message) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{message.Owner, message.Name}).Delete(&Message{})
if err != nil {
return false, err
}
return affected != 0, nil
}
func DeleteChatMessages(chat string) (bool, error) {
affected, err := adapter.Engine.Delete(&Message{Chat: chat})
if err != nil {
return false, err
}
return affected != 0, nil
}
func (p *Message) GetId() string {
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
}

View File

@ -24,10 +24,6 @@ import (
const MfaRecoveryCodesSession = "mfa_recovery_codes" const MfaRecoveryCodesSession = "mfa_recovery_codes"
type MfaSessionData struct {
UserId string
}
type MfaProps struct { type MfaProps struct {
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
IsPreferred bool `json:"isPreferred"` IsPreferred bool `json:"isPreferred"`

View File

@ -24,8 +24,8 @@ import (
) )
const ( const (
MfaSmsCountryCodeSession = "mfa_country_code" MfaCountryCodeSession = "mfa_country_code"
MfaSmsDestSession = "mfa_dest" MfaDestSession = "mfa_dest"
) )
type SmsMfa struct { type SmsMfa struct {
@ -48,9 +48,19 @@ func (mfa *SmsMfa) Initiate(ctx *context.Context, userId string) (*MfaProps, err
} }
func (mfa *SmsMfa) SetupVerify(ctx *context.Context, passCode string) error { func (mfa *SmsMfa) SetupVerify(ctx *context.Context, passCode string) error {
dest := ctx.Input.CruSession.Get(MfaSmsDestSession).(string) destSession := ctx.Input.CruSession.Get(MfaDestSession)
countryCode := ctx.Input.CruSession.Get(MfaSmsCountryCodeSession).(string) if destSession == nil {
return errors.New("dest session is missing")
}
dest := destSession.(string)
if !util.IsEmailValid(dest) { if !util.IsEmailValid(dest) {
countryCodeSession := ctx.Input.CruSession.Get(MfaCountryCodeSession)
if countryCodeSession == nil {
return errors.New("country code is missing")
}
countryCode := countryCodeSession.(string)
dest, _ = util.GetE164Number(dest, countryCode) dest, _ = util.GetE164Number(dest, countryCode)
} }
@ -78,8 +88,8 @@ func (mfa *SmsMfa) Enable(ctx *context.Context, user *User) error {
columns = append(columns, "mfa_phone_enabled") columns = append(columns, "mfa_phone_enabled")
if user.Phone == "" { if user.Phone == "" {
user.Phone = ctx.Input.CruSession.Get(MfaSmsDestSession).(string) user.Phone = ctx.Input.CruSession.Get(MfaDestSession).(string)
user.CountryCode = ctx.Input.CruSession.Get(MfaSmsCountryCodeSession).(string) user.CountryCode = ctx.Input.CruSession.Get(MfaCountryCodeSession).(string)
columns = append(columns, "phone", "country_code") columns = append(columns, "phone", "country_code")
} }
} else if mfa.Config.MfaType == EmailType { } else if mfa.Config.MfaType == EmailType {
@ -87,7 +97,7 @@ func (mfa *SmsMfa) Enable(ctx *context.Context, user *User) error {
columns = append(columns, "mfa_email_enabled") columns = append(columns, "mfa_email_enabled")
if user.Email == "" { if user.Email == "" {
user.Email = ctx.Input.CruSession.Get(MfaSmsDestSession).(string) user.Email = ctx.Input.CruSession.Get(MfaDestSession).(string)
columns = append(columns, "email") columns = append(columns, "email")
} }
} }
@ -96,6 +106,11 @@ func (mfa *SmsMfa) Enable(ctx *context.Context, user *User) error {
if err != nil { if err != nil {
return err return err
} }
ctx.Input.CruSession.Delete(MfaRecoveryCodesSession)
ctx.Input.CruSession.Delete(MfaDestSession)
ctx.Input.CruSession.Delete(MfaCountryCodeSession)
return nil return nil
} }

View File

@ -72,8 +72,11 @@ func (mfa *TotpMfa) Initiate(ctx *context.Context, userId string) (*MfaProps, er
} }
func (mfa *TotpMfa) SetupVerify(ctx *context.Context, passcode string) error { func (mfa *TotpMfa) SetupVerify(ctx *context.Context, passcode string) error {
secret := ctx.Input.CruSession.Get(MfaTotpSecretSession).(string) secret := ctx.Input.CruSession.Get(MfaTotpSecretSession)
result := totp.Validate(passcode, secret) if secret == nil {
return errors.New("totp secret is missing")
}
result := totp.Validate(passcode, secret.(string))
if result { if result {
return nil return nil
@ -104,6 +107,10 @@ func (mfa *TotpMfa) Enable(ctx *context.Context, user *User) error {
if err != nil { if err != nil {
return err return err
} }
ctx.Input.CruSession.Delete(MfaRecoveryCodesSession)
ctx.Input.CruSession.Delete(MfaTotpSecretSession)
return nil return nil
} }

View File

@ -43,7 +43,7 @@ func DoMigration() {
IDColumnName: "id", IDColumnName: "id",
} }
m := migrate.New(adapter.Engine, options, migrations) m := migrate.New(ormer.Engine, options, migrations)
err := m.Migrate() err := m.Migrate()
if err != nil { if err != nil {
panic(err) panic(err)

View File

@ -24,9 +24,9 @@ import (
type Migrator_1_101_0_PR_1083 struct{} type Migrator_1_101_0_PR_1083 struct{}
func (*Migrator_1_101_0_PR_1083) IsMigrationNeeded() bool { func (*Migrator_1_101_0_PR_1083) IsMigrationNeeded() bool {
exist1, _ := adapter.Engine.IsTableExist("model") exist1, _ := ormer.Engine.IsTableExist("model")
exist2, _ := adapter.Engine.IsTableExist("permission") exist2, _ := ormer.Engine.IsTableExist("permission")
exist3, _ := adapter.Engine.IsTableExist("permission_rule") exist3, _ := ormer.Engine.IsTableExist("permission_rule")
if exist1 && exist2 && exist3 { if exist1 && exist2 && exist3 {
return true return true

View File

@ -23,7 +23,7 @@ import (
type Migrator_1_235_0_PR_1530 struct{} type Migrator_1_235_0_PR_1530 struct{}
func (*Migrator_1_235_0_PR_1530) IsMigrationNeeded() bool { func (*Migrator_1_235_0_PR_1530) IsMigrationNeeded() bool {
exist, _ := adapter.Engine.IsTableExist("casbin_rule") exist, _ := ormer.Engine.IsTableExist("casbin_rule")
return exist return exist
} }

View File

@ -24,8 +24,8 @@ import (
type Migrator_1_240_0_PR_1539 struct{} type Migrator_1_240_0_PR_1539 struct{}
func (*Migrator_1_240_0_PR_1539) IsMigrationNeeded() bool { func (*Migrator_1_240_0_PR_1539) IsMigrationNeeded() bool {
exist, _ := adapter.Engine.IsTableExist("session") exist, _ := ormer.Engine.IsTableExist("session")
err := adapter.Engine.Table("session").Find(&[]*Session{}) err := ormer.Engine.Table("session").Find(&[]*Session{})
if exist && err != nil { if exist && err != nil {
return true return true

View File

@ -22,7 +22,7 @@ import (
type Migrator_1_314_0_PR_1841 struct{} type Migrator_1_314_0_PR_1841 struct{}
func (*Migrator_1_314_0_PR_1841) IsMigrationNeeded() bool { func (*Migrator_1_314_0_PR_1841) IsMigrationNeeded() bool {
count, err := adapter.Engine.Where("password_type=?", "").Count(&User{}) count, err := ormer.Engine.Where("password_type=?", "").Count(&User{})
if err != nil { if err != nil {
// table doesn't exist // table doesn't exist
return false return false

View File

@ -31,6 +31,8 @@ type Model struct {
ModelText string `xorm:"mediumtext" json:"modelText"` ModelText string `xorm:"mediumtext" json:"modelText"`
IsEnabled bool `json:"isEnabled"` IsEnabled bool `json:"isEnabled"`
model.Model `xorm:"-" json:"-"`
} }
func GetModelCount(owner, field, value string) (int64, error) { func GetModelCount(owner, field, value string) (int64, error) {
@ -40,7 +42,7 @@ func GetModelCount(owner, field, value string) (int64, error) {
func GetModels(owner string) ([]*Model, error) { func GetModels(owner string) ([]*Model, error) {
models := []*Model{} models := []*Model{}
err := adapter.Engine.Desc("created_time").Find(&models, &Model{Owner: owner}) err := ormer.Engine.Desc("created_time").Find(&models, &Model{Owner: owner})
if err != nil { if err != nil {
return models, err return models, err
} }
@ -65,7 +67,7 @@ func getModel(owner string, name string) (*Model, error) {
} }
m := Model{Owner: owner, Name: name} m := Model{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&m) existed, err := ormer.Engine.Get(&m)
if err != nil { if err != nil {
return &m, err return &m, err
} }
@ -111,7 +113,7 @@ func UpdateModel(id string, modelObj *Model) (bool, error) {
} }
} }
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(modelObj) affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(modelObj)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -120,7 +122,7 @@ func UpdateModel(id string, modelObj *Model) (bool, error) {
} }
func AddModel(model *Model) (bool, error) { func AddModel(model *Model) (bool, error) {
affected, err := adapter.Engine.Insert(model) affected, err := ormer.Engine.Insert(model)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -129,7 +131,7 @@ func AddModel(model *Model) (bool, error) {
} }
func DeleteModel(model *Model) (bool, error) { func DeleteModel(model *Model) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{model.Owner, model.Name}).Delete(&Model{}) affected, err := ormer.Engine.ID(core.PK{model.Owner, model.Name}).Delete(&Model{})
if err != nil { if err != nil {
return false, err return false, err
} }
@ -137,12 +139,12 @@ func DeleteModel(model *Model) (bool, error) {
return affected != 0, nil return affected != 0, nil
} }
func (model *Model) GetId() string { func (m *Model) GetId() string {
return fmt.Sprintf("%s/%s", model.Owner, model.Name) return fmt.Sprintf("%s/%s", m.Owner, m.Name)
} }
func modelChangeTrigger(oldName string, newName string) error { func modelChangeTrigger(oldName string, newName string) error {
session := adapter.Engine.NewSession() session := ormer.Engine.NewSession()
defer session.Close() defer session.Close()
err := session.Begin() err := session.Begin()
@ -154,6 +156,15 @@ func modelChangeTrigger(oldName string, newName string) error {
permission.Model = newName permission.Model = newName
_, err = session.Where("model=?", oldName).Update(permission) _, err = session.Where("model=?", oldName).Update(permission)
if err != nil { if err != nil {
session.Rollback()
return err
}
enforcer := new(Enforcer)
enforcer.Model = newName
_, err = session.Where("model=?", oldName).Update(enforcer)
if err != nil {
session.Rollback()
return err return err
} }
@ -161,5 +172,20 @@ func modelChangeTrigger(oldName string, newName string) error {
} }
func HasRoleDefinition(m model.Model) bool { func HasRoleDefinition(m model.Model) bool {
if m == nil {
return false
}
return m["g"] != nil return m["g"] != nil
} }
func (m *Model) initModel() error {
if m.Model == nil {
casbinModel, err := model.NewModelFromString(m.ModelText)
if err != nil {
return err
}
m.Model = casbinModel
}
return nil
}

View File

@ -123,6 +123,10 @@ func GetJsonWebKeySet() (jose.JSONWebKeySet, error) {
// link here: https://self-issued.info/docs/draft-ietf-jose-json-web-key.html // link here: https://self-issued.info/docs/draft-ietf-jose-json-web-key.html
// or https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key // or https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key
for _, cert := range certs { for _, cert := range certs {
if cert.Type != "x509" {
continue
}
certPemBlock := []byte(cert.Certificate) certPemBlock := []byte(cert.Certificate)
certDerBlock, _ := pem.Decode(certPemBlock) certDerBlock, _ := pem.Decode(certPemBlock)
x509Cert, _ := x509.ParseCertificate(certDerBlock.Bytes) x509Cert, _ := x509.ParseCertificate(certDerBlock.Bytes)

View File

@ -69,7 +69,7 @@ type Organization struct {
IsProfilePublic bool `json:"isProfilePublic"` IsProfilePublic bool `json:"isProfilePublic"`
MfaItems []*MfaItem `xorm:"varchar(300)" json:"mfaItems"` MfaItems []*MfaItem `xorm:"varchar(300)" json:"mfaItems"`
AccountItems []*AccountItem `xorm:"varchar(3000)" json:"accountItems"` AccountItems []*AccountItem `xorm:"varchar(5000)" json:"accountItems"`
} }
func GetOrganizationCount(owner, field, value string) (int64, error) { func GetOrganizationCount(owner, field, value string) (int64, error) {
@ -80,12 +80,12 @@ func GetOrganizationCount(owner, field, value string) (int64, error) {
func GetOrganizations(owner string, name ...string) ([]*Organization, error) { func GetOrganizations(owner string, name ...string) ([]*Organization, error) {
organizations := []*Organization{} organizations := []*Organization{}
if name != nil && len(name) > 0 { if name != nil && len(name) > 0 {
err := adapter.Engine.Desc("created_time").Where(builder.In("name", name)).Find(&organizations) err := ormer.Engine.Desc("created_time").Where(builder.In("name", name)).Find(&organizations)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else { } else {
err := adapter.Engine.Desc("created_time").Find(&organizations, &Organization{Owner: owner}) err := ormer.Engine.Desc("created_time").Find(&organizations, &Organization{Owner: owner})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -96,7 +96,7 @@ func GetOrganizations(owner string, name ...string) ([]*Organization, error) {
func GetOrganizationsByFields(owner string, fields ...string) ([]*Organization, error) { func GetOrganizationsByFields(owner string, fields ...string) ([]*Organization, error) {
organizations := []*Organization{} organizations := []*Organization{}
err := adapter.Engine.Desc("created_time").Cols(fields...).Find(&organizations, &Organization{Owner: owner}) err := ormer.Engine.Desc("created_time").Cols(fields...).Find(&organizations, &Organization{Owner: owner})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -126,7 +126,7 @@ func getOrganization(owner string, name string) (*Organization, error) {
} }
organization := Organization{Owner: owner, Name: name} organization := Organization{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&organization) existed, err := ormer.Engine.Get(&organization)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -189,7 +189,7 @@ func UpdateOrganization(id string, organization *Organization) (bool, error) {
if name != organization.Name { if name != organization.Name {
err := organizationChangeTrigger(name, organization.Name) err := organizationChangeTrigger(name, organization.Name)
if err != nil { if err != nil {
return false, nil return false, err
} }
} }
@ -201,7 +201,7 @@ func UpdateOrganization(id string, organization *Organization) (bool, error) {
} }
} }
session := adapter.Engine.ID(core.PK{owner, name}).AllCols() session := ormer.Engine.ID(core.PK{owner, name}).AllCols()
if organization.MasterPassword == "***" { if organization.MasterPassword == "***" {
session.Omit("master_password") session.Omit("master_password")
} }
@ -214,7 +214,7 @@ func UpdateOrganization(id string, organization *Organization) (bool, error) {
} }
func AddOrganization(organization *Organization) (bool, error) { func AddOrganization(organization *Organization) (bool, error) {
affected, err := adapter.Engine.Insert(organization) affected, err := ormer.Engine.Insert(organization)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -227,7 +227,7 @@ func DeleteOrganization(organization *Organization) (bool, error) {
return false, nil return false, nil
} }
affected, err := adapter.Engine.ID(core.PK{organization.Owner, organization.Name}).Delete(&Organization{}) affected, err := ormer.Engine.ID(core.PK{organization.Owner, organization.Name}).Delete(&Organization{})
if err != nil { if err != nil {
return false, err return false, err
} }
@ -299,7 +299,7 @@ func GetDefaultApplication(id string) (*Application, error) {
} }
applications := []*Application{} applications := []*Application{}
err = adapter.Engine.Asc("created_time").Find(&applications, &Application{Organization: organization.Name}) err = ormer.Engine.Asc("created_time").Find(&applications, &Application{Organization: organization.Name})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -330,7 +330,7 @@ func GetDefaultApplication(id string) (*Application, error) {
} }
func organizationChangeTrigger(oldName string, newName string) error { func organizationChangeTrigger(oldName string, newName string) error {
session := adapter.Engine.NewSession() session := ormer.Engine.NewSession()
defer session.Close() defer session.Close()
err := session.Begin() err := session.Begin()
@ -360,7 +360,7 @@ func organizationChangeTrigger(oldName string, newName string) error {
} }
role := new(Role) role := new(Role)
_, err = adapter.Engine.Where("owner=?", oldName).Get(role) _, err = ormer.Engine.Where("owner=?", oldName).Get(role)
if err != nil { if err != nil {
return err return err
} }
@ -385,7 +385,7 @@ func organizationChangeTrigger(oldName string, newName string) error {
} }
permission := new(Permission) permission := new(Permission)
_, err = adapter.Engine.Where("owner=?", oldName).Get(permission) _, err = ormer.Engine.Where("owner=?", oldName).Get(permission)
if err != nil { if err != nil {
return err return err
} }
@ -409,9 +409,9 @@ func organizationChangeTrigger(oldName string, newName string) error {
return err return err
} }
casbinAdapter := new(CasbinAdapter) adapter := new(Adapter)
casbinAdapter.Owner = newName adapter.Owner = newName
_, err = session.Where("owner=?", oldName).Update(casbinAdapter) _, err = session.Where("owner=?", oldName).Update(adapter)
if err != nil { if err != nil {
return err return err
} }
@ -431,8 +431,8 @@ func organizationChangeTrigger(oldName string, newName string) error {
} }
payment := new(Payment) payment := new(Payment)
payment.Organization = newName payment.Owner = newName
_, err = session.Where("organization=?", oldName).Update(payment) _, err = session.Where("owner=?", oldName).Update(payment)
if err != nil { if err != nil {
return err return err
} }
@ -476,10 +476,21 @@ func organizationChangeTrigger(oldName string, newName string) error {
return session.Commit() return session.Commit()
} }
func (org *Organization) HasRequiredMfa() bool { func IsNeedPromptMfa(org *Organization, user *User) bool {
if org == nil || user == nil {
return false
}
for _, item := range org.MfaItems { for _, item := range org.MfaItems {
if item.Rule == "Required" { if item.Rule == "Required" {
return true if item.Name == EmailType && !user.MfaEmailEnabled {
return true
}
if item.Name == SmsType && !user.MfaPhoneEnabled {
return true
}
if item.Name == TotpType && user.TotpSecret == "" {
return true
}
} }
} }
return false return false

369
object/ormer.go Normal file
View File

@ -0,0 +1,369 @@
// 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 object
import (
"database/sql"
"fmt"
"runtime"
"strings"
"github.com/beego/beego"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util"
xormadapter "github.com/casdoor/xorm-adapter/v3"
_ "github.com/denisenkom/go-mssqldb" // db = mssql
_ "github.com/go-sql-driver/mysql" // db = mysql
_ "github.com/lib/pq" // db = postgres
"github.com/xorm-io/core"
"github.com/xorm-io/xorm"
_ "modernc.org/sqlite" // db = sqlite
)
var ormer *Ormer
func InitConfig() {
err := beego.LoadAppConfig("ini", "../conf/app.conf")
if err != nil {
panic(err)
}
beego.BConfig.WebConfig.Session.SessionOn = true
InitAdapter(true)
CreateTables(true)
DoMigration()
}
func InitAdapter(createDatabase bool) {
if createDatabase {
err := createDatabaseForPostgres(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName"))
if err != nil {
panic(err)
}
}
ormer = NewAdapter(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName"))
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
tbMapper := core.NewPrefixMapper(core.SnakeMapper{}, tableNamePrefix)
ormer.Engine.SetTableMapper(tbMapper)
}
func CreateTables(createDatabase bool) {
if createDatabase {
err := ormer.CreateDatabase()
if err != nil {
panic(err)
}
}
ormer.createTable()
}
// Ormer represents the MySQL adapter for policy storage.
type Ormer struct {
driverName string
dataSourceName string
dbName string
Engine *xorm.Engine
}
// finalizer is the destructor for Ormer.
func finalizer(a *Ormer) {
err := a.Engine.Close()
if err != nil {
panic(err)
}
}
// NewAdapter is the constructor for Ormer.
func NewAdapter(driverName string, dataSourceName string, dbName string) *Ormer {
a := &Ormer{}
a.driverName = driverName
a.dataSourceName = dataSourceName
a.dbName = dbName
// Open the DB, create it if not existed.
a.open()
// Call the destructor when the object is released.
runtime.SetFinalizer(a, finalizer)
return a
}
func createDatabaseForPostgres(driverName string, dataSourceName string, dbName string) error {
if driverName == "postgres" {
db, err := sql.Open(driverName, dataSourceName)
if err != nil {
return err
}
defer db.Close()
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s;", dbName))
if err != nil {
if !strings.Contains(err.Error(), "already exists") {
return err
}
}
return nil
} else {
return nil
}
}
func (a *Ormer) CreateDatabase() error {
if a.driverName == "postgres" {
return nil
}
engine, err := xorm.NewEngine(a.driverName, a.dataSourceName)
if err != nil {
return err
}
defer engine.Close()
_, err = engine.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s default charset utf8mb4 COLLATE utf8mb4_general_ci", a.dbName))
return err
}
func (a *Ormer) open() {
dataSourceName := a.dataSourceName + a.dbName
if a.driverName != "mysql" {
dataSourceName = a.dataSourceName
}
engine, err := xorm.NewEngine(a.driverName, dataSourceName)
if err != nil {
panic(err)
}
a.Engine = engine
}
func (a *Ormer) close() {
_ = a.Engine.Close()
a.Engine = nil
}
func (a *Ormer) createTable() {
showSql := conf.GetConfigBool("showSql")
a.Engine.ShowSQL(showSql)
err := a.Engine.Sync2(new(Organization))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(User))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Group))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Role))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Permission))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Model))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Adapter))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Enforcer))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Provider))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Application))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Resource))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Token))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(VerificationRecord))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Record))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Webhook))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Syncer))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Cert))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Product))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Payment))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Ldap))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(PermissionRule))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(xormadapter.CasbinRule))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Session))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Subscription))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Plan))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Pricing))
if err != nil {
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
}

View File

@ -18,6 +18,8 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/casdoor/casdoor/pp"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
"github.com/xorm-io/core" "github.com/xorm-io/core"
) )
@ -27,43 +29,44 @@ type Payment struct {
Name string `xorm:"varchar(100) notnull pk" json:"name"` Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"` CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
DisplayName string `xorm:"varchar(100)" json:"displayName"` DisplayName string `xorm:"varchar(100)" json:"displayName"`
// Payment Provider Info
Provider string `xorm:"varchar(100)" json:"provider"` Provider string `xorm:"varchar(100)" json:"provider"`
Type string `xorm:"varchar(100)" json:"type"` Type string `xorm:"varchar(100)" json:"type"`
Organization string `xorm:"varchar(100)" json:"organization"` // Product Info
User string `xorm:"varchar(100)" json:"user"` ProductName string `xorm:"varchar(100)" json:"productName"`
ProductName string `xorm:"varchar(100)" json:"productName"` ProductDisplayName string `xorm:"varchar(100)" json:"productDisplayName"`
ProductDisplayName string `xorm:"varchar(100)" json:"productDisplayName"` Detail string `xorm:"varchar(255)" json:"detail"`
Tag string `xorm:"varchar(100)" json:"tag"`
Detail string `xorm:"varchar(255)" json:"detail"` Currency string `xorm:"varchar(100)" json:"currency"`
Tag string `xorm:"varchar(100)" json:"tag"` Price float64 `json:"price"`
Currency string `xorm:"varchar(100)" json:"currency"` ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"`
Price float64 `json:"price"` // Payer Info
User string `xorm:"varchar(100)" json:"user"`
PayUrl string `xorm:"varchar(2000)" json:"payUrl"` PersonName string `xorm:"varchar(100)" json:"personName"`
ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"` PersonIdCard string `xorm:"varchar(100)" json:"personIdCard"`
State string `xorm:"varchar(100)" json:"state"` PersonEmail string `xorm:"varchar(100)" json:"personEmail"`
Message string `xorm:"varchar(2000)" json:"message"` PersonPhone string `xorm:"varchar(100)" json:"personPhone"`
// Invoice Info
PersonName string `xorm:"varchar(100)" json:"personName"`
PersonIdCard string `xorm:"varchar(100)" json:"personIdCard"`
PersonEmail string `xorm:"varchar(100)" json:"personEmail"`
PersonPhone string `xorm:"varchar(100)" json:"personPhone"`
InvoiceType string `xorm:"varchar(100)" json:"invoiceType"` InvoiceType string `xorm:"varchar(100)" json:"invoiceType"`
InvoiceTitle string `xorm:"varchar(100)" json:"invoiceTitle"` InvoiceTitle string `xorm:"varchar(100)" json:"invoiceTitle"`
InvoiceTaxId string `xorm:"varchar(100)" json:"invoiceTaxId"` InvoiceTaxId string `xorm:"varchar(100)" json:"invoiceTaxId"`
InvoiceRemark string `xorm:"varchar(100)" json:"invoiceRemark"` InvoiceRemark string `xorm:"varchar(100)" json:"invoiceRemark"`
InvoiceUrl string `xorm:"varchar(255)" json:"invoiceUrl"` InvoiceUrl string `xorm:"varchar(255)" json:"invoiceUrl"`
// Order Info
OutOrderId string `xorm:"varchar(100)" json:"outOrderId"`
PayUrl string `xorm:"varchar(2000)" json:"payUrl"`
State pp.PaymentState `xorm:"varchar(100)" json:"state"`
Message string `xorm:"varchar(2000)" json:"message"`
} }
func GetPaymentCount(owner, organization, field, value string) (int64, error) { func GetPaymentCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "") session := GetSession(owner, -1, -1, field, value, "", "")
return session.Count(&Payment{Organization: organization}) return session.Count(&Payment{Owner: owner})
} }
func GetPayments(owner string) ([]*Payment, error) { func GetPayments(owner string) ([]*Payment, error) {
payments := []*Payment{} payments := []*Payment{}
err := adapter.Engine.Desc("created_time").Find(&payments, &Payment{Owner: owner}) err := ormer.Engine.Desc("created_time").Find(&payments, &Payment{Owner: owner})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -71,9 +74,9 @@ func GetPayments(owner string) ([]*Payment, error) {
return payments, nil return payments, nil
} }
func GetUserPayments(owner string, organization string, user string) ([]*Payment, error) { func GetUserPayments(owner, user string) ([]*Payment, error) {
payments := []*Payment{} payments := []*Payment{}
err := adapter.Engine.Desc("created_time").Find(&payments, &Payment{Owner: owner, Organization: organization, User: user}) err := ormer.Engine.Desc("created_time").Find(&payments, &Payment{Owner: owner, User: user})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -81,10 +84,10 @@ func GetUserPayments(owner string, organization string, user string) ([]*Payment
return payments, nil return payments, nil
} }
func GetPaginationPayments(owner, organization string, offset, limit int, field, value, sortField, sortOrder string) ([]*Payment, error) { func GetPaginationPayments(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Payment, error) {
payments := []*Payment{} payments := []*Payment{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder) session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&payments, &Payment{Organization: organization}) err := session.Find(&payments, &Payment{Owner: owner})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -98,7 +101,7 @@ func getPayment(owner string, name string) (*Payment, error) {
} }
payment := Payment{Owner: owner, Name: name} payment := Payment{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&payment) existed, err := ormer.Engine.Get(&payment)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -123,16 +126,16 @@ func UpdatePayment(id string, payment *Payment) (bool, error) {
return false, nil return false, nil
} }
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(payment) affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(payment)
if err != nil { if err != nil {
panic(err) return false, err
} }
return affected != 0, nil return affected != 0, nil
} }
func AddPayment(payment *Payment) (bool, error) { func AddPayment(payment *Payment) (bool, error) {
affected, err := adapter.Engine.Insert(payment) affected, err := ormer.Engine.Insert(payment)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -141,7 +144,7 @@ func AddPayment(payment *Payment) (bool, error) {
} }
func DeletePayment(payment *Payment) (bool, error) { func DeletePayment(payment *Payment) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{payment.Owner, payment.Name}).Delete(&Payment{}) affected, err := ormer.Engine.ID(core.PK{payment.Owner, payment.Name}).Delete(&Payment{})
if err != nil { if err != nil {
return false, err return false, err
} }
@ -149,73 +152,76 @@ func DeletePayment(payment *Payment) (bool, error) {
return affected != 0, nil return affected != 0, nil
} }
func notifyPayment(request *http.Request, body []byte, owner string, providerName string, productName string, paymentName string, orderId string) (*Payment, error, string) { func notifyPayment(request *http.Request, body []byte, owner string, paymentName string, orderId string) (*Payment, *pp.NotifyResult, error) {
provider, err := getProvider(owner, providerName)
if err != nil {
panic(err)
}
pProvider, cert, err := provider.getPaymentProvider()
if err != nil {
panic(err)
}
payment, err := getPayment(owner, paymentName) payment, err := getPayment(owner, paymentName)
if err != nil { if err != nil {
panic(err) return nil, nil, err
} }
if payment == nil { if payment == nil {
err = fmt.Errorf("the payment: %s does not exist", paymentName) err = fmt.Errorf("the payment: %s does not exist", paymentName)
return nil, err, pProvider.GetResponseError(err) return nil, nil, err
} }
product, err := getProduct(owner, productName) provider, err := getProvider(owner, payment.Provider)
if err != nil { if err != nil {
panic(err) return nil, nil, err
}
pProvider, cert, err := provider.getPaymentProvider()
if err != nil {
return nil, nil, err
} }
product, err := getProduct(owner, payment.ProductName)
if err != nil {
return nil, nil, err
}
if product == nil { if product == nil {
err = fmt.Errorf("the product: %s does not exist", productName) err = fmt.Errorf("the product: %s does not exist", payment.ProductName)
return payment, err, pProvider.GetResponseError(err) return nil, nil, err
} }
productDisplayName, paymentName, price, productName, providerName, err := pProvider.Notify(request, body, cert.AuthorityPublicKey, orderId) if orderId == "" {
orderId = payment.OutOrderId
}
notifyResult, err := pProvider.Notify(request, body, cert.AuthorityPublicKey, orderId)
if err != nil { if err != nil {
return payment, err, pProvider.GetResponseError(err) return payment, nil, err
}
if notifyResult.PaymentStatus != pp.PaymentStatePaid {
return payment, notifyResult, nil
}
// Only check paid payment
if notifyResult.ProductDisplayName != "" && notifyResult.ProductDisplayName != product.DisplayName {
err = fmt.Errorf("the payment's product name: %s doesn't equal to the expected product name: %s", notifyResult.ProductDisplayName, product.DisplayName)
return payment, nil, err
} }
if productDisplayName != "" && productDisplayName != product.DisplayName { if notifyResult.Price != product.Price {
err = fmt.Errorf("the payment's product name: %s doesn't equal to the expected product name: %s", productDisplayName, product.DisplayName) err = fmt.Errorf("the payment's price: %f doesn't equal to the expected price: %f", notifyResult.Price, product.Price)
return payment, err, pProvider.GetResponseError(err) return payment, nil, err
} }
if price != product.Price { return payment, notifyResult, nil
err = fmt.Errorf("the payment's price: %f doesn't equal to the expected price: %f", price, product.Price)
return payment, err, pProvider.GetResponseError(err)
}
err = nil
return payment, err, pProvider.GetResponseError(err)
} }
func NotifyPayment(request *http.Request, body []byte, owner string, providerName string, productName string, paymentName string, orderId string) (error, string) { func NotifyPayment(request *http.Request, body []byte, owner string, paymentName string, orderId string) (*Payment, error) {
payment, err, errorResponse := notifyPayment(request, body, owner, providerName, productName, paymentName, orderId) payment, notifyResult, err := notifyPayment(request, body, owner, paymentName, orderId)
if payment != nil { if payment != nil {
if err != nil { if err != nil {
payment.State = "Error" payment.State = pp.PaymentStateError
payment.Message = err.Error() payment.Message = err.Error()
} else { } else {
payment.State = "Paid" payment.State = notifyResult.PaymentStatus
payment.Message = notifyResult.NotifyMessage
} }
_, err = UpdatePayment(payment.GetId(), payment) _, err = UpdatePayment(payment.GetId(), payment)
if err != nil { if err != nil {
panic(err) return nil, err
} }
} }
return err, errorResponse return payment, nil
} }
func invoicePayment(payment *Payment) (string, error) { func invoicePayment(payment *Payment) (string, error) {
@ -242,7 +248,7 @@ func invoicePayment(payment *Payment) (string, error) {
} }
func InvoicePayment(payment *Payment) (string, error) { func InvoicePayment(payment *Payment) (string, error) {
if payment.State != "Paid" { if payment.State != pp.PaymentStatePaid {
return "", fmt.Errorf("the payment state is supposed to be: \"%s\", got: \"%s\"", "Paid", payment.State) return "", fmt.Errorf("the payment state is supposed to be: \"%s\", got: \"%s\"", "Paid", payment.State)
} }

View File

@ -58,10 +58,7 @@ type PermissionRule struct {
Id string `xorm:"varchar(100) index not null default ''" json:"id"` Id string `xorm:"varchar(100) index not null default ''" json:"id"`
} }
const ( const builtInAvailableField = 5 // Casdoor built-in adapter, use V5 to filter permission, so has 5 available field
builtInAvailableField = 5 // Casdoor built-in adapter, use V5 to filter permission, so has 5 available field
builtInAdapter = "permission_rule"
)
func (p *Permission) GetId() string { func (p *Permission) GetId() string {
return util.GetId(p.Owner, p.Name) return util.GetId(p.Owner, p.Name)
@ -74,7 +71,7 @@ func GetPermissionCount(owner, field, value string) (int64, error) {
func GetPermissions(owner string) ([]*Permission, error) { func GetPermissions(owner string) ([]*Permission, error) {
permissions := []*Permission{} permissions := []*Permission{}
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner}) err := ormer.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner})
if err != nil { if err != nil {
return permissions, err return permissions, err
} }
@ -99,7 +96,7 @@ func getPermission(owner string, name string) (*Permission, error) {
} }
permission := Permission{Owner: owner, Name: name} permission := Permission{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&permission) existed, err := ormer.Engine.Get(&permission)
if err != nil { if err != nil {
return &permission, err return &permission, err
} }
@ -112,13 +109,13 @@ func getPermission(owner string, name string) (*Permission, error) {
} }
func GetPermission(id string) (*Permission, error) { func GetPermission(id string) (*Permission, error) {
owner, name := util.GetOwnerAndNameFromId(id) owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
return getPermission(owner, name) return getPermission(owner, name)
} }
// checkPermissionValid verifies if the permission is valid // checkPermissionValid verifies if the permission is valid
func checkPermissionValid(permission *Permission) error { func checkPermissionValid(permission *Permission) error {
enforcer := getEnforcer(permission) enforcer := getPermissionEnforcer(permission)
enforcer.EnableAutoSave(false) enforcer.EnableAutoSave(false)
policies := getPolicies(permission) policies := getPolicies(permission)
@ -149,13 +146,13 @@ func UpdatePermission(id string, permission *Permission) (bool, error) {
return false, err return false, err
} }
owner, name := util.GetOwnerAndNameFromId(id) owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
oldPermission, err := getPermission(owner, name) oldPermission, err := getPermission(owner, name)
if oldPermission == nil { if oldPermission == nil {
return false, nil return false, nil
} }
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(permission) affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(permission)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -164,9 +161,9 @@ func UpdatePermission(id string, permission *Permission) (bool, error) {
removeGroupingPolicies(oldPermission) removeGroupingPolicies(oldPermission)
removePolicies(oldPermission) removePolicies(oldPermission)
if oldPermission.Adapter != "" && oldPermission.Adapter != permission.Adapter { if oldPermission.Adapter != "" && oldPermission.Adapter != permission.Adapter {
isEmpty, _ := adapter.Engine.IsTableEmpty(oldPermission.Adapter) isEmpty, _ := ormer.Engine.IsTableEmpty(oldPermission.Adapter)
if isEmpty { if isEmpty {
err = adapter.Engine.DropTables(oldPermission.Adapter) err = ormer.Engine.DropTables(oldPermission.Adapter)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -180,7 +177,7 @@ func UpdatePermission(id string, permission *Permission) (bool, error) {
} }
func AddPermission(permission *Permission) (bool, error) { func AddPermission(permission *Permission) (bool, error) {
affected, err := adapter.Engine.Insert(permission) affected, err := ormer.Engine.Insert(permission)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -198,7 +195,7 @@ func AddPermissions(permissions []*Permission) bool {
return false return false
} }
affected, err := adapter.Engine.Insert(permissions) affected, err := ormer.Engine.Insert(permissions)
if err != nil { if err != nil {
if !strings.Contains(err.Error(), "Duplicate entry") { if !strings.Contains(err.Error(), "Duplicate entry") {
panic(err) panic(err)
@ -242,7 +239,7 @@ func AddPermissionsInBatch(permissions []*Permission) bool {
} }
func DeletePermission(permission *Permission) (bool, error) { func DeletePermission(permission *Permission) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{permission.Owner, permission.Name}).Delete(&Permission{}) affected, err := ormer.Engine.ID(core.PK{permission.Owner, permission.Name}).Delete(&Permission{})
if err != nil { if err != nil {
return false, err return false, err
} }
@ -251,9 +248,9 @@ func DeletePermission(permission *Permission) (bool, error) {
removeGroupingPolicies(permission) removeGroupingPolicies(permission)
removePolicies(permission) removePolicies(permission)
if permission.Adapter != "" && permission.Adapter != "permission_rule" { if permission.Adapter != "" && permission.Adapter != "permission_rule" {
isEmpty, _ := adapter.Engine.IsTableEmpty(permission.Adapter) isEmpty, _ := ormer.Engine.IsTableEmpty(permission.Adapter)
if isEmpty { if isEmpty {
err = adapter.Engine.DropTables(permission.Adapter) err = ormer.Engine.DropTables(permission.Adapter)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -266,7 +263,7 @@ func DeletePermission(permission *Permission) (bool, error) {
func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error) { func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error) {
permissions := []*Permission{} permissions := []*Permission{}
err := adapter.Engine.Where("users like ?", "%"+userId+"\"%").Find(&permissions) err := ormer.Engine.Where("users like ?", "%"+userId+"\"%").Find(&permissions)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -290,7 +287,7 @@ func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error)
for _, role := range roles { for _, role := range roles {
perms := []*Permission{} perms := []*Permission{}
err := adapter.Engine.Where("roles like ?", "%"+role.Name+"\"%").Find(&perms) err := ormer.Engine.Where("roles like ?", "%"+role.GetId()+"\"%").Find(&perms)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -310,7 +307,7 @@ func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error)
func GetPermissionsByRole(roleId string) ([]*Permission, error) { func GetPermissionsByRole(roleId string) ([]*Permission, error) {
permissions := []*Permission{} permissions := []*Permission{}
err := adapter.Engine.Where("roles like ?", "%"+roleId+"\"%").Find(&permissions) err := ormer.Engine.Where("roles like ?", "%"+roleId+"\"%").Find(&permissions)
if err != nil { if err != nil {
return permissions, err return permissions, err
} }
@ -320,7 +317,7 @@ func GetPermissionsByRole(roleId string) ([]*Permission, error) {
func GetPermissionsByResource(resourceId string) ([]*Permission, error) { func GetPermissionsByResource(resourceId string) ([]*Permission, error) {
permissions := []*Permission{} permissions := []*Permission{}
err := adapter.Engine.Where("resources like ?", "%"+resourceId+"\"%").Find(&permissions) err := ormer.Engine.Where("resources like ?", "%"+resourceId+"\"%").Find(&permissions)
if err != nil { if err != nil {
return permissions, err return permissions, err
} }
@ -330,7 +327,7 @@ func GetPermissionsByResource(resourceId string) ([]*Permission, error) {
func GetPermissionsBySubmitter(owner string, submitter string) ([]*Permission, error) { func GetPermissionsBySubmitter(owner string, submitter string) ([]*Permission, error) {
permissions := []*Permission{} permissions := []*Permission{}
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Submitter: submitter}) err := ormer.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Submitter: submitter})
if err != nil { if err != nil {
return permissions, err return permissions, err
} }
@ -340,7 +337,7 @@ func GetPermissionsBySubmitter(owner string, submitter string) ([]*Permission, e
func GetPermissionsByModel(owner string, model string) ([]*Permission, error) { func GetPermissionsByModel(owner string, model string) ([]*Permission, error) {
permissions := []*Permission{} permissions := []*Permission{}
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Model: model}) err := ormer.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Model: model})
if err != nil { if err != nil {
return permissions, err return permissions, err
} }

View File

@ -26,42 +26,7 @@ import (
xormadapter "github.com/casdoor/xorm-adapter/v3" xormadapter "github.com/casdoor/xorm-adapter/v3"
) )
func getEnforcer(permission *Permission, permissionIDs ...string) *casbin.Enforcer { func getPermissionEnforcer(p *Permission, permissionIDs ...string) *casbin.Enforcer {
tableName := "permission_rule"
if len(permission.Adapter) != 0 {
adapterObj, err := getCasbinAdapter(permission.Owner, permission.Adapter)
if err != nil {
panic(err)
}
if adapterObj != nil && adapterObj.Table != "" {
tableName = adapterObj.Table
}
}
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
driverName := conf.GetConfigString("driverName")
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
adapter, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, tableName, tableNamePrefix, true)
if err != nil {
panic(err)
}
permissionModel, err := getModel(permission.Owner, permission.Model)
if err != nil {
panic(err)
}
m := model.Model{}
if permissionModel != nil {
m, err = GetBuiltInModel(permissionModel.ModelText)
} else {
m, err = GetBuiltInModel("")
}
if err != nil {
panic(err)
}
// Init an enforcer instance without specifying a model or adapter. // Init an enforcer instance without specifying a model or adapter.
// If you specify an adapter, it will load all policies, which is a // If you specify an adapter, it will load all policies, which is a
// heavy process that can slow down the application. // heavy process that can slow down the application.
@ -70,14 +35,17 @@ func getEnforcer(permission *Permission, permissionIDs ...string) *casbin.Enforc
panic(err) panic(err)
} }
err = enforcer.InitWithModelAndAdapter(m, nil) err = p.setEnforcerModel(enforcer)
if err != nil { if err != nil {
panic(err) panic(err)
} }
enforcer.SetAdapter(adapter) err = p.setEnforcerAdapter(enforcer)
if err != nil {
panic(err)
}
policyFilterV5 := []string{permission.GetId()} policyFilterV5 := []string{p.GetId()}
if len(permissionIDs) != 0 { if len(permissionIDs) != 0 {
policyFilterV5 = permissionIDs policyFilterV5 = permissionIDs
} }
@ -86,7 +54,7 @@ func getEnforcer(permission *Permission, permissionIDs ...string) *casbin.Enforc
V5: policyFilterV5, V5: policyFilterV5,
} }
if !HasRoleDefinition(m) { if !HasRoleDefinition(enforcer.GetModel()) {
policyFilter.Ptype = []string{"p"} policyFilter.Ptype = []string{"p"}
} }
@ -98,35 +66,70 @@ func getEnforcer(permission *Permission, permissionIDs ...string) *casbin.Enforc
return enforcer return enforcer
} }
func (p *Permission) setEnforcerAdapter(enforcer *casbin.Enforcer) error {
tableName := "permission_rule"
if len(p.Adapter) != 0 {
adapterObj, err := getAdapter(p.Owner, p.Adapter)
if err != nil {
return err
}
if adapterObj != nil && adapterObj.Table != "" {
tableName = adapterObj.Table
}
}
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
driverName := conf.GetConfigString("driverName")
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
adapter, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, tableName, tableNamePrefix, true)
if err != nil {
return err
}
enforcer.SetAdapter(adapter)
return nil
}
func (p *Permission) setEnforcerModel(enforcer *casbin.Enforcer) error {
permissionModel, err := getModel(p.Owner, p.Model)
if err != nil {
return err
}
// TODO: return error if permissionModel is nil.
m := model.Model{}
if permissionModel != nil {
m, err = GetBuiltInModel(permissionModel.ModelText)
} else {
m, err = GetBuiltInModel("")
}
if err != nil {
return err
}
err = enforcer.InitWithModelAndAdapter(m, nil)
if err != nil {
return err
}
return nil
}
func getPolicies(permission *Permission) [][]string { func getPolicies(permission *Permission) [][]string {
var policies [][]string var policies [][]string
permissionId := permission.GetId() permissionId := permission.GetId()
domainExist := len(permission.Domains) > 0 domainExist := len(permission.Domains) > 0
for _, user := range permission.Users { usersAndRoles := append(permission.Users, permission.Roles...)
for _, userOrRole := range usersAndRoles {
for _, resource := range permission.Resources { for _, resource := range permission.Resources {
for _, action := range permission.Actions { for _, action := range permission.Actions {
if domainExist { if domainExist {
for _, domain := range permission.Domains { for _, domain := range permission.Domains {
policies = append(policies, []string{user, domain, resource, strings.ToLower(action), "", permissionId}) policies = append(policies, []string{userOrRole, domain, resource, strings.ToLower(action), strings.ToLower(permission.Effect), permissionId})
} }
} else { } else {
policies = append(policies, []string{user, resource, strings.ToLower(action), "", "", permissionId}) policies = append(policies, []string{userOrRole, resource, strings.ToLower(action), strings.ToLower(permission.Effect), "", permissionId})
}
}
}
}
for _, role := range permission.Roles {
for _, resource := range permission.Resources {
for _, action := range permission.Actions {
if domainExist {
for _, domain := range permission.Domains {
policies = append(policies, []string{role, domain, resource, strings.ToLower(action), "", permissionId})
}
} else {
policies = append(policies, []string{role, resource, strings.ToLower(action), "", "", permissionId})
} }
} }
} }
@ -201,7 +204,7 @@ func getGroupingPolicies(permission *Permission) [][]string {
} }
func addPolicies(permission *Permission) { func addPolicies(permission *Permission) {
enforcer := getEnforcer(permission) enforcer := getPermissionEnforcer(permission)
policies := getPolicies(permission) policies := getPolicies(permission)
_, err := enforcer.AddPolicies(policies) _, err := enforcer.AddPolicies(policies)
@ -211,7 +214,7 @@ func addPolicies(permission *Permission) {
} }
func addGroupingPolicies(permission *Permission) { func addGroupingPolicies(permission *Permission) {
enforcer := getEnforcer(permission) enforcer := getPermissionEnforcer(permission)
groupingPolicies := getGroupingPolicies(permission) groupingPolicies := getGroupingPolicies(permission)
if len(groupingPolicies) > 0 { if len(groupingPolicies) > 0 {
@ -223,7 +226,7 @@ func addGroupingPolicies(permission *Permission) {
} }
func removeGroupingPolicies(permission *Permission) { func removeGroupingPolicies(permission *Permission) {
enforcer := getEnforcer(permission) enforcer := getPermissionEnforcer(permission)
groupingPolicies := getGroupingPolicies(permission) groupingPolicies := getGroupingPolicies(permission)
if len(groupingPolicies) > 0 { if len(groupingPolicies) > 0 {
@ -235,7 +238,7 @@ func removeGroupingPolicies(permission *Permission) {
} }
func removePolicies(permission *Permission) { func removePolicies(permission *Permission) {
enforcer := getEnforcer(permission) enforcer := getPermissionEnforcer(permission)
policies := getPolicies(permission) policies := getPolicies(permission)
_, err := enforcer.RemovePolicies(policies) _, err := enforcer.RemovePolicies(policies)
@ -247,12 +250,12 @@ func removePolicies(permission *Permission) {
type CasbinRequest = []interface{} type CasbinRequest = []interface{}
func Enforce(permission *Permission, request *CasbinRequest, permissionIds ...string) (bool, error) { func Enforce(permission *Permission, request *CasbinRequest, permissionIds ...string) (bool, error) {
enforcer := getEnforcer(permission, permissionIds...) enforcer := getPermissionEnforcer(permission, permissionIds...)
return enforcer.Enforce(*request...) return enforcer.Enforce(*request...)
} }
func BatchEnforce(permission *Permission, requests *[]CasbinRequest, permissionIds ...string) ([]bool, error) { func BatchEnforce(permission *Permission, requests *[]CasbinRequest, permissionIds ...string) ([]bool, error) {
enforcer := getEnforcer(permission, permissionIds...) enforcer := getPermissionEnforcer(permission, permissionIds...)
return enforcer.BatchEnforce(*requests) return enforcer.BatchEnforce(*requests)
} }
@ -273,7 +276,7 @@ func getAllValues(userId string, fn func(enforcer *casbin.Enforcer) []string) []
var values []string var values []string
for _, permission := range permissions { for _, permission := range permissions {
enforcer := getEnforcer(permission) enforcer := getPermissionEnforcer(permission)
values = append(values, fn(enforcer)...) values = append(values, fn(enforcer)...)
} }
return values return values
@ -332,7 +335,7 @@ m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`
policyDefinition := strings.Split(cfg.String("policy_definition::p"), ",") policyDefinition := strings.Split(cfg.String("policy_definition::p"), ",")
fieldsNum := len(policyDefinition) fieldsNum := len(policyDefinition)
if fieldsNum > builtInAvailableField { if fieldsNum > builtInAvailableField {
panic(fmt.Errorf("the maximum policy_definition field number cannot exceed %d", builtInAvailableField)) panic(fmt.Errorf("the maximum policy_definition field number cannot exceed %d, got %d", builtInAvailableField, fieldsNum))
} }
// filled empty field with "" and V5 with "permissionId" // filled empty field with "" and V5 with "permissionId"
for i := builtInAvailableField - fieldsNum; i > 0; i-- { for i := builtInAvailableField - fieldsNum; i > 0; i-- {

View File

@ -44,7 +44,7 @@ func GetPlanCount(owner, field, value string) (int64, error) {
func GetPlans(owner string) ([]*Plan, error) { func GetPlans(owner string) ([]*Plan, error) {
plans := []*Plan{} plans := []*Plan{}
err := adapter.Engine.Desc("created_time").Find(&plans, &Plan{Owner: owner}) err := ormer.Engine.Desc("created_time").Find(&plans, &Plan{Owner: owner})
if err != nil { if err != nil {
return plans, err return plans, err
} }
@ -67,7 +67,7 @@ func getPlan(owner, name string) (*Plan, error) {
} }
plan := Plan{Owner: owner, Name: name} plan := Plan{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&plan) existed, err := ormer.Engine.Get(&plan)
if err != nil { if err != nil {
return &plan, err return &plan, err
} }
@ -91,7 +91,7 @@ func UpdatePlan(id string, plan *Plan) (bool, error) {
return false, nil return false, nil
} }
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(plan) affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(plan)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -100,7 +100,7 @@ func UpdatePlan(id string, plan *Plan) (bool, error) {
} }
func AddPlan(plan *Plan) (bool, error) { func AddPlan(plan *Plan) (bool, error) {
affected, err := adapter.Engine.Insert(plan) affected, err := ormer.Engine.Insert(plan)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -108,7 +108,7 @@ func AddPlan(plan *Plan) (bool, error) {
} }
func DeletePlan(plan *Plan) (bool, error) { func DeletePlan(plan *Plan) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{plan.Owner, plan.Name}).Delete(plan) affected, err := ormer.Engine.ID(core.PK{plan.Owner, plan.Name}).Delete(plan)
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -48,7 +48,7 @@ func GetPricingCount(owner, field, value string) (int64, error) {
func GetPricings(owner string) ([]*Pricing, error) { func GetPricings(owner string) ([]*Pricing, error) {
pricings := []*Pricing{} pricings := []*Pricing{}
err := adapter.Engine.Desc("created_time").Find(&pricings, &Pricing{Owner: owner}) err := ormer.Engine.Desc("created_time").Find(&pricings, &Pricing{Owner: owner})
if err != nil { if err != nil {
return pricings, err return pricings, err
} }
@ -72,7 +72,7 @@ func getPricing(owner, name string) (*Pricing, error) {
} }
pricing := Pricing{Owner: owner, Name: name} pricing := Pricing{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&pricing) existed, err := ormer.Engine.Get(&pricing)
if err != nil { if err != nil {
return &pricing, err return &pricing, err
} }
@ -96,7 +96,7 @@ func UpdatePricing(id string, pricing *Pricing) (bool, error) {
return false, nil return false, nil
} }
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(pricing) affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(pricing)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -105,7 +105,7 @@ func UpdatePricing(id string, pricing *Pricing) (bool, error) {
} }
func AddPricing(pricing *Pricing) (bool, error) { func AddPricing(pricing *Pricing) (bool, error) {
affected, err := adapter.Engine.Insert(pricing) affected, err := ormer.Engine.Insert(pricing)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -113,7 +113,7 @@ func AddPricing(pricing *Pricing) (bool, error) {
} }
func DeletePricing(pricing *Pricing) (bool, error) { func DeletePricing(pricing *Pricing) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{pricing.Owner, pricing.Name}).Delete(pricing) affected, err := ormer.Engine.ID(core.PK{pricing.Owner, pricing.Name}).Delete(pricing)
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -17,6 +17,8 @@ package object
import ( import (
"fmt" "fmt"
"github.com/casdoor/casdoor/pp"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
"github.com/xorm-io/core" "github.com/xorm-io/core"
) )
@ -50,7 +52,7 @@ func GetProductCount(owner, field, value string) (int64, error) {
func GetProducts(owner string) ([]*Product, error) { func GetProducts(owner string) ([]*Product, error) {
products := []*Product{} products := []*Product{}
err := adapter.Engine.Desc("created_time").Find(&products, &Product{Owner: owner}) err := ormer.Engine.Desc("created_time").Find(&products, &Product{Owner: owner})
if err != nil { if err != nil {
return products, err return products, err
} }
@ -75,7 +77,7 @@ func getProduct(owner string, name string) (*Product, error) {
} }
product := Product{Owner: owner, Name: name} product := Product{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&product) existed, err := ormer.Engine.Get(&product)
if err != nil { if err != nil {
return &product, nil return &product, nil
} }
@ -100,7 +102,7 @@ func UpdateProduct(id string, product *Product) (bool, error) {
return false, nil return false, nil
} }
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(product) affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(product)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -109,7 +111,7 @@ func UpdateProduct(id string, product *Product) (bool, error) {
} }
func AddProduct(product *Product) (bool, error) { func AddProduct(product *Product) (bool, error) {
affected, err := adapter.Engine.Insert(product) affected, err := ormer.Engine.Insert(product)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -118,7 +120,7 @@ func AddProduct(product *Product) (bool, error) {
} }
func DeleteProduct(product *Product) (bool, error) { func DeleteProduct(product *Product) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{product.Owner, product.Name}).Delete(&Product{}) affected, err := ormer.Engine.ID(core.PK{product.Owner, product.Name}).Delete(&Product{})
if err != nil { if err != nil {
return false, err return false, err
} }
@ -183,36 +185,39 @@ func BuyProduct(id string, providerName string, user *User, host string) (string
productDisplayName := product.DisplayName productDisplayName := product.DisplayName
originFrontend, originBackend := getOriginFromHost(host) originFrontend, originBackend := getOriginFromHost(host)
returnUrl := fmt.Sprintf("%s/payments/%s/result", originFrontend, paymentName) returnUrl := fmt.Sprintf("%s/payments/%s/%s/result", originFrontend, owner, paymentName)
notifyUrl := fmt.Sprintf("%s/api/notify-payment/%s/%s/%s/%s", originBackend, owner, providerName, productName, paymentName) notifyUrl := fmt.Sprintf("%s/api/notify-payment/%s/%s", originBackend, owner, paymentName)
// Create an Order and get the payUrl
payUrl, orderId, err := pProvider.Pay(providerName, productName, payerName, paymentName, productDisplayName, product.Price, product.Currency, returnUrl, notifyUrl) payUrl, orderId, err := pProvider.Pay(providerName, productName, payerName, paymentName, productDisplayName, product.Price, product.Currency, returnUrl, notifyUrl)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
// Create a Payment linked with Product and Order
payment := Payment{ payment := Payment{
Owner: product.Owner, Owner: product.Owner,
Name: paymentName, Name: paymentName,
CreatedTime: util.GetCurrentTime(), CreatedTime: util.GetCurrentTime(),
DisplayName: paymentName, DisplayName: paymentName,
Provider: provider.Name,
Type: provider.Type, Provider: provider.Name,
Organization: user.Owner, Type: provider.Type,
User: user.Name,
ProductName: productName, ProductName: productName,
ProductDisplayName: productDisplayName, ProductDisplayName: productDisplayName,
Detail: product.Detail, Detail: product.Detail,
Tag: product.Tag, Tag: product.Tag,
Currency: product.Currency, Currency: product.Currency,
Price: product.Price, Price: product.Price,
PayUrl: payUrl,
ReturnUrl: product.ReturnUrl, ReturnUrl: product.ReturnUrl,
State: "Created",
User: user.Name,
PayUrl: payUrl,
State: pp.PaymentStateCreated,
OutOrderId: orderId,
} }
if provider.Type == "Dummy" { if provider.Type == "Dummy" {
payment.State = "Paid" payment.State = pp.PaymentStatePaid
} }
affected, err := AddPayment(&payment) affected, err := AddPayment(&payment)

View File

@ -119,7 +119,7 @@ func GetGlobalProviderCount(field, value string) (int64, error) {
func GetProviders(owner string) ([]*Provider, error) { func GetProviders(owner string) ([]*Provider, error) {
providers := []*Provider{} providers := []*Provider{}
err := adapter.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&providers, &Provider{}) err := ormer.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&providers, &Provider{})
if err != nil { if err != nil {
return providers, err return providers, err
} }
@ -129,7 +129,7 @@ func GetProviders(owner string) ([]*Provider, error) {
func GetGlobalProviders() ([]*Provider, error) { func GetGlobalProviders() ([]*Provider, error) {
providers := []*Provider{} providers := []*Provider{}
err := adapter.Engine.Desc("created_time").Find(&providers) err := ormer.Engine.Desc("created_time").Find(&providers)
if err != nil { if err != nil {
return providers, err return providers, err
} }
@ -165,7 +165,7 @@ func getProvider(owner string, name string) (*Provider, error) {
} }
provider := Provider{Name: name} provider := Provider{Name: name}
existed, err := adapter.Engine.Get(&provider) existed, err := ormer.Engine.Get(&provider)
if err != nil { if err != nil {
return &provider, err return &provider, err
} }
@ -182,20 +182,6 @@ func GetProvider(id string) (*Provider, error) {
return getProvider(owner, name) return getProvider(owner, name)
} }
func getDefaultAiProvider() (*Provider, error) {
provider := Provider{Owner: "admin", Category: "AI"}
existed, err := adapter.Engine.Get(&provider)
if err != nil {
return &provider, err
}
if !existed {
return nil, nil
}
return &provider, nil
}
func GetWechatMiniProgramProvider(application *Application) *Provider { func GetWechatMiniProgramProvider(application *Application) *Provider {
providers := application.Providers providers := application.Providers
for _, provider := range providers { for _, provider := range providers {
@ -217,11 +203,11 @@ func UpdateProvider(id string, provider *Provider) (bool, error) {
if name != provider.Name { if name != provider.Name {
err := providerChangeTrigger(name, provider.Name) err := providerChangeTrigger(name, provider.Name)
if err != nil { if err != nil {
return false, nil return false, err
} }
} }
session := adapter.Engine.ID(core.PK{owner, name}).AllCols() session := ormer.Engine.ID(core.PK{owner, name}).AllCols()
if provider.ClientSecret == "***" { if provider.ClientSecret == "***" {
session = session.Omit("client_secret") session = session.Omit("client_secret")
} }
@ -229,7 +215,7 @@ func UpdateProvider(id string, provider *Provider) (bool, error) {
session = session.Omit("client_secret2") session = session.Omit("client_secret2")
} }
if provider.Type != "Keycloak" { if provider.Type == "Tencent Cloud COS" {
provider.Endpoint = util.GetEndPoint(provider.Endpoint) provider.Endpoint = util.GetEndPoint(provider.Endpoint)
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint) provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
} }
@ -243,12 +229,12 @@ func UpdateProvider(id string, provider *Provider) (bool, error) {
} }
func AddProvider(provider *Provider) (bool, error) { func AddProvider(provider *Provider) (bool, error) {
if provider.Type != "Keycloak" { if provider.Type == "Tencent Cloud COS" {
provider.Endpoint = util.GetEndPoint(provider.Endpoint) provider.Endpoint = util.GetEndPoint(provider.Endpoint)
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint) provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
} }
affected, err := adapter.Engine.Insert(provider) affected, err := ormer.Engine.Insert(provider)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -257,7 +243,7 @@ func AddProvider(provider *Provider) (bool, error) {
} }
func DeleteProvider(provider *Provider) (bool, error) { func DeleteProvider(provider *Provider) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{provider.Owner, provider.Name}).Delete(&Provider{}) affected, err := ormer.Engine.ID(core.PK{provider.Owner, provider.Name}).Delete(&Provider{})
if err != nil { if err != nil {
return false, err return false, err
} }
@ -268,7 +254,8 @@ func DeleteProvider(provider *Provider) (bool, error) {
func (p *Provider) getPaymentProvider() (pp.PaymentProvider, *Cert, error) { func (p *Provider) getPaymentProvider() (pp.PaymentProvider, *Cert, error) {
cert := &Cert{} cert := &Cert{}
if p.Cert != "" { if p.Cert != "" {
cert, err := getCert(p.Owner, p.Cert) var err error
cert, err = getCert(p.Owner, p.Cert)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -297,7 +284,7 @@ func (p *Provider) GetId() string {
func GetCaptchaProviderByOwnerName(applicationId, lang string) (*Provider, error) { func GetCaptchaProviderByOwnerName(applicationId, lang string) (*Provider, error) {
owner, name := util.GetOwnerAndNameFromId(applicationId) owner, name := util.GetOwnerAndNameFromId(applicationId)
provider := Provider{Owner: owner, Name: name, Category: "Captcha"} provider := Provider{Owner: owner, Name: name, Category: "Captcha"}
existed, err := adapter.Engine.Get(&provider) existed, err := ormer.Engine.Get(&provider)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -333,7 +320,7 @@ func GetCaptchaProviderByApplication(applicationId, isCurrentProvider, lang stri
} }
func providerChangeTrigger(oldName string, newName string) error { func providerChangeTrigger(oldName string, newName string) error {
session := adapter.Engine.NewSession() session := ormer.Engine.NewSession()
defer session.Close() defer session.Close()
err := session.Begin() err := session.Begin()
@ -342,7 +329,7 @@ func providerChangeTrigger(oldName string, newName string) error {
} }
var applications []*Application var applications []*Application
err = adapter.Engine.Find(&applications) err = ormer.Engine.Find(&applications)
if err != nil { if err != nil {
return err return err
} }

View File

@ -49,7 +49,7 @@ func (pi *ProviderItem) IsProviderVisible() bool {
if pi.Provider == nil { if pi.Provider == nil {
return false return false
} }
return pi.Provider.Category == "OAuth" || pi.Provider.Category == "SAML" return pi.Provider.Category == "OAuth" || pi.Provider.Category == "SAML" || pi.Provider.Category == "Web3"
} }
func (pi *ProviderItem) isProviderPrompted() bool { func (pi *ProviderItem) isProviderPrompted() bool {

View File

@ -96,7 +96,7 @@ func AddRecord(record *Record) bool {
fmt.Println(errWebhook) fmt.Println(errWebhook)
} }
affected, err := adapter.Engine.Insert(record) affected, err := ormer.Engine.Insert(record)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -111,7 +111,7 @@ func GetRecordCount(field, value string, filterRecord *Record) (int64, error) {
func GetRecords() ([]*Record, error) { func GetRecords() ([]*Record, error) {
records := []*Record{} records := []*Record{}
err := adapter.Engine.Desc("id").Find(&records) err := ormer.Engine.Desc("id").Find(&records)
if err != nil { if err != nil {
return records, err return records, err
} }
@ -132,7 +132,7 @@ func GetPaginationRecords(offset, limit int, field, value, sortField, sortOrder
func GetRecordsByField(record *Record) ([]*Record, error) { func GetRecordsByField(record *Record) ([]*Record, error) {
records := []*Record{} records := []*Record{}
err := adapter.Engine.Find(&records, record) err := ormer.Engine.Find(&records, record)
if err != nil { if err != nil {
return records, err return records, err
} }
@ -161,7 +161,8 @@ func SendWebhooks(record *Record) error {
if matched { if matched {
if webhook.IsUserExtended { if webhook.IsUserExtended {
user, err := GetMaskedUser(getUser(record.Organization, record.User)) user, err := getUser(record.Organization, record.User)
user, err = GetMaskedUser(user, false, err)
if err != nil { if err != nil {
return err return err
} }

View File

@ -16,6 +16,7 @@ package object
import ( import (
"fmt" "fmt"
"strings"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
"github.com/xorm-io/core" "github.com/xorm-io/core"
@ -45,13 +46,13 @@ func GetResourceCount(owner, user, field, value string) (int64, error) {
} }
func GetResources(owner string, user string) ([]*Resource, error) { func GetResources(owner string, user string) ([]*Resource, error) {
if owner == "built-in" { if owner == "built-in" || owner == "" {
owner = "" owner = ""
user = "" user = ""
} }
resources := []*Resource{} resources := []*Resource{}
err := adapter.Engine.Desc("created_time").Find(&resources, &Resource{Owner: owner, User: user}) err := ormer.Engine.Desc("created_time").Find(&resources, &Resource{Owner: owner, User: user})
if err != nil { if err != nil {
return resources, err return resources, err
} }
@ -60,7 +61,7 @@ func GetResources(owner string, user string) ([]*Resource, error) {
} }
func GetPaginationResources(owner, user string, offset, limit int, field, value, sortField, sortOrder string) ([]*Resource, error) { func GetPaginationResources(owner, user string, offset, limit int, field, value, sortField, sortOrder string) ([]*Resource, error) {
if owner == "built-in" { if owner == "built-in" || owner == "" {
owner = "" owner = ""
user = "" user = ""
} }
@ -76,8 +77,12 @@ func GetPaginationResources(owner, user string, offset, limit int, field, value,
} }
func getResource(owner string, name string) (*Resource, error) { func getResource(owner string, name string) (*Resource, error) {
if !strings.HasPrefix(name, "/") {
name = "/" + name
}
resource := Resource{Owner: owner, Name: name} resource := Resource{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&resource) existed, err := ormer.Engine.Get(&resource)
if err != nil { if err != nil {
return &resource, err return &resource, err
} }
@ -102,7 +107,7 @@ func UpdateResource(id string, resource *Resource) (bool, error) {
return false, nil return false, nil
} }
_, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(resource) _, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(resource)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -112,7 +117,7 @@ func UpdateResource(id string, resource *Resource) (bool, error) {
} }
func AddResource(resource *Resource) (bool, error) { func AddResource(resource *Resource) (bool, error) {
affected, err := adapter.Engine.Insert(resource) affected, err := ormer.Engine.Insert(resource)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -121,7 +126,7 @@ func AddResource(resource *Resource) (bool, error) {
} }
func DeleteResource(resource *Resource) (bool, error) { func DeleteResource(resource *Resource) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{resource.Owner, resource.Name}).Delete(&Resource{}) affected, err := ormer.Engine.ID(core.PK{resource.Owner, resource.Name}).Delete(&Resource{})
if err != nil { if err != nil {
return false, err return false, err
} }

46
object/resource_direct.go Normal file
View File

@ -0,0 +1,46 @@
// 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"
"time"
"github.com/casdoor/casdoor/util"
)
func GetDirectResources(owner string, user string, provider *Provider, prefix string, lang string) ([]*Resource, error) {
storageProvider, err := getStorageProvider(provider, lang)
if err != nil {
return nil, err
}
res := []*Resource{}
objects, err := storageProvider.List(prefix)
for _, obj := range objects {
resource := &Resource{
Owner: owner,
Name: strings.TrimPrefix(obj.Path, "/"),
CreatedTime: obj.LastModified.Local().Format(time.RFC3339),
User: user,
Provider: "",
Application: "",
FileSize: int(obj.Size),
Url: util.UrlJoin(provider.Domain, obj.Path),
}
res = append(res, resource)
}
return res, err
}

View File

@ -44,7 +44,7 @@ func GetRoleCount(owner, field, value string) (int64, error) {
func GetRoles(owner string) ([]*Role, error) { func GetRoles(owner string) ([]*Role, error) {
roles := []*Role{} roles := []*Role{}
err := adapter.Engine.Desc("created_time").Find(&roles, &Role{Owner: owner}) err := ormer.Engine.Desc("created_time").Find(&roles, &Role{Owner: owner})
if err != nil { if err != nil {
return roles, err return roles, err
} }
@ -69,7 +69,7 @@ func getRole(owner string, name string) (*Role, error) {
} }
role := Role{Owner: owner, Name: name} role := Role{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&role) existed, err := ormer.Engine.Get(&role)
if err != nil { if err != nil {
return &role, err return &role, err
} }
@ -82,12 +82,12 @@ func getRole(owner string, name string) (*Role, error) {
} }
func GetRole(id string) (*Role, error) { func GetRole(id string) (*Role, error) {
owner, name := util.GetOwnerAndNameFromId(id) owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
return getRole(owner, name) return getRole(owner, name)
} }
func UpdateRole(id string, role *Role) (bool, error) { func UpdateRole(id string, role *Role) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id) owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
oldRole, err := getRole(owner, name) oldRole, err := getRole(owner, name)
if err != nil { if err != nil {
return false, err return false, err
@ -133,11 +133,11 @@ func UpdateRole(id string, role *Role) (bool, error) {
if name != role.Name { if name != role.Name {
err := roleChangeTrigger(name, role.Name) err := roleChangeTrigger(name, role.Name)
if err != nil { if err != nil {
return false, nil return false, err
} }
} }
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(role) affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(role)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -178,7 +178,7 @@ func UpdateRole(id string, role *Role) (bool, error) {
} }
func AddRole(role *Role) (bool, error) { func AddRole(role *Role) (bool, error) {
affected, err := adapter.Engine.Insert(role) affected, err := ormer.Engine.Insert(role)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -190,7 +190,7 @@ func AddRoles(roles []*Role) bool {
if len(roles) == 0 { if len(roles) == 0 {
return false return false
} }
affected, err := adapter.Engine.Insert(roles) affected, err := ormer.Engine.Insert(roles)
if err != nil { if err != nil {
if !strings.Contains(err.Error(), "Duplicate entry") { if !strings.Contains(err.Error(), "Duplicate entry") {
panic(err) panic(err)
@ -240,7 +240,7 @@ func DeleteRole(role *Role) (bool, error) {
} }
} }
affected, err := adapter.Engine.ID(core.PK{role.Owner, role.Name}).Delete(&Role{}) affected, err := ormer.Engine.ID(core.PK{role.Owner, role.Name}).Delete(&Role{})
if err != nil { if err != nil {
return false, err return false, err
} }
@ -254,7 +254,7 @@ func (role *Role) GetId() string {
func GetRolesByUser(userId string) ([]*Role, error) { func GetRolesByUser(userId string) ([]*Role, error) {
roles := []*Role{} roles := []*Role{}
err := adapter.Engine.Where("users like ?", "%"+userId+"\"%").Find(&roles) err := ormer.Engine.Where("users like ?", "%"+userId+"\"%").Find(&roles)
if err != nil { if err != nil {
return roles, err return roles, err
} }
@ -278,7 +278,7 @@ func GetRolesByUser(userId string) ([]*Role, error) {
} }
func roleChangeTrigger(oldName string, newName string) error { func roleChangeTrigger(oldName string, newName string) error {
session := adapter.Engine.NewSession() session := ormer.Engine.NewSession()
defer session.Close() defer session.Close()
err := session.Begin() err := session.Begin()
@ -287,7 +287,7 @@ func roleChangeTrigger(oldName string, newName string) error {
} }
var roles []*Role var roles []*Role
err = adapter.Engine.Find(&roles) err = ormer.Engine.Find(&roles)
if err != nil { if err != nil {
return err return err
} }
@ -306,7 +306,7 @@ func roleChangeTrigger(oldName string, newName string) error {
} }
var permissions []*Permission var permissions []*Permission
err = adapter.Engine.Find(&permissions) err = ormer.Engine.Find(&permissions)
if err != nil { if err != nil {
return err return err
} }
@ -338,7 +338,7 @@ func GetMaskedRoles(roles []*Role) []*Role {
func GetRolesByNamePrefix(owner string, prefix string) ([]*Role, error) { func GetRolesByNamePrefix(owner string, prefix string) ([]*Role, error) {
roles := []*Role{} roles := []*Role{}
err := adapter.Engine.Where("owner=? and name like ?", owner, prefix+"%").Find(&roles) err := ormer.Engine.Where("owner=? and name like ?", owner, prefix+"%").Find(&roles)
if err != nil { if err != nil {
return roles, err return roles, err
} }
@ -391,10 +391,13 @@ func GetAncestorRoles(roleIds ...string) ([]*Role, error) {
// containsRole is a helper function to check if a roles is related to any role in the given list roles // containsRole is a helper function to check if a roles is related to any role in the given list roles
func containsRole(role *Role, roleMap map[string]*Role, visited map[string]bool, roleIds ...string) bool { func containsRole(role *Role, roleMap map[string]*Role, visited map[string]bool, roleIds ...string) bool {
if isContain, ok := visited[role.GetId()]; ok { roleId := role.GetId()
if isContain, ok := visited[roleId]; ok {
return isContain return isContain
} }
visited[role.GetId()] = false
for _, subRole := range role.Roles { for _, subRole := range role.Roles {
if util.HasString(roleIds, subRole) { if util.HasString(roleIds, subRole) {
return true return true

View File

@ -40,9 +40,9 @@ func GetSessions(owner string) ([]*Session, error) {
sessions := []*Session{} sessions := []*Session{}
var err error var err error
if owner != "" { if owner != "" {
err = adapter.Engine.Desc("created_time").Where("owner = ?", owner).Find(&sessions) err = ormer.Engine.Desc("created_time").Where("owner = ?", owner).Find(&sessions)
} else { } else {
err = adapter.Engine.Desc("created_time").Find(&sessions) err = ormer.Engine.Desc("created_time").Find(&sessions)
} }
if err != nil { if err != nil {
return sessions, err return sessions, err
@ -70,7 +70,7 @@ func GetSessionCount(owner, field, value string) (int64, error) {
func GetSingleSession(id string) (*Session, error) { func GetSingleSession(id string) (*Session, error) {
owner, name, application := util.GetOwnerAndNameAndOtherFromId(id) owner, name, application := util.GetOwnerAndNameAndOtherFromId(id)
session := Session{Owner: owner, Name: name, Application: application} session := Session{Owner: owner, Name: name, Application: application}
get, err := adapter.Engine.Get(&session) get, err := ormer.Engine.Get(&session)
if err != nil { if err != nil {
return &session, err return &session, err
} }
@ -91,7 +91,7 @@ func UpdateSession(id string, session *Session) (bool, error) {
return false, nil return false, nil
} }
affected, err := adapter.Engine.ID(core.PK{owner, name, application}).Update(session) affected, err := ormer.Engine.ID(core.PK{owner, name, application}).Update(session)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -114,7 +114,7 @@ func AddSession(session *Session) (bool, error) {
if dbSession == nil { if dbSession == nil {
session.CreatedTime = util.GetCurrentTime() session.CreatedTime = util.GetCurrentTime()
affected, err := adapter.Engine.Insert(session) affected, err := ormer.Engine.Insert(session)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -150,7 +150,7 @@ func DeleteSession(id string) (bool, error) {
} }
} }
affected, err := adapter.Engine.ID(core.PK{owner, name, application}).Delete(&Session{}) affected, err := ormer.Engine.ID(core.PK{owner, name, application}).Delete(&Session{})
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -24,8 +24,10 @@ func getSmsClient(provider *Provider) (sender.SmsClient, error) {
var client sender.SmsClient var client sender.SmsClient
var err error var err error
if provider.Type == sender.HuaweiCloud { if provider.Type == sender.HuaweiCloud || provider.Type == sender.AzureACS {
client, err = sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.ProviderUrl, provider.AppId) client, err = sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.ProviderUrl, provider.AppId)
} else if provider.Type == "Custom HTTP SMS" {
client, err = newHttpSmsClient(provider.Endpoint, provider.Method, provider.ClientId, provider.Title)
} else { } else {
client, err = sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.AppId) client, err = sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.AppId)
} }
@ -42,7 +44,11 @@ func SendSms(provider *Provider, content string, phoneNumbers ...string) error {
return err return err
} }
if provider.Type == sender.Aliyun { if provider.Type == sender.Twilio {
if provider.AppId != "" {
phoneNumbers = append([]string{provider.AppId}, phoneNumbers...)
}
} else if provider.Type == sender.Aliyun {
for i, number := range phoneNumbers { for i, number := range phoneNumbers {
phoneNumbers[i] = strings.TrimPrefix(number, "+86") phoneNumbers[i] = strings.TrimPrefix(number, "+86")
} }

75
object/sms_custom.go Normal file
View File

@ -0,0 +1,75 @@
// 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 (
"bytes"
"fmt"
"net/http"
"github.com/casdoor/casdoor/proxy"
)
type HttpSmsClient struct {
endpoint string
method string
paramName string
text string
}
func newHttpSmsClient(endpoint string, method string, paramName string, text string) (*HttpSmsClient, error) {
client := &HttpSmsClient{
endpoint: endpoint,
method: method,
paramName: paramName,
text: text,
}
return client, nil
}
func (c *HttpSmsClient) SendMessage(param map[string]string, targetPhoneNumber ...string) error {
var err error
content := param["code"]
httpClient := proxy.DefaultHttpClient
req, err := http.NewRequest(c.method, c.endpoint, bytes.NewBufferString(content))
if err != nil {
return err
}
if c.method == "POST" {
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.PostForm = map[string][]string{
c.paramName: {content},
}
} else if c.method == "GET" {
q := req.URL.Query()
q.Add(c.paramName, content)
req.URL.RawQuery = q.Encode()
}
resp, err := httpClient.Do(req)
if err != nil {
return err
}
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 err
}

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