Compare commits

...

93 Commits

Author SHA1 Message Date
f6f4d44444 feat: remove url.JoinPath() to be compatible with Go 1.17 (#1995) 2023-06-20 17:44:40 +08:00
926e73ed1b fix: fix "Accept-Language" parsing in request (#1996) 2023-06-20 17:43:48 +08:00
65716af89e feat: deprecate the user group relation table (#1990)
* fix: deprecate the user group relation table

* fix: clean code

* fix: fix trigger

* Update group.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-06-19 19:08:45 +08:00
d9c4f401e3 Fix error in downloadImage() 2023-06-19 17:52:01 +08:00
58aa7dba6a Fix groups in GetUserInfo() 2023-06-19 11:06:55 +08:00
29fc820578 Set User.groups to [] 2023-06-19 09:42:17 +08:00
d0ac265c91 fix: Deprecate the id field in group (#1987) 2023-06-18 23:33:13 +08:00
3562c36817 feat: Revert "fix: fix URL path in MinIO storage provider" (#1988)
This reverts commit 3699177837.
2023-06-18 23:08:40 +08:00
7884e10ca3 Refactor adapter's owner and organization 2023-06-18 00:22:12 +08:00
12dee8afd3 Fix null options in checkPasswordComplexity() 2023-06-17 22:38:02 +08:00
ac4b870309 Improve getFaviconFileBuffer() 2023-06-17 12:50:01 +08:00
b9140e2d5a Refactor refreshAvatar() 2023-06-17 11:43:46 +08:00
501f0dc74f Add user_avatar.go 2023-06-17 01:25:15 +08:00
a932b76fba Remove useless check in SetPassword() 2023-06-17 00:58:31 +08:00
0f57ac297b ci: add password complexity options to organization edit page (#1949)
* Support uploading roles and permissions via xlsx file.

* Template xlsx file for uploading users and permissions.

* reformat according to gofumpt.

* fix typo.

* add password complexity options to organization edit page.

* add password complexity options to organization edit page.

* Fixed Typos.

* Fixed Typos.

* feat:add password complexity options to organization edit page

* Auto generate i18n fields.

* Refactor code according to instructions

* Support autocheck passwd complexity in frontend when setting passwd in user edit page.

* feat:Backend Support for password validation in signup and forget page.

* feat:Frontend Support for password validation in signup and forget page.

* Add default password complex option & Update historical empty filed with default option.

* Migrator for field `password_complex_options` in org table.

* feat: support frontend password complex option check in user_edit/forget/signup page.

* frontend update for user edit page

* update i18n file

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-06-17 00:07:36 +08:00
edc6aa0d50 feat: get all role/permission of an user (#1978) 2023-06-16 22:44:21 +08:00
ebc0e0f2c9 Update i18n words 2023-06-16 22:06:54 +08:00
63dd2e781e Update backend i18n files 2023-06-16 21:55:08 +08:00
b01ba792bb Rename to accessSecret 2023-06-16 20:42:15 +08:00
98fb9f25b0 feat: fix bug that users in role don't work for permissions (#1977)
* feat: fix check login permission

* feat: fix check login permission
2023-06-16 20:14:27 +08:00
cc456f265f feat: fix LDAP user password checking logic in GetOAuthToken() (#1975) 2023-06-15 21:04:09 +08:00
7058a34f87 feat: complete group tree (#1967)
* feat: complete group tree

* feat: ui

* fix: i18n

* refactor code

* fix: support remove user from group

* fix: format code

* Update organization.go

* Update organization.go

* Update user_group.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-06-14 23:27:46 +08:00
8e6755845f ci: fix bug in PaypalPaymentProvider (#1972) 2023-06-13 23:33:03 +08:00
967fa4be68 feat: add access key and secret key for user (#1971) 2023-06-13 22:18:17 +08:00
805cf20d04 feat: fix incorrect VerifyTypePhone value (#1968) 2023-06-13 17:26:37 +08:00
2a8001f490 fix: clean timeout when componentWillUnmount in PaymentResult page (#1962) 2023-06-13 02:00:52 +08:00
451fc9034f fix: fix bug in PayPal payment provider (#1959) 2023-06-12 13:43:37 +08:00
0e14a2597e feat: Add tree structure to organization page (#1910)
* rebase master

* feat: add group in userEditPage

* feat: use id as the pk

* feat: add groups item in user

* feat: add tree component

* rebase

* feat: ui

* fix: fix some bug

* fix: route

* fix: ui

* fix: improve ui
2023-06-12 09:27:16 +08:00
ff87c4ea33 feat: fix createDatabase arg not recognized bug 2023-06-12 01:57:58 +08:00
4f5396c70e Check error for CreateDatabase() 2023-06-12 01:47:26 +08:00
3c30222fce Fix payment owner issue 2023-06-12 00:34:41 +08:00
2d04731622 Provide default value for logConfig 2023-06-10 15:59:56 +08:00
e0d2bc3dc9 Return error in GetProviderFromContext() 2023-06-10 15:51:26 +08:00
0bda29f143 feat: show 404 error for non-existent objects in edit pages 2023-06-10 01:56:15 +08:00
05703720c5 Add Custom to resourceType 2023-06-09 21:52:30 +08:00
cc566bf31f Move DoMigration() after CreateTables() 2023-06-09 09:36:20 +08:00
e93d8c19d9 feat: resolve user pages malfunction after using tableNamePrefix (#1945) 2023-06-08 00:43:05 +08:00
f2e3182a69 Fix null value in backend Translate() 2023-06-07 02:17:48 +08:00
f934531083 Fix organization search in some pages 2023-06-06 20:53:45 +08:00
e1c0af345f feat: resolve casdoor as SAML SP with keycloak login not work bug (#1937)
* fix: resolve casdoor as SAML SP with keycloak login not work

* Update provider.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-06-06 15:19:00 +08:00
3b3bfe39f9 Fix user field bug 2023-06-06 14:59:50 +08:00
18cc952f8e feat: Customization of the initialization file (#1936) 2023-06-05 21:00:28 +08:00
43439bc8c6 Apply tableNamePrefix before migration 2023-06-05 00:30:48 +08:00
9a2800e3b3 Add error to Enforce() 2023-06-04 17:29:34 +08:00
fdaad2b608 chore: refactor enforce() handler and update Swagger docs (#1931)
* chore: add swaggerof enforce api

* Update enforcer.go

* Update string.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-06-04 17:19:58 +08:00
2d43fe0b39 Fix cert empty issue in GetSamlMeta() 2023-06-04 01:25:18 +08:00
5d776a3ce6 fix: handle error of list in frontend (#1930) 2023-06-04 01:21:24 +08:00
5ec7a54bf8 Add description fields to objects 2023-06-04 01:21:17 +08:00
0c118477e8 Add groups to UserInfo 2023-06-04 01:21:10 +08:00
c858d0e0b0 Fix model page bug 2023-06-03 10:35:58 +08:00
9cffb43265 Fix subscription page bugs 2023-06-03 10:15:29 +08:00
51a76518ad Init adapter in getEnabledSyncerForOrganization() 2023-06-03 09:23:36 +08:00
08dbbab70e feat: revert "feat: fix the bug that sycner does not initialize" (#1926)
This reverts commit ec3c24ba68.
2023-06-03 09:17:34 +08:00
0ec22ae6ff Fix null bug in getLanguage() 2023-06-03 00:29:08 +08:00
ec3c24ba68 feat: fix the bug that sycner does not initialize (#1924) 2023-06-03 00:15:28 +08:00
ed688efdbb Fix bug in org user list page 2023-06-02 22:09:18 +08:00
06543a01d3 Add organization to /userinfo 2023-06-02 21:51:05 +08:00
70c372c3f7 Fix Provider API responses 2023-06-02 11:49:38 +08:00
b1b3184e75 Speed up user pagination query 2023-06-01 22:55:44 +08:00
5349fa7ff3 Speed up object.DoMigration() 2023-06-01 22:25:19 +08:00
9147225956 feat: fix table sticky columns on chat and message pages (#1917) 2023-06-01 21:02:21 +08:00
11f3af1ede Improve Select modes 2023-05-31 17:36:11 +08:00
0aa4df40c6 Fix i18n 2023-05-31 11:46:03 +08:00
7caa885131 Fix subscription bugs 2023-05-31 11:33:01 +08:00
f4b69cad9b Add owner to select-plan page 2023-05-31 00:29:54 +08:00
fb1db7823b Add DummyPaymentProvider 2023-05-30 23:25:58 +08:00
10e66f8020 fix: Get logger configuration from app.conf file (#1907)
* feat: Get logger configuration from file

* feat: Get logger configuration from file

* Remove GetConfigLogs()
2023-05-30 21:30:09 +08:00
4c8648d323 Add PaypalPaymentProvider 2023-05-30 20:32:05 +08:00
02e692a300 feat: return most backend API errors to frontend (#1836)
* feat: return most backend API errros to frontend

Signed-off-by: yehong <239859435@qq.com>

* refactor: reduce int type change

Signed-off-by: yehong <239859435@qq.com>

* feat: return err backend in token.go

Signed-off-by: yehong <239859435@qq.com>

---------

Signed-off-by: yehong <239859435@qq.com>
2023-05-30 15:49:39 +08:00
34151c0095 feat: Support uploading roles and permssions via xlsx files. (#1899)
* Support uploading roles and permissions via xlsx file.

* Template xlsx file for uploading users and permissions.

* reformat according to gofumpt.

* fix typo.
2023-05-28 11:29:43 +08:00
c7cea331e2 Improve NewWechatPaymentProvider() arg 2023-05-27 19:28:24 +08:00
8ede4993af feat: specify login organization 2023-05-27 19:02:54 +08:00
d04dd33d8b refactor: New Crowdin Backend translations by Github Action 2023-05-27 09:52:47 +00:00
8cb21253f6 refactor: New Crowdin translations by Github Action 2023-05-27 09:52:19 +00:00
7fc697b711 ci: fix bug in WeChat payment provider 2023-05-27 17:50:56 +08:00
80e6e7f0a7 fix: fix bug about updating parent component value in CountryCodeSelect (#1891) 2023-05-25 10:45:13 +08:00
d29fc88d68 Add getRawGetParameter() 2023-05-25 09:47:39 +08:00
225e9cf70a fix: set initial value in CountryCodeSelect (#1890) 2023-05-24 23:27:04 +08:00
c57c6e37dd Fix bug in getRedirectUri() 2023-05-24 23:22:25 +08:00
4d860525bf feat: fix MFA page bug in OAuth login (#1889) 2023-05-24 21:31:03 +08:00
a64263f812 Support "#" in redirectUri 2023-05-24 21:29:45 +08:00
95ab2472ce Make logo length to 200 2023-05-23 21:57:35 +08:00
54e4747dbc refactor: code-optimization (#1885)
* refactor: code-optimization

* fix: restoring code style

* fix: gofmt
2023-05-23 17:54:51 +08:00
2389d47c34 Fix getFormattedDate() 2023-05-23 15:09:53 +08:00
9c4f0f042e fix: update Go dependencies (#1880)
* Vulnerability fix : CVE-2021-30080  CVE-2021-39391 CVE-2022-41723 CVE-2022-21698  CVE-2023-26483 etc.

* fix: CVE-2021-30080  CVE-2021-39391 CVE-2022-41723 CVE-2022-21698  CVE-2023-26483 etc.
2023-05-23 14:43:18 +08:00
e25e210b06 Improve upload resource page 2023-05-23 10:07:59 +08:00
df61a536c1 feat: add gzip support for static filter (#1875)
* feat: add gzip support for static filter

* Update static_filter.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-05-22 22:40:46 +08:00
47da3cdaa0 fix: resolve get resource list problem (#1877) 2023-05-22 22:35:12 +08:00
8d246f2d98 ci: revert "feat: fix UI in IE11" (#1879)
This reverts commit 44cd55e55f.
2023-05-22 22:21:56 +08:00
44cd55e55f feat: fix UI in IE11 (#1878) 2023-05-22 16:59:37 +08:00
6b42d35223 Fix state encoding for Moodle 2023-05-21 15:47:18 +08:00
c84150cede Fix getObject() bug for some API 2023-05-21 11:07:01 +08:00
de2689ac39 fix: revert "feat: fix UI in IE11" (#1873)
* Revert "feat: fix UI in IE11 (#1871)"

This reverts commit 319031da28.

* Update MfaVerifyForm.js
2023-05-21 00:43:42 +08:00
240 changed files with 10664 additions and 3445 deletions

4
.gitignore vendored
View File

@ -29,4 +29,6 @@ lastupdate.tmp
commentsRouter*.go
# ignore build result
casdoor
casdoor
server_linux_arm64
server_linux_amd64

View File

@ -124,9 +124,9 @@ p, *, *, GET, /api/get-release, *, *
p, *, *, GET, /api/get-default-application, *, *
p, *, *, GET, /api/get-prometheus-info, *, *
p, *, *, *, /api/metrics, *, *
p, *, *, GET, /api/get-subscriptions, *, *
p, *, *, GET, /api/get-pricing, *, *
p, *, *, GET, /api/get-plan, *, *
p, *, *, GET, /api/get-organization-names, *, *
`
sa := stringadapter.NewAdapter(ruleText)
@ -153,7 +153,11 @@ func IsAllowed(subOwner string, subName string, method string, urlPath string, o
}
}
user := object.GetUser(util.GetId(subOwner, subName))
user, err := object.GetUser(util.GetId(subOwner, subName))
if err != nil {
panic(err)
}
if user != nil && user.IsAdmin && (subOwner == objOwner || (objOwner == "admin")) {
return true
}

View File

@ -21,3 +21,5 @@ isDemoMode = false
batchSize = 100
ldapServerPort = 389
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
initDataFile = "./init_data.json"

View File

@ -16,7 +16,6 @@ package conf
import (
"encoding/json"
"fmt"
"os"
"runtime"
"strconv"
@ -67,20 +66,21 @@ func GetConfigString(key string) string {
if res == "" {
if key == "staticBaseUrl" {
res = "https://cdn.casbin.org"
} else if key == "logConfig" {
res = "{\"filename\": \"logs/casdoor.log\", \"maxdays\":99999, \"perm\":\"0770\"}"
}
}
return res
}
func GetConfigBool(key string) (bool, error) {
func GetConfigBool(key string) bool {
value := GetConfigString(key)
if value == "true" {
return true, nil
} else if value == "false" {
return false, nil
return true
} else {
return false
}
return false, fmt.Errorf("value %s cannot be converted into bool", value)
}
func GetConfigInt64(key string) (int64, error) {
@ -110,10 +110,10 @@ func GetLanguage(language string) string {
return "en"
}
if len(language) < 2 {
if len(language) != 2 {
return "en"
} else {
return language[0:2]
return language
}
}

View File

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

View File

@ -78,13 +78,23 @@ func (c *ApiController) Signup() {
return
}
application := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error())
return
}
if !application.EnableSignUp {
c.ResponseError(c.T("account:The application does not allow to sign up new account"))
return
}
organization := object.GetOrganization(util.GetId("admin", authForm.Organization))
organization, err := object.GetOrganization(util.GetId("admin", authForm.Organization))
if err != nil {
c.ResponseError(c.T(err.Error()))
return
}
msg := object.CheckUserSignup(application, organization, &authForm, c.GetAcceptLanguage())
if msg != "" {
c.ResponseError(msg)
@ -111,7 +121,11 @@ func (c *ApiController) Signup() {
id := util.GenerateId()
if application.GetSignupItemRule("ID") == "Incremental" {
lastUser := object.GetLastUser(authForm.Organization)
lastUser, err := object.GetLastUser(authForm.Organization)
if err != nil {
c.ResponseError(err.Error())
return
}
lastIdInt := -1
if lastUser != nil {
@ -126,6 +140,13 @@ func (c *ApiController) Signup() {
username = id
}
password := authForm.Password
msg = object.CheckPasswordComplexityByOrg(organization, password)
if msg != "" {
c.ResponseError(msg)
return
}
initScore, err := organization.GetInitScore()
if err != nil {
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
@ -173,25 +194,47 @@ func (c *ApiController) Signup() {
}
}
affected := object.AddUser(user)
affected, err := object.AddUser(user)
if err != nil {
c.ResponseError(err.Error())
return
}
if !affected {
c.ResponseError(c.T("account:Failed to add user"), util.StructToJson(user))
return
}
object.AddUserToOriginalDatabase(user)
err = object.AddUserToOriginalDatabase(user)
if err != nil {
c.ResponseError(err.Error())
return
}
if application.HasPromptPage() {
// The prompt page needs the user to be signed in
c.SetSessionUsername(user.GetId())
}
object.DisableVerificationCode(authForm.Email)
object.DisableVerificationCode(checkPhone)
err = object.DisableVerificationCode(authForm.Email)
if err != nil {
c.ResponseError(err.Error())
return
}
err = object.DisableVerificationCode(checkPhone)
if err != nil {
c.ResponseError(err.Error())
return
}
isSignupFromPricing := authForm.Plan != "" && authForm.Pricing != ""
if isSignupFromPricing {
object.Subscribe(organization.Name, user.Name, authForm.Plan, authForm.Pricing)
_, err = object.Subscribe(organization.Name, user.Name, authForm.Plan, authForm.Pricing)
if err != nil {
c.ResponseError(err.Error())
return
}
}
record := object.NewRecord(c.Ctx)
@ -231,7 +274,11 @@ func (c *ApiController) Logout() {
c.ClearUserSession()
owner, username := util.GetOwnerAndNameFromId(user)
object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID())
_, err := object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID())
if err != nil {
c.ResponseError(err.Error())
return
}
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
@ -252,7 +299,12 @@ func (c *ApiController) Logout() {
return
}
affected, application, token := object.ExpireTokenByAccessToken(accessToken)
affected, application, token, err := object.ExpireTokenByAccessToken(accessToken)
if err != nil {
c.ResponseError(err.Error())
return
}
if !affected {
c.ResponseError(c.T("token:Token not found, invalid accessToken"))
return
@ -272,7 +324,12 @@ func (c *ApiController) Logout() {
// TODO https://github.com/casdoor/casdoor/pull/1494#discussion_r1095675265
owner, username := util.GetOwnerAndNameFromId(user)
object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID())
_, err := object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID())
if err != nil {
c.ResponseError(err.Error())
return
}
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
c.Ctx.Redirect(http.StatusFound, fmt.Sprintf("%s?state=%s", strings.TrimRight(redirectUri, "/"), state))
@ -290,6 +347,7 @@ func (c *ApiController) Logout() {
// @Success 200 {object} controllers.Response The Response object
// @router /get-account [get]
func (c *ApiController) GetAccount() {
var err error
user, ok := c.RequireSignedInUser()
if !ok {
return
@ -297,20 +355,39 @@ func (c *ApiController) GetAccount() {
managedAccounts := c.Input().Get("managedAccounts")
if managedAccounts == "1" {
user = object.ExtendManagedAccountsWithUser(user)
user, err = object.ExtendManagedAccountsWithUser(user)
if err != nil {
c.ResponseError(err.Error())
return
}
}
object.ExtendUserWithRolesAndPermissions(user)
err = object.ExtendUserWithRolesAndPermissions(user)
if err != nil {
c.ResponseError(err.Error())
return
}
user.Permissions = object.GetMaskedPermissions(user.Permissions)
user.Roles = object.GetMaskedRoles(user.Roles)
organization := object.GetMaskedOrganization(object.GetOrganizationByUser(user))
organization, err := object.GetMaskedOrganization(object.GetOrganizationByUser(user))
if err != nil {
c.ResponseError(err.Error())
return
}
u, err := object.GetMaskedUser(user)
if err != nil {
c.ResponseError(err.Error())
return
}
resp := Response{
Status: "ok",
Sub: user.Id,
Name: user.Name,
Data: object.GetMaskedUser(user),
Data: u,
Data2: organization,
}
c.Data["json"] = resp
@ -391,7 +468,12 @@ func (c *ApiController) GetCaptcha() {
if captchaProvider != nil {
if captchaProvider.Type == "Default" {
id, img := object.GetCaptcha()
id, img, err := object.GetCaptcha()
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(Captcha{Type: captchaProvider.Type, CaptchaId: id, CaptchaImage: img})
return
} else if captchaProvider.Type != "" {

View File

@ -40,21 +40,35 @@ func (c *ApiController) GetApplications() {
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
organization := c.Input().Get("organization")
var err error
if limit == "" || page == "" {
var applications []*object.Application
if organization == "" {
applications = object.GetApplications(owner)
applications, err = object.GetApplications(owner)
} else {
applications = object.GetOrganizationApplications(owner, organization)
applications, err = object.GetOrganizationApplications(owner, organization)
}
if err != nil {
panic(err)
}
c.Data["json"] = object.GetMaskedApplications(applications, userId)
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetApplicationCount(owner, field, value)))
applications := object.GetMaskedApplications(object.GetPaginationApplications(owner, paginator.Offset(), limit, field, value, sortField, sortOrder), userId)
count, err := object.GetApplicationCount(owner, field, value)
if err != nil {
panic(err)
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
app, err := object.GetPaginationApplications(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
panic(err)
}
applications := object.GetMaskedApplications(app, userId)
c.ResponseOk(applications, paginator.Nums())
}
}
@ -69,8 +83,12 @@ func (c *ApiController) GetApplications() {
func (c *ApiController) GetApplication() {
userId := c.GetSessionUsername()
id := c.Input().Get("id")
app, err := object.GetApplication(id)
if err != nil {
panic(err)
}
c.Data["json"] = object.GetMaskedApplication(object.GetApplication(id), userId)
c.Data["json"] = object.GetMaskedApplication(app, userId)
c.ServeJSON()
}
@ -84,13 +102,22 @@ func (c *ApiController) GetApplication() {
func (c *ApiController) GetUserApplication() {
userId := c.GetSessionUsername()
id := c.Input().Get("id")
user := object.GetUser(id)
user, err := object.GetUser(id)
if err != nil {
panic(err)
}
if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), id))
return
}
c.Data["json"] = object.GetMaskedApplication(object.GetApplicationByUser(user), userId)
app, err := object.GetApplicationByUser(user)
if err != nil {
panic(err)
}
c.Data["json"] = object.GetMaskedApplication(app, userId)
c.ServeJSON()
}
@ -118,14 +145,30 @@ func (c *ApiController) GetOrganizationApplications() {
}
if limit == "" || page == "" {
var applications []*object.Application
applications = object.GetOrganizationApplications(owner, organization)
applications, err := object.GetOrganizationApplications(owner, organization)
if err != nil {
panic(err)
}
c.Data["json"] = object.GetMaskedApplications(applications, userId)
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetOrganizationApplicationCount(owner, organization, field, value)))
applications := object.GetMaskedApplications(object.GetPaginationOrganizationApplications(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder), userId)
count, err := object.GetOrganizationApplicationCount(owner, organization, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
app, err := object.GetPaginationOrganizationApplications(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
applications := object.GetMaskedApplications(app, userId)
c.ResponseOk(applications, paginator.Nums())
}
}
@ -167,8 +210,13 @@ func (c *ApiController) AddApplication() {
return
}
count := object.GetApplicationCount("", "", "")
if err := checkQuotaForApplication(count); err != nil {
count, err := object.GetApplicationCount("", "", "")
if err != nil {
c.ResponseError(err.Error())
return
}
if err := checkQuotaForApplication(int(count)); err != nil {
c.ResponseError(err.Error())
return
}

View File

@ -93,7 +93,12 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
c.ResponseError(c.T("auth:Challenge method should be S256"))
return
}
code := object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, c.Ctx.Request.Host, c.GetAcceptLanguage())
code, err := object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, c.Ctx.Request.Host, c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error(), nil)
return
}
resp = codeToResponse(code)
if application.EnableSigninSession || application.HasPromptPage() {
@ -142,12 +147,16 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
}
if resp.Status == "ok" {
object.AddSession(&object.Session{
_, err = object.AddSession(&object.Session{
Owner: user.Owner,
Name: user.Name,
Application: application.Name,
SessionId: []string{c.Ctx.Input.CruSession.SessionID()},
})
if err != nil {
c.ResponseError(err.Error(), nil)
return
}
}
return resp
@ -171,7 +180,12 @@ func (c *ApiController) GetApplicationLogin() {
scope := c.Input().Get("scope")
state := c.Input().Get("state")
msg, application := object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state, c.GetAcceptLanguage())
msg, application, err := object.CheckOAuthLogin(clientId, responseType, redirectUri, scope, state, c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error())
return
}
application = object.GetMaskedApplication(application, "")
if msg != "" {
c.ResponseError(msg, application)
@ -248,7 +262,10 @@ func (c *ApiController) Login() {
var msg string
if authForm.Password == "" {
if user = object.GetUserByFields(authForm.Organization, authForm.Username); user == nil {
if user, err = object.GetUserByFields(authForm.Organization, authForm.Username); err != nil {
c.ResponseError(err.Error(), nil)
return
} else if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(authForm.Organization, authForm.Username)))
return
}
@ -272,9 +289,18 @@ func (c *ApiController) Login() {
}
// disable the verification code
object.DisableVerificationCode(checkDest)
err := object.DisableVerificationCode(checkDest)
if err != nil {
c.ResponseError(err.Error(), nil)
return
}
} else {
application := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error(), nil)
return
}
if application == nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
return
@ -284,7 +310,10 @@ func (c *ApiController) Login() {
return
}
var enableCaptcha bool
if enableCaptcha = object.CheckToEnableCaptcha(application, authForm.Organization, authForm.Username); enableCaptcha {
if enableCaptcha, err = object.CheckToEnableCaptcha(application, authForm.Organization, authForm.Username); err != nil {
c.ResponseError(err.Error())
return
} else if enableCaptcha {
isHuman, err := captcha.VerifyCaptchaByCaptchaType(authForm.CaptchaType, authForm.CaptchaToken, authForm.ClientSecret)
if err != nil {
c.ResponseError(err.Error())
@ -304,7 +333,12 @@ func (c *ApiController) Login() {
if msg != "" {
resp = &Response{Status: "error", Msg: msg}
} else {
application := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
return
@ -312,7 +346,11 @@ func (c *ApiController) Login() {
resp = c.HandleLoggedIn(application, user, &authForm)
organization := object.GetOrganizationByUser(user)
organization, err := object.GetOrganizationByUser(user)
if err != nil {
c.ResponseError(err.Error())
}
if user != nil && organization.HasRequiredMfa() && !user.IsMfaEnabled() {
resp.Msg = object.RequiredMfa
}
@ -325,18 +363,34 @@ func (c *ApiController) Login() {
} else if authForm.Provider != "" {
var application *object.Application
if authForm.ClientId != "" {
application = object.GetApplicationByClientId(authForm.ClientId)
application, err = object.GetApplicationByClientId(authForm.ClientId)
if err != nil {
c.ResponseError(err.Error())
return
}
} else {
application = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
application, err = object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error())
return
}
}
if application == nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
return
}
organization, err := object.GetOrganization(util.GetId("admin", application.Organization))
if err != nil {
c.ResponseError(c.T(err.Error()))
}
provider, err := object.GetProvider(util.GetId("admin", authForm.Provider))
if err != nil {
c.ResponseError(err.Error())
return
}
organization := object.GetOrganization(util.GetId("admin", application.Organization))
provider := object.GetProvider(util.GetId("admin", authForm.Provider))
providerItem := application.GetProviderItem(provider.Name)
if !providerItem.IsProviderVisible() {
c.ResponseError(fmt.Sprintf(c.T("auth:The provider: %s is not enabled for the application"), provider.Name))
@ -396,9 +450,17 @@ func (c *ApiController) Login() {
if authForm.Method == "signup" {
user := &object.User{}
if provider.Category == "SAML" {
user = object.GetUser(util.GetId(application.Organization, userInfo.Id))
user, err = object.GetUser(util.GetId(application.Organization, userInfo.Id))
if err != nil {
c.ResponseError(err.Error())
return
}
} else if provider.Category == "OAuth" {
user = object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
user, err = object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
}
if user != nil && !user.IsDeleted {
@ -419,12 +481,20 @@ func (c *ApiController) Login() {
if application.EnableLinkWithEmail {
if userInfo.Email != "" {
// Find existing user with Email
user = object.GetUserByField(application.Organization, "email", userInfo.Email)
user, err = object.GetUserByField(application.Organization, "email", userInfo.Email)
if err != nil {
c.ResponseError(err.Error())
return
}
}
if user == nil && userInfo.Phone != "" {
// Find existing user with phone number
user = object.GetUserByField(application.Organization, "phone", userInfo.Phone)
user, err = object.GetUserByField(application.Organization, "phone", userInfo.Phone)
if err != nil {
c.ResponseError(err.Error())
return
}
}
}
@ -440,7 +510,12 @@ func (c *ApiController) Login() {
}
// Handle username conflicts
tmpUser := object.GetUser(util.GetId(application.Organization, userInfo.Username))
tmpUser, err := object.GetUser(util.GetId(application.Organization, userInfo.Username))
if err != nil {
c.ResponseError(err.Error())
return
}
if tmpUser != nil {
uid, err := uuid.NewRandom()
if err != nil {
@ -453,7 +528,13 @@ func (c *ApiController) Login() {
}
properties := map[string]string{}
properties["no"] = strconv.Itoa(object.GetUserCount(application.Organization, "", "") + 2)
count, err := object.GetUserCount(application.Organization, "", "", "")
if err != nil {
c.ResponseError(err.Error())
return
}
properties["no"] = strconv.Itoa(int(count + 2))
initScore, err := organization.GetInitScore()
if err != nil {
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
@ -482,7 +563,12 @@ func (c *ApiController) Login() {
Properties: properties,
}
affected := object.AddUser(user)
affected, err := object.AddUser(user)
if err != nil {
c.ResponseError(err.Error())
return
}
if !affected {
c.ResponseError(fmt.Sprintf(c.T("auth:Failed to create user, user information is invalid: %s"), util.StructToJson(user)))
return
@ -490,8 +576,17 @@ func (c *ApiController) Login() {
}
// sync info from 3rd-party if possible
object.SetUserOAuthProperties(organization, user, provider.Type, userInfo)
object.LinkUserAccount(user, provider.Type, userInfo.Id)
_, err := object.SetUserOAuthProperties(organization, user, provider.Type, userInfo)
if err != nil {
c.ResponseError(err.Error())
return
}
_, err = object.LinkUserAccount(user, provider.Type, userInfo.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
resp = c.HandleLoggedIn(application, user, &authForm)
@ -516,18 +611,36 @@ func (c *ApiController) Login() {
return
}
oldUser := object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
oldUser, err := object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
if oldUser != nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)"), provider.Type, userInfo.Username, userInfo.DisplayName, oldUser.Name, oldUser.DisplayName))
return
}
user := object.GetUser(userId)
user, err := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
// sync info from 3rd-party if possible
object.SetUserOAuthProperties(organization, user, provider.Type, userInfo)
_, err = object.SetUserOAuthProperties(organization, user, provider.Type, userInfo)
if err != nil {
c.ResponseError(err.Error())
return
}
isLinked, err := object.LinkUserAccount(user, provider.Type, userInfo.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
isLinked := object.LinkUserAccount(user, provider.Type, userInfo.Id)
if isLinked {
resp = &Response{Status: "ok", Msg: "", Data: isLinked}
} else {
@ -536,7 +649,11 @@ func (c *ApiController) Login() {
}
} else if c.getMfaSessionData() != nil {
mfaSession := c.getMfaSessionData()
user := object.GetUser(mfaSession.UserId)
user, err := object.GetUser(mfaSession.UserId)
if err != nil {
c.ResponseError(err.Error())
return
}
if authForm.Passcode != "" {
MfaUtil := object.GetMfaUtil(authForm.MfaType, user.GetPreferMfa(false))
@ -554,7 +671,12 @@ func (c *ApiController) Login() {
}
}
application := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
return
@ -569,7 +691,12 @@ func (c *ApiController) Login() {
} else {
if c.GetSessionUsername() != "" {
// user already signed in to Casdoor, so let the user click the avatar button to do the quick sign-in
application := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), authForm.Application))
return
@ -624,8 +751,9 @@ func (c *ApiController) HandleSamlLogin() {
func (c *ApiController) HandleOfficialAccountEvent() {
respBytes, err := ioutil.ReadAll(c.Ctx.Request.Body)
if err != nil {
c.ResponseError(err.Error())
panic(err)
}
var data struct {
MsgType string `xml:"MsgType"`
Event string `xml:"Event"`
@ -633,8 +761,9 @@ func (c *ApiController) HandleOfficialAccountEvent() {
}
err = xml.Unmarshal(respBytes, &data)
if err != nil {
c.ResponseError(err.Error())
panic(err)
}
lock.Lock()
defer lock.Unlock()
if data.EventKey != "" {
@ -670,7 +799,12 @@ func (c *ApiController) GetWebhookEventType() {
func (c *ApiController) GetCaptchaStatus() {
organization := c.Input().Get("organization")
userId := c.Input().Get("user_id")
user := object.GetUserByFields(organization, userId)
user, err := object.GetUserByFields(organization, userId)
if err != nil {
c.ResponseError(err.Error())
return
}
var captchaEnabled bool
if user != nil && user.SigninWrongTimes >= object.SigninWrongTimesLimit {
captchaEnabled = true

View File

@ -72,11 +72,15 @@ func (c *ApiController) isGlobalAdmin() (bool, *object.User) {
func (c *ApiController) getCurrentUser() *object.User {
var user *object.User
var err error
userId := c.GetSessionUsername()
if userId == "" {
user = nil
} else {
user = object.GetUser(userId)
user, err = object.GetUser(userId)
if err != nil {
panic(err)
}
}
return user
}
@ -106,7 +110,11 @@ func (c *ApiController) GetSessionApplication() *object.Application {
if clientId == nil {
return nil
}
application := object.GetApplicationByClientId(clientId.(string))
application, err := object.GetApplicationByClientId(clientId.(string))
if err != nil {
panic(err)
}
return application
}
@ -192,8 +200,10 @@ func (c *ApiController) setExpireForSession() {
})
}
func wrapActionResponse(affected bool) *Response {
if affected {
func wrapActionResponse(affected bool, e ...error) *Response {
if len(e) != 0 && e[0] != nil {
return &Response{Status: "error", Msg: e[0].Error()}
} else if affected {
return &Response{Status: "ok", Msg: "", Data: "Affected"}
} else {
return &Response{Status: "ok", Msg: "", Data: "Unaffected"}

View File

@ -23,6 +23,13 @@ import (
xormadapter "github.com/casdoor/xorm-adapter/v3"
)
// GetCasbinAdapters
// @Title GetCasbinAdapters
// @Tag Adapter API
// @Description get adapters
// @Param owner query string true "The owner of adapters"
// @Success 200 {array} object.Adapter The Response object
// @router /get-adapters [get]
func (c *ApiController) GetCasbinAdapters() {
owner := c.Input().Get("owner")
limit := c.Input().Get("pageSize")
@ -31,24 +38,61 @@ func (c *ApiController) GetCasbinAdapters() {
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
organization := c.Input().Get("organization")
if limit == "" || page == "" {
adapters := object.GetCasbinAdapters(owner, organization)
adapters, err := object.GetCasbinAdapters(owner)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(adapters)
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetCasbinAdapterCount(owner, organization, field, value)))
adapters := object.GetPaginationCasbinAdapters(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
count, err := object.GetCasbinAdapterCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
adapters, err := object.GetPaginationCasbinAdapters(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(adapters, paginator.Nums())
}
}
// GetCasbinAdapter
// @Title GetCasbinAdapter
// @Tag Adapter API
// @Description get adapter
// @Param id query string true "The id ( owner/name ) of the adapter"
// @Success 200 {object} object.Adapter The Response object
// @router /get-adapter [get]
func (c *ApiController) GetCasbinAdapter() {
id := c.Input().Get("id")
adapter := object.GetCasbinAdapter(id)
adapter, err := object.GetCasbinAdapter(id)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(adapter)
}
// UpdateCasbinAdapter
// @Title UpdateCasbinAdapter
// @Tag Adapter API
// @Description update adapter
// @Param id query string true "The id ( owner/name ) of the adapter"
// @Param body body object.Adapter true "The details of the adapter"
// @Success 200 {object} controllers.Response The Response object
// @router /update-adapter [post]
func (c *ApiController) UpdateCasbinAdapter() {
id := c.Input().Get("id")
@ -63,6 +107,13 @@ func (c *ApiController) UpdateCasbinAdapter() {
c.ServeJSON()
}
// AddCasbinAdapter
// @Title AddCasbinAdapter
// @Tag Adapter API
// @Description add adapter
// @Param body body object.Adapter true "The details of the adapter"
// @Success 200 {object} controllers.Response The Response object
// @router /add-adapter [post]
func (c *ApiController) AddCasbinAdapter() {
var casbinAdapter object.CasbinAdapter
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter)
@ -75,6 +126,13 @@ func (c *ApiController) AddCasbinAdapter() {
c.ServeJSON()
}
// DeleteCasbinAdapter
// @Title DeleteCasbinAdapter
// @Tag Adapter API
// @Description delete adapter
// @Param body body object.Adapter true "The details of the adapter"
// @Success 200 {object} controllers.Response The Response object
// @router /delete-adapter [post]
func (c *ApiController) DeleteCasbinAdapter() {
var casbinAdapter object.CasbinAdapter
err := json.Unmarshal(c.Ctx.Input.RequestBody, &casbinAdapter)
@ -89,7 +147,11 @@ func (c *ApiController) DeleteCasbinAdapter() {
func (c *ApiController) SyncPolicies() {
id := c.Input().Get("id")
adapter := object.GetCasbinAdapter(id)
adapter, err := object.GetCasbinAdapter(id)
if err != nil {
c.ResponseError(err.Error())
return
}
policies, err := object.SyncPolicies(adapter)
if err != nil {
@ -102,9 +164,14 @@ func (c *ApiController) SyncPolicies() {
func (c *ApiController) UpdatePolicy() {
id := c.Input().Get("id")
adapter := object.GetCasbinAdapter(id)
adapter, err := object.GetCasbinAdapter(id)
if err != nil {
c.ResponseError(err.Error())
return
}
var policies []xormadapter.CasbinRule
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policies)
err = json.Unmarshal(c.Ctx.Input.RequestBody, &policies)
if err != nil {
c.ResponseError(err.Error())
return
@ -121,9 +188,14 @@ func (c *ApiController) UpdatePolicy() {
func (c *ApiController) AddPolicy() {
id := c.Input().Get("id")
adapter := object.GetCasbinAdapter(id)
adapter, err := object.GetCasbinAdapter(id)
if err != nil {
c.ResponseError(err.Error())
return
}
var policy xormadapter.CasbinRule
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
err = json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
if err != nil {
c.ResponseError(err.Error())
return
@ -140,9 +212,14 @@ func (c *ApiController) AddPolicy() {
func (c *ApiController) RemovePolicy() {
id := c.Input().Get("id")
adapter := object.GetCasbinAdapter(id)
adapter, err := object.GetCasbinAdapter(id)
if err != nil {
c.ResponseError(err.Error())
return
}
var policy xormadapter.CasbinRule
err := json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
err = json.Unmarshal(c.Ctx.Input.RequestBody, &policy)
if err != nil {
c.ResponseError(err.Error())
return

View File

@ -37,13 +37,28 @@ func (c *ApiController) GetCerts() {
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetMaskedCerts(object.GetCerts(owner))
maskedCerts, err := object.GetMaskedCerts(object.GetCerts(owner))
if err != nil {
panic(err)
}
c.Data["json"] = maskedCerts
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetCertCount(owner, field, value)))
certs := object.GetMaskedCerts(object.GetPaginationCerts(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
count, err := object.GetCertCount(owner, field, value)
if err != nil {
panic(err)
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
certs, err := object.GetMaskedCerts(object.GetPaginationCerts(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
if err != nil {
panic(err)
}
c.ResponseOk(certs, paginator.Nums())
}
}
@ -61,13 +76,28 @@ func (c *ApiController) GetGlobleCerts() {
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetMaskedCerts(object.GetGlobleCerts())
maskedCerts, err := object.GetMaskedCerts(object.GetGlobleCerts())
if err != nil {
panic(err)
}
c.Data["json"] = maskedCerts
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetGlobalCertsCount(field, value)))
certs := object.GetMaskedCerts(object.GetPaginationGlobalCerts(paginator.Offset(), limit, field, value, sortField, sortOrder))
count, err := object.GetGlobalCertsCount(field, value)
if err != nil {
panic(err)
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
certs, err := object.GetMaskedCerts(object.GetPaginationGlobalCerts(paginator.Offset(), limit, field, value, sortField, sortOrder))
if err != nil {
panic(err)
}
c.ResponseOk(certs, paginator.Nums())
}
}
@ -81,8 +111,12 @@ func (c *ApiController) GetGlobleCerts() {
// @router /get-cert [get]
func (c *ApiController) GetCert() {
id := c.Input().Get("id")
cert, err := object.GetCert(id)
if err != nil {
panic(err)
}
c.Data["json"] = object.GetMaskedCert(object.GetCert(id))
c.Data["json"] = object.GetMaskedCert(cert)
c.ServeJSON()
}

View File

@ -30,21 +30,37 @@ import (
// @Success 200 {array} object.Chat The Response object
// @router /get-chats [get]
func (c *ApiController) GetChats() {
owner := c.Input().Get("owner")
owner = "admin"
owner := "admin"
limit := c.Input().Get("pageSize")
page := c.Input().Get("p")
field := c.Input().Get("field")
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetMaskedChats(object.GetChats(owner))
maskedChats, err := object.GetMaskedChats(object.GetChats(owner))
if err != nil {
panic(err)
}
c.Data["json"] = maskedChats
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetChatCount(owner, field, value)))
chats := object.GetMaskedChats(object.GetPaginationChats(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
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())
}
}
@ -59,7 +75,12 @@ func (c *ApiController) GetChats() {
func (c *ApiController) GetChat() {
id := c.Input().Get("id")
c.Data["json"] = object.GetMaskedChat(object.GetChat(id))
maskedChat, err := object.GetMaskedChat(object.GetChat(id))
if err != nil {
panic(err)
}
c.Data["json"] = maskedChat
c.ServeJSON()
}

View File

@ -21,6 +21,16 @@ import (
"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")
@ -34,28 +44,59 @@ func (c *ApiController) Enforce() {
}
if permissionId != "" {
c.Data["json"] = object.Enforce(permissionId, &request)
c.ServeJSON()
enforceResult, err := object.Enforce(permissionId, &request)
if err != nil {
c.ResponseError(err.Error())
return
}
res := []bool{}
res = append(res, enforceResult)
c.ResponseOk(res)
return
}
permissions := make([]*object.Permission, 0)
res := []bool{}
permissions := []*object.Permission{}
if modelId != "" {
owner, modelName := util.GetOwnerAndNameFromId(modelId)
permissions = object.GetPermissionsByModel(owner, modelName)
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 {
permissions = object.GetPermissionsByResource(resourceId)
c.ResponseError(c.T("general:Missing parameter"))
return
}
res := []bool{}
for _, permission := range permissions {
res = append(res, object.Enforce(permission.GetId(), &request))
enforceResult, err := object.Enforce(permission.GetId(), &request)
if err != nil {
c.ResponseError(err.Error())
return
}
res = append(res, enforceResult)
}
c.Data["json"] = res
c.ServeJSON()
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")
@ -68,19 +109,42 @@ func (c *ApiController) BatchEnforce() {
}
if permissionId != "" {
c.Data["json"] = object.BatchEnforce(permissionId, &requests)
c.ServeJSON()
} else {
owner, modelName := util.GetOwnerAndNameFromId(modelId)
permissions := object.GetPermissionsByModel(owner, modelName)
enforceResult, err := object.BatchEnforce(permissionId, &requests)
if err != nil {
c.ResponseError(err.Error())
return
}
res := [][]bool{}
for _, permission := range permissions {
res = append(res, object.BatchEnforce(permission.GetId(), &requests))
}
c.Data["json"] = res
c.ServeJSON()
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{}
for _, permission := range permissions {
enforceResult, err := object.BatchEnforce(permission.GetId(), &requests)
if err != nil {
c.ResponseError(err.Error())
return
}
res = append(res, enforceResult)
}
c.ResponseOk(res)
}
func (c *ApiController) GetAllObjects() {
@ -90,8 +154,7 @@ func (c *ApiController) GetAllObjects() {
return
}
c.Data["json"] = object.GetAllObjects(userId)
c.ServeJSON()
c.ResponseOk(object.GetAllObjects(userId))
}
func (c *ApiController) GetAllActions() {
@ -101,8 +164,7 @@ func (c *ApiController) GetAllActions() {
return
}
c.Data["json"] = object.GetAllActions(userId)
c.ServeJSON()
c.ResponseOk(object.GetAllActions(userId))
}
func (c *ApiController) GetAllRoles() {
@ -112,6 +174,5 @@ func (c *ApiController) GetAllRoles() {
return
}
c.Data["json"] = object.GetAllRoles(userId)
c.ServeJSON()
c.ResponseOk(object.GetAllRoles(userId))
}

148
controllers/group.go Normal file
View File

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

View File

@ -45,7 +45,11 @@ func (c *ApiController) GetLdapUsers() {
id := c.Input().Get("id")
_, ldapId := util.GetOwnerAndNameFromId(id)
ldapServer := object.GetLdap(ldapId)
ldapServer, err := object.GetLdap(ldapId)
if err != nil {
c.ResponseError(err.Error())
return
}
conn, err := ldapServer.GetLdapConn()
if err != nil {
@ -76,7 +80,11 @@ func (c *ApiController) GetLdapUsers() {
for i, user := range users {
uuids[i] = user.GetLdapUuid()
}
existUuids := object.GetExistUuids(ldapServer.Owner, uuids)
existUuids, err := object.GetExistUuids(ldapServer.Owner, uuids)
if err != nil {
c.ResponseError(err.Error())
return
}
resp := LdapResp{
Users: object.AutoAdjustLdapUser(users),
@ -128,17 +136,23 @@ func (c *ApiController) AddLdap() {
return
}
if object.CheckLdapExist(&ldap) {
if ok, err := object.CheckLdapExist(&ldap); err != nil {
c.ResponseError(err.Error())
return
} else if ok {
c.ResponseError(c.T("ldap:Ldap server exist"))
return
}
affected := object.AddLdap(&ldap)
resp := wrapActionResponse(affected)
resp := wrapActionResponse(object.AddLdap(&ldap))
resp.Data2 = ldap
if ldap.AutoSync != 0 {
object.GetLdapAutoSynchronizer().StartAutoSync(ldap.Id)
err = object.GetLdapAutoSynchronizer().StartAutoSync(ldap.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
}
c.Data["json"] = resp
@ -157,11 +171,24 @@ func (c *ApiController) UpdateLdap() {
return
}
prevLdap := object.GetLdap(ldap.Id)
affected := object.UpdateLdap(&ldap)
prevLdap, err := object.GetLdap(ldap.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
affected, err := object.UpdateLdap(&ldap)
if err != nil {
c.ResponseError(err.Error())
return
}
if ldap.AutoSync != 0 {
object.GetLdapAutoSynchronizer().StartAutoSync(ldap.Id)
err := object.GetLdapAutoSynchronizer().StartAutoSync(ldap.Id)
if err != nil {
c.ResponseError(err.Error())
return
}
} else if ldap.AutoSync == 0 && prevLdap.AutoSync != 0 {
object.GetLdapAutoSynchronizer().StopAutoSync(ldap.Id)
}
@ -182,7 +209,11 @@ func (c *ApiController) DeleteLdap() {
return
}
affected := object.DeleteLdap(&ldap)
affected, err := object.DeleteLdap(&ldap)
if err != nil {
c.ResponseError(err.Error())
return
}
object.GetLdapAutoSynchronizer().StopAutoSync(ldap.Id)
@ -204,7 +235,11 @@ func (c *ApiController) SyncLdapUsers() {
return
}
object.UpdateLdapSyncTime(ldapId)
err = object.UpdateLdapSyncTime(ldapId)
if err != nil {
c.ResponseError(err.Error())
return
}
exist, failed, _ := object.SyncLdapUsers(owner, users, ldapId)

View File

@ -53,7 +53,12 @@ func (c *ApiController) Unlink() {
if user.Id == unlinkedUser.Id && !user.IsGlobalAdmin {
// if the user is unlinking themselves, should check the provider can be unlinked, if not, we should return an error.
application := object.GetApplicationByUser(user)
application, err := object.GetApplicationByUser(user)
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil {
c.ResponseError(c.T("link:You can't unlink yourself, you are not a member of any application"))
return
@ -88,8 +93,17 @@ func (c *ApiController) Unlink() {
return
}
object.ClearUserOAuthProperties(&unlinkedUser, providerType)
_, err = object.ClearUserOAuthProperties(&unlinkedUser, providerType)
if err != nil {
c.ResponseError(err.Error())
return
}
_, err = object.LinkUserAccount(&unlinkedUser, providerType, "")
if err != nil {
c.ResponseError(err.Error())
return
}
object.LinkUserAccount(&unlinkedUser, providerType, "")
c.ResponseOk()
}

View File

@ -34,6 +34,7 @@ import (
// @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")
@ -41,21 +42,38 @@ func (c *ApiController) GetMessages() {
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
chat := c.Input().Get("chat")
organization := c.Input().Get("organization")
if limit == "" || page == "" {
var messages []*object.Message
var err error
if chat == "" {
messages = object.GetMessages(owner)
messages, err = object.GetMessages(owner)
} else {
messages = object.GetChatMessages(chat)
messages, err = object.GetChatMessages(chat)
}
if err != nil {
panic(err)
}
c.Data["json"] = object.GetMaskedMessages(messages)
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetMessageCount(owner, organization, field, value)))
messages := object.GetMaskedMessages(object.GetPaginationMessages(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder))
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())
}
}
@ -69,8 +87,12 @@ func (c *ApiController) GetMessages() {
// @router /get-message [get]
func (c *ApiController) GetMessage() {
id := c.Input().Get("id")
message, err := object.GetMessage(id)
if err != nil {
panic(err)
}
c.Data["json"] = object.GetMaskedMessage(object.GetMessage(id))
c.Data["json"] = object.GetMaskedMessage(message)
c.ServeJSON()
}
@ -96,7 +118,12 @@ func (c *ApiController) GetMessageAnswer() {
c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache")
c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive")
message := object.GetMessage(id)
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
@ -108,7 +135,12 @@ func (c *ApiController) GetMessageAnswer() {
}
chatId := util.GetId("admin", message.Chat)
chat := object.GetChat(chatId)
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
@ -119,14 +151,19 @@ func (c *ApiController) GetMessageAnswer() {
return
}
questionMessage := object.GetMessage(message.ReplyTo)
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 := object.GetProvider(providerId)
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
@ -148,7 +185,7 @@ func (c *ApiController) GetMessageAnswer() {
fmt.Printf("Question: [%s]\n", questionMessage.Text)
fmt.Printf("Answer: [")
err := ai.QueryAnswerStream(authToken, question, c.Ctx.ResponseWriter, &stringBuilder)
err = ai.QueryAnswerStream(authToken, question, c.Ctx.ResponseWriter, &stringBuilder)
if err != nil {
c.ResponseErrorStream(err.Error())
return
@ -165,7 +202,10 @@ func (c *ApiController) GetMessageAnswer() {
answer := stringBuilder.String()
message.Text = answer
object.UpdateMessage(message.GetId(), message)
_, err = object.UpdateMessage(message.GetId(), message)
if err != nil {
panic(err)
}
}
// UpdateMessage
@ -208,14 +248,24 @@ func (c *ApiController) AddMessage() {
var chat *object.Chat
if message.Chat != "" {
chatId := util.GetId("admin", message.Chat)
chat = object.GetChat(chatId)
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 := object.AddMessage(&message)
affected, err := object.AddMessage(&message)
if err != nil {
c.ResponseError(err.Error())
return
}
if affected {
if chat != nil && chat.Type == "AI" {
answerMessage := &object.Message{
@ -228,7 +278,11 @@ func (c *ApiController) AddMessage() {
Author: "AI",
Text: "",
}
object.AddMessage(answerMessage)
_, err = object.AddMessage(answerMessage)
if err != nil {
c.ResponseError(err.Error())
return
}
}
}

View File

@ -46,7 +46,12 @@ func (c *ApiController) MfaSetupInitiate() {
if MfaUtil == nil {
c.ResponseError("Invalid auth type")
}
user := object.GetUser(userId)
user, err := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError("User doesn't exist")
return
@ -105,14 +110,19 @@ func (c *ApiController) MfaSetupEnable() {
name := c.Ctx.Request.Form.Get("name")
authType := c.Ctx.Request.Form.Get("type")
user := object.GetUser(util.GetId(owner, name))
user, err := object.GetUser(util.GetId(owner, name))
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError("User doesn't exist")
return
}
twoFactor := object.GetMfaUtil(authType, nil)
err := twoFactor.Enable(c.Ctx, user)
err = twoFactor.Enable(c.Ctx, user)
if err != nil {
c.ResponseError(err.Error())
return
@ -136,7 +146,12 @@ func (c *ApiController) DeleteMfa() {
name := c.Ctx.Request.Form.Get("name")
userId := util.GetId(owner, name)
user := object.GetUser(userId)
user, err := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError("User doesn't exist")
return
@ -151,7 +166,12 @@ func (c *ApiController) DeleteMfa() {
}
}
user.MultiFactorAuths = mfaProps
object.UpdateUser(userId, user, []string{"multi_factor_auths"}, user.IsAdminUser())
_, err = object.UpdateUser(userId, user, []string{"multi_factor_auths"}, user.IsAdminUser())
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(user.MultiFactorAuths)
}
@ -170,7 +190,12 @@ func (c *ApiController) SetPreferredMfa() {
name := c.Ctx.Request.Form.Get("name")
userId := util.GetId(owner, name)
user := object.GetUser(userId)
user, err := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError("User doesn't exist")
return
@ -185,7 +210,11 @@ func (c *ApiController) SetPreferredMfa() {
}
}
object.UpdateUser(userId, user, []string{"multi_factor_auths"}, user.IsAdminUser())
_, err = object.UpdateUser(userId, user, []string{"multi_factor_auths"}, user.IsAdminUser())
if err != nil {
c.ResponseError(err.Error())
return
}
for i, mfaProp := range mfaProps {
mfaProps[i] = object.GetMaskedProps(mfaProp)

View File

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

View File

@ -37,14 +37,41 @@ func (c *ApiController) GetOrganizations() {
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetMaskedOrganizations(object.GetOrganizations(owner))
maskedOrganizations, err := object.GetMaskedOrganizations(object.GetOrganizations(owner))
if err != nil {
panic(err)
}
c.Data["json"] = maskedOrganizations
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetOrganizationCount(owner, field, value)))
organizations := object.GetMaskedOrganizations(object.GetPaginationOrganizations(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
c.ResponseOk(organizations, paginator.Nums())
isGlobalAdmin := c.IsGlobalAdmin()
if !isGlobalAdmin {
maskedOrganizations, err := object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner))
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(maskedOrganizations)
} else {
limit := util.ParseInt(limit)
count, err := object.GetOrganizationCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
organizations, err := object.GetMaskedOrganizations(object.GetPaginationOrganizations(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(organizations, paginator.Nums())
}
}
}
@ -57,9 +84,13 @@ func (c *ApiController) GetOrganizations() {
// @router /get-organization [get]
func (c *ApiController) GetOrganization() {
id := c.Input().Get("id")
maskedOrganization, err := object.GetMaskedOrganization(object.GetOrganization(id))
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = object.GetMaskedOrganization(object.GetOrganization(id))
c.ServeJSON()
c.ResponseOk(maskedOrganization)
}
// UpdateOrganization ...
@ -99,8 +130,13 @@ func (c *ApiController) AddOrganization() {
return
}
count := object.GetOrganizationCount("", "", "")
if err := checkQuotaForOrganization(count); err != nil {
count, err := object.GetOrganizationCount("", "", "")
if err != nil {
c.ResponseError(err.Error())
return
}
if err = checkQuotaForOrganization(int(count)); err != nil {
c.ResponseError(err.Error())
return
}
@ -148,3 +184,21 @@ func (c *ApiController) GetDefaultApplication() {
maskedApplication := object.GetMaskedApplication(application, userId)
c.ResponseOk(maskedApplication)
}
// GetOrganizationNames ...
// @Title GetOrganizationNames
// @Tag Organization API
// @Param owner query string true "owner"
// @Description get all organization name and displayName
// @Success 200 {array} object.Organization The Response object
// @router /get-organization-names [get]
func (c *ApiController) GetOrganizationNames() {
owner := c.Input().Get("owner")
organizationNames, err := object.GetOrganizationsByFields(owner, []string{"name", "display_name"}...)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(organizationNames)
}

View File

@ -16,7 +16,6 @@ package controllers
import (
"encoding/json"
"fmt"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
@ -32,19 +31,35 @@ import (
// @router /get-payments [get]
func (c *ApiController) GetPayments() {
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")
if limit == "" || page == "" {
c.Data["json"] = object.GetPayments(owner)
payments, err := object.GetPayments(owner)
if err != nil {
panic(err)
}
c.Data["json"] = payments
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetPaymentCount(owner, field, value)))
payments := object.GetPaginationPayments(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
count, err := object.GetPaymentCount(owner, organization, field, value)
if err != nil {
panic(err)
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
payments, err := object.GetPaginationPayments(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
panic(err)
}
c.ResponseOk(payments, paginator.Nums())
}
}
@ -63,7 +78,12 @@ func (c *ApiController) GetUserPayments() {
organization := c.Input().Get("organization")
user := c.Input().Get("user")
payments := object.GetUserPayments(owner, organization, user)
payments, err := object.GetUserPayments(owner, organization, user)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(payments)
}
@ -77,7 +97,12 @@ func (c *ApiController) GetUserPayments() {
func (c *ApiController) GetPayment() {
id := c.Input().Get("id")
c.Data["json"] = object.GetPayment(id)
payment, err := object.GetPayment(id)
if err != nil {
panic(err)
}
c.Data["json"] = payment
c.ServeJSON()
}
@ -153,18 +178,19 @@ func (c *ApiController) NotifyPayment() {
providerName := c.Ctx.Input.Param(":provider")
productName := c.Ctx.Input.Param(":product")
paymentName := c.Ctx.Input.Param(":payment")
orderId := c.Ctx.Input.Param("order")
body := c.Ctx.Input.RequestBody
ok := object.NotifyPayment(c.Ctx.Request, body, owner, providerName, productName, paymentName)
if ok {
_, err := c.Ctx.ResponseWriter.Write([]byte("success"))
if err != nil {
c.ResponseError(err.Error())
return
}
} else {
panic(fmt.Errorf("NotifyPayment() failed: %v", ok))
err, errorResponse := object.NotifyPayment(c.Ctx.Request, body, owner, providerName, productName, paymentName, orderId)
_, err2 := c.Ctx.ResponseWriter.Write([]byte(errorResponse))
if err2 != nil {
panic(err2)
}
if err != nil {
panic(err)
}
}
@ -178,7 +204,12 @@ func (c *ApiController) NotifyPayment() {
func (c *ApiController) InvoicePayment() {
id := c.Input().Get("id")
payment := object.GetPayment(id)
payment, err := object.GetPayment(id)
if err != nil {
c.ResponseError(err.Error())
return
}
invoiceUrl, err := object.InvoicePayment(payment)
if err != nil {
c.ResponseError(err.Error())

View File

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

View File

@ -0,0 +1,54 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package controllers
import (
"fmt"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
func (c *ApiController) UploadPermissions() {
userId := c.GetSessionUsername()
owner, user := util.GetOwnerAndNameFromId(userId)
file, header, err := c.Ctx.Request.FormFile("file")
if err != nil {
c.ResponseError(err.Error())
return
}
fileId := fmt.Sprintf("%s_%s_%s", owner, user, util.RemoveExt(header.Filename))
path := util.GetUploadXlsxPath(fileId)
util.EnsureFileFolderExists(path)
err = saveFile(path, &file)
if err != nil {
c.ResponseError(err.Error())
return
}
affected, err := object.UploadPermissions(owner, fileId)
if err != nil {
c.ResponseError(err.Error())
}
if affected {
c.ResponseOk()
} else {
c.ResponseError(c.T("user_upload:Failed to import users"))
}
}

View File

@ -37,13 +37,30 @@ func (c *ApiController) GetPlans() {
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetPlans(owner)
plans, err := object.GetPlans(owner)
if err != nil {
panic(err)
}
c.Data["json"] = plans
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetPlanCount(owner, field, value)))
plan := object.GetPaginatedPlans(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
count, err := object.GetPlanCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
plan, err := object.GetPaginatedPlans(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(plan, paginator.Nums())
}
}
@ -60,10 +77,16 @@ func (c *ApiController) GetPlan() {
id := c.Input().Get("id")
includeOption := c.Input().Get("includeOption") == "true"
plan := object.GetPlan(id)
plan, err := object.GetPlan(id)
if err != nil {
panic(err)
}
if includeOption {
options := object.GetPermissionsByRole(plan.Role)
options, err := object.GetPermissionsByRole(plan.Role)
if err != nil {
panic(err)
}
for _, option := range options {
plan.Options = append(plan.Options, option.DisplayName)

View File

@ -37,13 +37,30 @@ func (c *ApiController) GetPricings() {
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetPricings(owner)
pricings, err := object.GetPricings(owner)
if err != nil {
panic(err)
}
c.Data["json"] = pricings
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetPricingCount(owner, field, value)))
pricing := object.GetPaginatedPricings(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
count, err := object.GetPricingCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
pricing, err := object.GetPaginatedPricings(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(pricing, paginator.Nums())
}
}
@ -58,7 +75,10 @@ func (c *ApiController) GetPricings() {
func (c *ApiController) GetPricing() {
id := c.Input().Get("id")
pricing := object.GetPricing(id)
pricing, err := object.GetPricing(id)
if err != nil {
panic(err)
}
c.Data["json"] = pricing
c.ServeJSON()

View File

@ -38,13 +38,30 @@ func (c *ApiController) GetProducts() {
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetProducts(owner)
products, err := object.GetProducts(owner)
if err != nil {
panic(err)
}
c.Data["json"] = products
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetProductCount(owner, field, value)))
products := object.GetPaginationProducts(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
count, err := object.GetProductCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
products, err := object.GetPaginationProducts(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(products, paginator.Nums())
}
}
@ -59,8 +76,15 @@ func (c *ApiController) GetProducts() {
func (c *ApiController) GetProduct() {
id := c.Input().Get("id")
product := object.GetProduct(id)
object.ExtendProductWithProviders(product)
product, err := object.GetProduct(id)
if err != nil {
panic(err)
}
err = object.ExtendProductWithProviders(product)
if err != nil {
panic(err)
}
c.Data["json"] = product
c.ServeJSON()
@ -145,17 +169,22 @@ func (c *ApiController) BuyProduct() {
return
}
user := object.GetUser(userId)
if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId))
return
}
payUrl, err := object.BuyProduct(id, providerName, user, host)
user, err := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(payUrl)
if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId))
return
}
payUrl, orderId, err := object.BuyProduct(id, providerName, user, host)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(payUrl, orderId)
}

View File

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

View File

@ -42,14 +42,31 @@ func (c *ApiController) GetRecords() {
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetRecords()
records, err := object.GetRecords()
if err != nil {
panic(err)
}
c.Data["json"] = records
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
filterRecord := &object.Record{Organization: organization}
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetRecordCount(field, value, filterRecord)))
records := object.GetPaginationRecords(paginator.Offset(), limit, field, value, sortField, sortOrder, filterRecord)
count, err := object.GetRecordCount(field, value, filterRecord)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
records, err := object.GetPaginationRecords(paginator.Offset(), limit, field, value, sortField, sortOrder, filterRecord)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(records, paginator.Nums())
}
}
@ -67,11 +84,15 @@ func (c *ApiController) GetRecordsByFilter() {
record := &object.Record{}
err := util.JsonToStruct(body, record)
if err != nil {
c.ResponseError(err.Error())
return
panic(err)
}
c.Data["json"] = object.GetRecordsByField(record)
records, err := object.GetRecordsByField(record)
if err != nil {
panic(err)
}
c.Data["json"] = records
c.ServeJSON()
}

View File

@ -51,12 +51,28 @@ func (c *ApiController) GetResources() {
}
if limit == "" || page == "" {
c.Data["json"] = object.GetResources(owner, user)
resources, err := object.GetResources(owner, user)
if err != nil {
panic(err)
}
c.Data["json"] = resources
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetResourceCount(owner, user, field, value)))
resources := object.GetPaginationResources(owner, user, paginator.Offset(), limit, field, value, sortField, sortOrder)
count, err := object.GetResourceCount(owner, user, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
resources, err := object.GetPaginationResources(owner, user, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(resources, paginator.Nums())
}
}
@ -68,7 +84,12 @@ func (c *ApiController) GetResources() {
func (c *ApiController) GetResource() {
id := c.Input().Get("id")
c.Data["json"] = object.GetResource(id)
resource, err := object.GetResource(id)
if err != nil {
panic(err)
}
c.Data["json"] = resource
c.ServeJSON()
}
@ -118,8 +139,9 @@ func (c *ApiController) DeleteResource() {
return
}
provider, _, ok := c.GetProviderFromContext("Storage")
if !ok {
provider, err := c.GetProviderFromContext("Storage")
if err != nil {
c.ResponseError(err.Error())
return
}
@ -166,8 +188,9 @@ func (c *ApiController) UploadResource() {
return
}
provider, _, ok := c.GetProviderFromContext("Storage")
if !ok {
provider, err := c.GetProviderFromContext("Storage")
if err != nil {
c.ResponseError(err.Error())
return
}
@ -187,7 +210,10 @@ func (c *ApiController) UploadResource() {
index := len(fullFilePath) - len(ext)
for i := 1; ; i++ {
_, objectKey := object.GetUploadFileUrl(provider, fullFilePath, true)
if object.GetResourceCount(owner, username, "name", objectKey) == 0 {
if count, err := object.GetResourceCount(owner, username, "name", objectKey); err != nil {
c.ResponseError(err.Error())
return
} else if count == 0 {
break
}
@ -223,20 +249,39 @@ func (c *ApiController) UploadResource() {
Url: fileUrl,
Description: description,
}
object.AddOrUpdateResource(resource)
_, err = object.AddOrUpdateResource(resource)
if err != nil {
c.ResponseError(err.Error())
return
}
switch tag {
case "avatar":
user := object.GetUserNoCheck(util.GetId(owner, username))
user, err := object.GetUserNoCheck(util.GetId(owner, username))
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError(c.T("resource:User is nil for tag: avatar"))
return
}
user.Avatar = fileUrl
object.UpdateUser(user.GetId(), user, []string{"avatar"}, false)
_, err = object.UpdateUser(user.GetId(), user, []string{"avatar"}, false)
if err != nil {
c.ResponseError(err.Error())
return
}
case "termsOfUse":
user := object.GetUserNoCheck(util.GetId(owner, username))
user, err := object.GetUserNoCheck(util.GetId(owner, username))
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(owner, username)))
return
@ -248,9 +293,18 @@ func (c *ApiController) UploadResource() {
}
_, applicationId := util.GetOwnerAndNameFromIdNoCheck(strings.TrimRight(fullFilePath, ".html"))
applicationObj := object.GetApplication(applicationId)
applicationObj, err := object.GetApplication(applicationId)
if err != nil {
c.ResponseError(err.Error())
return
}
applicationObj.TermsOfUse = fileUrl
object.UpdateApplication(applicationId, applicationObj)
_, err = object.UpdateApplication(applicationId, applicationObj)
if err != nil {
c.ResponseError(err.Error())
return
}
}
c.ResponseOk(fileUrl, objectKey)

View File

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

View File

@ -0,0 +1,54 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package controllers
import (
"fmt"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
)
func (c *ApiController) UploadRoles() {
userId := c.GetSessionUsername()
owner, user := util.GetOwnerAndNameFromId(userId)
file, header, err := c.Ctx.Request.FormFile("file")
if err != nil {
c.ResponseError(err.Error())
return
}
fileId := fmt.Sprintf("%s_%s_%s", owner, user, util.RemoveExt(header.Filename))
path := util.GetUploadXlsxPath(fileId)
util.EnsureFileFolderExists(path)
err = saveFile(path, &file)
if err != nil {
c.ResponseError(err.Error())
return
}
affected, err := object.UploadRoles(owner, fileId)
if err != nil {
c.ResponseError(err.Error())
}
if affected {
c.ResponseOk()
} else {
c.ResponseError(c.T("user_upload:Failed to import users"))
}
}

View File

@ -23,7 +23,12 @@ import (
func (c *ApiController) GetSamlMeta() {
host := c.Ctx.Request.Host
paramApp := c.Input().Get("application")
application := object.GetApplication(paramApp)
application, err := object.GetApplication(paramApp)
if err != nil {
c.ResponseError(err.Error())
return
}
if application == nil {
c.ResponseError(fmt.Sprintf(c.T("saml:Application %s not found"), paramApp))
return

View File

@ -61,12 +61,17 @@ func (c *ApiController) SendEmail() {
var provider *object.Provider
if emailForm.Provider != "" {
// called by frontend's TestEmailWidget, provider name is set by frontend
provider = object.GetProvider(util.GetId("admin", emailForm.Provider))
provider, err = object.GetProvider(util.GetId("admin", emailForm.Provider))
if err != nil {
c.ResponseError(err.Error())
return
}
} else {
// called by Casdoor SDK via Client ID & Client Secret, so the used Email provider will be the application' Email provider or the default Email provider
var ok bool
provider, _, ok = c.GetProviderFromContext("Email")
if !ok {
provider, err = c.GetProviderFromContext("Email")
if err != nil {
c.ResponseError(err.Error())
return
}
}
@ -122,13 +127,14 @@ func (c *ApiController) SendEmail() {
// @Success 200 {object} Response object
// @router /api/send-sms [post]
func (c *ApiController) SendSms() {
provider, _, ok := c.GetProviderFromContext("SMS")
if !ok {
provider, err := c.GetProviderFromContext("SMS")
if err != nil {
c.ResponseError(err.Error())
return
}
var smsForm SmsForm
err := json.Unmarshal(c.Ctx.Input.RequestBody, &smsForm)
err = json.Unmarshal(c.Ctx.Input.RequestBody, &smsForm)
if err != nil {
c.ResponseError(err.Error())
return

View File

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

View File

@ -37,13 +37,30 @@ func (c *ApiController) GetSubscriptions() {
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetSubscriptions(owner)
subscriptions, err := object.GetSubscriptions(owner)
if err != nil {
panic(err)
}
c.Data["json"] = subscriptions
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetSubscriptionCount(owner, field, value)))
subscription := object.GetPaginationSubscriptions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
count, err := object.GetSubscriptionCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
subscription, err := object.GetPaginationSubscriptions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(subscription, paginator.Nums())
}
}
@ -58,7 +75,10 @@ func (c *ApiController) GetSubscriptions() {
func (c *ApiController) GetSubscription() {
id := c.Input().Get("id")
subscription := object.GetSubscription(id)
subscription, err := object.GetSubscription(id)
if err != nil {
panic(err)
}
c.Data["json"] = subscription
c.ServeJSON()

View File

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

View File

@ -41,12 +41,28 @@ func (c *ApiController) GetTokens() {
sortOrder := c.Input().Get("sortOrder")
organization := c.Input().Get("organization")
if limit == "" || page == "" {
c.Data["json"] = object.GetTokens(owner, organization)
token, err := object.GetTokens(owner, organization)
if err != nil {
panic(err)
}
c.Data["json"] = token
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetTokenCount(owner, organization, field, value)))
tokens := object.GetPaginationTokens(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
count, err := object.GetTokenCount(owner, organization, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
tokens, err := object.GetPaginationTokens(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(tokens, paginator.Nums())
}
}
@ -60,8 +76,12 @@ func (c *ApiController) GetTokens() {
// @router /get-token [get]
func (c *ApiController) GetToken() {
id := c.Input().Get("id")
token, err := object.GetToken(id)
if err != nil {
panic(err)
}
c.Data["json"] = object.GetToken(id)
c.Data["json"] = token
c.ServeJSON()
}
@ -171,8 +191,12 @@ func (c *ApiController) GetOAuthToken() {
}
}
host := c.Ctx.Request.Host
oAuthtoken, err := object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
if err != nil {
panic(err)
}
c.Data["json"] = object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
c.Data["json"] = oAuthtoken
c.SetTokenErrorHttpStatus()
c.ServeJSON()
}
@ -210,7 +234,12 @@ func (c *ApiController) RefreshToken() {
}
}
c.Data["json"] = object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
refreshToken2, err := object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
if err != nil {
panic(err)
}
c.Data["json"] = refreshToken2
c.SetTokenErrorHttpStatus()
c.ServeJSON()
}
@ -245,7 +274,11 @@ func (c *ApiController) IntrospectToken() {
return
}
}
application := object.GetApplicationByClientId(clientId)
application, err := object.GetApplicationByClientId(clientId)
if err != nil {
panic(err)
}
if application == nil || application.ClientSecret != clientSecret {
c.ResponseError(c.T("token:Invalid application or wrong clientSecret"))
c.Data["json"] = &object.TokenError{
@ -254,7 +287,11 @@ func (c *ApiController) IntrospectToken() {
c.SetTokenErrorHttpStatus()
return
}
token := object.GetTokenByTokenAndApplication(tokenValue, application.Name)
token, err := object.GetTokenByTokenAndApplication(tokenValue, application.Name)
if err != nil {
panic(err)
}
if token == nil {
c.Data["json"] = &object.IntrospectionResponse{Active: false}
c.ServeJSON()

View File

@ -37,14 +37,36 @@ func (c *ApiController) GetGlobalUsers() {
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetMaskedUsers(object.GetGlobalUsers())
maskedUsers, err := object.GetMaskedUsers(object.GetGlobalUsers())
if err != nil {
panic(err)
}
c.Data["json"] = maskedUsers
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetGlobalUserCount(field, value)))
users := object.GetPaginationGlobalUsers(paginator.Offset(), limit, field, value, sortField, sortOrder)
users = object.GetMaskedUsers(users)
count, err := object.GetGlobalUserCount(field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
users, err := object.GetPaginationGlobalUsers(paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
users, err = object.GetMaskedUsers(users)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(users, paginator.Nums())
}
}
@ -58,20 +80,53 @@ func (c *ApiController) GetGlobalUsers() {
// @router /get-users [get]
func (c *ApiController) GetUsers() {
owner := c.Input().Get("owner")
groupName := c.Input().Get("groupName")
limit := c.Input().Get("pageSize")
page := c.Input().Get("p")
field := c.Input().Get("field")
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" {
c.Data["json"] = object.GetMaskedUsers(object.GetUsers(owner))
if groupName != "" {
maskedUsers, err := object.GetMaskedUsers(object.GetGroupUsers(groupName))
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(maskedUsers)
return
}
maskedUsers, err := object.GetMaskedUsers(object.GetUsers(owner))
if err != nil {
panic(err)
}
c.Data["json"] = maskedUsers
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetUserCount(owner, field, value)))
users := object.GetPaginationUsers(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
users = object.GetMaskedUsers(users)
count, err := object.GetUserCount(owner, field, value, groupName)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
users, err := object.GetPaginationUsers(owner, paginator.Offset(), limit, field, value, sortField, sortOrder, groupName)
if err != nil {
c.ResponseError(err.Error())
return
}
users, err = object.GetMaskedUsers(users)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(users, paginator.Nums())
}
}
@ -93,10 +148,14 @@ func (c *ApiController) GetUser() {
phone := c.Input().Get("phone")
userId := c.Input().Get("userId")
owner := c.Input().Get("owner")
var err error
var userFromUserId *object.User
if userId != "" && owner != "" {
userFromUserId = object.GetUserByUserId(owner, userId)
userFromUserId, err = object.GetUserByUserId(owner, userId)
if err != nil {
panic(err)
}
id = util.GetId(userFromUserId.Owner, userFromUserId.Name)
}
@ -104,7 +163,11 @@ func (c *ApiController) GetUser() {
owner = util.GetOwnerFromId(id)
}
organization := object.GetOrganization(util.GetId("admin", owner))
organization, err := object.GetOrganization(util.GetId("admin", owner))
if err != nil {
panic(err)
}
if !organization.IsProfilePublic {
requestUserId := c.GetSessionUsername()
hasPermission, err := object.CheckUserPermission(requestUserId, id, false, c.GetAcceptLanguage())
@ -117,18 +180,30 @@ func (c *ApiController) GetUser() {
var user *object.User
switch {
case email != "":
user = object.GetUserByEmail(owner, email)
user, err = object.GetUserByEmail(owner, email)
case phone != "":
user = object.GetUserByPhone(owner, phone)
user, err = object.GetUserByPhone(owner, phone)
case userId != "":
user = userFromUserId
default:
user = object.GetUser(id)
user, err = object.GetUser(id)
}
object.ExtendUserWithRolesAndPermissions(user)
if err != nil {
panic(err)
}
c.Data["json"] = object.GetMaskedUser(user)
err = object.ExtendUserWithRolesAndPermissions(user)
if err != nil {
panic(err)
}
maskedUser, err := object.GetMaskedUser(user)
if err != nil {
panic(err)
}
c.Data["json"] = maskedUser
c.ServeJSON()
}
@ -158,7 +233,12 @@ func (c *ApiController) UpdateUser() {
return
}
}
oldUser := object.GetUser(id)
oldUser, err := object.GetUser(id)
if err != nil {
c.ResponseError(err.Error())
return
}
if oldUser == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), id))
return
@ -185,9 +265,18 @@ func (c *ApiController) UpdateUser() {
columns = strings.Split(columnsStr, ",")
}
affected := object.UpdateUser(id, &user, columns, isAdmin)
affected, err := object.UpdateUser(id, &user, columns, isAdmin)
if err != nil {
c.ResponseError(err.Error())
return
}
if affected {
object.UpdateUserToOriginalDatabase(&user)
err = object.UpdateUserToOriginalDatabase(&user)
if err != nil {
c.ResponseError(err.Error())
return
}
}
c.Data["json"] = wrapActionResponse(affected)
@ -209,8 +298,13 @@ func (c *ApiController) AddUser() {
return
}
count := object.GetUserCount("", "", "")
if err := checkQuotaForUser(count); err != nil {
count, err := object.GetUserCount("", "", "", "")
if err != nil {
c.ResponseError(err.Error())
return
}
if err := checkQuotaForUser(int(count)); err != nil {
c.ResponseError(err.Error())
return
}
@ -261,7 +355,12 @@ func (c *ApiController) GetEmailAndPhone() {
organization := c.Ctx.Request.Form.Get("organization")
username := c.Ctx.Request.Form.Get("username")
user := object.GetUserByFields(organization, username)
user, err := object.GetUserByFields(organization, username)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(organization, username)))
return
@ -311,10 +410,6 @@ func (c *ApiController) SetPassword() {
c.ResponseError(c.T("user:New password cannot contain blank space."))
return
}
if len(newPassword) <= 5 {
c.ResponseError(c.T("user:New password must have at least 6 characters"))
return
}
userId := util.GetId(userOwner, userName)
@ -335,7 +430,11 @@ func (c *ApiController) SetPassword() {
c.SetSession("verifiedCode", "")
}
targetUser := object.GetUser(userId)
targetUser, err := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
if oldPassword != "" {
msg := object.CheckPassword(targetUser, oldPassword, c.GetAcceptLanguage())
@ -345,8 +444,19 @@ func (c *ApiController) SetPassword() {
}
}
msg := object.CheckPasswordComplexity(targetUser, newPassword)
if msg != "" {
c.ResponseError(msg)
return
}
targetUser.Password = newPassword
object.SetUserField(targetUser, "password", targetUser.Password)
_, err = object.SetUserField(targetUser, "password", targetUser.Password)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk()
}
@ -384,7 +494,12 @@ func (c *ApiController) GetSortedUsers() {
sorter := c.Input().Get("sorter")
limit := util.ParseInt(c.Input().Get("limit"))
c.Data["json"] = object.GetMaskedUsers(object.GetSortedUsers(owner, sorter, limit))
maskedUsers, err := object.GetMaskedUsers(object.GetSortedUsers(owner, sorter, limit))
if err != nil {
panic(err)
}
c.Data["json"] = maskedUsers
c.ServeJSON()
}
@ -400,13 +515,49 @@ func (c *ApiController) GetUserCount() {
owner := c.Input().Get("owner")
isOnline := c.Input().Get("isOnline")
count := 0
var count int64
var err error
if isOnline == "" {
count = object.GetUserCount(owner, "", "")
count, err = object.GetUserCount(owner, "", "", "")
} else {
count = object.GetOnlineUserCount(owner, util.ParseInt(isOnline))
count, err = object.GetOnlineUserCount(owner, util.ParseInt(isOnline))
}
if err != nil {
c.ResponseError(err.Error())
return
}
c.Data["json"] = count
c.ServeJSON()
}
// AddUserkeys
// @Title AddUserkeys
// @router /add-user-keys [post]
// @Tag User API
func (c *ApiController) AddUserkeys() {
var user object.User
err := json.Unmarshal(c.Ctx.Input.RequestBody, &user)
if err != nil {
c.ResponseError(err.Error())
return
}
isAdmin := c.IsAdmin()
affected, err := object.AddUserkeys(&user, isAdmin)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(affected)
}
func (c *ApiController) RemoveUserFromGroup() {
owner := c.Ctx.Request.Form.Get("owner")
name := c.Ctx.Request.Form.Get("name")
groupName := c.Ctx.Request.Form.Get("groupName")
c.Data["json"] = wrapActionResponse(object.RemoveUserFromGroup(owner, name, groupName))
c.ServeJSON()
}

View File

@ -57,7 +57,12 @@ func (c *ApiController) UploadUsers() {
return
}
affected := object.UploadUsers(owner, fileId)
affected, err := object.UploadUsers(owner, fileId)
if err != nil {
c.ResponseError(err.Error())
return
}
if affected {
c.ResponseOk()
} else {

View File

@ -55,6 +55,9 @@ func (c *ApiController) T(error string) string {
// GetAcceptLanguage ...
func (c *ApiController) GetAcceptLanguage() string {
language := c.Ctx.Request.Header.Get("Accept-Language")
if len(language) > 2 {
language = language[0:2]
}
return conf.GetLanguage(language)
}
@ -92,7 +95,11 @@ func (c *ApiController) RequireSignedInUser() (*object.User, bool) {
return nil, false
}
user := object.GetUser(userId)
user, err := object.GetUser(userId)
if err != nil {
panic(err)
}
if user == nil {
c.ClearUserSession()
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId))
@ -135,35 +142,46 @@ func (c *ApiController) IsMaskedEnabled() (bool, bool) {
return true, isMaskEnabled
}
func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, *object.User, bool) {
func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, error) {
providerName := c.Input().Get("provider")
if providerName != "" {
provider := object.GetProvider(util.GetId("admin", providerName))
if provider == nil {
c.ResponseError(fmt.Sprintf(c.T("util:The provider: %s is not found"), providerName))
return nil, nil, false
provider, err := object.GetProvider(util.GetId("admin", providerName))
if err != nil {
return nil, err
}
return provider, nil, true
if provider == nil {
err = fmt.Errorf(c.T("util:The provider: %s is not found"), providerName)
return nil, err
}
return provider, nil
}
userId, ok := c.RequireSignedIn()
if !ok {
return nil, nil, false
return nil, fmt.Errorf(c.T("general:Please login first"))
}
application, err := object.GetApplicationByUserId(userId)
if err != nil {
return nil, err
}
application, user := object.GetApplicationByUserId(userId)
if application == nil {
c.ResponseError(fmt.Sprintf(c.T("util:No application is found for userId: %s"), userId))
return nil, nil, false
return nil, fmt.Errorf(c.T("util:No application is found for userId: %s"), userId)
}
provider, err := application.GetProviderByCategory(category)
if err != nil {
return nil, err
}
provider := application.GetProviderByCategory(category)
if provider == nil {
c.ResponseError(fmt.Sprintf(c.T("util:No provider for category: %s is found for application: %s"), category, application.Name))
return nil, nil, false
return nil, fmt.Errorf(c.T("util:No provider for category: %s is found for application: %s"), category, application.Name)
}
return provider, user, true
return provider, nil
}
func checkQuotaForApplication(count int) error {

View File

@ -66,8 +66,17 @@ func (c *ApiController) SendVerificationCode() {
}
}
application := object.GetApplication(vform.ApplicationId)
organization := object.GetOrganization(util.GetId(application.Owner, application.Organization))
application, err := object.GetApplication(vform.ApplicationId)
if err != nil {
c.ResponseError(err.Error())
return
}
organization, err := object.GetOrganization(util.GetId(application.Owner, application.Organization))
if err != nil {
c.ResponseError(c.T(err.Error()))
}
if organization == nil {
c.ResponseError(c.T("check:Organization does not exist"))
return
@ -77,12 +86,20 @@ func (c *ApiController) SendVerificationCode() {
// checkUser != "", means method is ForgetVerification
if vform.CheckUser != "" {
owner := application.Organization
user = object.GetUser(util.GetId(owner, vform.CheckUser))
user, err = object.GetUser(util.GetId(owner, vform.CheckUser))
if err != nil {
c.ResponseError(err.Error())
return
}
}
// mfaSessionData != nil, means method is MfaSetupVerification
if mfaSessionData := c.getMfaSessionData(); mfaSessionData != nil {
user = object.GetUser(mfaSessionData.UserId)
user, err = object.GetUser(mfaSessionData.UserId)
if err != nil {
c.ResponseError(err.Error())
return
}
}
sendResp := errors.New("invalid dest type")
@ -99,7 +116,12 @@ func (c *ApiController) SendVerificationCode() {
vform.Dest = user.Email
}
user = object.GetUserByEmail(organization.Name, vform.Dest)
user, err = object.GetUserByEmail(organization.Name, vform.Dest)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
return
@ -113,7 +135,12 @@ func (c *ApiController) SendVerificationCode() {
}
}
provider := application.GetEmailProvider()
provider, err := application.GetEmailProvider()
if err != nil {
c.ResponseError(err.Error())
return
}
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, remoteAddr, vform.Dest)
case object.VerifyTypePhone:
if vform.Method == LoginVerification || vform.Method == ForgetVerification {
@ -121,7 +148,10 @@ func (c *ApiController) SendVerificationCode() {
vform.Dest = user.Phone
}
if user = object.GetUserByPhone(organization.Name, vform.Dest); user == nil {
if user, err = object.GetUserByPhone(organization.Name, vform.Dest); err != nil {
c.ResponseError(err.Error())
return
} else if user == nil {
c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
return
}
@ -140,7 +170,12 @@ func (c *ApiController) SendVerificationCode() {
vform.CountryCode = mfaProps.CountryCode
}
provider := application.GetSmsProvider()
provider, err := application.GetSmsProvider()
if err != nil {
c.ResponseError(err.Error())
return
}
if phone, ok := util.GetE164Number(vform.Dest, vform.CountryCode); !ok {
c.ResponseError(fmt.Sprintf(c.T("verification:Phone number is invalid in your region %s"), vform.CountryCode))
return
@ -213,7 +248,12 @@ func (c *ApiController) ResetEmailOrPhone() {
}
checkDest := dest
organization := object.GetOrganizationByUser(user)
organization, err := object.GetOrganizationByUser(user)
if err != nil {
c.ResponseError(c.T(err.Error()))
return
}
if destType == object.VerifyTypePhone {
if object.HasUserByField(user.Owner, "phone", dest) {
c.ResponseError(c.T("check:Phone already exists"))
@ -260,16 +300,25 @@ func (c *ApiController) ResetEmailOrPhone() {
switch destType {
case object.VerifyTypeEmail:
user.Email = dest
object.SetUserField(user, "email", user.Email)
_, err = object.SetUserField(user, "email", user.Email)
case object.VerifyTypePhone:
user.Phone = dest
object.SetUserField(user, "phone", user.Phone)
_, err = object.SetUserField(user, "phone", user.Phone)
default:
c.ResponseError(c.T("verification:Unknown type"))
return
}
if err != nil {
c.ResponseError(err.Error())
return
}
err = object.DisableVerificationCode(checkDest)
if err != nil {
c.ResponseError(err.Error())
return
}
object.DisableVerificationCode(checkDest)
c.ResponseOk()
}
@ -287,7 +336,11 @@ func (c *ApiController) VerifyCode() {
var user *object.User
if authForm.Name != "" {
user = object.GetUserByFields(authForm.Organization, authForm.Name)
user, err = object.GetUserByFields(authForm.Organization, authForm.Name)
if err != nil {
c.ResponseError(err.Error())
return
}
}
var checkDest string
@ -302,7 +355,10 @@ func (c *ApiController) VerifyCode() {
}
}
if user = object.GetUserByFields(authForm.Organization, authForm.Username); user == nil {
if user, err = object.GetUserByFields(authForm.Organization, authForm.Username); err != nil {
c.ResponseError(err.Error())
return
} else if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(authForm.Organization, authForm.Username)))
return
}
@ -321,7 +377,11 @@ func (c *ApiController) VerifyCode() {
c.ResponseError(result.Msg)
return
}
object.DisableVerificationCode(checkDest)
err = object.DisableVerificationCode(checkDest)
if err != nil {
c.ResponseError(err.Error())
return
}
c.SetSession("verifiedCode", authForm.Code)
c.ResponseOk()

View File

@ -33,7 +33,12 @@ import (
// @Success 200 {object} protocol.CredentialCreation The CredentialCreationOptions object
// @router /webauthn/signup/begin [get]
func (c *ApiController) WebAuthnSignupBegin() {
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host)
if err != nil {
c.ResponseError(err.Error())
return
}
user := c.getCurrentUser()
if user == nil {
c.ResponseError(c.T("general:Please login first"))
@ -64,7 +69,12 @@ func (c *ApiController) WebAuthnSignupBegin() {
// @Success 200 {object} Response "The Response object"
// @router /webauthn/signup/finish [post]
func (c *ApiController) WebAuthnSignupFinish() {
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host)
if err != nil {
c.ResponseError(err.Error())
return
}
user := c.getCurrentUser()
if user == nil {
c.ResponseError(c.T("general:Please login first"))
@ -84,7 +94,12 @@ func (c *ApiController) WebAuthnSignupFinish() {
return
}
isGlobalAdmin := c.IsGlobalAdmin()
user.AddCredentials(*credential, isGlobalAdmin)
_, err = user.AddCredentials(*credential, isGlobalAdmin)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk()
}
@ -97,10 +112,20 @@ func (c *ApiController) WebAuthnSignupFinish() {
// @Success 200 {object} protocol.CredentialAssertion The CredentialAssertion object
// @router /webauthn/signin/begin [get]
func (c *ApiController) WebAuthnSigninBegin() {
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host)
if err != nil {
c.ResponseError(err.Error())
return
}
userOwner := c.Input().Get("owner")
userName := c.Input().Get("name")
user := object.GetUserByFields(userOwner, userName)
user, err := object.GetUserByFields(userOwner, userName)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(userOwner, userName)))
return
@ -129,7 +154,12 @@ func (c *ApiController) WebAuthnSigninBegin() {
// @router /webauthn/signin/finish [post]
func (c *ApiController) WebAuthnSigninFinish() {
responseType := c.Input().Get("responseType")
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host)
if err != nil {
c.ResponseError(err.Error())
return
}
sessionObj := c.GetSession("authentication")
sessionData, ok := sessionObj.(webauthn.SessionData)
if !ok {
@ -138,8 +168,13 @@ func (c *ApiController) WebAuthnSigninFinish() {
}
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
userId := string(sessionData.UserID)
user := object.GetUser(userId)
_, err := webauthnObj.FinishLogin(user, sessionData, c.Ctx.Request)
user, err := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
_, err = webauthnObj.FinishLogin(user, sessionData, c.Ctx.Request)
if err != nil {
c.ResponseError(err.Error())
return
@ -147,7 +182,12 @@ func (c *ApiController) WebAuthnSigninFinish() {
c.SetSessionUsername(userId)
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
application := object.GetApplicationByUser(user)
application, err := object.GetApplicationByUser(user)
if err != nil {
c.ResponseError(err.Error())
return
}
var authForm form.AuthForm
authForm.Type = responseType
resp := c.HandleLoggedIn(application, user, &authForm)

View File

@ -38,13 +38,31 @@ func (c *ApiController) GetWebhooks() {
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")
organization := c.Input().Get("organization")
if limit == "" || page == "" {
c.Data["json"] = object.GetWebhooks(owner, organization)
webhooks, err := object.GetWebhooks(owner, organization)
if err != nil {
panic(err)
}
c.Data["json"] = webhooks
c.ServeJSON()
} else {
limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetWebhookCount(owner, organization, field, value)))
webhooks := object.GetPaginationWebhooks(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
count, err := object.GetWebhookCount(owner, organization, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}
paginator := pagination.SetPaginator(c.Ctx, limit, count)
webhooks, err := object.GetPaginationWebhooks(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(webhooks, paginator.Nums())
}
}
@ -59,7 +77,12 @@ func (c *ApiController) GetWebhooks() {
func (c *ApiController) GetWebhook() {
id := c.Input().Get("id")
c.Data["json"] = object.GetWebhook(id)
webhook, err := object.GetWebhook(id)
if err != nil {
panic(err)
}
c.Data["json"] = webhook
c.ServeJSON()
}

22
go.mod
View File

@ -8,8 +8,9 @@ require (
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
github.com/aliyun/alibaba-cloud-sdk-go v1.62.188 // indirect
github.com/aws/aws-sdk-go v1.44.4
github.com/beego/beego v1.12.11
github.com/beego/beego v1.12.12
github.com/beevik/etree v1.1.0
github.com/casbin/casbin v1.9.1 // indirect
github.com/casbin/casbin/v2 v2.30.1
github.com/casdoor/go-sms-sender v0.6.1
github.com/casdoor/gomail/v2 v2.0.1
@ -18,6 +19,7 @@ require (
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
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/fogleman/gg v1.3.0
github.com/forestmgy/ldapserver v1.1.0
github.com/go-git/go-git/v5 v5.6.0
@ -28,24 +30,28 @@ require (
github.com/go-webauthn/webauthn v0.6.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/gorilla/mux v1.7.3 // indirect
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
github.com/lestrrat-go/jwx v1.2.21
github.com/lib/pq v1.8.0
github.com/lib/pq v1.10.2
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
github.com/markbates/goth v1.75.2
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
github.com/nyaruka/phonenumbers v1.1.5
github.com/pkoukk/tiktoken-go v0.1.1
github.com/prometheus/client_golang v1.7.0
github.com/plutov/paypal/v4 v4.7.0
github.com/prometheus/client_golang v1.11.1
github.com/prometheus/client_model v0.2.0
github.com/qiangmzsx/string-adapter/v2 v2.1.0
github.com/robfig/cron/v3 v3.0.1
github.com/russellhaering/gosaml2 v0.6.0
github.com/russellhaering/goxmldsig v1.1.1
github.com/russellhaering/gosaml2 v0.9.0
github.com/russellhaering/goxmldsig v1.2.0
github.com/sashabaranov/go-openai v1.9.1
github.com/satori/go.uuid v1.2.0
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
@ -53,14 +59,16 @@ require (
github.com/tealeg/xlsx v1.0.5
github.com/thanhpk/randstr v1.0.4
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/xorm-io/builder v0.3.13 // indirect
github.com/xorm-io/core v0.7.4
github.com/xorm-io/xorm v1.1.6
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.6.0
golang.org/x/net v0.6.0
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
golang.org/x/net v0.7.0
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0
gopkg.in/yaml.v2 v2.3.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84
)

75
go.sum
View File

@ -73,6 +73,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387 h1:loy0fjI90vF44BPW4ZYOkE3tDkGTy7yHURusOJimt+I=
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387/go.mod h1:GuR5j/NW7AU7tDAQUDGCtpiPxWIOy/c3kiRDnlwiCHc=
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
@ -92,8 +93,8 @@ github.com/aws/aws-sdk-go v1.44.4 h1:ePN0CVJMdiz2vYUcJH96eyxRrtKGSDMgyhP6rah2OgE
github.com/aws/aws-sdk-go v1.44.4/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/beego/beego v1.12.11 h1:MWKcnpavb7iAIS0m6uuEq6pHKkYvGNw/5umIUKqL7jM=
github.com/beego/beego v1.12.11/go.mod h1:QURFL1HldOcCZAxnc1cZ7wrplsYR5dKPHFjmk6WkLAs=
github.com/beego/beego v1.12.12 h1:ARY1sNVSS23N0mEQIhSqRDTyyDlx95JY0V3GogBbZbQ=
github.com/beego/beego v1.12.12/go.mod h1:QURFL1HldOcCZAxnc1cZ7wrplsYR5dKPHFjmk6WkLAs=
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
@ -106,8 +107,9 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/casbin/casbin v1.7.0 h1:PuzlE8w0JBg/DhIqnkF1Dewf3z+qmUZMVN07PonvVUQ=
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
github.com/casbin/casbin v1.9.1 h1:ucjbS5zTrmSLtH4XogqOG920Poe6QatdXtz1FEbApeM=
github.com/casbin/casbin v1.9.1/go.mod h1:z8uPsfBJGUsnkagrt3G8QvjgTKFMBJ32UP8HpZllfog=
github.com/casbin/casbin/v2 v2.1.0/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/casbin/casbin/v2 v2.28.3/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
github.com/casbin/casbin/v2 v2.30.1 h1:P5HWadDL7olwUXNdcuKUBk+x75Y2eitFxYTcLNKeKF0=
@ -168,8 +170,9 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -205,10 +208,12 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-ldap/ldap/v3 v3.3.0 h1:lwx+SJpgOHd8tG6SumBQZXCmNX51zM8B1cfxJ5gv4tQ=
github.com/go-ldap/ldap/v3 v3.3.0/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-mysql-org/go-mysql v1.7.0 h1:qE5FTRb3ZeTQmlk3pjE+/m2ravGxxRDrVDTyDe9tvqI=
github.com/go-mysql-org/go-mysql v1.7.0/go.mod h1:9cRWLtuXNKhamUPMkrDVzBhaomGvqLRLtBiyjvjc4pk=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
@ -273,8 +278,10 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
@ -292,6 +299,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
@ -321,8 +330,9 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY=
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
@ -356,9 +366,9 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jmoiron/sqlx v1.3.3/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@ -368,6 +378,7 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
@ -377,6 +388,7 @@ github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@ -408,8 +420,9 @@ github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmt
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 h1:wIONC+HMNRqmWBjuMxhatuSzHaljStc4gjDeKycxy0A=
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@ -419,8 +432,8 @@ github.com/markbates/goth v1.75.2 h1:C7KloBMMk50JyXaHhzfqWYLW6+bDcSVIvUGHXneLWro
github.com/markbates/goth v1.75.2/go.mod h1:X6xdNgpapSENS0O35iTBBcMHoJDQDfI9bJl+APCkYMc=
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911 h1:erppMjjp69Rertg1zlgRbLJH1u+eCmRPxKjMZ5I8/Ro=
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU=
github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI=
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
@ -445,6 +458,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA=
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
@ -481,13 +495,17 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkoukk/tiktoken-go v0.1.1 h1:jtkYlIECjyM9OW1w4rjPmTohK4arORP9V25y6TM6nXo=
github.com/pkoukk/tiktoken-go v0.1.1/go.mod h1:boMWvk9pQCOTx11pgu0DrIdrAKgQzzJKUP6vLXaz7Rw=
github.com/plutov/paypal/v4 v4.7.0 h1:6TRvYD4ny6yQfHaABeStNf43GFM1wpW5jU/XEDGQmq0=
github.com/plutov/paypal/v4 v4.7.0/go.mod h1:D56boafCRGcF/fEM0w282kj0fCDKIyrwOPX/Te1jCmw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R9JX0FuA/U=
github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s=
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -496,13 +514,15 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qiangmzsx/string-adapter/v2 v2.1.0 h1:q0y8TPa/sTwtriJPRe8gWL++PuZ+XbOUuvKU+hvtTYs=
github.com/qiangmzsx/string-adapter/v2 v2.1.0/go.mod h1:PElPB7b7HnGKTsuADAffFpOQXHqjEGJz1+U1a6yR5wA=
@ -518,11 +538,10 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/russellhaering/gosaml2 v0.6.0 h1:OED8FLgczXxXAPlKhnJHQfmEig52tDX2qeXdPtZRIKc=
github.com/russellhaering/gosaml2 v0.6.0/go.mod h1:CtzxpPr4+bevsATaqR0rw3aqrNlX274b+3C6vFTLCk8=
github.com/russellhaering/goxmldsig v1.1.0/go.mod h1:QK8GhXPB3+AfuCrfo0oRISa9NfzeCpWmxeGnqEpDF9o=
github.com/russellhaering/goxmldsig v1.1.1 h1:vI0r2osGF1A9PLvsGdPUAGwEIrKa4Pj5sesSBsebIxM=
github.com/russellhaering/goxmldsig v1.1.1/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
github.com/russellhaering/gosaml2 v0.9.0 h1:CNMnH42z/GirrKjdmNrSS6bAAs47F9bPdl4PfRmVOIk=
github.com/russellhaering/gosaml2 v0.9.0/go.mod h1:byViER/1YPUa0Puj9ROZblpoq2jsE7h/CJmitzX0geU=
github.com/russellhaering/goxmldsig v1.2.0 h1:Y6GTTc9Un5hCxSzVz4UIWQ/zuVwDvzJk80guqzwx6Vg=
github.com/russellhaering/goxmldsig v1.2.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sashabaranov/go-openai v1.9.1 h1:3N52HkJKo9Zlo/oe1AVv5ZkCOny0ra58/ACvAxkN3MM=
@ -531,8 +550,9 @@ github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik=
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE=
@ -548,6 +568,7 @@ github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKz
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag=
@ -574,6 +595,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@ -700,8 +722,9 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@ -758,8 +781,9 @@ golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfS
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -817,6 +841,7 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -827,6 +852,7 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210629170331-7dc0b73dc9fb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -1005,8 +1031,10 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
@ -1039,8 +1067,9 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -68,7 +68,8 @@
"Missing parameter": "Fehlender Parameter",
"Please login first": "Bitte zuerst einloggen",
"The user: %s doesn't exist": "Der Benutzer %s existiert nicht",
"don't support captchaProvider: ": "Unterstütze captchaProvider nicht:"
"don't support captchaProvider: ": "Unterstütze captchaProvider nicht:",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Es gibt einen LDAP-Server"
@ -119,8 +120,7 @@
},
"user": {
"Display name cannot be empty": "Anzeigename darf nicht leer sein",
"New password cannot contain blank space.": "Das neue Passwort darf keine Leerzeichen enthalten.",
"New password must have at least 6 characters": "Das neue Passwort muss mindestens 6 Zeichen haben"
"New password cannot contain blank space.": "Das neue Passwort darf keine Leerzeichen enthalten."
},
"user_upload": {
"Failed to import users": "Fehler beim Importieren von Benutzern"

View File

@ -68,7 +68,8 @@
"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: "
"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"
@ -119,8 +120,7 @@
},
"user": {
"Display name cannot be empty": "Display name cannot be empty",
"New password cannot contain blank space.": "New password cannot contain blank space.",
"New password must have at least 6 characters": "New password must have at least 6 characters"
"New password cannot contain blank space.": "New password cannot contain blank space."
},
"user_upload": {
"Failed to import users": "Failed to import users"

View File

@ -68,7 +68,8 @@
"Missing parameter": "Parámetro faltante",
"Please login first": "Por favor, inicia sesión primero",
"The user: %s doesn't exist": "El usuario: %s no existe",
"don't support captchaProvider: ": "No apoyo a captchaProvider"
"don't support captchaProvider: ": "No apoyo a captchaProvider",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "El servidor LDAP existe"
@ -119,8 +120,7 @@
},
"user": {
"Display name cannot be empty": "El nombre de pantalla no puede estar vacío",
"New password cannot contain blank space.": "La nueva contraseña no puede contener espacios en blanco.",
"New password must have at least 6 characters": "La nueva contraseña debe tener al menos 6 caracteres"
"New password cannot contain blank space.": "La nueva contraseña no puede contener espacios en blanco."
},
"user_upload": {
"Failed to import users": "Error al importar usuarios"

View File

@ -68,7 +68,8 @@
"Missing parameter": "Paramètre manquant",
"Please login first": "Veuillez d'abord vous connecter",
"The user: %s doesn't exist": "L'utilisateur : %s n'existe pas",
"don't support captchaProvider: ": "Ne pas prendre en charge la captchaProvider"
"don't support captchaProvider: ": "Ne pas prendre en charge la captchaProvider",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Le serveur LDAP existe"
@ -119,8 +120,7 @@
},
"user": {
"Display name cannot be empty": "Le nom d'affichage ne peut pas être vide",
"New password cannot contain blank space.": "Le nouveau mot de passe ne peut pas contenir d'espace.",
"New password must have at least 6 characters": "Le nouveau mot de passe doit comporter au moins 6 caractères"
"New password cannot contain blank space.": "Le nouveau mot de passe ne peut pas contenir d'espace."
},
"user_upload": {
"Failed to import users": "Échec de l'importation des utilisateurs"

View File

@ -68,7 +68,8 @@
"Missing parameter": "Parameter hilang",
"Please login first": "Silahkan login terlebih dahulu",
"The user: %s doesn't exist": "Pengguna: %s tidak ada",
"don't support captchaProvider: ": "Jangan mendukung captchaProvider:"
"don't support captchaProvider: ": "Jangan mendukung captchaProvider:",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Server ldap ada"
@ -119,8 +120,7 @@
},
"user": {
"Display name cannot be empty": "Nama tampilan tidak boleh kosong",
"New password cannot contain blank space.": "Kata sandi baru tidak boleh mengandung spasi kosong.",
"New password must have at least 6 characters": "Kata sandi baru harus memiliki setidaknya 6 karakter"
"New password cannot contain blank space.": "Kata sandi baru tidak boleh mengandung spasi kosong."
},
"user_upload": {
"Failed to import users": "Gagal mengimpor pengguna"

View File

@ -68,7 +68,8 @@
"Missing parameter": "不足しているパラメーター",
"Please login first": "最初にログインしてください",
"The user: %s doesn't exist": "そのユーザー:%sは存在しません",
"don't support captchaProvider: ": "captchaProviderをサポートしないでください"
"don't support captchaProvider: ": "captchaProviderをサポートしないでください",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "LDAPサーバーは存在します"
@ -119,8 +120,7 @@
},
"user": {
"Display name cannot be empty": "表示名は空にできません",
"New password cannot contain blank space.": "新しいパスワードにはスペースを含めることはできません。",
"New password must have at least 6 characters": "新しいパスワードは少なくとも6文字必要です"
"New password cannot contain blank space.": "新しいパスワードにはスペースを含めることはできません。"
},
"user_upload": {
"Failed to import users": "ユーザーのインポートに失敗しました"

View File

@ -68,7 +68,8 @@
"Missing parameter": "누락된 매개변수",
"Please login first": "먼저 로그인 하십시오",
"The user: %s doesn't exist": "사용자 %s는 존재하지 않습니다",
"don't support captchaProvider: ": "CaptchaProvider를 지원하지 마세요"
"don't support captchaProvider: ": "CaptchaProvider를 지원하지 마세요",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "LDAP 서버가 존재합니다"
@ -119,8 +120,7 @@
},
"user": {
"Display name cannot be empty": "디스플레이 이름은 비어 있을 수 없습니다",
"New password cannot contain blank space.": "새 비밀번호에는 공백이 포함될 수 없습니다.",
"New password must have at least 6 characters": "새로운 비밀번호는 최소 6자 이상이어야 합니다"
"New password cannot contain blank space.": "새 비밀번호에는 공백이 포함될 수 없습니다."
},
"user_upload": {
"Failed to import users": "사용자 가져오기를 실패했습니다"

149
i18n/locales/pt/data.json Normal file
View File

@ -0,0 +1,149 @@
{
"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"
},
"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

@ -68,7 +68,8 @@
"Missing parameter": "Отсутствующий параметр",
"Please login first": "Пожалуйста, сначала войдите в систему",
"The user: %s doesn't exist": "Пользователь %s не существует",
"don't support captchaProvider: ": "не поддерживайте captchaProvider:"
"don't support captchaProvider: ": "не поддерживайте captchaProvider:",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "LDAP-сервер существует"
@ -119,8 +120,7 @@
},
"user": {
"Display name cannot be empty": "Отображаемое имя не может быть пустым",
"New password cannot contain blank space.": "Новый пароль не может содержать пробелы.",
"New password must have at least 6 characters": "Новый пароль должен содержать не менее 6 символов"
"New password cannot contain blank space.": "Новый пароль не может содержать пробелы."
},
"user_upload": {
"Failed to import users": "Не удалось импортировать пользователей"

View File

@ -68,10 +68,11 @@
"Missing parameter": "Thiếu tham số",
"Please login first": "Vui lòng đăng nhập trước",
"The user: %s doesn't exist": "Người dùng: %s không tồn tại",
"don't support captchaProvider: ": "Không hỗ trợ captchaProvider:"
"don't support captchaProvider: ": "không hỗ trợ captchaProvider: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "Máy chủ Ldap tồn tại"
"Ldap server exist": "Máy chủ LDAP tồn tại"
},
"link": {
"Please link first": "Vui lòng kết nối trước tiên",
@ -119,8 +120,7 @@
},
"user": {
"Display name cannot be empty": "Tên hiển thị không thể trống",
"New password cannot contain blank space.": "Mật khẩu mới không thể chứa dấu trắng.",
"New password must have at least 6 characters": "Mật khẩu mới phải có ít nhất 6 ký tự"
"New password cannot contain blank space.": "Mật khẩu mới không thể chứa dấu trắng."
},
"user_upload": {
"Failed to import users": "Không thể nhập người dùng"

View File

@ -68,7 +68,8 @@
"Missing parameter": "缺少参数",
"Please login first": "请先登录",
"The user: %s doesn't exist": "用户: %s不存在",
"don't support captchaProvider: ": "不支持验证码提供商: "
"don't support captchaProvider: ": "不支持验证码提供商: ",
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
},
"ldap": {
"Ldap server exist": "LDAP服务器已存在"
@ -83,7 +84,7 @@
},
"organization": {
"Only admin can modify the %s.": "仅允许管理员可以修改%s",
"The %s is immutable.": "%s是不可变的",
"The %s is immutable.": "%s 是不可变的",
"Unknown modify rule %s.": "未知的修改规则: %s"
},
"provider": {
@ -119,8 +120,7 @@
},
"user": {
"Display name cannot be empty": "显示名称不可为空",
"New password cannot contain blank space.": "新密码不可以包含空格",
"New password must have at least 6 characters": "新密码至少需要6位字符"
"New password cannot contain blank space.": "新密码不可以包含空格"
},
"user_upload": {
"Failed to import users": "导入用户失败"
@ -143,7 +143,7 @@
"the user does not exist, please sign up first": "用户不存在,请先注册"
},
"webauthn": {
"Found no credentials for this user": "该用户没有WebAuthn凭据",
"Found no credentials for this user": "该用户没有 WebAuthn 凭据",
"Please call WebAuthnSigninBegin first": "请先调用WebAuthnSigninBegin函数"
}
}

View File

@ -16,6 +16,7 @@ package idp
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
@ -83,7 +84,7 @@ func (idp *CasdoorIdProvider) GetToken(code string) (*oauth2.Token, error) {
// check if token is expired
if pToken.ExpiresIn <= 0 {
return nil, fmt.Errorf("%s", pToken.AccessToken)
return nil, errors.New(pToken.AccessToken)
}
token := &oauth2.Token{
AccessToken: pToken.AccessToken,

View File

@ -75,7 +75,9 @@ func (idp *WeComIdProvider) GetToken(code string) (*oauth2.Token, error) {
ProviderSecret string `json:"provider_secret"`
}{idp.Config.ClientID, idp.Config.ClientSecret}
data, err := idp.postWithBody(pTokenParams, "https://qyapi.weixin.qq.com/cgi-bin/service/get_provider_token")
if err != nil {
return nil, err
}
pToken := &WeComProviderToken{}
err = json.Unmarshal(data, pToken)
if err != nil {

View File

@ -8,6 +8,7 @@
"favicon": "",
"passwordType": "plain",
"passwordSalt": "",
"passwordOptions": ["AtLeast6"],
"countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"],
"defaultAvatar": "",
"defaultApplication": "",

View File

@ -84,6 +84,7 @@ func stringInSlice(value string, list []string) bool {
}
func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int) {
var err error
r := m.GetSearchRequest()
name, org, code := getNameAndOrgFromFilter(string(r.BaseObject()), r.FilterString())
@ -93,11 +94,19 @@ func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int)
if name == "*" && m.Client.IsOrgAdmin { // get all users from organization 'org'
if m.Client.IsGlobalAdmin && org == "*" {
filteredUsers = object.GetGlobalUsers()
filteredUsers, err = object.GetGlobalUsers()
if err != nil {
panic(err)
}
return filteredUsers, ldap.LDAPResultSuccess
}
if m.Client.IsGlobalAdmin || org == m.Client.OrgName {
filteredUsers = object.GetUsers(org)
filteredUsers, err = object.GetUsers(org)
if err != nil {
panic(err)
}
return filteredUsers, ldap.LDAPResultSuccess
} else {
return nil, ldap.LDAPResultInsufficientAccessRights
@ -112,13 +121,21 @@ func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int)
return nil, ldap.LDAPResultInsufficientAccessRights
}
user := object.GetUser(userId)
user, err := object.GetUser(userId)
if err != nil {
panic(err)
}
if user != nil {
filteredUsers = append(filteredUsers, user)
return filteredUsers, ldap.LDAPResultSuccess
}
organization := object.GetOrganization(util.GetId("admin", org))
organization, err := object.GetOrganization(util.GetId("admin", org))
if err != nil {
panic(err)
}
if organization == nil {
return nil, ldap.LDAPResultNoSuchObject
}
@ -127,7 +144,11 @@ func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int)
return nil, ldap.LDAPResultNoSuchObject
}
users := object.GetUsersByTag(org, name)
users, err := object.GetUsersByTag(org, name)
if err != nil {
panic(err)
}
filteredUsers = append(filteredUsers, users...)
return filteredUsers, ldap.LDAPResultSuccess
}
@ -137,7 +158,11 @@ func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int)
// TODO not handle salt yet
// @return {md5}5f4dcc3b5aa765d61d8327deb882cf99
func getUserPasswordWithType(user *object.User) string {
org := object.GetOrganizationByUser(user)
org, err := object.GetOrganizationByUser(user)
if err != nil {
panic(err)
}
if org.PasswordType == "" || org.PasswordType == "plain" {
return user.Password
}

14
main.go
View File

@ -27,17 +27,21 @@ import (
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/proxy"
"github.com/casdoor/casdoor/routers"
_ "github.com/casdoor/casdoor/routers"
"github.com/casdoor/casdoor/util"
)
func main() {
createDatabase := flag.Bool("createDatabase", false, "true if you need Casdoor to create database")
func getCreateDatabaseFlag() bool {
res := flag.Bool("createDatabase", false, "true if you need Casdoor to create database")
flag.Parse()
return *res
}
func main() {
createDatabase := getCreateDatabaseFlag()
object.InitAdapter()
object.CreateTables(createDatabase)
object.DoMigration()
object.CreateTables(*createDatabase)
object.InitDb()
object.InitFromFile()
@ -74,7 +78,7 @@ func main() {
beego.BConfig.WebConfig.Session.SessionCookieLifeTime = 3600 * 24 * 30
// beego.BConfig.WebConfig.Session.SessionCookieSameSite = http.SameSiteNoneMode
err := logs.SetLogger("file", `{"filename":"logs/casdoor.log","maxdays":99999,"perm":"0770"}`)
err := logs.SetLogger(logs.AdapterFile, conf.GetConfigString("logConfig"))
if err != nil {
panic(err)
}

View File

@ -41,18 +41,26 @@ func InitConfig() {
beego.BConfig.WebConfig.Session.SessionOn = true
InitAdapter()
DoMigration()
CreateTables(true)
DoMigration()
}
func InitAdapter() {
adapter = NewAdapter(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName"))
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
tbMapper := core.NewPrefixMapper(core.SnakeMapper{}, tableNamePrefix)
adapter.Engine.SetTableMapper(tbMapper)
}
func CreateTables(createDatabase bool) {
if createDatabase {
adapter.CreateDatabase()
err := adapter.CreateDatabase()
if err != nil {
panic(err)
}
}
adapter.createTable()
}
@ -119,13 +127,9 @@ func (a *Adapter) close() {
}
func (a *Adapter) createTable() {
showSql, _ := conf.GetConfigBool("showSql")
showSql := conf.GetConfigBool("showSql")
a.Engine.ShowSQL(showSql)
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
tbMapper := core.NewPrefixMapper(core.SnakeMapper{}, tableNamePrefix)
a.Engine.SetTableMapper(tbMapper)
err := a.Engine.Sync2(new(Organization))
if err != nil {
panic(err)
@ -136,6 +140,11 @@ func (a *Adapter) createTable() {
panic(err)
}
err = a.Engine.Sync2(new(Group))
if err != nil {
panic(err)
}
err = a.Engine.Sync2(new(Role))
if err != nil {
panic(err)
@ -280,3 +289,52 @@ func GetSession(owner string, offset, limit int, field, value, sortField, sortOr
}
return session
}
func GetSessionForUser(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 != "" {
if offset == -1 {
session = session.And("owner=?", owner)
} else {
session = session.And("a.owner=?", owner)
}
}
if field != "" && value != "" {
if 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

@ -38,7 +38,7 @@ type Application struct {
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
DisplayName string `xorm:"varchar(100)" json:"displayName"`
Logo string `xorm:"varchar(100)" json:"logo"`
Logo string `xorm:"varchar(200)" json:"logo"`
HomepageUrl string `xorm:"varchar(100)" json:"homepageUrl"`
Description string `xorm:"varchar(100)" json:"description"`
Organization string `xorm:"varchar(100)" json:"organization"`
@ -51,6 +51,7 @@ type Application struct {
EnableSamlCompress bool `json:"enableSamlCompress"`
EnableWebAuthn bool `json:"enableWebAuthn"`
EnableLinkWithEmail bool `json:"enableLinkWithEmail"`
OrgChoiceMode string `json:"orgChoiceMode"`
SamlReplyUrl string `xorm:"varchar(100)" json:"samlReplyUrl"`
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
@ -78,134 +79,155 @@ type Application struct {
FormBackgroundUrl string `xorm:"varchar(200)" json:"formBackgroundUrl"`
}
func GetApplicationCount(owner, field, value string) int {
func GetApplicationCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Application{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Application{})
}
func GetOrganizationApplicationCount(owner, Organization, field, value string) int {
func GetOrganizationApplicationCount(owner, Organization, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Application{Organization: Organization})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Application{Organization: Organization})
}
func GetApplications(owner string) []*Application {
func GetApplications(owner string) ([]*Application, error) {
applications := []*Application{}
err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Owner: owner})
if err != nil {
panic(err)
return applications, err
}
return applications
return applications, nil
}
func GetOrganizationApplications(owner string, organization string) []*Application {
func GetOrganizationApplications(owner string, organization string) ([]*Application, error) {
applications := []*Application{}
err := adapter.Engine.Desc("created_time").Find(&applications, &Application{Organization: organization})
if err != nil {
panic(err)
return applications, err
}
return applications
return applications, nil
}
func GetPaginationApplications(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Application {
func GetPaginationApplications(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Application, error) {
var applications []*Application
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&applications)
if err != nil {
panic(err)
return applications, err
}
return applications
return applications, nil
}
func GetPaginationOrganizationApplications(owner, organization string, offset, limit int, field, value, sortField, sortOrder string) []*Application {
func GetPaginationOrganizationApplications(owner, organization string, offset, limit int, field, value, sortField, sortOrder string) ([]*Application, error) {
applications := []*Application{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&applications, &Application{Organization: organization})
if err != nil {
panic(err)
return applications, err
}
return applications
return applications, nil
}
func getProviderMap(owner string) map[string]*Provider {
providers := GetProviders(owner)
m := map[string]*Provider{}
func getProviderMap(owner string) (m map[string]*Provider, err error) {
providers, err := GetProviders(owner)
if err != nil {
return nil, err
}
m = map[string]*Provider{}
for _, provider := range providers {
// Get QRCode only once
if provider.Type == "WeChat" && provider.DisableSsl == true && provider.Content == "" {
provider.Content, _ = idp.GetWechatOfficialAccountQRCode(provider.ClientId2, provider.ClientSecret2)
if provider.Type == "WeChat" && provider.DisableSsl && provider.Content == "" {
provider.Content, err = idp.GetWechatOfficialAccountQRCode(provider.ClientId2, provider.ClientSecret2)
if err != nil {
return
}
UpdateProvider(provider.Owner+"/"+provider.Name, provider)
}
m[provider.Name] = GetMaskedProvider(provider, true)
}
return m
return m, err
}
func extendApplicationWithProviders(application *Application) {
m := getProviderMap(application.Organization)
func extendApplicationWithProviders(application *Application) (err error) {
m, err := getProviderMap(application.Organization)
if err != nil {
return err
}
for _, providerItem := range application.Providers {
if provider, ok := m[providerItem.Name]; ok {
providerItem.Provider = provider
}
}
return
}
func extendApplicationWithOrg(application *Application) {
organization := getOrganization(application.Owner, application.Organization)
func extendApplicationWithOrg(application *Application) (err error) {
organization, err := getOrganization(application.Owner, application.Organization)
application.OrganizationObj = organization
return
}
func getApplication(owner string, name string) *Application {
func getApplication(owner string, name string) (*Application, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
application := Application{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&application)
if err != nil {
panic(err)
return nil, err
}
if existed {
extendApplicationWithProviders(&application)
extendApplicationWithOrg(&application)
return &application
err = extendApplicationWithProviders(&application)
if err != nil {
return nil, err
}
err = extendApplicationWithOrg(&application)
if err != nil {
return nil, err
}
return &application, nil
} else {
return nil
return nil, nil
}
}
func GetApplicationByOrganizationName(organization string) *Application {
func GetApplicationByOrganizationName(organization string) (*Application, error) {
application := Application{}
existed, err := adapter.Engine.Where("organization=?", organization).Get(&application)
if err != nil {
panic(err)
return nil, nil
}
if existed {
extendApplicationWithProviders(&application)
extendApplicationWithOrg(&application)
return &application
err = extendApplicationWithProviders(&application)
if err != nil {
return nil, err
}
err = extendApplicationWithOrg(&application)
if err != nil {
return nil, err
}
return &application, nil
} else {
return nil
return nil, nil
}
}
func GetApplicationByUser(user *User) *Application {
func GetApplicationByUser(user *User) (*Application, error) {
if user.SignupApplication != "" {
return getApplication("admin", user.SignupApplication)
} else {
@ -213,38 +235,46 @@ func GetApplicationByUser(user *User) *Application {
}
}
func GetApplicationByUserId(userId string) (*Application, *User) {
var application *Application
func GetApplicationByUserId(userId string) (application *Application, err error) {
owner, name := util.GetOwnerAndNameFromId(userId)
if owner == "app" {
application = getApplication("admin", name)
return application, nil
application, err = getApplication("admin", name)
return
}
user := GetUser(userId)
application = GetApplicationByUser(user)
return application, user
user, err := GetUser(userId)
if err != nil {
return nil, err
}
application, err = GetApplicationByUser(user)
return
}
func GetApplicationByClientId(clientId string) *Application {
func GetApplicationByClientId(clientId string) (*Application, error) {
application := Application{}
existed, err := adapter.Engine.Where("client_id=?", clientId).Get(&application)
if err != nil {
panic(err)
return nil, err
}
if existed {
extendApplicationWithProviders(&application)
extendApplicationWithOrg(&application)
return &application
err = extendApplicationWithProviders(&application)
if err != nil {
return nil, err
}
err = extendApplicationWithOrg(&application)
if err != nil {
return nil, err
}
return &application, nil
} else {
return nil
return nil, nil
}
}
func GetApplication(id string) *Application {
func GetApplication(id string) (*Application, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getApplication(owner, name)
}
@ -287,11 +317,11 @@ func GetMaskedApplications(applications []*Application, userId string) []*Applic
return applications
}
func UpdateApplication(id string, application *Application) bool {
func UpdateApplication(id string, application *Application) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
oldApplication := getApplication(owner, name)
oldApplication, err := getApplication(owner, name)
if oldApplication == nil {
return false
return false, err
}
if name == "app-built-in" {
@ -299,14 +329,19 @@ func UpdateApplication(id string, application *Application) bool {
}
if name != application.Name {
err := applicationChangeTrigger(name, application.Name)
err = applicationChangeTrigger(name, application.Name)
if err != nil {
return false
return false, err
}
}
if oldApplication.ClientId != application.ClientId && GetApplicationByClientId(application.ClientId) != nil {
return false
applicationByClientId, err := GetApplicationByClientId(application.ClientId)
if err != nil {
return false, err
}
if oldApplication.ClientId != application.ClientId && applicationByClientId != nil {
return false, err
}
for _, providerItem := range application.Providers {
@ -319,13 +354,13 @@ func UpdateApplication(id string, application *Application) bool {
}
affected, err := session.Update(application)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func AddApplication(application *Application) bool {
func AddApplication(application *Application) (bool, error) {
if application.Owner == "" {
application.Owner = "admin"
}
@ -338,32 +373,39 @@ func AddApplication(application *Application) bool {
if application.ClientSecret == "" {
application.ClientSecret = util.GenerateClientSecret()
}
if GetApplicationByClientId(application.ClientId) != nil {
return false
app, err := GetApplicationByClientId(application.ClientId)
if err != nil {
return false, err
}
if app != nil {
return false, nil
}
for _, providerItem := range application.Providers {
providerItem.Provider = nil
}
affected, err := adapter.Engine.Insert(application)
if err != nil {
panic(err)
return false, nil
}
return affected != 0
return affected != 0, nil
}
func DeleteApplication(application *Application) bool {
func DeleteApplication(application *Application) (bool, error) {
if application.Name == "app-built-in" {
return false
return false, nil
}
affected, err := adapter.Engine.ID(core.PK{application.Owner, application.Name}).Delete(&Application{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func (application *Application) GetId() string {
@ -382,33 +424,43 @@ func (application *Application) IsRedirectUriValid(redirectUri string) bool {
return isValid
}
func IsOriginAllowed(origin string) bool {
applications := GetApplications("")
func IsOriginAllowed(origin string) (bool, error) {
applications, err := GetApplications("")
if err != nil {
return false, err
}
for _, application := range applications {
if application.IsRedirectUriValid(origin) {
return true
return true, nil
}
}
return false
return false, nil
}
func getApplicationMap(organization string) map[string]*Application {
applications := GetOrganizationApplications("admin", organization)
func getApplicationMap(organization string) (map[string]*Application, error) {
applicationMap := make(map[string]*Application)
applications, err := GetOrganizationApplications("admin", organization)
if err != nil {
return applicationMap, err
}
for _, application := range applications {
applicationMap[application.Name] = application
}
return applicationMap
return applicationMap, nil
}
func ExtendManagedAccountsWithUser(user *User) *User {
func ExtendManagedAccountsWithUser(user *User) (*User, error) {
if user.ManagedAccounts == nil || len(user.ManagedAccounts) == 0 {
return user
return user, nil
}
applicationMap := getApplicationMap(user.Owner)
applicationMap, err := getApplicationMap(user.Owner)
if err != nil {
return user, err
}
var managedAccounts []ManagedAccount
for _, managedAccount := range user.ManagedAccounts {
@ -420,7 +472,7 @@ func ExtendManagedAccountsWithUser(user *User) *User {
}
user.ManagedAccounts = managedAccounts
return user
return user, nil
}
func applicationChangeTrigger(oldName string, newName string) error {

View File

@ -14,8 +14,12 @@
package object
func (application *Application) GetProviderByCategory(category string) *Provider {
providers := GetProviders(application.Organization)
func (application *Application) GetProviderByCategory(category string) (*Provider, error) {
providers, err := GetProviders(application.Organization)
if err != nil {
return nil, err
}
m := map[string]*Provider{}
for _, provider := range providers {
if provider.Category != category {
@ -27,22 +31,22 @@ func (application *Application) GetProviderByCategory(category string) *Provider
for _, providerItem := range application.Providers {
if provider, ok := m[providerItem.Name]; ok {
return provider
return provider, nil
}
}
return nil
return nil, nil
}
func (application *Application) GetEmailProvider() *Provider {
func (application *Application) GetEmailProvider() (*Provider, error) {
return application.GetProviderByCategory("Email")
}
func (application *Application) GetSmsProvider() *Provider {
func (application *Application) GetSmsProvider() (*Provider, error) {
return application.GetProviderByCategory("SMS")
}
func (application *Application) GetStorageProvider() *Provider {
func (application *Application) GetStorageProvider() (*Provider, error) {
return application.GetProviderByCategory("Storage")
}

View File

@ -28,7 +28,11 @@ var defaultStorageProvider *Provider = nil
func InitDefaultStorageProvider() {
defaultStorageProviderStr := conf.GetConfigString("defaultStorageProvider")
if defaultStorageProviderStr != "" {
defaultStorageProvider = getProvider("admin", defaultStorageProviderStr)
var err error
defaultStorageProvider, err = getProvider("admin", defaultStorageProviderStr)
if err != nil {
panic(err)
}
}
}
@ -50,40 +54,44 @@ func downloadFile(url string) (*bytes.Buffer, error) {
return fileBuffer, nil
}
func getPermanentAvatarUrl(organization string, username string, url string, upload bool) string {
func getPermanentAvatarUrl(organization string, username string, url string, upload bool) (string, error) {
if url == "" {
return ""
return "", nil
}
if defaultStorageProvider == nil {
return ""
return "", nil
}
fullFilePath := fmt.Sprintf("/avatar/%s/%s.png", organization, username)
uploadedFileUrl, _ := GetUploadFileUrl(defaultStorageProvider, fullFilePath, false)
if upload {
DownloadAndUpload(url, fullFilePath, "en")
if err := DownloadAndUpload(url, fullFilePath, "en"); err != nil {
return "", err
}
}
return uploadedFileUrl
return uploadedFileUrl, nil
}
func DownloadAndUpload(url string, fullFilePath string, lang string) {
func DownloadAndUpload(url string, fullFilePath string, lang string) (err error) {
fileBuffer, err := downloadFile(url)
if err != nil {
panic(err)
return
}
_, _, err = UploadFileSafe(defaultStorageProvider, fullFilePath, fileBuffer, lang)
if err != nil {
panic(err)
return
}
return
}
func getPermanentAvatarUrlFromBuffer(organization string, username string, fileBuffer *bytes.Buffer, ext string, upload bool) string {
func getPermanentAvatarUrlFromBuffer(organization string, username string, fileBuffer *bytes.Buffer, ext string, upload bool) (string, error) {
if defaultStorageProvider == nil {
return ""
return "", nil
}
fullFilePath := fmt.Sprintf("/avatar/%s/%s%s", organization, username, ext)
@ -92,9 +100,9 @@ func getPermanentAvatarUrlFromBuffer(organization string, username string, fileB
if upload {
_, _, err := UploadFileSafe(defaultStorageProvider, fullFilePath, fileBuffer, "en")
if err != nil {
panic(err)
return "", err
}
}
return uploadedFileUrl
return uploadedFileUrl, nil
}

View File

@ -1,167 +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 (
"bytes"
"crypto/md5"
"fmt"
"image"
"image/color"
"image/png"
"io"
"net/http"
"strings"
"github.com/fogleman/gg"
)
func hasGravatar(client *http.Client, email string) (bool, error) {
// Clean and lowercase the email
email = strings.TrimSpace(strings.ToLower(email))
// Generate MD5 hash of the email
hash := md5.New()
io.WriteString(hash, email)
hashedEmail := fmt.Sprintf("%x", hash.Sum(nil))
// Create Gravatar URL with d=404 parameter
gravatarURL := fmt.Sprintf("https://www.gravatar.com/avatar/%s?d=404", hashedEmail)
// Send a request to Gravatar
req, err := http.NewRequest("GET", gravatarURL, nil)
if err != nil {
return false, err
}
resp, err := client.Do(req)
if err != nil {
return false, err
}
defer resp.Body.Close()
// Check if the user has a custom Gravatar image
if resp.StatusCode == http.StatusOK {
return true, nil
} else if resp.StatusCode == http.StatusNotFound {
return false, nil
} else {
return false, fmt.Errorf("failed to fetch gravatar image: %s", resp.Status)
}
}
func getGravatarFileBuffer(client *http.Client, email string) (*bytes.Buffer, string, error) {
// Clean and lowercase the email
email = strings.TrimSpace(strings.ToLower(email))
// Generate MD5 hash of the email
hash := md5.New()
io.WriteString(hash, email)
hashedEmail := fmt.Sprintf("%x", hash.Sum(nil))
// Create Gravatar URL
gravatarURL := fmt.Sprintf("https://www.gravatar.com/avatar/%s", hashedEmail)
// Download the image
req, err := http.NewRequest("GET", gravatarURL, nil)
if err != nil {
return nil, "", err
}
resp, err := client.Do(req)
if err != nil {
return nil, "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, "", fmt.Errorf("failed to download gravatar image: %s", resp.Status)
}
// Get the content type and determine the file extension
contentType := resp.Header.Get("Content-Type")
fileExtension := ""
switch contentType {
case "image/jpeg":
fileExtension = ".jpg"
case "image/png":
fileExtension = ".png"
case "image/gif":
fileExtension = ".gif"
default:
return nil, "", fmt.Errorf("unsupported content type: %s", contentType)
}
// Save the image to a bytes.Buffer
buffer := &bytes.Buffer{}
_, err = io.Copy(buffer, resp.Body)
if err != nil {
return nil, "", err
}
return buffer, fileExtension, nil
}
func getColor(data []byte) color.RGBA {
r := int(data[0]) % 256
g := int(data[1]) % 256
b := int(data[2]) % 256
return color.RGBA{uint8(r), uint8(g), uint8(b), 255}
}
func getIdenticonFileBuffer(username string) (*bytes.Buffer, string, error) {
username = strings.TrimSpace(strings.ToLower(username))
hash := md5.New()
io.WriteString(hash, username)
hashedUsername := hash.Sum(nil)
// Define the size of the image
const imageSize = 420
const cellSize = imageSize / 7
// Create a new image
img := image.NewRGBA(image.Rect(0, 0, imageSize, imageSize))
// Create a context
dc := gg.NewContextForRGBA(img)
// Set a background color
dc.SetColor(color.RGBA{240, 240, 240, 255})
dc.Clear()
// Get avatar color
avatarColor := getColor(hashedUsername)
// Draw cells
for i := 0; i < 7; i++ {
for j := 0; j < 7; j++ {
if (hashedUsername[i] >> uint(j) & 1) == 1 {
dc.SetColor(avatarColor)
dc.DrawRectangle(float64(j*cellSize), float64(i*cellSize), float64(cellSize), float64(cellSize))
dc.Fill()
}
}
}
// Save image to a bytes.Buffer
buffer := &bytes.Buffer{}
err := png.Encode(buffer, img)
if err != nil {
return nil, "", fmt.Errorf("failed to save image: %w", err)
}
return buffer, ".png", nil
}

View File

@ -20,17 +20,17 @@ import (
"github.com/dchest/captcha"
)
func GetCaptcha() (string, []byte) {
func GetCaptcha() (string, []byte, error) {
id := captcha.NewLen(5)
var buffer bytes.Buffer
err := captcha.WriteImage(&buffer, id, 200, 80)
if err != nil {
panic(err)
return "", nil, err
}
return id, buffer.Bytes()
return id, buffer.Bytes(), nil
}
func VerifyCaptcha(id string, digits string) bool {

View File

@ -30,9 +30,8 @@ type CasbinAdapter struct {
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
Organization string `xorm:"varchar(100)" json:"organization"`
Type string `xorm:"varchar(100)" json:"type"`
Model string `xorm:"varchar(100)" json:"model"`
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"`
@ -46,64 +45,59 @@ type CasbinAdapter struct {
Adapter *xormadapter.Adapter `xorm:"-" json:"-"`
}
func GetCasbinAdapterCount(owner, organization, field, value string) int {
func GetCasbinAdapterCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&CasbinAdapter{Organization: organization})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&CasbinAdapter{})
}
func GetCasbinAdapters(owner string, organization string) []*CasbinAdapter {
func GetCasbinAdapters(owner string) ([]*CasbinAdapter, error) {
adapters := []*CasbinAdapter{}
err := adapter.Engine.Where("owner = ? and organization = ?", owner, organization).Find(&adapters)
err := adapter.Engine.Desc("created_time").Find(&adapters, &CasbinAdapter{Owner: owner})
if err != nil {
panic(err)
return adapters, err
}
return adapters
return adapters, nil
}
func GetPaginationCasbinAdapters(owner, organization string, page, limit int, field, value, sort, order string) []*CasbinAdapter {
session := GetSession(owner, page, limit, field, value, sort, order)
func GetPaginationCasbinAdapters(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*CasbinAdapter, error) {
adapters := []*CasbinAdapter{}
err := session.Find(&adapters, &CasbinAdapter{Organization: organization})
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&adapters)
if err != nil {
panic(err)
return adapters, err
}
return adapters
return adapters, nil
}
func getCasbinAdapter(owner, name string) *CasbinAdapter {
func getCasbinAdapter(owner, name string) (*CasbinAdapter, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
casbinAdapter := CasbinAdapter{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&casbinAdapter)
if err != nil {
panic(err)
return nil, err
}
if existed {
return &casbinAdapter
return &casbinAdapter, nil
} else {
return nil
return nil, nil
}
}
func GetCasbinAdapter(id string) *CasbinAdapter {
func GetCasbinAdapter(id string) (*CasbinAdapter, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getCasbinAdapter(owner, name)
}
func UpdateCasbinAdapter(id string, casbinAdapter *CasbinAdapter) bool {
func UpdateCasbinAdapter(id string, casbinAdapter *CasbinAdapter) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if getCasbinAdapter(owner, name) == nil {
return false
if casbinAdapter, err := getCasbinAdapter(owner, name); casbinAdapter == nil {
return false, err
}
session := adapter.Engine.ID(core.PK{owner, name}).AllCols()
@ -112,28 +106,28 @@ func UpdateCasbinAdapter(id string, casbinAdapter *CasbinAdapter) bool {
}
affected, err := session.Update(casbinAdapter)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func AddCasbinAdapter(casbinAdapter *CasbinAdapter) bool {
func AddCasbinAdapter(casbinAdapter *CasbinAdapter) (bool, error) {
affected, err := adapter.Engine.Insert(casbinAdapter)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeleteCasbinAdapter(casbinAdapter *CasbinAdapter) bool {
func DeleteCasbinAdapter(casbinAdapter *CasbinAdapter) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{casbinAdapter.Owner, casbinAdapter.Name}).Delete(&CasbinAdapter{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func (casbinAdapter *CasbinAdapter) GetId() string {
@ -214,7 +208,15 @@ func matrixToCasbinRules(Ptype string, policies [][]string) []*xormadapter.Casbi
}
func SyncPolicies(casbinAdapter *CasbinAdapter) ([]*xormadapter.CasbinRule, error) {
modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
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
@ -229,7 +231,11 @@ func SyncPolicies(casbinAdapter *CasbinAdapter) ([]*xormadapter.CasbinRule, erro
}
func UpdatePolicy(oldPolicy, newPolicy []string, casbinAdapter *CasbinAdapter) (bool, error) {
modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
modelObj, err := getModel(casbinAdapter.Owner, casbinAdapter.Model)
if err != nil {
return false, err
}
enforcer, err := initEnforcer(modelObj, casbinAdapter)
if err != nil {
return false, err
@ -243,7 +249,11 @@ func UpdatePolicy(oldPolicy, newPolicy []string, casbinAdapter *CasbinAdapter) (
}
func AddPolicy(policy []string, casbinAdapter *CasbinAdapter) (bool, error) {
modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
modelObj, err := getModel(casbinAdapter.Owner, casbinAdapter.Model)
if err != nil {
return false, err
}
enforcer, err := initEnforcer(modelObj, casbinAdapter)
if err != nil {
return false, err
@ -257,7 +267,11 @@ func AddPolicy(policy []string, casbinAdapter *CasbinAdapter) (bool, error) {
}
func RemovePolicy(policy []string, casbinAdapter *CasbinAdapter) (bool, error) {
modelObj := getModel(casbinAdapter.Owner, casbinAdapter.Model)
modelObj, err := getModel(casbinAdapter.Owner, casbinAdapter.Model)
if err != nil {
return false, err
}
enforcer, err := initEnforcer(modelObj, casbinAdapter)
if err != nil {
return false, err

View File

@ -47,137 +47,133 @@ func GetMaskedCert(cert *Cert) *Cert {
return cert
}
func GetMaskedCerts(certs []*Cert) []*Cert {
func GetMaskedCerts(certs []*Cert, err error) ([]*Cert, error) {
if err != nil {
return nil, err
}
for _, cert := range certs {
cert = GetMaskedCert(cert)
}
return certs
return certs, nil
}
func GetCertCount(owner, field, value string) int {
func GetCertCount(owner, field, value string) (int64, error) {
session := GetSession("", -1, -1, field, value, "", "")
count, err := session.Where("owner = ? or owner = ? ", "admin", owner).Count(&Cert{})
if err != nil {
panic(err)
}
return int(count)
return session.Where("owner = ? or owner = ? ", "admin", owner).Count(&Cert{})
}
func GetCerts(owner string) []*Cert {
func GetCerts(owner string) ([]*Cert, error) {
certs := []*Cert{}
err := adapter.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&certs, &Cert{})
if err != nil {
panic(err)
return certs, err
}
return certs
return certs, nil
}
func GetPaginationCerts(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Cert {
func GetPaginationCerts(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Cert, error) {
certs := []*Cert{}
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
err := session.Where("owner = ? or owner = ? ", "admin", owner).Find(&certs)
if err != nil {
panic(err)
return certs, err
}
return certs
return certs, nil
}
func GetGlobalCertsCount(field, value string) int {
func GetGlobalCertsCount(field, value string) (int64, error) {
session := GetSession("", -1, -1, field, value, "", "")
count, err := session.Count(&Cert{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Cert{})
}
func GetGlobleCerts() []*Cert {
func GetGlobleCerts() ([]*Cert, error) {
certs := []*Cert{}
err := adapter.Engine.Desc("created_time").Find(&certs)
if err != nil {
panic(err)
return certs, err
}
return certs
return certs, nil
}
func GetPaginationGlobalCerts(offset, limit int, field, value, sortField, sortOrder string) []*Cert {
func GetPaginationGlobalCerts(offset, limit int, field, value, sortField, sortOrder string) ([]*Cert, error) {
certs := []*Cert{}
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
err := session.Find(&certs)
if err != nil {
panic(err)
return certs, err
}
return certs
return certs, nil
}
func getCert(owner string, name string) *Cert {
func getCert(owner string, name string) (*Cert, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
cert := Cert{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&cert)
if err != nil {
panic(err)
return &cert, err
}
if existed {
return &cert
return &cert, nil
} else {
return nil
return nil, nil
}
}
func getCertByName(name string) *Cert {
func getCertByName(name string) (*Cert, error) {
if name == "" {
return nil
return nil, nil
}
cert := Cert{Name: name}
existed, err := adapter.Engine.Get(&cert)
if err != nil {
panic(err)
return &cert, nil
}
if existed {
return &cert
return &cert, nil
} else {
return nil
return nil, nil
}
}
func GetCert(id string) *Cert {
func GetCert(id string) (*Cert, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getCert(owner, name)
}
func UpdateCert(id string, cert *Cert) bool {
func UpdateCert(id string, cert *Cert) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if getCert(owner, name) == nil {
return false
if c, err := getCert(owner, name); err != nil {
return false, err
} else if c == nil {
return false, nil
}
if name != cert.Name {
err := certChangeTrigger(name, cert.Name)
if err != nil {
return false
return false, nil
}
}
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(cert)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func AddCert(cert *Cert) bool {
func AddCert(cert *Cert) (bool, error) {
if cert.Certificate == "" || cert.PrivateKey == "" {
certificate, privateKey := generateRsaKeys(cert.BitSize, cert.ExpireInYears, cert.Name, cert.Owner)
cert.Certificate = certificate
@ -186,26 +182,26 @@ func AddCert(cert *Cert) bool {
affected, err := adapter.Engine.Insert(cert)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeleteCert(cert *Cert) bool {
func DeleteCert(cert *Cert) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{cert.Owner, cert.Name}).Delete(&Cert{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func (p *Cert) GetId() string {
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
}
func getCertByApplication(application *Application) *Cert {
func getCertByApplication(application *Application) (*Cert, error) {
if application.Cert != "" {
return getCertByName(application.Cert)
} else {
@ -213,7 +209,7 @@ func getCertByApplication(application *Application) *Cert {
}
}
func GetDefaultCert() *Cert {
func GetDefaultCert() (*Cert, error) {
return getCert("admin", "cert-built-in")
}

View File

@ -37,92 +37,104 @@ type Chat struct {
MessageCount int `json:"messageCount"`
}
func GetMaskedChat(chat *Chat) *Chat {
func GetMaskedChat(chat *Chat, err ...error) (*Chat, error) {
if len(err) > 0 && err[0] != nil {
return nil, err[0]
}
if chat == nil {
return nil
return nil, nil
}
return chat
return chat, nil
}
func GetMaskedChats(chats []*Chat) []*Chat {
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 = GetMaskedChat(chat)
chat, err = GetMaskedChat(chat)
if err != nil {
return nil, err
}
}
return chats
return chats, nil
}
func GetChatCount(owner, field, value string) int {
func GetChatCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Chat{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Chat{})
}
func GetChats(owner string) []*Chat {
func GetChats(owner string) ([]*Chat, error) {
chats := []*Chat{}
err := adapter.Engine.Desc("created_time").Find(&chats, &Chat{Owner: owner})
if err != nil {
panic(err)
return chats, err
}
return chats
return chats, nil
}
func GetPaginationChats(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Chat {
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 {
panic(err)
return chats, err
}
return chats
return chats, nil
}
func getChat(owner string, name string) *Chat {
func getChat(owner string, name string) (*Chat, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
chat := Chat{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&chat)
if err != nil {
panic(err)
return &chat, err
}
if existed {
return &chat
return &chat, nil
} else {
return nil
return nil, nil
}
}
func GetChat(id string) *Chat {
func GetChat(id string) (*Chat, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getChat(owner, name)
}
func UpdateChat(id string, chat *Chat) bool {
func UpdateChat(id string, chat *Chat) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if getChat(owner, name) == nil {
return false
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 {
panic(err)
return false, nil
}
return affected != 0
return affected != 0, nil
}
func AddChat(chat *Chat) bool {
func AddChat(chat *Chat) (bool, error) {
if chat.Type == "AI" && chat.User2 == "" {
provider := getDefaultAiProvider()
provider, err := getDefaultAiProvider()
if err != nil {
return false, err
}
if provider != nil {
chat.User2 = provider.Name
}
@ -130,23 +142,23 @@ func AddChat(chat *Chat) bool {
affected, err := adapter.Engine.Insert(chat)
if err != nil {
panic(err)
return false, nil
}
return affected != 0
return affected != 0, nil
}
func DeleteChat(chat *Chat) bool {
func DeleteChat(chat *Chat) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{chat.Owner, chat.Name}).Delete(&Chat{})
if err != nil {
panic(err)
return false, err
}
if affected != 0 {
return DeleteChatMessages(chat.Name)
}
return affected != 0
return affected != 0, nil
}
func (p *Chat) GetId() string {

View File

@ -170,7 +170,11 @@ func CheckPassword(user *User, password string, lang string, options ...bool) st
}
}
organization := GetOrganizationByUser(user)
organization, err := GetOrganizationByUser(user)
if err != nil {
panic(err)
}
if organization == nil {
return i18n.Translate(lang, "check:Organization does not exist")
}
@ -199,8 +203,22 @@ func CheckPassword(user *User, password string, lang string, options ...bool) st
}
}
func CheckPasswordComplexityByOrg(organization *Organization, password string) string {
errorMsg := checkPasswordComplexity(password, organization.PasswordOptions)
return errorMsg
}
func CheckPasswordComplexity(user *User, password string) string {
organization, _ := GetOrganizationByUser(user)
return CheckPasswordComplexityByOrg(organization, password)
}
func checkLdapUserPassword(user *User, password string, lang string) string {
ldaps := GetLdaps(user.Owner)
ldaps, err := GetLdaps(user.Owner)
if err != nil {
return err.Error()
}
ldapLoginSuccess := false
hit := false
@ -247,8 +265,12 @@ func CheckUserPassword(organization string, username string, password string, la
if len(options) > 0 {
enableCaptcha = options[0]
}
user := GetUserByFields(organization, username)
if user == nil || user.IsDeleted == true {
user, err := GetUserByFields(organization, username)
if err != nil {
panic(err)
}
if user == nil || user.IsDeleted {
return nil, fmt.Sprintf(i18n.Translate(lang, "general:The user: %s doesn't exist"), util.GetId(organization, username))
}
@ -284,7 +306,11 @@ func CheckUserPermission(requestUserId, userId string, strict bool, lang string)
userOwner := util.GetOwnerFromId(userId)
if userId != "" {
targetUser := GetUser(userId)
targetUser, err := GetUser(userId)
if err != nil {
panic(err)
}
if targetUser == nil {
if strings.HasPrefix(requestUserId, "built-in/") {
return true, nil
@ -300,7 +326,11 @@ func CheckUserPermission(requestUserId, userId string, strict bool, lang string)
if strings.HasPrefix(requestUserId, "app/") {
hasPermission = true
} else {
requestUser := GetUser(requestUserId)
requestUser, err := GetUser(requestUserId)
if err != nil {
return false, err
}
if requestUser == nil {
return false, fmt.Errorf(i18n.Translate(lang, "check:Session outdated, please login again"))
}
@ -321,15 +351,19 @@ func CheckUserPermission(requestUserId, userId string, strict bool, lang string)
}
func CheckAccessPermission(userId string, application *Application) (bool, error) {
var err error
if userId == "built-in/admin" {
return true, nil
}
permissions := GetPermissions(application.Organization)
permissions, err := GetPermissions(application.Organization)
if err != nil {
return false, err
}
allowed := true
var err error
for _, permission := range permissions {
if !permission.IsEnabled || len(permission.Users) == 0 {
if !permission.IsEnabled {
continue
}
@ -403,9 +437,9 @@ func CheckUpdateUser(oldUser, user *User, lang string) string {
return ""
}
func CheckToEnableCaptcha(application *Application, organization, username string) bool {
func CheckToEnableCaptcha(application *Application, organization, username string) (bool, error) {
if len(application.Providers) == 0 {
return false
return false, nil
}
for _, providerItem := range application.Providers {
@ -414,12 +448,15 @@ func CheckToEnableCaptcha(application *Application, organization, username strin
}
if providerItem.Provider.Category == "Captcha" {
if providerItem.Rule == "Dynamic" {
user := GetUserByFields(organization, username)
return user != nil && user.SigninWrongTimes >= SigninWrongTimesLimit
user, err := GetUserByFields(organization, username)
if err != nil {
return false, err
}
return user != nil && user.SigninWrongTimes >= SigninWrongTimesLimit, nil
}
return providerItem.Rule == "Always"
return providerItem.Rule == "Always", nil
}
}
return false
return false, nil
}

View File

@ -0,0 +1,98 @@
// 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 (
"regexp"
)
type ValidatorFunc func(password string) string
var (
regexLowerCase = regexp.MustCompile(`[a-z]`)
regexUpperCase = regexp.MustCompile(`[A-Z]`)
regexDigit = regexp.MustCompile(`\d`)
regexSpecial = regexp.MustCompile(`[!@#$%^&*]`)
)
func isValidOption_AtLeast6(password string) string {
if len(password) < 6 {
return "The password must have at least 6 characters"
}
return ""
}
func isValidOption_AtLeast8(password string) string {
if len(password) < 8 {
return "The password must have at least 8 characters"
}
return ""
}
func isValidOption_Aa123(password string) string {
hasLowerCase := regexLowerCase.MatchString(password)
hasUpperCase := regexUpperCase.MatchString(password)
hasDigit := regexDigit.MatchString(password)
if !hasLowerCase || !hasUpperCase || !hasDigit {
return "The password must contain at least one uppercase letter, one lowercase letter and one digit"
}
return ""
}
func isValidOption_SpecialChar(password string) string {
if !regexSpecial.MatchString(password) {
return "The password must contain at least one special character"
}
return ""
}
func isValidOption_NoRepeat(password string) string {
for i := 0; i < len(password)-1; i++ {
if password[i] == password[i+1] {
return "The password must not contain any repeated characters"
}
}
return ""
}
func checkPasswordComplexity(password string, options []string) string {
if len(password) == 0 {
return "Please input your password!"
}
if len(options) == 0 {
options = []string{"AtLeast6"}
}
checkers := map[string]ValidatorFunc{
"AtLeast6": isValidOption_AtLeast6,
"AtLeast8": isValidOption_AtLeast8,
"Aa123": isValidOption_Aa123,
"SpecialChar": isValidOption_SpecialChar,
"NoRepeat": isValidOption_NoRepeat,
}
for _, option := range options {
checkerFunc, ok := checkers[option]
if ok {
errorMsg := checkerFunc(password)
if errorMsg != "" {
return errorMsg
}
}
}
return ""
}

304
object/group.go Normal file
View File

@ -0,0 +1,304 @@
// 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 (
"errors"
"fmt"
"github.com/casdoor/casdoor/util"
"github.com/xorm-io/builder"
"github.com/xorm-io/core"
)
type Group struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk unique index" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
UpdatedTime string `xorm:"varchar(100)" json:"updatedTime"`
DisplayName string `xorm:"varchar(100)" json:"displayName"`
Manager string `xorm:"varchar(100)" json:"manager"`
ContactEmail string `xorm:"varchar(100)" json:"contactEmail"`
Type string `xorm:"varchar(100)" json:"type"`
ParentId string `xorm:"varchar(100)" json:"parentId"`
IsTopGroup bool `xorm:"bool" json:"isTopGroup"`
Users []*User `xorm:"-" json:"users"`
Title string `json:"title,omitempty"`
Key string `json:"key,omitempty"`
Children []*Group `json:"children,omitempty"`
IsEnabled bool `json:"isEnabled"`
}
type GroupNode struct{}
func GetGroupCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Group{})
if err != nil {
return 0, err
}
return count, nil
}
func GetGroups(owner string) ([]*Group, error) {
groups := []*Group{}
err := adapter.Engine.Desc("created_time").Find(&groups, &Group{Owner: owner})
if err != nil {
return nil, err
}
return groups, nil
}
func GetPaginationGroups(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Group, error) {
groups := []*Group{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&groups)
if err != nil {
return nil, err
}
return groups, nil
}
func getGroup(owner string, name string) (*Group, error) {
if owner == "" || name == "" {
return nil, nil
}
group := Group{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&group)
if err != nil {
return nil, err
}
if existed {
return &group, nil
} else {
return nil, nil
}
}
func GetGroup(id string) (*Group, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getGroup(owner, name)
}
func UpdateGroup(id string, group *Group) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
oldGroup, err := getGroup(owner, name)
if oldGroup == nil {
return false, err
}
if name != group.Name {
err := GroupChangeTrigger(name, group.Name)
if err != nil {
return false, err
}
}
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(group)
if err != nil {
return false, err
}
return affected != 0, nil
}
func AddGroup(group *Group) (bool, error) {
affected, err := adapter.Engine.Insert(group)
if err != nil {
return false, err
}
return affected != 0, nil
}
func AddGroups(groups []*Group) (bool, error) {
if len(groups) == 0 {
return false, nil
}
affected, err := adapter.Engine.Insert(groups)
if err != nil {
return false, err
}
return affected != 0, nil
}
func DeleteGroup(group *Group) (bool, error) {
_, err := adapter.Engine.Get(group)
if err != nil {
return false, err
}
if count, err := adapter.Engine.Where("parent_id = ?", group.Name).Count(&Group{}); err != nil {
return false, err
} else if count > 0 {
return false, errors.New("group has children group")
}
if count, err := GetGroupUserCount(group.Name, "", ""); err != nil {
return false, err
} else if count > 0 {
return false, errors.New("group has users")
}
affected, err := adapter.Engine.ID(core.PK{group.Owner, group.Name}).Delete(&Group{})
if err != nil {
return false, err
}
return affected != 0, nil
}
func (group *Group) GetId() string {
return fmt.Sprintf("%s/%s", group.Owner, group.Name)
}
func ConvertToTreeData(groups []*Group, parentId string) []*Group {
treeData := []*Group{}
for _, group := range groups {
if group.ParentId == parentId {
node := &Group{
Title: group.DisplayName,
Key: group.Name,
Type: group.Type,
Owner: group.Owner,
}
children := ConvertToTreeData(groups, group.Name)
if len(children) > 0 {
node.Children = children
}
treeData = append(treeData, node)
}
}
return treeData
}
func RemoveUserFromGroup(owner, name, groupName string) (bool, error) {
user, err := getUser(owner, name)
if err != nil {
return false, 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 == "" {
return adapter.Engine.Where(builder.Like{"`groups`", groupName}).
Count(&User{})
} else {
return adapter.Engine.Table("user").
Where(builder.Like{"`groups`", groupName}).
And(fmt.Sprintf("user.%s LIKE ?", util.CamelToSnakeCase(field)), "%"+value+"%").
Count()
}
}
func GetPaginationGroupUsers(groupName string, offset, limit int, field, value, sortField, sortOrder string) ([]*User, error) {
users := []*User{}
session := adapter.Engine.Table("user").
Where(builder.Like{"`groups`", groupName})
if offset != -1 && limit != -1 {
session.Limit(limit, offset)
}
if field != "" && value != "" {
session = session.And(fmt.Sprintf("user.%s LIKE ?", util.CamelToSnakeCase(field)), "%"+value+"%")
}
if sortField == "" || sortOrder == "" {
sortField = "created_time"
}
if sortOrder == "ascend" {
session = session.Asc(fmt.Sprintf("user.%s", util.SnakeString(sortField)))
} else {
session = session.Desc(fmt.Sprintf("user.%s", util.SnakeString(sortField)))
}
err := session.Find(&users)
if err != nil {
return nil, err
}
return users, nil
}
func GetGroupUsers(groupName string) ([]*User, error) {
users := []*User{}
err := adapter.Engine.Table("user").
Where(builder.Like{"`groups`", groupName}).
Find(&users)
if err != nil {
return nil, err
}
return users, nil
}
func GroupChangeTrigger(oldName, newName string) error {
session := adapter.Engine.NewSession()
defer session.Close()
err := session.Begin()
if err != nil {
return err
}
users := []*User{}
err = session.Where(builder.Like{"`groups`", oldName}).Find(&users)
if err != nil {
return err
}
for _, user := range users {
user.Groups = util.ReplaceVal(user.Groups, oldName, newName)
_, err := updateUser(user.GetId(), user, []string{"groups"})
if err != nil {
return err
}
}
groups := []*Group{}
err = session.Where("parent_id = ?", oldName).Find(&groups)
for _, group := range groups {
group.ParentId = newName
_, err := session.ID(core.PK{group.Owner, group.Name}).Cols("parent_id").Update(group)
if err != nil {
return err
}
}
err = session.Commit()
if err != nil {
return err
}
return nil
}

View File

@ -61,6 +61,7 @@ func getBuiltInAccountItems() []*AccountItem {
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
{Name: "Groups", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
@ -74,7 +75,11 @@ func getBuiltInAccountItems() []*AccountItem {
}
func initBuiltInOrganization() bool {
organization := getOrganization("admin", "built-in")
organization, err := getOrganization("admin", "built-in")
if err != nil {
panic(err)
}
if organization != nil {
return true
}
@ -87,6 +92,7 @@ func initBuiltInOrganization() bool {
WebsiteUrl: "https://example.com",
Favicon: fmt.Sprintf("%s/img/casbin/favicon.ico", conf.GetConfigString("staticBaseUrl")),
PasswordType: "plain",
PasswordOptions: []string{"AtLeast6"},
CountryCodes: []string{"US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"},
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
Tags: []string{},
@ -96,12 +102,19 @@ func initBuiltInOrganization() bool {
EnableSoftDeletion: false,
IsProfilePublic: false,
}
AddOrganization(organization)
_, err = AddOrganization(organization)
if err != nil {
panic(err)
}
return false
}
func initBuiltInUser() {
user := getUser("built-in", "admin")
user, err := getUser("built-in", "admin")
if err != nil {
panic(err)
}
if user != nil {
return
}
@ -131,11 +144,18 @@ func initBuiltInUser() {
CreatedIp: "127.0.0.1",
Properties: make(map[string]string),
}
AddUser(user)
_, err = AddUser(user)
if err != nil {
panic(err)
}
}
func initBuiltInApplication() {
application := getApplication("admin", "app-built-in")
application, err := getApplication("admin", "app-built-in")
if err != nil {
panic(err)
}
if application != nil {
return
}
@ -168,7 +188,10 @@ func initBuiltInApplication() {
ExpireInHours: 168,
FormOffset: 2,
}
AddApplication(application)
_, err = AddApplication(application)
if err != nil {
panic(err)
}
}
func readTokenFromFile() (string, string) {
@ -187,7 +210,11 @@ func readTokenFromFile() (string, string) {
func initBuiltInCert() {
tokenJwtCertificate, tokenJwtPrivateKey := readTokenFromFile()
cert := getCert("admin", "cert-built-in")
cert, err := getCert("admin", "cert-built-in")
if err != nil {
panic(err)
}
if cert != nil {
return
}
@ -205,11 +232,18 @@ func initBuiltInCert() {
Certificate: tokenJwtCertificate,
PrivateKey: tokenJwtPrivateKey,
}
AddCert(cert)
_, err = AddCert(cert)
if err != nil {
panic(err)
}
}
func initBuiltInLdap() {
ldap := GetLdap("ldap-built-in")
ldap, err := GetLdap("ldap-built-in")
if err != nil {
panic(err)
}
if ldap != nil {
return
}
@ -226,11 +260,18 @@ func initBuiltInLdap() {
AutoSync: 0,
LastSync: "",
}
AddLdap(ldap)
_, err = AddLdap(ldap)
if err != nil {
panic(err)
}
}
func initBuiltInProvider() {
provider := GetProvider(util.GetId("admin", "provider_captcha_default"))
provider, err := GetProvider(util.GetId("admin", "provider_captcha_default"))
if err != nil {
panic(err)
}
if provider != nil {
return
}
@ -243,7 +284,10 @@ func initBuiltInProvider() {
Category: "Captcha",
Type: "Default",
}
AddProvider(provider)
_, err = AddProvider(provider)
if err != nil {
panic(err)
}
}
func initWebAuthn() {
@ -251,7 +295,11 @@ func initWebAuthn() {
}
func initBuiltInModel() {
model := GetModel("built-in/model-built-in")
model, err := GetModel("built-in/model-built-in")
if err != nil {
panic(err)
}
if model != nil {
return
}
@ -274,11 +322,17 @@ e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`,
}
AddModel(model)
_, err = AddModel(model)
if err != nil {
panic(err)
}
}
func initBuiltInPermission() {
permission := GetPermission("built-in/permission-built-in")
permission, err := GetPermission("built-in/permission-built-in")
if err != nil {
panic(err)
}
if permission != nil {
return
}
@ -298,5 +352,8 @@ func initBuiltInPermission() {
Effect: "Allow",
IsEnabled: true,
}
AddPermission(permission)
_, err = AddPermission(permission)
if err != nil {
panic(err)
}
}

View File

@ -14,7 +14,10 @@
package object
import "github.com/casdoor/casdoor/util"
import (
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util"
)
type InitData struct {
Organizations []*Organization `json:"organizations"`
@ -35,7 +38,16 @@ type InitData struct {
}
func InitFromFile() {
initData := readInitDataFromFile("./init_data.json")
initDataFile := conf.GetConfigString("initDataFile")
if initDataFile == "" {
return
}
initData, err := readInitDataFromFile(initDataFile)
if err != nil {
panic(err)
}
if initData != nil {
for _, organization := range initData.Organizations {
initDefinedOrganization(organization)
@ -85,9 +97,9 @@ func InitFromFile() {
}
}
func readInitDataFromFile(filePath string) *InitData {
func readInitDataFromFile(filePath string) (*InitData, error) {
if !util.FileExist(filePath) {
return nil
return nil, nil
}
s := util.ReadStringFromPath(filePath)
@ -111,7 +123,7 @@ func readInitDataFromFile(filePath string) *InitData {
}
err := util.JsonToStruct(s, data)
if err != nil {
panic(err)
return nil, err
}
// transform nil slice to empty slice
@ -170,142 +182,246 @@ func readInitDataFromFile(filePath string) *InitData {
}
}
return data
return data, nil
}
func initDefinedOrganization(organization *Organization) {
existed := getOrganization(organization.Owner, organization.Name)
existed, err := getOrganization(organization.Owner, organization.Name)
if err != nil {
panic(err)
}
if existed != nil {
return
}
organization.CreatedTime = util.GetCurrentTime()
organization.AccountItems = getBuiltInAccountItems()
AddOrganization(organization)
_, err = AddOrganization(organization)
if err != nil {
panic(err)
}
}
func initDefinedApplication(application *Application) {
existed := getApplication(application.Owner, application.Name)
existed, err := getApplication(application.Owner, application.Name)
if err != nil {
panic(err)
}
if existed != nil {
return
}
application.CreatedTime = util.GetCurrentTime()
AddApplication(application)
_, err = AddApplication(application)
if err != nil {
panic(err)
}
}
func initDefinedUser(user *User) {
existed := getUser(user.Owner, user.Name)
existed, err := getUser(user.Owner, user.Name)
if err != nil {
panic(err)
}
if existed != nil {
return
}
user.CreatedTime = util.GetCurrentTime()
user.Id = util.GenerateId()
user.Properties = make(map[string]string)
AddUser(user)
_, err = AddUser(user)
if err != nil {
panic(err)
}
}
func initDefinedCert(cert *Cert) {
existed := getCert(cert.Owner, cert.Name)
existed, err := getCert(cert.Owner, cert.Name)
if err != nil {
panic(err)
}
if existed != nil {
return
}
cert.CreatedTime = util.GetCurrentTime()
AddCert(cert)
_, err = AddCert(cert)
if err != nil {
panic(err)
}
}
func initDefinedLdap(ldap *Ldap) {
existed := GetLdap(ldap.Id)
existed, err := GetLdap(ldap.Id)
if err != nil {
panic(err)
}
if existed != nil {
return
}
AddLdap(ldap)
_, err = AddLdap(ldap)
if err != nil {
panic(err)
}
}
func initDefinedProvider(provider *Provider) {
existed := GetProvider(util.GetId("admin", provider.Name))
existed, err := GetProvider(util.GetId("admin", provider.Name))
if err != nil {
panic(err)
}
if existed != nil {
return
}
AddProvider(provider)
_, err = AddProvider(provider)
if err != nil {
panic(err)
}
}
func initDefinedModel(model *Model) {
existed := GetModel(model.GetId())
existed, err := GetModel(model.GetId())
if err != nil {
panic(err)
}
if existed != nil {
return
}
model.CreatedTime = util.GetCurrentTime()
AddModel(model)
_, err = AddModel(model)
if err != nil {
panic(err)
}
}
func initDefinedPermission(permission *Permission) {
existed := GetPermission(permission.GetId())
existed, err := GetPermission(permission.GetId())
if err != nil {
panic(err)
}
if existed != nil {
return
}
permission.CreatedTime = util.GetCurrentTime()
AddPermission(permission)
_, err = AddPermission(permission)
if err != nil {
panic(err)
}
}
func initDefinedPayment(payment *Payment) {
existed := GetPayment(payment.GetId())
existed, err := GetPayment(payment.GetId())
if err != nil {
panic(err)
}
if existed != nil {
return
}
payment.CreatedTime = util.GetCurrentTime()
AddPayment(payment)
_, err = AddPayment(payment)
if err != nil {
panic(err)
}
}
func initDefinedProduct(product *Product) {
existed := GetProduct(product.GetId())
existed, err := GetProduct(product.GetId())
if err != nil {
panic(err)
}
if existed != nil {
return
}
product.CreatedTime = util.GetCurrentTime()
AddProduct(product)
_, err = AddProduct(product)
if err != nil {
panic(err)
}
}
func initDefinedResource(resource *Resource) {
existed := GetResource(resource.GetId())
existed, err := GetResource(resource.GetId())
if err != nil {
panic(err)
}
if existed != nil {
return
}
resource.CreatedTime = util.GetCurrentTime()
AddResource(resource)
_, err = AddResource(resource)
if err != nil {
panic(err)
}
}
func initDefinedRole(role *Role) {
existed := GetRole(role.GetId())
existed, err := GetRole(role.GetId())
if err != nil {
panic(err)
}
if existed != nil {
return
}
role.CreatedTime = util.GetCurrentTime()
AddRole(role)
_, err = AddRole(role)
if err != nil {
panic(err)
}
}
func initDefinedSyncer(syncer *Syncer) {
existed := GetSyncer(syncer.GetId())
existed, err := GetSyncer(syncer.GetId())
if err != nil {
panic(err)
}
if existed != nil {
return
}
syncer.CreatedTime = util.GetCurrentTime()
AddSyncer(syncer)
_, err = AddSyncer(syncer)
if err != nil {
panic(err)
}
}
func initDefinedToken(token *Token) {
existed := GetToken(token.GetId())
existed, err := GetToken(token.GetId())
if err != nil {
panic(err)
}
if existed != nil {
return
}
token.CreatedTime = util.GetCurrentTime()
AddToken(token)
_, err = AddToken(token)
if err != nil {
panic(err)
}
}
func initDefinedWebhook(webhook *Webhook) {
existed := GetWebhook(webhook.GetId())
existed, err := GetWebhook(webhook.GetId())
if err != nil {
panic(err)
}
if existed != nil {
return
}
webhook.CreatedTime = util.GetCurrentTime()
AddWebhook(webhook)
_, err = AddWebhook(webhook)
if err != nil {
panic(err)
}
}

View File

@ -37,7 +37,7 @@ type Ldap struct {
LastSync string `xorm:"varchar(100)" json:"lastSync"`
}
func AddLdap(ldap *Ldap) bool {
func AddLdap(ldap *Ldap) (bool, error) {
if len(ldap.Id) == 0 {
ldap.Id = util.GenerateId()
}
@ -48,13 +48,13 @@ func AddLdap(ldap *Ldap) bool {
affected, err := adapter.Engine.Insert(ldap)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func CheckLdapExist(ldap *Ldap) bool {
func CheckLdapExist(ldap *Ldap) (bool, error) {
var result []*Ldap
err := adapter.Engine.Find(&result, &Ldap{
Owner: ldap.Owner,
@ -65,63 +65,65 @@ func CheckLdapExist(ldap *Ldap) bool {
BaseDn: ldap.BaseDn,
})
if err != nil {
panic(err)
return false, err
}
if len(result) > 0 {
return true
return true, nil
}
return false
return false, nil
}
func GetLdaps(owner string) []*Ldap {
func GetLdaps(owner string) ([]*Ldap, error) {
var ldaps []*Ldap
err := adapter.Engine.Desc("created_time").Find(&ldaps, &Ldap{Owner: owner})
if err != nil {
panic(err)
return ldaps, err
}
return ldaps
return ldaps, nil
}
func GetLdap(id string) *Ldap {
func GetLdap(id string) (*Ldap, error) {
if util.IsStringsEmpty(id) {
return nil
return nil, nil
}
ldap := Ldap{Id: id}
existed, err := adapter.Engine.Get(&ldap)
if err != nil {
panic(err)
return &ldap, nil
}
if existed {
return &ldap
return &ldap, nil
} else {
return nil
return nil, nil
}
}
func UpdateLdap(ldap *Ldap) bool {
if GetLdap(ldap.Id) == nil {
return false
func UpdateLdap(ldap *Ldap) (bool, error) {
if l, err := GetLdap(ldap.Id); err != nil {
return false, nil
} else if l == nil {
return false, nil
}
affected, err := adapter.Engine.ID(ldap.Id).Cols("owner", "server_name", "host",
"port", "enable_ssl", "username", "password", "base_dn", "filter", "filter_fields", "auto_sync").Update(ldap)
if err != nil {
panic(err)
return false, nil
}
return affected != 0
return affected != 0, nil
}
func DeleteLdap(ldap *Ldap) bool {
func DeleteLdap(ldap *Ldap) (bool, error) {
affected, err := adapter.Engine.ID(ldap.Id).Delete(&Ldap{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}

View File

@ -18,7 +18,10 @@ var globalLdapAutoSynchronizer *LdapAutoSynchronizer
func InitLdapAutoSynchronizer() {
globalLdapAutoSynchronizer = NewLdapAutoSynchronizer()
globalLdapAutoSynchronizer.LdapAutoSynchronizerStartUpAll()
err := globalLdapAutoSynchronizer.LdapAutoSynchronizerStartUpAll()
if err != nil {
panic(err)
}
}
func NewLdapAutoSynchronizer() *LdapAutoSynchronizer {
@ -37,7 +40,11 @@ func (l *LdapAutoSynchronizer) StartAutoSync(ldapId string) error {
l.Lock()
defer l.Unlock()
ldap := GetLdap(ldapId)
ldap, err := GetLdap(ldapId)
if err != nil {
return err
}
if ldap == nil {
return fmt.Errorf("ldap %s doesn't exist", ldapId)
}
@ -49,7 +56,12 @@ func (l *LdapAutoSynchronizer) StartAutoSync(ldapId string) error {
stopChan := make(chan struct{})
l.ldapIdToStopChan[ldapId] = stopChan
logs.Info(fmt.Sprintf("autoSync started for %s", ldap.Id))
util.SafeGoroutine(func() { l.syncRoutine(ldap, stopChan) })
util.SafeGoroutine(func() {
err := l.syncRoutine(ldap, stopChan)
if err != nil {
panic(err)
}
})
return nil
}
@ -63,18 +75,22 @@ func (l *LdapAutoSynchronizer) StopAutoSync(ldapId string) {
}
// autosync goroutine
func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) {
func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) error {
ticker := time.NewTicker(time.Duration(ldap.AutoSync) * time.Minute)
defer ticker.Stop()
for {
select {
case <-stopChan:
logs.Info(fmt.Sprintf("autoSync goroutine for %s stopped", ldap.Id))
return
return nil
case <-ticker.C:
}
UpdateLdapSyncTime(ldap.Id)
err := UpdateLdapSyncTime(ldap.Id)
if err != nil {
return err
}
// fetch all users
conn, err := ldap.GetLdapConn()
if err != nil {
@ -100,24 +116,35 @@ func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) {
// LdapAutoSynchronizerStartUpAll
// start all autosync goroutine for existing ldap servers in each organizations
func (l *LdapAutoSynchronizer) LdapAutoSynchronizerStartUpAll() {
func (l *LdapAutoSynchronizer) LdapAutoSynchronizerStartUpAll() error {
organizations := []*Organization{}
err := adapter.Engine.Desc("created_time").Find(&organizations)
if err != nil {
logs.Info("failed to Star up LdapAutoSynchronizer; ")
}
for _, org := range organizations {
for _, ldap := range GetLdaps(org.Name) {
ldaps, err := GetLdaps(org.Name)
if err != nil {
return err
}
for _, ldap := range ldaps {
if ldap.AutoSync != 0 {
l.StartAutoSync(ldap.Id)
err = l.StartAutoSync(ldap.Id)
if err != nil {
return err
}
}
}
}
return nil
}
func UpdateLdapSyncTime(ldapId string) {
func UpdateLdapSyncTime(ldapId string) error {
_, err := adapter.Engine.ID(ldapId).Update(&Ldap{LastSync: util.GetCurrentTime()})
if err != nil {
panic(err)
return err
}
return nil
}

View File

@ -255,8 +255,12 @@ func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUser
uuids = append(uuids, user.Uuid)
}
organization := getOrganization("admin", owner)
ldap := GetLdap(ldapId)
organization, err := getOrganization("admin", owner)
if err != nil {
panic(err)
}
ldap, err := GetLdap(ldapId)
var dc []string
for _, basedn := range strings.Split(ldap.BaseDn, ",") {
@ -275,7 +279,11 @@ func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUser
tag := strings.Join(ou, ".")
for _, syncUser := range syncUsers {
existUuids := GetExistUuids(owner, uuids)
existUuids, err := GetExistUuids(owner, uuids)
if err != nil {
return nil, nil, err
}
found := false
if len(existUuids) > 0 {
for _, existUuid := range existUuids {
@ -287,10 +295,19 @@ func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUser
}
if !found {
score, _ := organization.GetInitScore()
score, err := organization.GetInitScore()
if err != nil {
return nil, nil, err
}
name, err := syncUser.buildLdapUserName()
if err != nil {
return nil, nil, err
}
newUser := &User{
Owner: owner,
Name: syncUser.buildLdapUserName(),
Name: name,
CreatedTime: util.GetCurrentTime(),
DisplayName: syncUser.buildLdapDisplayName(),
Avatar: organization.DefaultAvatar,
@ -303,7 +320,11 @@ func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUser
Ldap: syncUser.Uuid,
}
affected := AddUser(newUser)
affected, err := AddUser(newUser)
if err != nil {
return nil, nil, err
}
if !affected {
failedUsers = append(failedUsers, syncUser)
continue
@ -314,38 +335,38 @@ func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUser
return existUsers, failedUsers, err
}
func GetExistUuids(owner string, uuids []string) []string {
func GetExistUuids(owner string, uuids []string) ([]string, error) {
var existUuids []string
err := adapter.Engine.Table("user").Where("owner = ?", owner).Cols("ldap").
In("ldap", uuids).Select("DISTINCT ldap").Find(&existUuids)
if err != nil {
panic(err)
return existUuids, err
}
return existUuids
return existUuids, nil
}
func (ldapUser *LdapUser) buildLdapUserName() string {
func (ldapUser *LdapUser) buildLdapUserName() (string, error) {
user := User{}
uidWithNumber := fmt.Sprintf("%s_%s", ldapUser.Uid, ldapUser.UidNumber)
has, err := adapter.Engine.Where("name = ? or name = ?", ldapUser.Uid, uidWithNumber).Get(&user)
if err != nil {
panic(err)
return "", err
}
if has {
if user.Name == ldapUser.Uid {
return uidWithNumber
return uidWithNumber, nil
}
return fmt.Sprintf("%s_%s", uidWithNumber, randstr.Hex(6))
return fmt.Sprintf("%s_%s", uidWithNumber, randstr.Hex(6)), nil
}
if ldapUser.Uid != "" {
return ldapUser.Uid
return ldapUser.Uid, nil
}
return ldapUser.Cn
return ldapUser.Cn, nil
}
func (ldapUser *LdapUser) buildLdapDisplayName() string {

View File

@ -48,109 +48,94 @@ func GetMaskedMessages(messages []*Message) []*Message {
return messages
}
func GetMessageCount(owner, organization, field, value string) int {
func GetMessageCount(owner, organization, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Message{Organization: organization})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Message{Organization: organization})
}
func GetMessages(owner string) []*Message {
func GetMessages(owner string) ([]*Message, error) {
messages := []*Message{}
err := adapter.Engine.Desc("created_time").Find(&messages, &Message{Owner: owner})
if err != nil {
panic(err)
}
return messages
return messages, err
}
func GetChatMessages(chat string) []*Message {
func GetChatMessages(chat string) ([]*Message, error) {
messages := []*Message{}
err := adapter.Engine.Asc("created_time").Find(&messages, &Message{Chat: chat})
if err != nil {
panic(err)
}
return messages
return messages, err
}
func GetPaginationMessages(owner, organization string, offset, limit int, field, value, sortField, sortOrder string) []*Message {
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})
if err != nil {
panic(err)
}
return messages
return messages, err
}
func getMessage(owner string, name string) *Message {
func getMessage(owner string, name string) (*Message, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
message := Message{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&message)
if err != nil {
panic(err)
return nil, err
}
if existed {
return &message
return &message, nil
} else {
return nil
return nil, nil
}
}
func GetMessage(id string) *Message {
func GetMessage(id string) (*Message, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getMessage(owner, name)
}
func UpdateMessage(id string, message *Message) bool {
func UpdateMessage(id string, message *Message) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if getMessage(owner, name) == nil {
return false
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 {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func AddMessage(message *Message) bool {
func AddMessage(message *Message) (bool, error) {
affected, err := adapter.Engine.Insert(message)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeleteMessage(message *Message) bool {
func DeleteMessage(message *Message) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{message.Owner, message.Name}).Delete(&Message{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeleteChatMessages(chat string) bool {
func DeleteChatMessages(chat string) (bool, error) {
affected, err := adapter.Engine.Delete(&Message{Chat: chat})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func (p *Message) GetId() string {

View File

@ -83,7 +83,11 @@ func RecoverTfs(user *User, recoveryCode string) error {
return fmt.Errorf("recovery code not found")
}
affected := UpdateUser(user.GetId(), user, []string{"two_factor_auth"}, user.IsAdminUser())
affected, err := UpdateUser(user.GetId(), user, []string{"two_factor_auth"}, user.IsAdminUser())
if err != nil {
return err
}
if !affected {
return fmt.Errorf("")
}

View File

@ -100,7 +100,11 @@ func (mfa *SmsMfa) Enable(ctx *context.Context, user *User) error {
}
user.MultiFactorAuths = append(user.MultiFactorAuths, mfa.Config)
affected := UpdateUser(user.GetId(), user, []string{"multi_factor_auths"}, user.IsAdminUser())
affected, err := UpdateUser(user.GetId(), user, []string{"multi_factor_auths"}, user.IsAdminUser())
if err != nil {
return err
}
if !affected {
return fmt.Errorf("failed to enable two factor authentication")
}

View File

@ -44,5 +44,8 @@ func DoMigration() {
}
m := migrate.New(adapter.Engine, options, migrations)
m.Migrate()
err := m.Migrate()
if err != nil {
panic(err)
}
}

View File

@ -25,10 +25,7 @@ type Migrator_1_235_0_PR_1530 struct{}
func (*Migrator_1_235_0_PR_1530) IsMigrationNeeded() bool {
exist, _ := adapter.Engine.IsTableExist("casbin_rule")
if exist {
return true
}
return false
return exist
}
func (*Migrator_1_235_0_PR_1530) DoMigration() *migrate.Migration {

View File

@ -22,20 +22,13 @@ import (
type Migrator_1_314_0_PR_1841 struct{}
func (*Migrator_1_314_0_PR_1841) IsMigrationNeeded() bool {
users := []*User{}
err := adapter.Engine.Table("user").Find(&users)
count, err := adapter.Engine.Where("password_type=?", "").Count(&User{})
if err != nil {
// table doesn't exist
return false
}
for _, u := range users {
if u.PasswordType != "" {
return false
}
}
return true
return count > 100
}
func (*Migrator_1_314_0_PR_1841) DoMigration() *migrate.Migration {

View File

@ -27,61 +27,57 @@ type Model struct {
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
DisplayName string `xorm:"varchar(100)" json:"displayName"`
Description string `xorm:"varchar(100)" json:"description"`
ModelText string `xorm:"mediumtext" json:"modelText"`
IsEnabled bool `json:"isEnabled"`
}
func GetModelCount(owner, field, value string) int {
func GetModelCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Model{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Model{})
}
func GetModels(owner string) []*Model {
func GetModels(owner string) ([]*Model, error) {
models := []*Model{}
err := adapter.Engine.Desc("created_time").Find(&models, &Model{Owner: owner})
if err != nil {
panic(err)
return models, err
}
return models
return models, nil
}
func GetPaginationModels(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Model {
func GetPaginationModels(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Model, error) {
models := []*Model{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&models)
if err != nil {
panic(err)
return models, err
}
return models
return models, nil
}
func getModel(owner string, name string) *Model {
func getModel(owner string, name string) (*Model, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
m := Model{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&m)
if err != nil {
panic(err)
return &m, err
}
if existed {
return &m
return &m, nil
} else {
return nil
return nil, nil
}
}
func GetModel(id string) *Model {
func GetModel(id string) (*Model, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getModel(owner, name)
}
@ -92,48 +88,53 @@ func UpdateModelWithCheck(id string, modelObj *Model) error {
if err != nil {
return err
}
UpdateModel(id, modelObj)
_, err = UpdateModel(id, modelObj)
if err != nil {
return err
}
return nil
}
func UpdateModel(id string, modelObj *Model) bool {
func UpdateModel(id string, modelObj *Model) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if getModel(owner, name) == nil {
return false
if m, err := getModel(owner, name); err != nil {
return false, err
} else if m == nil {
return false, nil
}
if name != modelObj.Name {
err := modelChangeTrigger(name, modelObj.Name)
if err != nil {
return false
return false, err
}
}
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(modelObj)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, err
}
func AddModel(model *Model) bool {
func AddModel(model *Model) (bool, error) {
affected, err := adapter.Engine.Insert(model)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeleteModel(model *Model) bool {
func DeleteModel(model *Model) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{model.Owner, model.Name}).Delete(&Model{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func (model *Model) GetId() string {

View File

@ -55,13 +55,8 @@ func isIpAddress(host string) bool {
// Attempt to parse the host as an IP address (both IPv4 and IPv6)
ip := net.ParseIP(hostWithoutPort)
if ip != nil {
// The host is an IP address
return true
}
// The host is not an IP address
return false
// if host is not nil is an IP address else is not an IP address
return ip != nil
}
func getOriginFromHost(host string) (string, string) {
@ -115,8 +110,12 @@ func GetOidcDiscovery(host string) OidcDiscovery {
}
func GetJsonWebKeySet() (jose.JSONWebKeySet, error) {
certs := GetCerts("admin")
jwks := jose.JSONWebKeySet{}
certs, err := GetCerts("admin")
if err != nil {
return jwks, err
}
// follows the protocol rfc 7517(draft)
// 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

View File

@ -22,6 +22,7 @@ import (
"github.com/casdoor/casdoor/cred"
"github.com/casdoor/casdoor/i18n"
"github.com/casdoor/casdoor/util"
"github.com/xorm-io/builder"
"github.com/xorm-io/core"
)
@ -55,6 +56,7 @@ type Organization struct {
Favicon string `xorm:"varchar(100)" json:"favicon"`
PasswordType string `xorm:"varchar(100)" json:"passwordType"`
PasswordSalt string `xorm:"varchar(100)" json:"passwordSalt"`
PasswordOptions []string `xorm:"varchar(100)" json:"passwordOptions"`
CountryCodes []string `xorm:"varchar(200)" json:"countryCodes"`
DefaultAvatar string `xorm:"varchar(200)" json:"defaultAvatar"`
DefaultApplication string `xorm:"varchar(100)" json:"defaultApplication"`
@ -70,82 +72,109 @@ type Organization struct {
AccountItems []*AccountItem `xorm:"varchar(3000)" json:"accountItems"`
}
func GetOrganizationCount(owner, field, value string) int {
func GetOrganizationCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Organization{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Organization{})
}
func GetOrganizations(owner string) []*Organization {
func GetOrganizations(owner string, name ...string) ([]*Organization, error) {
organizations := []*Organization{}
err := adapter.Engine.Desc("created_time").Find(&organizations, &Organization{Owner: owner})
if err != nil {
panic(err)
if name != nil && len(name) > 0 {
err := adapter.Engine.Desc("created_time").Where(builder.In("name", name)).Find(&organizations)
if err != nil {
return nil, err
}
} else {
err := adapter.Engine.Desc("created_time").Find(&organizations, &Organization{Owner: owner})
if err != nil {
return nil, err
}
}
return organizations
return organizations, nil
}
func GetPaginationOrganizations(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Organization {
func GetOrganizationsByFields(owner string, fields ...string) ([]*Organization, error) {
organizations := []*Organization{}
err := adapter.Engine.Desc("created_time").Cols(fields...).Find(&organizations, &Organization{Owner: owner})
if err != nil {
return nil, err
}
return organizations, nil
}
func GetPaginationOrganizations(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Organization, error) {
organizations := []*Organization{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&organizations)
if err != nil {
panic(err)
return nil, err
}
return organizations
return organizations, nil
}
func getOrganization(owner string, name string) *Organization {
func getOrganization(owner string, name string) (*Organization, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
organization := Organization{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&organization)
if err != nil {
panic(err)
return nil, err
}
if existed {
return &organization
return &organization, nil
}
return nil
return nil, nil
}
func GetOrganization(id string) *Organization {
func GetOrganization(id string) (*Organization, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getOrganization(owner, name)
}
func GetMaskedOrganization(organization *Organization) *Organization {
func GetMaskedOrganization(organization *Organization, errs ...error) (*Organization, error) {
if len(errs) > 0 && errs[0] != nil {
return nil, errs[0]
}
if organization == nil {
return nil
return nil, nil
}
if organization.MasterPassword != "" {
organization.MasterPassword = "***"
}
return organization
return organization, nil
}
func GetMaskedOrganizations(organizations []*Organization) []*Organization {
for _, organization := range organizations {
organization = GetMaskedOrganization(organization)
func GetMaskedOrganizations(organizations []*Organization, errs ...error) ([]*Organization, error) {
if len(errs) > 0 && errs[0] != nil {
return nil, errs[0]
}
return organizations
var err error
for _, organization := range organizations {
organization, err = GetMaskedOrganization(organization)
if err != nil {
return nil, err
}
}
return organizations, nil
}
func UpdateOrganization(id string, organization *Organization) bool {
func UpdateOrganization(id string, organization *Organization) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if getOrganization(owner, name) == nil {
return false
if org, err := getOrganization(owner, name); err != nil {
return false, err
} else if org == nil {
return false, nil
}
if name == "built-in" {
@ -155,7 +184,7 @@ func UpdateOrganization(id string, organization *Organization) bool {
if name != organization.Name {
err := organizationChangeTrigger(name, organization.Name)
if err != nil {
return false
return false, nil
}
}
@ -173,35 +202,35 @@ func UpdateOrganization(id string, organization *Organization) bool {
}
affected, err := session.Update(organization)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func AddOrganization(organization *Organization) bool {
func AddOrganization(organization *Organization) (bool, error) {
affected, err := adapter.Engine.Insert(organization)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeleteOrganization(organization *Organization) bool {
func DeleteOrganization(organization *Organization) (bool, error) {
if organization.Name == "built-in" {
return false
return false, nil
}
affected, err := adapter.Engine.ID(core.PK{organization.Owner, organization.Name}).Delete(&Organization{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func GetOrganizationByUser(user *User) *Organization {
func GetOrganizationByUser(user *User) (*Organization, error) {
return getOrganization("admin", user.Owner)
}
@ -238,13 +267,21 @@ func CheckAccountItemModifyRule(accountItem *AccountItem, isAdmin bool, lang str
}
func GetDefaultApplication(id string) (*Application, error) {
organization := GetOrganization(id)
organization, err := GetOrganization(id)
if err != nil {
return nil, err
}
if organization == nil {
return nil, fmt.Errorf("The organization: %s does not exist", id)
}
if organization.DefaultApplication != "" {
defaultApplication := getApplication("admin", organization.DefaultApplication)
defaultApplication, err := getApplication("admin", organization.DefaultApplication)
if err != nil {
return nil, err
}
if defaultApplication == nil {
return nil, fmt.Errorf("The default application: %s does not exist", organization.DefaultApplication)
} else {
@ -253,9 +290,9 @@ func GetDefaultApplication(id string) (*Application, error) {
}
applications := []*Application{}
err := adapter.Engine.Asc("created_time").Find(&applications, &Application{Organization: organization.Name})
err = adapter.Engine.Asc("created_time").Find(&applications, &Application{Organization: organization.Name})
if err != nil {
panic(err)
return nil, err
}
if len(applications) == 0 {
@ -270,8 +307,15 @@ func GetDefaultApplication(id string) (*Application, error) {
}
}
extendApplicationWithProviders(defaultApplication)
extendApplicationWithOrg(defaultApplication)
err = extendApplicationWithProviders(defaultApplication)
if err != nil {
return nil, err
}
err = extendApplicationWithOrg(defaultApplication)
if err != nil {
return nil, err
}
return defaultApplication, nil
}
@ -299,6 +343,13 @@ func organizationChangeTrigger(oldName string, newName string) error {
return err
}
group := new(Group)
group.Owner = newName
_, err = session.Where("owner=?", oldName).Update(group)
if err != nil {
return err
}
role := new(Role)
_, err = adapter.Engine.Where("owner=?", oldName).Get(role)
if err != nil {
@ -351,7 +402,6 @@ func organizationChangeTrigger(oldName string, newName string) error {
casbinAdapter := new(CasbinAdapter)
casbinAdapter.Owner = newName
casbinAdapter.Organization = newName
_, err = session.Where("owner=?", oldName).Update(casbinAdapter)
if err != nil {
return err

View File

@ -56,74 +56,71 @@ type Payment struct {
InvoiceUrl string `xorm:"varchar(255)" json:"invoiceUrl"`
}
func GetPaymentCount(owner, field, value string) int {
func GetPaymentCount(owner, organization, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Payment{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Payment{Organization: organization})
}
func GetPayments(owner string) []*Payment {
func GetPayments(owner string) ([]*Payment, error) {
payments := []*Payment{}
err := adapter.Engine.Desc("created_time").Find(&payments, &Payment{Owner: owner})
if err != nil {
panic(err)
return nil, err
}
return payments
return payments, nil
}
func GetUserPayments(owner string, organization string, user string) []*Payment {
func GetUserPayments(owner string, organization string, user string) ([]*Payment, error) {
payments := []*Payment{}
err := adapter.Engine.Desc("created_time").Find(&payments, &Payment{Owner: owner, Organization: organization, User: user})
if err != nil {
panic(err)
return nil, err
}
return payments
return payments, nil
}
func GetPaginationPayments(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Payment {
func GetPaginationPayments(owner, organization string, offset, limit int, field, value, sortField, sortOrder string) ([]*Payment, error) {
payments := []*Payment{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&payments)
err := session.Find(&payments, &Payment{Organization: organization})
if err != nil {
panic(err)
return nil, err
}
return payments
return payments, nil
}
func getPayment(owner string, name string) *Payment {
func getPayment(owner string, name string) (*Payment, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
payment := Payment{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&payment)
if err != nil {
panic(err)
return nil, err
}
if existed {
return &payment
return &payment, nil
} else {
return nil
return nil, nil
}
}
func GetPayment(id string) *Payment {
func GetPayment(id string) (*Payment, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getPayment(owner, name)
}
func UpdatePayment(id string, payment *Payment) bool {
func UpdatePayment(id string, payment *Payment) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if getPayment(owner, name) == nil {
return false
if p, err := getPayment(owner, name); err != nil {
return false, err
} else if p == nil {
return false, nil
}
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(payment)
@ -131,67 +128,79 @@ func UpdatePayment(id string, payment *Payment) bool {
panic(err)
}
return affected != 0
return affected != 0, nil
}
func AddPayment(payment *Payment) bool {
func AddPayment(payment *Payment) (bool, error) {
affected, err := adapter.Engine.Insert(payment)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeletePayment(payment *Payment) bool {
func DeletePayment(payment *Payment) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{payment.Owner, payment.Name}).Delete(&Payment{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func notifyPayment(request *http.Request, body []byte, owner string, providerName string, productName string, paymentName string) (*Payment, error) {
payment := getPayment(owner, paymentName)
if payment == nil {
return nil, fmt.Errorf("the payment: %s does not exist", paymentName)
}
product := getProduct(owner, productName)
if product == nil {
return nil, fmt.Errorf("the product: %s does not exist", productName)
}
provider, err := product.getProvider(providerName)
func notifyPayment(request *http.Request, body []byte, owner string, providerName string, productName string, paymentName string, orderId string) (*Payment, error, string) {
provider, err := getProvider(owner, providerName)
if err != nil {
return payment, err
panic(err)
}
pProvider, cert, err := provider.getPaymentProvider()
if err != nil {
return payment, err
panic(err)
}
productDisplayName, paymentName, price, productName, providerName, err := pProvider.Notify(request, body, cert.AuthorityPublicKey)
payment, err := getPayment(owner, paymentName)
if err != nil {
return payment, err
panic(err)
}
if payment == nil {
err = fmt.Errorf("the payment: %s does not exist", paymentName)
return nil, err, pProvider.GetResponseError(err)
}
product, err := getProduct(owner, productName)
if err != nil {
panic(err)
}
if product == nil {
err = fmt.Errorf("the product: %s does not exist", productName)
return payment, err, pProvider.GetResponseError(err)
}
productDisplayName, paymentName, price, productName, providerName, err := pProvider.Notify(request, body, cert.AuthorityPublicKey, orderId)
if err != nil {
return payment, err, pProvider.GetResponseError(err)
}
if productDisplayName != "" && productDisplayName != product.DisplayName {
return nil, 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 product name: %s doesn't equal to the expected product name: %s", productDisplayName, product.DisplayName)
return payment, err, pProvider.GetResponseError(err)
}
if price != product.Price {
return nil, fmt.Errorf("the payment's price: %f doesn't equal to the expected price: %f", price, product.Price)
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)
}
return payment, nil
err = nil
return payment, err, pProvider.GetResponseError(err)
}
func NotifyPayment(request *http.Request, body []byte, owner string, providerName string, productName string, paymentName string) bool {
payment, err := notifyPayment(request, body, owner, providerName, productName, paymentName)
func NotifyPayment(request *http.Request, body []byte, owner string, providerName string, productName string, paymentName string, orderId string) (error, string) {
payment, err, errorResponse := notifyPayment(request, body, owner, providerName, productName, paymentName, orderId)
if payment != nil {
if err != nil {
payment.State = "Error"
@ -200,15 +209,21 @@ func NotifyPayment(request *http.Request, body []byte, owner string, providerNam
payment.State = "Paid"
}
UpdatePayment(payment.GetId(), payment)
_, err = UpdatePayment(payment.GetId(), payment)
if err != nil {
panic(err)
}
}
ok := err == nil
return ok
return err, errorResponse
}
func invoicePayment(payment *Payment) (string, error) {
provider := getProvider(payment.Owner, payment.Provider)
provider, err := getProvider(payment.Owner, payment.Provider)
if err != nil {
panic(err)
}
if provider == nil {
return "", fmt.Errorf("the payment provider: %s does not exist", payment.Provider)
}
@ -237,7 +252,11 @@ func InvoicePayment(payment *Payment) (string, error) {
}
payment.InvoiceUrl = invoiceUrl
affected := UpdatePayment(payment.GetId(), payment)
affected, err := UpdatePayment(payment.GetId(), payment)
if err != nil {
return "", err
}
if !affected {
return "", fmt.Errorf("failed to update the payment: %s", payment.Name)
}

View File

@ -15,6 +15,9 @@
package object
import (
"strings"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util"
"github.com/xorm-io/core"
)
@ -24,6 +27,7 @@ type Permission struct {
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
DisplayName string `xorm:"varchar(100)" json:"displayName"`
Description string `xorm:"varchar(100)" json:"description"`
Users []string `xorm:"mediumtext" json:"users"`
Roles []string `xorm:"mediumtext" json:"roles"`
@ -63,96 +67,97 @@ func (p *Permission) GetId() string {
return util.GetId(p.Owner, p.Name)
}
func GetPermissionCount(owner, field, value string) int {
func GetPermissionCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Permission{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Permission{})
}
func GetPermissions(owner string) []*Permission {
func GetPermissions(owner string) ([]*Permission, error) {
permissions := []*Permission{}
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner})
if err != nil {
panic(err)
return permissions, err
}
return permissions
return permissions, nil
}
func GetPaginationPermissions(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Permission {
func GetPaginationPermissions(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Permission, error) {
permissions := []*Permission{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&permissions)
if err != nil {
panic(err)
return permissions, err
}
return permissions
return permissions, nil
}
func getPermission(owner string, name string) *Permission {
func getPermission(owner string, name string) (*Permission, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
permission := Permission{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&permission)
if err != nil {
panic(err)
return &permission, err
}
if existed {
return &permission
return &permission, nil
} else {
return nil
return nil, nil
}
}
func GetPermission(id string) *Permission {
func GetPermission(id string) (*Permission, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getPermission(owner, name)
}
// checkPermissionValid verifies if the permission is valid
func checkPermissionValid(permission *Permission) {
func checkPermissionValid(permission *Permission) error {
enforcer := getEnforcer(permission)
enforcer.EnableAutoSave(false)
policies := getPolicies(permission)
_, err := enforcer.AddPolicies(policies)
if err != nil {
panic(err)
return err
}
if !HasRoleDefinition(enforcer.GetModel()) {
permission.Roles = []string{}
return
return nil
}
groupingPolicies := getGroupingPolicies(permission)
if len(groupingPolicies) > 0 {
_, err := enforcer.AddGroupingPolicies(groupingPolicies)
if err != nil {
panic(err)
return err
}
}
return nil
}
func UpdatePermission(id string, permission *Permission) bool {
checkPermissionValid(permission)
func UpdatePermission(id string, permission *Permission) (bool, error) {
err := checkPermissionValid(permission)
if err != nil {
return false, err
}
owner, name := util.GetOwnerAndNameFromId(id)
oldPermission := getPermission(owner, name)
oldPermission, err := getPermission(owner, name)
if oldPermission == nil {
return false
return false, nil
}
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(permission)
if err != nil {
panic(err)
return false, err
}
if affected != 0 {
@ -163,7 +168,7 @@ func UpdatePermission(id string, permission *Permission) bool {
if isEmpty {
err = adapter.Engine.DropTables(oldPermission.Adapter)
if err != nil {
panic(err)
return false, err
}
}
}
@ -171,13 +176,13 @@ func UpdatePermission(id string, permission *Permission) bool {
addPolicies(permission)
}
return affected != 0
return affected != 0, nil
}
func AddPermission(permission *Permission) bool {
func AddPermission(permission *Permission) (bool, error) {
affected, err := adapter.Engine.Insert(permission)
if err != nil {
panic(err)
return false, err
}
if affected != 0 {
@ -185,13 +190,61 @@ func AddPermission(permission *Permission) bool {
addPolicies(permission)
}
return affected != 0, nil
}
func AddPermissions(permissions []*Permission) bool {
if len(permissions) == 0 {
return false
}
affected, err := adapter.Engine.Insert(permissions)
if err != nil {
if !strings.Contains(err.Error(), "Duplicate entry") {
panic(err)
}
}
for _, permission := range permissions {
// add using for loop
if affected != 0 {
addGroupingPolicies(permission)
addPolicies(permission)
}
}
return affected != 0
}
func DeletePermission(permission *Permission) bool {
func AddPermissionsInBatch(permissions []*Permission) bool {
batchSize := conf.GetConfigBatchSize()
if len(permissions) == 0 {
return false
}
affected := false
for i := 0; i < (len(permissions)-1)/batchSize+1; i++ {
start := i * batchSize
end := (i + 1) * batchSize
if end > len(permissions) {
end = len(permissions)
}
tmp := permissions[start:end]
// TODO: save to log instead of standard output
// fmt.Printf("Add Permissions: [%d - %d].\n", start, end)
if AddPermissions(tmp) {
affected = true
}
}
return affected
}
func DeletePermission(permission *Permission) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{permission.Owner, permission.Name}).Delete(&Permission{})
if err != nil {
panic(err)
return false, err
}
if affected != 0 {
@ -202,67 +255,97 @@ func DeletePermission(permission *Permission) bool {
if isEmpty {
err = adapter.Engine.DropTables(permission.Adapter)
if err != nil {
panic(err)
return false, err
}
}
}
}
return affected != 0
return affected != 0, nil
}
func GetPermissionsByUser(userId string) []*Permission {
func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error) {
permissions := []*Permission{}
err := adapter.Engine.Where("users like ?", "%"+userId+"\"%").Find(&permissions)
if err != nil {
panic(err)
return nil, nil, err
}
for i := range permissions {
permissions[i].Users = nil
existedPerms := map[string]struct{}{}
for _, perm := range permissions {
perm.Users = nil
if _, ok := existedPerms[perm.Name]; !ok {
existedPerms[perm.Name] = struct{}{}
}
}
return permissions
permFromRoles := []*Permission{}
roles, err := GetRolesByUser(userId)
if err != nil {
return nil, nil, err
}
for _, role := range roles {
perms := []*Permission{}
err := adapter.Engine.Where("roles like ?", "%"+role.Name+"\"%").Find(&perms)
if err != nil {
return nil, nil, err
}
permFromRoles = append(permFromRoles, perms...)
}
for _, perm := range permFromRoles {
perm.Users = nil
if _, ok := existedPerms[perm.Name]; !ok {
existedPerms[perm.Name] = struct{}{}
permissions = append(permissions, perm)
}
}
return permissions, roles, nil
}
func GetPermissionsByRole(roleId string) []*Permission {
func GetPermissionsByRole(roleId string) ([]*Permission, error) {
permissions := []*Permission{}
err := adapter.Engine.Where("roles like ?", "%"+roleId+"\"%").Find(&permissions)
if err != nil {
panic(err)
return permissions, err
}
return permissions
return permissions, nil
}
func GetPermissionsByResource(resourceId string) []*Permission {
func GetPermissionsByResource(resourceId string) ([]*Permission, error) {
permissions := []*Permission{}
err := adapter.Engine.Where("resources like ?", "%"+resourceId+"\"%").Find(&permissions)
if err != nil {
panic(err)
return permissions, err
}
return permissions
return permissions, nil
}
func GetPermissionsBySubmitter(owner string, submitter string) []*Permission {
func GetPermissionsBySubmitter(owner string, submitter string) ([]*Permission, error) {
permissions := []*Permission{}
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Submitter: submitter})
if err != nil {
panic(err)
return permissions, err
}
return permissions
return permissions, nil
}
func GetPermissionsByModel(owner string, model string) []*Permission {
func GetPermissionsByModel(owner string, model string) ([]*Permission, error) {
permissions := []*Permission{}
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Model: model})
if err != nil {
panic(err)
return permissions, err
}
return permissions
return permissions, nil
}
func ContainsAsterisk(userId string, users []string) bool {

View File

@ -29,7 +29,11 @@ import (
func getEnforcer(permission *Permission) *casbin.Enforcer {
tableName := "permission_rule"
if len(permission.Adapter) != 0 {
adapterObj := getCasbinAdapter(permission.Owner, permission.Adapter)
adapterObj, err := getCasbinAdapter(permission.Owner, permission.Adapter)
if err != nil {
panic(err)
}
if adapterObj != nil && adapterObj.Table != "" {
tableName = adapterObj.Table
}
@ -42,7 +46,11 @@ func getEnforcer(permission *Permission) *casbin.Enforcer {
panic(err)
}
permissionModel := getModel(permission.Owner, permission.Model)
permissionModel, err := getModel(permission.Owner, permission.Model)
if err != nil {
panic(err)
}
m := model.Model{}
if permissionModel != nil {
m, err = GetBuiltInModel(permissionModel.ModelText)
@ -122,21 +130,30 @@ func getPolicies(permission *Permission) [][]string {
return policies
}
func getRolesInRole(roleId string, visited map[string]struct{}) []*Role {
role := GetRole(roleId)
func getRolesInRole(roleId string, visited map[string]struct{}) ([]*Role, error) {
role, err := GetRole(roleId)
if err != nil {
return []*Role{}, err
}
if role == nil {
return []*Role{}
return []*Role{}, nil
}
visited[roleId] = struct{}{}
roles := []*Role{role}
for _, subRole := range role.Roles {
if _, ok := visited[subRole]; !ok {
roles = append(roles, getRolesInRole(subRole, visited)...)
r, err := getRolesInRole(subRole, visited)
if err != nil {
return []*Role{}, err
}
roles = append(roles, r...)
}
}
return roles
return roles, nil
}
func getGroupingPolicies(permission *Permission) [][]string {
@ -147,8 +164,10 @@ func getGroupingPolicies(permission *Permission) [][]string {
for _, roleId := range permission.Roles {
visited := map[string]struct{}{}
rolesInRole := getRolesInRole(roleId, visited)
rolesInRole, err := getRolesInRole(roleId, visited)
if err != nil {
panic(err)
}
for _, role := range rolesInRole {
roleId := role.GetId()
for _, subUser := range role.Users {
@ -222,31 +241,44 @@ func removePolicies(permission *Permission) {
type CasbinRequest = []interface{}
func Enforce(permissionId string, request *CasbinRequest) bool {
permission := GetPermission(permissionId)
enforcer := getEnforcer(permission)
allow, err := enforcer.Enforce(*request...)
func Enforce(permissionId string, request *CasbinRequest) (bool, error) {
permission, err := GetPermission(permissionId)
if err != nil {
panic(err)
return false, err
}
return allow
enforcer := getEnforcer(permission)
return enforcer.Enforce(*request...)
}
func BatchEnforce(permissionId string, requests *[]CasbinRequest) []bool {
permission := GetPermission(permissionId)
enforcer := getEnforcer(permission)
allow, err := enforcer.BatchEnforce(*requests)
func BatchEnforce(permissionId string, requests *[]CasbinRequest) ([]bool, error) {
permission, err := GetPermission(permissionId)
if err != nil {
panic(err)
res := []bool{}
for i := 0; i < len(*requests); i++ {
res = append(res, false)
}
return res, err
}
return allow
enforcer := getEnforcer(permission)
return enforcer.BatchEnforce(*requests)
}
func getAllValues(userId string, fn func(enforcer *casbin.Enforcer) []string) []string {
permissions := GetPermissionsByUser(userId)
permissions, _, err := GetPermissionsAndRolesByUser(userId)
if err != nil {
panic(err)
}
for _, role := range GetAllRoles(userId) {
permissions = append(permissions, GetPermissionsByRole(role)...)
permissionsByRole, err := GetPermissionsByRole(role)
if err != nil {
panic(err)
}
permissions = append(permissions, permissionsByRole...)
}
var values []string
@ -270,7 +302,11 @@ func GetAllActions(userId string) []string {
}
func GetAllRoles(userId string) []string {
roles := GetRolesByUser(userId)
roles, err := GetRolesByUser(userId)
if err != nil {
panic(err)
}
var res []string
for _, role := range roles {
res = append(res, role.Name)

View File

@ -0,0 +1,85 @@
// 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 (
"github.com/casdoor/casdoor/xlsx"
)
func getPermissionMap(owner string) (map[string]*Permission, error) {
m := map[string]*Permission{}
permissions, err := GetPermissions(owner)
if err != nil {
return nil, err
}
for _, permission := range permissions {
m[permission.GetId()] = permission
}
return m, err
}
func UploadPermissions(owner string, fileId string) (bool, error) {
table := xlsx.ReadXlsxFile(fileId)
oldUserMap, err := getPermissionMap(owner)
if err != nil {
return false, err
}
newPermissions := []*Permission{}
for index, line := range table {
if index == 0 || parseLineItem(&line, 0) == "" {
continue
}
permission := &Permission{
Owner: parseLineItem(&line, 0),
Name: parseLineItem(&line, 1),
CreatedTime: parseLineItem(&line, 2),
DisplayName: parseLineItem(&line, 3),
Users: parseListItem(&line, 4),
Roles: parseListItem(&line, 5),
Domains: parseListItem(&line, 6),
Model: parseLineItem(&line, 7),
Adapter: parseLineItem(&line, 8),
ResourceType: parseLineItem(&line, 9),
Resources: parseListItem(&line, 10),
Actions: parseListItem(&line, 11),
Effect: parseLineItem(&line, 12),
IsEnabled: parseLineItemBool(&line, 13),
Submitter: parseLineItem(&line, 14),
Approver: parseLineItem(&line, 15),
ApproveTime: parseLineItem(&line, 16),
State: parseLineItem(&line, 17),
}
if _, ok := oldUserMap[permission.GetId()]; !ok {
newPermissions = append(newPermissions, permission)
}
}
if len(newPermissions) == 0 {
return false, nil
}
return AddPermissionsInBatch(newPermissions), nil
}

View File

@ -37,109 +37,115 @@ type Plan struct {
Options []string `xorm:"-" json:"options"`
}
func GetPlanCount(owner, field, value string) int {
func GetPlanCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Plan{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Plan{})
}
func GetPlans(owner string) []*Plan {
func GetPlans(owner string) ([]*Plan, error) {
plans := []*Plan{}
err := adapter.Engine.Desc("created_time").Find(&plans, &Plan{Owner: owner})
if err != nil {
panic(err)
return plans, err
}
return plans
return plans, nil
}
func GetPaginatedPlans(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Plan {
func GetPaginatedPlans(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Plan, error) {
plans := []*Plan{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&plans)
if err != nil {
panic(err)
return plans, err
}
return plans
return plans, nil
}
func getPlan(owner, name string) *Plan {
func getPlan(owner, name string) (*Plan, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
plan := Plan{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&plan)
if err != nil {
panic(err)
return &plan, err
}
if existed {
return &plan
return &plan, nil
} else {
return nil
return nil, nil
}
}
func GetPlan(id string) *Plan {
func GetPlan(id string) (*Plan, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getPlan(owner, name)
}
func UpdatePlan(id string, plan *Plan) bool {
func UpdatePlan(id string, plan *Plan) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if getPlan(owner, name) == nil {
return false
if p, err := getPlan(owner, name); err != nil {
return false, err
} else if p == nil {
return false, nil
}
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(plan)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func AddPlan(plan *Plan) bool {
func AddPlan(plan *Plan) (bool, error) {
affected, err := adapter.Engine.Insert(plan)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeletePlan(plan *Plan) bool {
func DeletePlan(plan *Plan) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{plan.Owner, plan.Name}).Delete(plan)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func (plan *Plan) GetId() string {
return fmt.Sprintf("%s/%s", plan.Owner, plan.Name)
}
func Subscribe(owner string, user string, plan string, pricing string) *Subscription {
selectedPricing := GetPricing(fmt.Sprintf("%s/%s", owner, pricing))
func Subscribe(owner string, user string, plan string, pricing string) (*Subscription, error) {
selectedPricing, err := GetPricing(fmt.Sprintf("%s/%s", owner, pricing))
if err != nil {
return nil, err
}
valid := selectedPricing != nil && selectedPricing.IsEnabled
if !valid {
return nil
return nil, nil
}
planBelongToPricing := selectedPricing.HasPlan(owner, plan)
planBelongToPricing, err := selectedPricing.HasPlan(owner, plan)
if err != nil {
return nil, err
}
if planBelongToPricing {
newSubscription := NewSubscription(owner, user, plan, selectedPricing.TrialDuration)
affected := AddSubscription(newSubscription)
affected, err := AddSubscription(newSubscription)
if err != nil {
return nil, err
}
if affected {
return newSubscription
return newSubscription, nil
}
}
return nil
return nil, nil
}

View File

@ -31,7 +31,6 @@ type Pricing struct {
Plans []string `xorm:"mediumtext" json:"plans"`
IsEnabled bool `json:"isEnabled"`
HasTrial bool `json:"hasTrial"`
TrialDuration int `json:"trialDuration"`
Application string `xorm:"varchar(100)" json:"application"`
@ -42,96 +41,97 @@ type Pricing struct {
State string `xorm:"varchar(100)" json:"state"`
}
func GetPricingCount(owner, field, value string) int {
func GetPricingCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Pricing{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Pricing{})
}
func GetPricings(owner string) []*Pricing {
func GetPricings(owner string) ([]*Pricing, error) {
pricings := []*Pricing{}
err := adapter.Engine.Desc("created_time").Find(&pricings, &Pricing{Owner: owner})
if err != nil {
panic(err)
return pricings, err
}
return pricings
return pricings, nil
}
func GetPaginatedPricings(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Pricing {
func GetPaginatedPricings(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Pricing, error) {
pricings := []*Pricing{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&pricings)
if err != nil {
panic(err)
return pricings, err
}
return pricings
return pricings, nil
}
func getPricing(owner, name string) *Pricing {
func getPricing(owner, name string) (*Pricing, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
pricing := Pricing{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&pricing)
if err != nil {
panic(err)
return &pricing, err
}
if existed {
return &pricing
return &pricing, nil
} else {
return nil
return nil, nil
}
}
func GetPricing(id string) *Pricing {
func GetPricing(id string) (*Pricing, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getPricing(owner, name)
}
func UpdatePricing(id string, pricing *Pricing) bool {
func UpdatePricing(id string, pricing *Pricing) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if getPricing(owner, name) == nil {
return false
if p, err := getPricing(owner, name); err != nil {
return false, err
} else if p == nil {
return false, nil
}
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(pricing)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func AddPricing(pricing *Pricing) bool {
func AddPricing(pricing *Pricing) (bool, error) {
affected, err := adapter.Engine.Insert(pricing)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeletePricing(pricing *Pricing) bool {
func DeletePricing(pricing *Pricing) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{pricing.Owner, pricing.Name}).Delete(pricing)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func (pricing *Pricing) GetId() string {
return fmt.Sprintf("%s/%s", pricing.Owner, pricing.Name)
}
func (pricing *Pricing) HasPlan(owner string, plan string) bool {
selectedPlan := GetPlan(fmt.Sprintf("%s/%s", owner, plan))
func (pricing *Pricing) HasPlan(owner string, plan string) (bool, error) {
selectedPlan, err := GetPlan(fmt.Sprintf("%s/%s", owner, plan))
if err != nil {
return false, err
}
if selectedPlan == nil {
return false
return false, nil
}
result := false
@ -143,5 +143,5 @@ func (pricing *Pricing) HasPlan(owner string, plan string) bool {
}
}
return result
return result, nil
}

View File

@ -43,90 +43,87 @@ type Product struct {
ProviderObjs []*Provider `xorm:"-" json:"providerObjs"`
}
func GetProductCount(owner, field, value string) int {
func GetProductCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Product{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Product{})
}
func GetProducts(owner string) []*Product {
func GetProducts(owner string) ([]*Product, error) {
products := []*Product{}
err := adapter.Engine.Desc("created_time").Find(&products, &Product{Owner: owner})
if err != nil {
panic(err)
return products, err
}
return products
return products, nil
}
func GetPaginationProducts(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Product {
func GetPaginationProducts(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Product, error) {
products := []*Product{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&products)
if err != nil {
panic(err)
return products, err
}
return products
return products, nil
}
func getProduct(owner string, name string) *Product {
func getProduct(owner string, name string) (*Product, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
product := Product{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&product)
if err != nil {
panic(err)
return &product, nil
}
if existed {
return &product
return &product, nil
} else {
return nil
return nil, nil
}
}
func GetProduct(id string) *Product {
func GetProduct(id string) (*Product, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getProduct(owner, name)
}
func UpdateProduct(id string, product *Product) bool {
func UpdateProduct(id string, product *Product) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if getProduct(owner, name) == nil {
return false
if p, err := getProduct(owner, name); err != nil {
return false, err
} else if p == nil {
return false, nil
}
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(product)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func AddProduct(product *Product) bool {
func AddProduct(product *Product) (bool, error) {
affected, err := adapter.Engine.Insert(product)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeleteProduct(product *Product) bool {
func DeleteProduct(product *Product) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{product.Owner, product.Name}).Delete(&Product{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func (product *Product) GetId() string {
@ -143,7 +140,11 @@ func (product *Product) isValidProvider(provider *Provider) bool {
}
func (product *Product) getProvider(providerId string) (*Provider, error) {
provider := getProvider(product.Owner, providerId)
provider, err := getProvider(product.Owner, providerId)
if err != nil {
return nil, err
}
if provider == nil {
return nil, fmt.Errorf("the payment provider: %s does not exist", providerId)
}
@ -155,20 +156,24 @@ func (product *Product) getProvider(providerId string) (*Provider, error) {
return provider, nil
}
func BuyProduct(id string, providerName string, user *User, host string) (string, error) {
product := GetProduct(id)
func BuyProduct(id string, providerName string, user *User, host string) (string, string, error) {
product, err := GetProduct(id)
if err != nil {
return "", "", err
}
if product == nil {
return "", fmt.Errorf("the product: %s does not exist", id)
return "", "", fmt.Errorf("the product: %s does not exist", id)
}
provider, err := product.getProvider(providerName)
if err != nil {
return "", err
return "", "", err
}
pProvider, _, err := provider.getPaymentProvider()
if err != nil {
return "", err
return "", "", err
}
owner := product.Owner
@ -181,9 +186,9 @@ func BuyProduct(id string, providerName string, user *User, host string) (string
returnUrl := fmt.Sprintf("%s/payments/%s/result", originFrontend, paymentName)
notifyUrl := fmt.Sprintf("%s/api/notify-payment/%s/%s/%s/%s", originBackend, owner, providerName, productName, paymentName)
payUrl, err := pProvider.Pay(providerName, productName, payerName, paymentName, productDisplayName, product.Price, returnUrl, notifyUrl)
payUrl, orderId, err := pProvider.Pay(providerName, productName, payerName, paymentName, productDisplayName, product.Price, product.Currency, returnUrl, notifyUrl)
if err != nil {
return "", err
return "", "", err
}
payment := Payment{
@ -205,25 +210,40 @@ func BuyProduct(id string, providerName string, user *User, host string) (string
ReturnUrl: product.ReturnUrl,
State: "Created",
}
affected := AddPayment(&payment)
if !affected {
return "", fmt.Errorf("failed to add payment: %s", util.StructToJson(payment))
if provider.Type == "Dummy" {
payment.State = "Paid"
}
return payUrl, err
affected, err := AddPayment(&payment)
if err != nil {
return "", "", err
}
if !affected {
return "", "", fmt.Errorf("failed to add payment: %s", util.StructToJson(payment))
}
return payUrl, orderId, err
}
func ExtendProductWithProviders(product *Product) {
func ExtendProductWithProviders(product *Product) error {
if product == nil {
return
return nil
}
product.ProviderObjs = []*Provider{}
m := getProviderMap(product.Owner)
m, err := getProviderMap(product.Owner)
if err != nil {
return err
}
for _, providerItem := range product.Providers {
if provider, ok := m[providerItem]; ok {
product.ProviderObjs = append(product.ProviderObjs, provider)
}
}
return nil
}

View File

@ -27,9 +27,9 @@ import (
func TestProduct(t *testing.T) {
InitConfig()
product := GetProduct("admin/product_123")
provider := getProvider(product.Owner, "provider_pay_alipay")
cert := getCert(product.Owner, "cert-pay-alipay")
product, _ := GetProduct("admin/product_123")
provider, _ := getProvider(product.Owner, "provider_pay_alipay")
cert, _ := getCert(product.Owner, "cert-pay-alipay")
pProvider, err := pp.GetPaymentProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, cert.Certificate, cert.PrivateKey, cert.AuthorityPublicKey, cert.AuthorityRootPublicKey, provider.ClientId2)
if err != nil {
panic(err)
@ -38,7 +38,7 @@ func TestProduct(t *testing.T) {
paymentName := util.GenerateTimeId()
returnUrl := ""
notifyUrl := ""
payUrl, err := pProvider.Pay(provider.Name, product.Name, "alice", paymentName, product.DisplayName, product.Price, returnUrl, notifyUrl)
payUrl, _, err := pProvider.Pay(provider.Name, product.Name, "alice", paymentName, product.DisplayName, product.Price, product.Currency, returnUrl, notifyUrl)
if err != nil {
panic(err)
}

View File

@ -103,103 +103,93 @@ func GetMaskedProviders(providers []*Provider, isMaskEnabled bool) []*Provider {
return providers
}
func GetProviderCount(owner, field, value string) int {
func GetProviderCount(owner, field, value string) (int64, error) {
session := GetSession("", -1, -1, field, value, "", "")
count, err := session.Where("owner = ? or owner = ? ", "admin", owner).Count(&Provider{})
if err != nil {
panic(err)
}
return int(count)
return session.Where("owner = ? or owner = ? ", "admin", owner).Count(&Provider{})
}
func GetGlobalProviderCount(field, value string) int {
func GetGlobalProviderCount(field, value string) (int64, error) {
session := GetSession("", -1, -1, field, value, "", "")
count, err := session.Count(&Provider{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Provider{})
}
func GetProviders(owner string) []*Provider {
func GetProviders(owner string) ([]*Provider, error) {
providers := []*Provider{}
err := adapter.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&providers, &Provider{})
if err != nil {
panic(err)
return providers, err
}
return providers
return providers, nil
}
func GetGlobalProviders() []*Provider {
func GetGlobalProviders() ([]*Provider, error) {
providers := []*Provider{}
err := adapter.Engine.Desc("created_time").Find(&providers)
if err != nil {
panic(err)
return providers, err
}
return providers
return providers, nil
}
func GetPaginationProviders(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Provider {
func GetPaginationProviders(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Provider, error) {
providers := []*Provider{}
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
err := session.Where("owner = ? or owner = ? ", "admin", owner).Find(&providers)
if err != nil {
panic(err)
return providers, err
}
return providers
return providers, nil
}
func GetPaginationGlobalProviders(offset, limit int, field, value, sortField, sortOrder string) []*Provider {
func GetPaginationGlobalProviders(offset, limit int, field, value, sortField, sortOrder string) ([]*Provider, error) {
providers := []*Provider{}
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
err := session.Find(&providers)
if err != nil {
panic(err)
return providers, err
}
return providers
return providers, nil
}
func getProvider(owner string, name string) *Provider {
func getProvider(owner string, name string) (*Provider, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
provider := Provider{Name: name}
existed, err := adapter.Engine.Get(&provider)
if err != nil {
panic(err)
return &provider, err
}
if existed {
return &provider
return &provider, nil
} else {
return nil
return nil, nil
}
}
func GetProvider(id string) *Provider {
func GetProvider(id string) (*Provider, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getProvider(owner, name)
}
func getDefaultAiProvider() *Provider {
func getDefaultAiProvider() (*Provider, error) {
provider := Provider{Owner: "admin", Category: "AI"}
existed, err := adapter.Engine.Get(&provider)
if err != nil {
panic(err)
return &provider, err
}
if !existed {
return nil
return nil, nil
}
return &provider
return &provider, nil
}
func GetWechatMiniProgramProvider(application *Application) *Provider {
@ -212,16 +202,18 @@ func GetWechatMiniProgramProvider(application *Application) *Provider {
return nil
}
func UpdateProvider(id string, provider *Provider) bool {
func UpdateProvider(id string, provider *Provider) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
if getProvider(owner, name) == nil {
return false
if p, err := getProvider(owner, name); err != nil {
return false, err
} else if p == nil {
return false, nil
}
if name != provider.Name {
err := providerChangeTrigger(name, provider.Name)
if err != nil {
return false
return false, nil
}
}
@ -233,42 +225,50 @@ func UpdateProvider(id string, provider *Provider) bool {
session = session.Omit("client_secret2")
}
provider.Endpoint = util.GetEndPoint(provider.Endpoint)
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
if provider.Type != "Keycloak" {
provider.Endpoint = util.GetEndPoint(provider.Endpoint)
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
}
affected, err := session.Update(provider)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func AddProvider(provider *Provider) bool {
provider.Endpoint = util.GetEndPoint(provider.Endpoint)
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
func AddProvider(provider *Provider) (bool, error) {
if provider.Type != "Keycloak" {
provider.Endpoint = util.GetEndPoint(provider.Endpoint)
provider.IntranetEndpoint = util.GetEndPoint(provider.IntranetEndpoint)
}
affected, err := adapter.Engine.Insert(provider)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeleteProvider(provider *Provider) bool {
func DeleteProvider(provider *Provider) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{provider.Owner, provider.Name}).Delete(&Provider{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func (p *Provider) getPaymentProvider() (pp.PaymentProvider, *Cert, error) {
cert := &Cert{}
if p.Cert != "" {
cert = getCert(p.Owner, p.Cert)
cert, err := getCert(p.Owner, p.Cert)
if err != nil {
return nil, nil, err
}
if cert == nil {
return nil, nil, fmt.Errorf("the cert: %s does not exist", p.Cert)
}
@ -309,7 +309,11 @@ func GetCaptchaProviderByApplication(applicationId, isCurrentProvider, lang stri
if isCurrentProvider == "true" {
return GetCaptchaProviderByOwnerName(applicationId, lang)
}
application := GetApplication(applicationId)
application, err := GetApplication(applicationId)
if err != nil {
return nil, err
}
if application == nil || len(application.Providers) == 0 {
return nil, fmt.Errorf(i18n.Translate(lang, "provider:Invalid application id"))
}

View File

@ -26,11 +26,7 @@ import (
var logPostOnly bool
func init() {
var err error
logPostOnly, err = conf.GetConfigBool("logPostOnly")
if err != nil {
// panic(err)
}
logPostOnly = conf.GetConfigBool("logPostOnly")
}
type Record struct {
@ -108,49 +104,48 @@ func AddRecord(record *Record) bool {
return affected != 0
}
func GetRecordCount(field, value string, filterRecord *Record) int {
func GetRecordCount(field, value string, filterRecord *Record) (int64, error) {
session := GetSession("", -1, -1, field, value, "", "")
count, err := session.Count(filterRecord)
if err != nil {
panic(err)
}
return int(count)
return session.Count(filterRecord)
}
func GetRecords() []*Record {
func GetRecords() ([]*Record, error) {
records := []*Record{}
err := adapter.Engine.Desc("id").Find(&records)
if err != nil {
panic(err)
return records, err
}
return records
return records, nil
}
func GetPaginationRecords(offset, limit int, field, value, sortField, sortOrder string, filterRecord *Record) []*Record {
func GetPaginationRecords(offset, limit int, field, value, sortField, sortOrder string, filterRecord *Record) ([]*Record, error) {
records := []*Record{}
session := GetSession("", offset, limit, field, value, sortField, sortOrder)
err := session.Find(&records, filterRecord)
if err != nil {
panic(err)
return records, err
}
return records
return records, nil
}
func GetRecordsByField(record *Record) []*Record {
func GetRecordsByField(record *Record) ([]*Record, error) {
records := []*Record{}
err := adapter.Engine.Find(&records, record)
if err != nil {
panic(err)
return records, err
}
return records
return records, nil
}
func SendWebhooks(record *Record) error {
webhooks := getWebhooksByOrganization(record.Organization)
webhooks, err := getWebhooksByOrganization(record.Organization)
if err != nil {
return err
}
for _, webhook := range webhooks {
if !webhook.IsEnabled {
continue
@ -166,7 +161,11 @@ func SendWebhooks(record *Record) error {
if matched {
if webhook.IsUserExtended {
user := GetMaskedUser(getUser(record.Organization, record.User))
user, err := GetMaskedUser(getUser(record.Organization, record.User))
if err != nil {
return err
}
record.ExtendedUser = user
}

View File

@ -39,17 +39,12 @@ type Resource struct {
Description string `xorm:"varchar(255)" json:"description"`
}
func GetResourceCount(owner, user, field, value string) int {
func GetResourceCount(owner, user, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Resource{User: user})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Resource{User: user})
}
func GetResources(owner string, user string) []*Resource {
func GetResources(owner string, user string) ([]*Resource, error) {
if owner == "built-in" {
owner = ""
user = ""
@ -58,13 +53,13 @@ func GetResources(owner string, user string) []*Resource {
resources := []*Resource{}
err := adapter.Engine.Desc("created_time").Find(&resources, &Resource{Owner: owner, User: user})
if err != nil {
panic(err)
return resources, err
}
return resources
return resources, err
}
func GetPaginationResources(owner, user string, offset, limit int, field, value, sortField, sortOrder string) []*Resource {
func GetPaginationResources(owner, user string, offset, limit int, field, value, sortField, sortOrder string) ([]*Resource, error) {
if owner == "built-in" {
owner = ""
user = ""
@ -74,70 +69,74 @@ func GetPaginationResources(owner, user string, offset, limit int, field, value,
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&resources, &Resource{User: user})
if err != nil {
panic(err)
return resources, err
}
return resources
return resources, nil
}
func getResource(owner string, name string) *Resource {
func getResource(owner string, name string) (*Resource, error) {
resource := Resource{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&resource)
if err != nil {
panic(err)
return &resource, err
}
if existed {
return &resource
return &resource, nil
}
return nil
return nil, nil
}
func GetResource(id string) *Resource {
func GetResource(id string) (*Resource, error) {
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
return getResource(owner, name)
}
func UpdateResource(id string, resource *Resource) bool {
func UpdateResource(id string, resource *Resource) (bool, error) {
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
if getResource(owner, name) == nil {
return false
if r, err := getResource(owner, name); err != nil {
return false, err
} else if r == nil {
return false, nil
}
_, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(resource)
if err != nil {
panic(err)
return false, err
}
// return affected != 0
return true
return true, nil
}
func AddResource(resource *Resource) bool {
func AddResource(resource *Resource) (bool, error) {
affected, err := adapter.Engine.Insert(resource)
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func DeleteResource(resource *Resource) bool {
func DeleteResource(resource *Resource) (bool, error) {
affected, err := adapter.Engine.ID(core.PK{resource.Owner, resource.Name}).Delete(&Resource{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func (resource *Resource) GetId() string {
return fmt.Sprintf("%s/%s", resource.Owner, resource.Name)
}
func AddOrUpdateResource(resource *Resource) bool {
if getResource(resource.Owner, resource.Name) == nil {
func AddOrUpdateResource(resource *Resource) (bool, error) {
if r, err := getResource(resource.Owner, resource.Name); err != nil {
return false, err
} else if r == nil {
return AddResource(resource)
} else {
return UpdateResource(resource.GetId(), resource)

View File

@ -16,6 +16,9 @@ package object
import (
"fmt"
"strings"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util"
"github.com/xorm-io/core"
@ -26,6 +29,7 @@ type Role struct {
Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
DisplayName string `xorm:"varchar(100)" json:"displayName"`
Description string `xorm:"varchar(100)" json:"description"`
Users []string `xorm:"mediumtext" json:"users"`
Roles []string `xorm:"mediumtext" json:"roles"`
@ -33,79 +37,90 @@ type Role struct {
IsEnabled bool `json:"isEnabled"`
}
func GetRoleCount(owner, field, value string) int {
func GetRoleCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Role{})
if err != nil {
panic(err)
}
return int(count)
return session.Count(&Role{})
}
func GetRoles(owner string) []*Role {
func GetRoles(owner string) ([]*Role, error) {
roles := []*Role{}
err := adapter.Engine.Desc("created_time").Find(&roles, &Role{Owner: owner})
if err != nil {
panic(err)
return roles, err
}
return roles
return roles, nil
}
func GetPaginationRoles(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Role {
func GetPaginationRoles(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Role, error) {
roles := []*Role{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Find(&roles)
if err != nil {
panic(err)
return roles, err
}
return roles
return roles, nil
}
func getRole(owner string, name string) *Role {
func getRole(owner string, name string) (*Role, error) {
if owner == "" || name == "" {
return nil
return nil, nil
}
role := Role{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&role)
if err != nil {
panic(err)
return &role, err
}
if existed {
return &role
return &role, nil
} else {
return nil
return nil, nil
}
}
func GetRole(id string) *Role {
func GetRole(id string) (*Role, error) {
owner, name := util.GetOwnerAndNameFromId(id)
return getRole(owner, name)
}
func UpdateRole(id string, role *Role) bool {
func UpdateRole(id string, role *Role) (bool, error) {
owner, name := util.GetOwnerAndNameFromId(id)
oldRole := getRole(owner, name)
oldRole, err := getRole(owner, name)
if err != nil {
return false, err
}
if oldRole == nil {
return false
return false, nil
}
visited := map[string]struct{}{}
permissions := GetPermissionsByRole(id)
permissions, err := GetPermissionsByRole(id)
if err != nil {
return false, err
}
for _, permission := range permissions {
removeGroupingPolicies(permission)
removePolicies(permission)
visited[permission.GetId()] = struct{}{}
}
ancestorRoles := GetAncestorRoles(id)
ancestorRoles, err := GetAncestorRoles(id)
if err != nil {
return false, err
}
for _, r := range ancestorRoles {
permissions := GetPermissionsByRole(r.GetId())
permissions, err := GetPermissionsByRole(r.GetId())
if err != nil {
return false, err
}
for _, permission := range permissions {
permissionId := permission.GetId()
if _, ok := visited[permissionId]; !ok {
@ -118,27 +133,38 @@ func UpdateRole(id string, role *Role) bool {
if name != role.Name {
err := roleChangeTrigger(name, role.Name)
if err != nil {
return false
return false, nil
}
}
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(role)
if err != nil {
panic(err)
return false, err
}
visited = map[string]struct{}{}
newRoleID := role.GetId()
permissions = GetPermissionsByRole(newRoleID)
permissions, err = GetPermissionsByRole(newRoleID)
if err != nil {
return false, err
}
for _, permission := range permissions {
addGroupingPolicies(permission)
addPolicies(permission)
visited[permission.GetId()] = struct{}{}
}
ancestorRoles = GetAncestorRoles(newRoleID)
ancestorRoles, err = GetAncestorRoles(newRoleID)
if err != nil {
return false, err
}
for _, r := range ancestorRoles {
permissions := GetPermissionsByRole(r.GetId())
permissions, err := GetPermissionsByRole(r.GetId())
if err != nil {
return false, err
}
for _, permission := range permissions {
permissionId := permission.GetId()
if _, ok := visited[permissionId]; !ok {
@ -148,50 +174,107 @@ func UpdateRole(id string, role *Role) bool {
}
}
return affected != 0
return affected != 0, nil
}
func AddRole(role *Role) bool {
func AddRole(role *Role) (bool, error) {
affected, err := adapter.Engine.Insert(role)
if err != nil {
panic(err)
return false, err
}
return affected != 0, nil
}
func AddRoles(roles []*Role) bool {
if len(roles) == 0 {
return false
}
affected, err := adapter.Engine.Insert(roles)
if err != nil {
if !strings.Contains(err.Error(), "Duplicate entry") {
panic(err)
}
}
return affected != 0
}
func DeleteRole(role *Role) bool {
func AddRolesInBatch(roles []*Role) bool {
batchSize := conf.GetConfigBatchSize()
if len(roles) == 0 {
return false
}
affected := false
for i := 0; i < (len(roles)-1)/batchSize+1; i++ {
start := i * batchSize
end := (i + 1) * batchSize
if end > len(roles) {
end = len(roles)
}
tmp := roles[start:end]
// TODO: save to log instead of standard output
// fmt.Printf("Add users: [%d - %d].\n", start, end)
if AddRoles(tmp) {
affected = true
}
}
return affected
}
func DeleteRole(role *Role) (bool, error) {
roleId := role.GetId()
permissions := GetPermissionsByRole(roleId)
permissions, err := GetPermissionsByRole(roleId)
if err != nil {
return false, err
}
for _, permission := range permissions {
permission.Roles = util.DeleteVal(permission.Roles, roleId)
UpdatePermission(permission.GetId(), permission)
_, err := UpdatePermission(permission.GetId(), permission)
if err != nil {
return false, err
}
}
affected, err := adapter.Engine.ID(core.PK{role.Owner, role.Name}).Delete(&Role{})
if err != nil {
panic(err)
return false, err
}
return affected != 0
return affected != 0, nil
}
func (role *Role) GetId() string {
return fmt.Sprintf("%s/%s", role.Owner, role.Name)
}
func GetRolesByUser(userId string) []*Role {
func GetRolesByUser(userId string) ([]*Role, error) {
roles := []*Role{}
err := adapter.Engine.Where("users like ?", "%"+userId+"\"%").Find(&roles)
if err != nil {
panic(err)
return roles, err
}
for i := range roles {
roles[i].Users = nil
allRolesIds := make([]string, 0, len(roles))
for _, role := range roles {
allRolesIds = append(allRolesIds, role.GetId())
}
return roles
allRoles, err := GetAncestorRoles(allRolesIds...)
if err != nil {
return nil, err
}
for i := range allRoles {
allRoles[i].Users = nil
}
return allRoles, nil
}
func roleChangeTrigger(oldName string, newName string) error {
@ -208,6 +291,7 @@ func roleChangeTrigger(oldName string, newName string) error {
if err != nil {
return err
}
for _, role := range roles {
for j, u := range role.Roles {
owner, name := util.GetOwnerAndNameFromId(u)
@ -226,6 +310,7 @@ func roleChangeTrigger(oldName string, newName string) error {
if err != nil {
return err
}
for _, permission := range permissions {
for j, u := range permission.Roles {
// u = organization/username
@ -251,26 +336,38 @@ func GetMaskedRoles(roles []*Role) []*Role {
return roles
}
func GetRolesByNamePrefix(owner string, prefix string) []*Role {
func GetRolesByNamePrefix(owner string, prefix string) ([]*Role, error) {
roles := []*Role{}
err := adapter.Engine.Where("owner=? and name like ?", owner, prefix+"%").Find(&roles)
if err != nil {
panic(err)
return roles, err
}
return roles
return roles, nil
}
func GetAncestorRoles(roleId string) []*Role {
// GetAncestorRoles returns a list of roles that contain the given roleIds
func GetAncestorRoles(roleIds ...string) ([]*Role, error) {
var (
result []*Role
result = []*Role{}
roleMap = make(map[string]*Role)
visited = make(map[string]bool)
)
if len(roleIds) == 0 {
return result, nil
}
owner, _ := util.GetOwnerAndNameFromIdNoCheck(roleId)
for _, roleId := range roleIds {
visited[roleId] = true
}
owner, _ := util.GetOwnerAndNameFromIdNoCheck(roleIds[0])
allRoles, err := GetRoles(owner)
if err != nil {
return nil, err
}
allRoles := GetRoles(owner)
for _, r := range allRoles {
roleMap[r.GetId()] = r
}
@ -282,29 +379,29 @@ func GetAncestorRoles(roleId string) []*Role {
result = append(result, r)
} else if !ok {
rId := r.GetId()
visited[rId] = containsRole(r, roleId, roleMap, visited)
visited[rId] = containsRole(r, roleMap, visited, roleIds...)
if visited[rId] {
result = append(result, r)
}
}
}
return result
return result, nil
}
// containsRole is a helper function to check if a slice of roles contains a specific roleId
func containsRole(role *Role, roleId string, roleMap map[string]*Role, visited map[string]bool) bool {
// 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 {
if isContain, ok := visited[role.GetId()]; ok {
return isContain
}
for _, subRole := range role.Roles {
if subRole == roleId {
if util.HasString(roleIds, subRole) {
return true
}
r, ok := roleMap[subRole]
if ok && containsRole(r, roleId, roleMap, visited) {
if ok && containsRole(r, roleMap, visited, roleIds...) {
return true
}
}

71
object/role_upload.go Normal file
View File

@ -0,0 +1,71 @@
// 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 (
"github.com/casdoor/casdoor/xlsx"
)
func getRoleMap(owner string) (map[string]*Role, error) {
m := map[string]*Role{}
roles, err := GetRoles(owner)
if err != nil {
return nil, err
}
for _, role := range roles {
m[role.GetId()] = role
}
return m, nil
}
func UploadRoles(owner string, fileId string) (bool, error) {
table := xlsx.ReadXlsxFile(fileId)
oldUserMap, err := getRoleMap(owner)
if err != nil {
return false, err
}
newRoles := []*Role{}
for index, line := range table {
if index == 0 || parseLineItem(&line, 0) == "" {
continue
}
role := &Role{
Owner: parseLineItem(&line, 0),
Name: parseLineItem(&line, 1),
CreatedTime: parseLineItem(&line, 2),
DisplayName: parseLineItem(&line, 3),
Users: parseListItem(&line, 4),
Roles: parseListItem(&line, 5),
Domains: parseListItem(&line, 6),
IsEnabled: parseLineItemBool(&line, 7),
}
if _, ok := oldUserMap[role.GetId()]; !ok {
newRoles = append(newRoles, role)
}
}
if len(newRoles) == 0 {
return false, nil
}
return AddRolesInBatch(newRoles), nil
}

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