Compare commits

...

12 Commits

Author SHA1 Message Date
Bingchang Chen
53ad454962 feat: responsive footer (#1003) 2022-08-10 20:31:42 +08:00
leoshine
fb203a6f30 feat: delete .env to fix static file path bug (#999) 2022-08-10 12:22:27 +08:00
Gucheng Wang
f716a0985f Add disableSsl to provider. 2022-08-09 23:38:35 +08:00
Gucheng Wang
340fbe135d Fix error in wrapActionResponse() 2022-08-09 23:34:07 +08:00
Mikey
79119760f2 style: golint (#988) 2022-08-09 16:50:49 +08:00
jakiuncle
4dd67a8dcb fix: fix all frontend warnings (#983)
* fix:fix all frontend warnings

* fix:fix all frontend warnings

* fix:fix all frontend warnings

* fix:fix all frontend warnings

* fix:fix all frontend warnings

* fix:fix all frontend warnings
2022-08-09 12:19:56 +08:00
q1anx1
deed857788 chore(style): allow case declarations and ban var (#987)
* chore(style): allow case declarations

* chore(style): ban `var` and prefer `const`
2022-08-08 23:35:24 +08:00
Mikey
802995ed16 refactor: remove WeChat unionId to properties (#985) 2022-08-08 18:43:12 +08:00
q1anx1
b14554a5ba feat(web): check style when commit (#980)
feat(web): check style when commit
2022-08-08 00:10:31 +08:00
Gucheng Wang
4665ffa759 Update i18n data 2022-08-08 00:02:47 +08:00
Gucheng Wang
f914e8e929 Add permission_enforcer.go 2022-08-07 23:57:06 +08:00
Yixiang Zhao
dc33b41107 feat: expose some casbin APIs (#955)
* feat: expose some casbin APIs

Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>

* feat: add BatchEnforce API

Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>

* fix: solve requested changes

Signed-off-by: Yixiang Zhao <seriouszyx@foxmail.com>
2022-08-07 23:42:45 +08:00
147 changed files with 1180 additions and 536 deletions

View File

@@ -18,7 +18,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"sort"
@@ -80,7 +80,7 @@ func (captcha *AliyunCaptchaProvider) VerifyCaptcha(token, clientSecret string)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return false, err
}

View File

@@ -18,7 +18,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"time"
@@ -58,7 +58,7 @@ func (captcha *GEETESTCaptchaProvider) VerifyCaptcha(token, clientSecret string)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return false, err
}

View File

@@ -17,7 +17,7 @@ package captcha
import (
"encoding/json"
"errors"
"io/ioutil"
"io"
"net/http"
"net/url"
"strings"
@@ -43,7 +43,7 @@ func (captcha *HCaptchaProvider) VerifyCaptcha(token, clientSecret string) (bool
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return false, err
}

View File

@@ -17,7 +17,7 @@ package captcha
import (
"encoding/json"
"errors"
"io/ioutil"
"io"
"net/http"
"net/url"
"strings"
@@ -43,7 +43,7 @@ func (captcha *ReCaptchaProvider) VerifyCaptcha(token, clientSecret string) (boo
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return false, err
}

View File

@@ -274,6 +274,7 @@ func (c *ApiController) GetAccount() {
c.ServeJSON()
}
// GetUserinfo
// UserInfo
// @Title UserInfo
// @Tag Account API

View File

@@ -118,7 +118,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
}
} else {
resp = wrapErrorResponse(fmt.Errorf("Unknown response type: %s", form.Type))
resp = wrapErrorResponse(fmt.Errorf("unknown response type: %s", form.Type))
}
// if user did not check auto signin

View File

@@ -23,11 +23,13 @@ import (
"github.com/casdoor/casdoor/util"
)
// ApiController
// controller for handlers under /api uri
type ApiController struct {
beego.Controller
}
// RootController
// controller for handlers directly under / (root)
type RootController struct {
ApiController
@@ -136,9 +138,9 @@ func (c *ApiController) SetSessionData(s *SessionData) {
func wrapActionResponse(affected bool) *Response {
if affected {
return &Response{Status: "ok", Msg: "", Data: "Affected"}
return &Response{Status: "ok", Msg: ""}
} else {
return &Response{Status: "ok", Msg: "", Data: "Unaffected"}
return &Response{Status: "error", Msg: "this operation has no effect"}
}
}

View File

@@ -31,7 +31,7 @@ const (
InvalidProxyCallback string = "INVALID_PROXY_CALLBACK"
InvalidTicket string = "INVALID_TICKET"
InvalidService string = "INVALID_SERVICE"
InteralError string = "INTERNAL_ERROR"
InternalError string = "INTERNAL_ERROR"
UnauthorizedService string = "UNAUTHORIZED_SERVICE"
)
@@ -116,7 +116,7 @@ func (c *RootController) CasP3ServiceAndProxyValidate() {
}
// make a request to pgturl passing pgt and pgtiou
if err != nil {
c.sendCasAuthenticationResponseErr(InteralError, err.Error(), format)
c.sendCasAuthenticationResponseErr(InternalError, err.Error(), format)
return
}
param := pgtUrlObj.Query()
@@ -126,7 +126,7 @@ func (c *RootController) CasP3ServiceAndProxyValidate() {
request, err := http.NewRequest("GET", pgtUrlObj.String(), nil)
if err != nil {
c.sendCasAuthenticationResponseErr(InteralError, err.Error(), format)
c.sendCasAuthenticationResponseErr(InternalError, err.Error(), format)
return
}
@@ -214,7 +214,7 @@ func (c *RootController) SamlValidate() {
return
}
envelopReponse := struct {
envelopResponse := struct {
XMLName xml.Name `xml:"SOAP-ENV:Envelope"`
Xmlns string `xml:"xmlns:SOAP-ENV"`
Body struct {
@@ -222,15 +222,15 @@ func (c *RootController) SamlValidate() {
Content string `xml:",innerxml"`
}
}{}
envelopReponse.Xmlns = "http://schemas.xmlsoap.org/soap/envelope/"
envelopReponse.Body.Content = response
envelopResponse.Xmlns = "http://schemas.xmlsoap.org/soap/envelope/"
envelopResponse.Body.Content = response
data, err := xml.Marshal(envelopReponse)
data, err := xml.Marshal(envelopResponse)
if err != nil {
c.ResponseError(err.Error())
return
}
c.Ctx.Output.Body([]byte(data))
c.Ctx.Output.Body(data)
}
func (c *RootController) sendCasProxyResponseErr(code, msg, format string) {

View File

@@ -48,6 +48,7 @@ func (c *ApiController) GetCerts() {
}
}
// GetCert
// @Title GetCert
// @Tag Cert API
// @Description get cert
@@ -61,6 +62,7 @@ func (c *ApiController) GetCert() {
c.ServeJSON()
}
// UpdateCert
// @Title UpdateCert
// @Tag Cert API
// @Description update cert
@@ -81,6 +83,7 @@ func (c *ApiController) UpdateCert() {
c.ServeJSON()
}
// AddCert
// @Title AddCert
// @Tag Cert API
// @Description add cert
@@ -98,6 +101,7 @@ func (c *ApiController) AddCert() {
c.ServeJSON()
}
// DeleteCert
// @Title DeleteCert
// @Tag Cert API
// @Description delete cert

88
controllers/enforcer.go Normal file
View File

@@ -0,0 +1,88 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package controllers
import (
"encoding/json"
"github.com/casdoor/casdoor/object"
)
func (c *ApiController) Enforce() {
userId := c.GetSessionUsername()
if userId == "" {
c.ResponseError("Please sign in first")
return
}
var permissionRule object.PermissionRule
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permissionRule)
if err != nil {
panic(err)
}
c.Data["json"] = object.Enforce(userId, &permissionRule)
c.ServeJSON()
}
func (c *ApiController) BatchEnforce() {
userId := c.GetSessionUsername()
if userId == "" {
c.ResponseError("Please sign in first")
return
}
var permissionRules []object.PermissionRule
err := json.Unmarshal(c.Ctx.Input.RequestBody, &permissionRules)
if err != nil {
panic(err)
}
c.Data["json"] = object.BatchEnforce(userId, permissionRules)
c.ServeJSON()
}
func (c *ApiController) GetAllObjects() {
userId := c.GetSessionUsername()
if userId == "" {
c.ResponseError("Please sign in first")
return
}
c.Data["json"] = object.GetAllObjects(userId)
c.ServeJSON()
}
func (c *ApiController) GetAllActions() {
userId := c.GetSessionUsername()
if userId == "" {
c.ResponseError("Please sign in first")
return
}
c.Data["json"] = object.GetAllActions(userId)
c.ServeJSON()
}
func (c *ApiController) GetAllRoles() {
userId := c.GetSessionUsername()
if userId == "" {
c.ResponseError("Please sign in first")
return
}
c.Data["json"] = object.GetAllRoles(userId)
c.ServeJSON()
}

View File

@@ -44,6 +44,7 @@ type LdapSyncResp struct {
Failed []object.LdapRespUser `json:"failed"`
}
// GetLdapUser
// @Tag Account API
// @Title GetLdapser
// @router /get-ldap-user [post]
@@ -100,6 +101,7 @@ func (c *ApiController) GetLdapUser() {
c.ServeJSON()
}
// GetLdaps
// @Tag Account API
// @Title GetLdaps
// @router /get-ldaps [post]
@@ -110,6 +112,7 @@ func (c *ApiController) GetLdaps() {
c.ServeJSON()
}
// GetLdap
// @Tag Account API
// @Title GetLdap
// @router /get-ldap [post]
@@ -125,6 +128,7 @@ func (c *ApiController) GetLdap() {
c.ServeJSON()
}
// AddLdap
// @Tag Account API
// @Title AddLdap
// @router /add-ldap [post]
@@ -159,6 +163,7 @@ func (c *ApiController) AddLdap() {
c.ServeJSON()
}
// UpdateLdap
// @Tag Account API
// @Title UpdateLdap
// @router /update-ldap [post]
@@ -186,6 +191,7 @@ func (c *ApiController) UpdateLdap() {
c.ServeJSON()
}
// DeleteLdap
// @Tag Account API
// @Title DeleteLdap
// @router /delete-ldap [post]
@@ -201,6 +207,7 @@ func (c *ApiController) DeleteLdap() {
c.ServeJSON()
}
// SyncLdapUsers
// @Tag Account API
// @Title SyncLdapUsers
// @router /sync-ldap-users [post]
@@ -223,6 +230,7 @@ func (c *ApiController) SyncLdapUsers() {
c.ServeJSON()
}
// CheckLdapUsersExist
// @Tag Account API
// @Title CheckLdapUserExist
// @router /check-ldap-users-exist [post]

View File

@@ -16,6 +16,7 @@ package controllers
import "github.com/casdoor/casdoor/object"
// GetOidcDiscovery
// @Title GetOidcDiscovery
// @Tag OIDC API
// @Description Get Oidc Discovery
@@ -27,6 +28,7 @@ func (c *RootController) GetOidcDiscovery() {
c.ServeJSON()
}
// GetJwks
// @Title GetJwks
// @Tag OIDC API
// @Success 200 {object} jose.JSONWebKey

View File

@@ -67,6 +67,7 @@ func (c *ApiController) GetUserPayments() {
c.ResponseOk(payments)
}
// GetPayment
// @Title GetPayment
// @Tag Payment API
// @Description get payment
@@ -80,6 +81,7 @@ func (c *ApiController) GetPayment() {
c.ServeJSON()
}
// UpdatePayment
// @Title UpdatePayment
// @Tag Payment API
// @Description update payment
@@ -100,6 +102,7 @@ func (c *ApiController) UpdatePayment() {
c.ServeJSON()
}
// AddPayment
// @Title AddPayment
// @Tag Payment API
// @Description add payment
@@ -117,6 +120,7 @@ func (c *ApiController) AddPayment() {
c.ServeJSON()
}
// DeletePayment
// @Title DeletePayment
// @Tag Payment API
// @Description delete payment
@@ -134,6 +138,7 @@ func (c *ApiController) DeletePayment() {
c.ServeJSON()
}
// NotifyPayment
// @Title NotifyPayment
// @Tag Payment API
// @Description notify payment
@@ -159,6 +164,7 @@ func (c *ApiController) NotifyPayment() {
}
}
// InvoicePayment
// @Title InvoicePayment
// @Tag Payment API
// @Description invoice payment

View File

@@ -48,6 +48,7 @@ func (c *ApiController) GetPermissions() {
}
}
// GetPermission
// @Title GetPermission
// @Tag Permission API
// @Description get permission
@@ -61,6 +62,7 @@ func (c *ApiController) GetPermission() {
c.ServeJSON()
}
// UpdatePermission
// @Title UpdatePermission
// @Tag Permission API
// @Description update permission
@@ -81,6 +83,7 @@ func (c *ApiController) UpdatePermission() {
c.ServeJSON()
}
// AddPermission
// @Title AddPermission
// @Tag Permission API
// @Description add permission
@@ -98,6 +101,7 @@ func (c *ApiController) AddPermission() {
c.ServeJSON()
}
// DeletePermission
// @Title DeletePermission
// @Tag Permission API
// @Description delete permission

View File

@@ -49,6 +49,7 @@ func (c *ApiController) GetProducts() {
}
}
// GetProduct
// @Title GetProduct
// @Tag Product API
// @Description get product
@@ -65,6 +66,7 @@ func (c *ApiController) GetProduct() {
c.ServeJSON()
}
// UpdateProduct
// @Title UpdateProduct
// @Tag Product API
// @Description update product
@@ -85,6 +87,7 @@ func (c *ApiController) UpdateProduct() {
c.ServeJSON()
}
// AddProduct
// @Title AddProduct
// @Tag Product API
// @Description add product
@@ -102,6 +105,7 @@ func (c *ApiController) AddProduct() {
c.ServeJSON()
}
// DeleteProduct
// @Title DeleteProduct
// @Tag Product API
// @Description delete product
@@ -119,6 +123,7 @@ func (c *ApiController) DeleteProduct() {
c.ServeJSON()
}
// BuyProduct
// @Title BuyProduct
// @Tag Product API
// @Description buy product

View File

@@ -48,6 +48,7 @@ func (c *ApiController) GetProviders() {
}
}
// GetProvider
// @Title GetProvider
// @Tag Provider API
// @Description get provider
@@ -61,6 +62,7 @@ func (c *ApiController) GetProvider() {
c.ServeJSON()
}
// UpdateProvider
// @Title UpdateProvider
// @Tag Provider API
// @Description update provider
@@ -81,6 +83,7 @@ func (c *ApiController) UpdateProvider() {
c.ServeJSON()
}
// AddProvider
// @Title AddProvider
// @Tag Provider API
// @Description add provider
@@ -98,6 +101,7 @@ func (c *ApiController) AddProvider() {
c.ServeJSON()
}
// DeleteProvider
// @Title DeleteProvider
// @Tag Provider API
// @Description delete provider

View File

@@ -27,6 +27,7 @@ import (
"github.com/casdoor/casdoor/util"
)
// GetResources
// @router /get-resources [get]
// @Tag Resource API
// @Title GetResources
@@ -50,6 +51,7 @@ func (c *ApiController) GetResources() {
}
}
// GetResource
// @Tag Resource API
// @Title GetResource
// @router /get-resource [get]
@@ -60,6 +62,7 @@ func (c *ApiController) GetResource() {
c.ServeJSON()
}
// UpdateResource
// @Tag Resource API
// @Title UpdateResource
// @router /update-resource [post]
@@ -76,6 +79,7 @@ func (c *ApiController) UpdateResource() {
c.ServeJSON()
}
// AddResource
// @Tag Resource API
// @Title AddResource
// @router /add-resource [post]
@@ -90,6 +94,7 @@ func (c *ApiController) AddResource() {
c.ServeJSON()
}
// DeleteResource
// @Tag Resource API
// @Title DeleteResource
// @router /delete-resource [post]
@@ -115,6 +120,7 @@ func (c *ApiController) DeleteResource() {
c.ServeJSON()
}
// UploadResource
// @Tag Resource API
// @Title UploadResource
// @router /upload-resource [post]

View File

@@ -48,6 +48,7 @@ func (c *ApiController) GetRoles() {
}
}
// GetRole
// @Title GetRole
// @Tag Role API
// @Description get role
@@ -61,6 +62,7 @@ func (c *ApiController) GetRole() {
c.ServeJSON()
}
// UpdateRole
// @Title UpdateRole
// @Tag Role API
// @Description update role
@@ -81,6 +83,7 @@ func (c *ApiController) UpdateRole() {
c.ServeJSON()
}
// AddRole
// @Title AddRole
// @Tag Role API
// @Description add role
@@ -98,6 +101,7 @@ func (c *ApiController) AddRole() {
c.ServeJSON()
}
// DeleteRole
// @Title DeleteRole
// @Tag Role API
// @Description delete role

View File

@@ -48,6 +48,7 @@ func (c *ApiController) GetSyncers() {
}
}
// GetSyncer
// @Title GetSyncer
// @Tag Syncer API
// @Description get syncer
@@ -61,6 +62,7 @@ func (c *ApiController) GetSyncer() {
c.ServeJSON()
}
// UpdateSyncer
// @Title UpdateSyncer
// @Tag Syncer API
// @Description update syncer
@@ -81,6 +83,7 @@ func (c *ApiController) UpdateSyncer() {
c.ServeJSON()
}
// AddSyncer
// @Title AddSyncer
// @Tag Syncer API
// @Description add syncer
@@ -98,6 +101,7 @@ func (c *ApiController) AddSyncer() {
c.ServeJSON()
}
// DeleteSyncer
// @Title DeleteSyncer
// @Tag Syncer API
// @Description delete syncer
@@ -115,6 +119,7 @@ func (c *ApiController) DeleteSyncer() {
c.ServeJSON()
}
// RunSyncer
// @Title RunSyncer
// @Tag Syncer API
// @Description run syncer

View File

@@ -255,7 +255,7 @@ func (c *ApiController) RefreshToken() {
// @router /login/oauth/logout [get]
func (c *ApiController) TokenLogout() {
token := c.Input().Get("id_token_hint")
flag, application := object.DeleteTokenByAceessToken(token)
flag, application := object.DeleteTokenByAccessToken(token)
redirectUri := c.Input().Get("post_logout_redirect_uri")
state := c.Input().Get("state")
if application != nil && object.CheckRedirectUriValid(application, redirectUri) {
@@ -288,7 +288,7 @@ func (c *ApiController) IntrospectToken() {
if clientId == "" || clientSecret == "" {
c.ResponseError("empty clientId or clientSecret")
c.Data["json"] = &object.TokenError{
Error: object.INVALID_REQUEST,
Error: object.InvalidRequest,
}
c.SetTokenErrorHttpStatus()
c.ServeJSON()
@@ -299,7 +299,7 @@ func (c *ApiController) IntrospectToken() {
if application == nil || application.ClientSecret != clientSecret {
c.ResponseError("invalid application or wrong clientSecret")
c.Data["json"] = &object.TokenError{
Error: object.INVALID_CLIENT,
Error: object.InvalidClient,
}
c.SetTokenErrorHttpStatus()
return

View File

@@ -298,6 +298,7 @@ func (c *ApiController) SetPassword() {
c.ServeJSON()
}
// CheckUserPassword
// @Title CheckUserPassword
// @router /check-user-password [post]
// @Tag User API

View File

@@ -55,7 +55,7 @@ func (c *ApiController) ResponseError(error string, data ...interface{}) {
func (c *ApiController) SetTokenErrorHttpStatus() {
_, ok := c.Data["json"].(*object.TokenError)
if ok {
if c.Data["json"].(*object.TokenError).Error == object.INVALID_CLIENT {
if c.Data["json"].(*object.TokenError).Error == object.InvalidClient {
c.Ctx.Output.SetStatus(401)
c.Ctx.Output.Header("WWW-Authenticate", "Basic realm=\"OAuth2\"")
} else {

View File

@@ -98,7 +98,7 @@ func (c *ApiController) SendVerificationCode() {
return
}
sendResp := errors.New("Invalid dest type")
sendResp := errors.New("invalid dest type")
if user == nil && checkUser != "" && checkUser != "true" {
name := application.Organization

View File

@@ -16,7 +16,7 @@ package controllers
import (
"bytes"
"io/ioutil"
"io"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/util"
@@ -24,6 +24,7 @@ import (
"github.com/duo-labs/webauthn/webauthn"
)
// WebAuthnSignupBegin
// @Title WebAuthnSignupBegin
// @Tag User API
// @Description WebAuthn Registration Flow 1st stage
@@ -53,6 +54,7 @@ func (c *ApiController) WebAuthnSignupBegin() {
c.ServeJSON()
}
// WebAuthnSignupFinish
// @Title WebAuthnSignupFinish
// @Tag User API
// @Description WebAuthn Registration Flow 2nd stage
@@ -72,7 +74,7 @@ func (c *ApiController) WebAuthnSignupFinish() {
c.ResponseError("Please call WebAuthnSignupBegin first")
return
}
c.Ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
credential, err := webauthnObj.FinishRegistration(user, sessionData, c.Ctx.Request)
if err != nil {
@@ -84,6 +86,7 @@ func (c *ApiController) WebAuthnSignupFinish() {
c.ResponseOk()
}
// WebAuthnSigninBegin
// @Title WebAuthnSigninBegin
// @Tag Login API
// @Description WebAuthn Login Flow 1st stage
@@ -110,6 +113,7 @@ func (c *ApiController) WebAuthnSigninBegin() {
c.ServeJSON()
}
// WebAuthnSigninFinish
// @Title WebAuthnSigninBegin
// @Tag Login API
// @Description WebAuthn Login Flow 2nd stage
@@ -124,7 +128,7 @@ func (c *ApiController) WebAuthnSigninFinish() {
c.ResponseError("Please call WebAuthnSigninBegin first")
return
}
c.Ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
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)

View File

@@ -48,6 +48,7 @@ func (c *ApiController) GetWebhooks() {
}
}
// GetWebhook
// @Title GetWebhook
// @Tag Webhook API
// @Description get webhook
@@ -61,6 +62,7 @@ func (c *ApiController) GetWebhook() {
c.ServeJSON()
}
// UpdateWebhook
// @Title UpdateWebhook
// @Tag Webhook API
// @Description update webhook
@@ -81,6 +83,7 @@ func (c *ApiController) UpdateWebhook() {
c.ServeJSON()
}
// AddWebhook
// @Title AddWebhook
// @Tag Webhook API
// @Description add webhook
@@ -98,6 +101,7 @@ func (c *ApiController) AddWebhook() {
c.ServeJSON()
}
// DeleteWebhook
// @Title DeleteWebhook
// @Tag Webhook API
// @Description delete webhook

View File

@@ -19,7 +19,7 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"time"
@@ -77,6 +77,7 @@ type AdfsToken struct {
ErrMsg string `json:"error_description"`
}
// GetToken
// get more detail via: https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios#request-an-access-token
func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
payload := url.Values{}
@@ -88,7 +89,7 @@ func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -109,6 +110,7 @@ func (idp *AdfsIdProvider) GetToken(code string) (*oauth2.Token, error) {
return token, nil
}
// GetUserInfo
// Since the userinfo endpoint of ADFS only returns sub,
// the id_token is used to resolve the userinfo
func (idp *AdfsIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
@@ -122,10 +124,10 @@ func (idp *AdfsIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
}
tokenSrc := []byte(token.AccessToken)
publicKey, _ := keyset.Keys[0].Materialize()
id_token, _ := jwt.Parse(bytes.NewReader(tokenSrc), jwt.WithVerify(jwa.RS256, publicKey))
sid, _ := id_token.Get("sid")
upn, _ := id_token.Get("upn")
name, _ := id_token.Get("unique_name")
idToken, _ := jwt.Parse(bytes.NewReader(tokenSrc), jwt.WithVerify(jwa.RS256, publicKey))
sid, _ := idToken.Get("sid")
upn, _ := idToken.Get("upn")
name, _ := idToken.Get("unique_name")
userinfo := &UserInfo{
Id: sid.(string),
Username: name.(string),

View File

@@ -24,7 +24,6 @@ import (
"encoding/json"
"encoding/pem"
"io"
"io/ioutil"
"net/http"
"net/url"
"sort"
@@ -205,7 +204,7 @@ func (idp *AlipayIdProvider) postWithBody(body interface{}, targetUrl string) ([
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -18,7 +18,7 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"golang.org/x/oauth2"
@@ -97,7 +97,7 @@ func (idp *BaiduIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -18,7 +18,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
@@ -76,6 +75,7 @@ type BilibiliIdProviderTokenResponse struct {
Data BilibiliProviderToken `json:"data"`
}
// GetToken
/*
{
"code": 0,
@@ -170,7 +170,7 @@ func (idp *BilibiliIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -204,7 +204,7 @@ func (idp *BilibiliIdProvider) postWithBody(body interface{}, url string) ([]byt
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -17,7 +17,7 @@ package idp
import (
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"time"
@@ -71,7 +71,7 @@ func (idp *CasdoorIdProvider) GetToken(code string) (*oauth2.Token, error) {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -131,7 +131,7 @@ func (idp *CasdoorIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -18,7 +18,7 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
_ "net/url"
_ "time"
@@ -84,7 +84,7 @@ func (idp *CustomIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -18,7 +18,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
"time"
@@ -101,7 +100,7 @@ func (idp *DingTalkIdProvider) GetToken(code string) (*oauth2.Token, error) {
token := &oauth2.Token{
AccessToken: pToken.AccessToken,
Expiry: time.Unix(time.Now().Unix()+int64(pToken.ExpiresIn), 0),
Expiry: time.Unix(time.Now().Unix()+pToken.ExpiresIn, 0),
}
return token, nil
}
@@ -145,7 +144,7 @@ func (idp *DingTalkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -180,7 +179,7 @@ func (idp *DingTalkIdProvider) postWithBody(body interface{}, url string) ([]byt
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -18,7 +18,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"time"
@@ -98,7 +98,7 @@ func (idp *DouyinIdProvider) GetToken(code string) (*oauth2.Token, error) {
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -177,7 +177,7 @@ func (idp *DouyinIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -71,6 +71,7 @@ type FacebookCheckToken struct {
Data string `json:"data"`
}
// FacebookCheckTokenData
// Get more detail via: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#checktoken
type FacebookCheckTokenData struct {
UserId string `json:"user_id"`

View File

@@ -19,7 +19,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strconv"
@@ -93,7 +92,7 @@ func (idp *GiteeIdProvider) GetToken(code string) (*oauth2.Token, error) {
if err != nil {
return nil, err
}
rbs, err := ioutil.ReadAll(resp.Body)
rbs, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -18,7 +18,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strconv"
"strings"
@@ -202,7 +201,7 @@ func (idp *GithubIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -236,7 +235,7 @@ func (idp *GithubIdProvider) postWithBody(body interface{}, url string) ([]byte,
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -17,7 +17,7 @@ package idp
import (
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"strconv"
@@ -85,7 +85,7 @@ func (idp *GitlabIdProvider) GetToken(code string) (*oauth2.Token, error) {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -209,7 +209,7 @@ func (idp *GitlabIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -19,7 +19,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"io"
"net/http"
"golang.org/x/oauth2"
@@ -95,7 +95,7 @@ func (idp *GoogleIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -207,6 +207,7 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
return &idp
}
// SetHttpClient
// Goth's idp all implement the Client method, but since the goth.Provider interface does not provide to modify idp's client method, reflection is required
func (idp *GothIdProvider) SetHttpClient(client *http.Client) {
idpClient := reflect.ValueOf(idp.Provider).Elem().FieldByName("HTTPClient")

View File

@@ -17,7 +17,7 @@ package idp
import (
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"golang.org/x/oauth2"
@@ -58,6 +58,7 @@ type InfoflowInterToken struct {
AccessToken string `json:"access_token"`
}
// GetToken
// get more detail via: https://qy.baidu.com/doc/index.html#/inner_quickstart/flow?id=%E8%8E%B7%E5%8F%96accesstoken
func (idp *InfoflowInternalIdProvider) GetToken(code string) (*oauth2.Token, error) {
pTokenParams := &struct {
@@ -69,7 +70,7 @@ func (idp *InfoflowInternalIdProvider) GetToken(code string) (*oauth2.Token, err
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -137,6 +138,7 @@ type InfoflowInternalUserInfo struct {
Email string `json:"email"`
}
// GetUserInfo
// get more detail via: https://qy.baidu.com/doc/index.html#/inner_serverapi/contacts?id=%e8%8e%b7%e5%8f%96%e6%88%90%e5%91%98
func (idp *InfoflowInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
// Get userid first
@@ -147,7 +149,7 @@ func (idp *InfoflowInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserIn
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -165,7 +167,7 @@ func (idp *InfoflowInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserIn
return nil, err
}
data, err = ioutil.ReadAll(resp.Body)
data, err = io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -18,7 +18,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
"time"
@@ -63,6 +62,7 @@ type InfoflowToken struct {
ExpiresIn int `json:"expires_in"`
}
// GetToken
// get more detail via: https://qy.baidu.com/doc/index.html#/third_serverapi/authority
func (idp *InfoflowIdProvider) GetToken(code string) (*oauth2.Token, error) {
pTokenParams := &struct {
@@ -134,6 +134,7 @@ type InfoflowUserInfo struct {
Email string `json:"email"`
}
// GetUserInfo
// get more detail via: https://qy.baidu.com/doc/index.html#/third_serverapi/contacts?id=%e8%8e%b7%e5%8f%96%e6%88%90%e5%91%98
func (idp *InfoflowIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
// Get userid first
@@ -144,7 +145,7 @@ func (idp *InfoflowIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -162,7 +163,7 @@ func (idp *InfoflowIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
return nil, err
}
data, err = ioutil.ReadAll(resp.Body)
data, err = io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -197,7 +198,7 @@ func (idp *InfoflowIdProvider) postWithBody(body interface{}, url string) ([]byt
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -17,7 +17,6 @@ package idp
import (
"encoding/json"
"io"
"io/ioutil"
"net/http"
"strings"
"time"
@@ -173,7 +172,7 @@ func (idp *LarkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
return nil, err
}
defer resp.Body.Close()
data, err = ioutil.ReadAll(resp.Body)
data, err = io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -204,7 +203,7 @@ func (idp *LarkIdProvider) postWithBody(body interface{}, url string) ([]byte, e
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -18,7 +18,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
@@ -85,7 +84,7 @@ func (idp *LinkedInIdProvider) GetToken(code string) (*oauth2.Token, error) {
if err != nil {
return nil, err
}
rbs, err := ioutil.ReadAll(resp.Body)
rbs, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -323,7 +322,7 @@ func (idp *LinkedInIdProvider) GetUrlRespWithAuthorization(url, token string) ([
}
}(resp.Body)
bs, err := ioutil.ReadAll(resp.Body)
bs, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -17,7 +17,7 @@ package idp
import (
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"time"
@@ -114,7 +114,7 @@ func (idp *OktaIdProvider) GetToken(code string) (*oauth2.Token, error) {
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -178,7 +178,7 @@ func (idp *OktaIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -18,7 +18,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"io"
"net/http"
"net/url"
"regexp"
@@ -75,7 +75,7 @@ func (idp *QqIdProvider) GetToken(code string) (*oauth2.Token, error) {
}
defer resp.Body.Close()
tokenContent, err := ioutil.ReadAll(resp.Body)
tokenContent, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -148,7 +148,7 @@ func (idp *QqIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
}
defer resp.Body.Close()
openIdBody, err := ioutil.ReadAll(resp.Body)
openIdBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -167,7 +167,7 @@ func (idp *QqIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
}
defer resp.Body.Close()
userInfoBody, err := ioutil.ReadAll(resp.Body)
userInfoBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -144,7 +144,7 @@ type WechatUserInfo struct {
City string `json:"city"` // City filled in by general user's personal data
Province string `json:"province"` // Province filled in by ordinary user's personal information
Country string `json:"country"` // Country, such as China is CN
Headimgurl string `json:"headimgurl"` // User avatar, the last value represents the size of the square avatar (there are optional values of 0, 46, 64, 96, 132, 0 represents a 640*640 square avatar), this item is empty when the user does not have a avatar
Headimgurl string `json:"headimgurl"` // User avatar, the last value represents the size of the square avatar (there are optional values of 0, 46, 64, 96, 132, 0 represents a 640*640 square avatar), this item is empty when the user does not have an avatar
Privilege []string `json:"privilege"` // User Privilege information, json array, such as Wechat Woka user (chinaunicom)
Unionid string `json:"unionid"` // Unified user identification. For an application under a WeChat open platform account, the unionid of the same user is unique.
}

View File

@@ -17,7 +17,7 @@ package idp
import (
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"golang.org/x/oauth2"
@@ -65,7 +65,7 @@ func (idp *WeChatMiniProgramIdProvider) GetSessionByCode(code string) (*WeChatMi
return nil, err
}
defer sessionResponse.Body.Close()
data, err := ioutil.ReadAll(sessionResponse.Body)
data, err := io.ReadAll(sessionResponse.Body)
if err != nil {
return nil, err
}

View File

@@ -17,13 +17,14 @@ package idp
import (
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"time"
"golang.org/x/oauth2"
)
// WeComInternalIdProvider
// This idp is using wecom internal application api as idp
type WeComInternalIdProvider struct {
Client *http.Client
@@ -72,7 +73,7 @@ func (idp *WeComInternalIdProvider) GetToken(code string) (*oauth2.Token, error)
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -123,7 +124,7 @@ func (idp *WeComInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo,
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
@@ -144,7 +145,7 @@ func (idp *WeComInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo,
return nil, err
}
data, err = ioutil.ReadAll(resp.Body)
data, err = io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -18,7 +18,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
"time"
@@ -195,7 +194,7 @@ func (idp *WeComIdProvider) postWithBody(body interface{}, url string) ([]byte,
if err != nil {
return nil, err
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -19,7 +19,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strconv"
@@ -92,7 +91,7 @@ func (idp *WeiBoIdProvider) GetToken(code string) (*oauth2.Token, error) {
return
}
}(resp.Body)
bs, err := ioutil.ReadAll(resp.Body)
bs, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -33,6 +33,7 @@ func SendEmail(provider *Provider, title string, content string, dest string, se
// DailSmtpServer Dail Smtp server
func DailSmtpServer(provider *Provider) error {
dialer := gomail.NewDialer(provider.Host, provider.Port, provider.ClientId, provider.ClientSecret)
dialer.SSL = !provider.DisableSsl
sender, err := dialer.Dial()
if err != nil {

View File

@@ -16,7 +16,7 @@ package object
import (
"encoding/gob"
"io/ioutil"
"os"
"github.com/casdoor/casdoor/util"
"github.com/duo-labs/webauthn/webauthn"
@@ -158,11 +158,11 @@ func initBuiltInApplication() {
func readTokenFromFile() (string, string) {
pemPath := "./object/token_jwt_key.pem"
keyPath := "./object/token_jwt_key.key"
pem, err := ioutil.ReadFile(pemPath)
pem, err := os.ReadFile(pemPath)
if err != nil {
return "", ""
}
key, err := ioutil.ReadFile(keyPath)
key, err := os.ReadFile(keyPath)
if err != nil {
return "", ""
}

View File

@@ -31,6 +31,7 @@ func GetLdapAutoSynchronizer() *LdapAutoSynchronizer {
return globalLdapAutoSynchronizer
}
// StartAutoSync
// start autosync for specified ldap, old existing autosync goroutine will be ceased
func (l *LdapAutoSynchronizer) StartAutoSync(ldapId string) error {
l.Lock()
@@ -95,6 +96,7 @@ 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() {
organizations := []*Organization{}

View File

@@ -16,12 +16,7 @@ package object
import (
"fmt"
"strings"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
xormadapter "github.com/casbin/xorm-adapter/v2"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util"
"xorm.io/core"
)
@@ -45,13 +40,13 @@ type Permission struct {
}
type PermissionRule struct {
PType string `xorm:"varchar(100) index not null default ''"`
V0 string `xorm:"varchar(100) index not null default ''"`
V1 string `xorm:"varchar(100) index not null default ''"`
V2 string `xorm:"varchar(100) index not null default ''"`
V3 string `xorm:"varchar(100) index not null default ''"`
V4 string `xorm:"varchar(100) index not null default ''"`
V5 string `xorm:"varchar(100) index not null default ''"`
Ptype string `xorm:"varchar(100) index not null default ''" json:"ptype"`
V0 string `xorm:"varchar(100) index not null default ''" json:"v0"`
V1 string `xorm:"varchar(100) index not null default ''" json:"v1"`
V2 string `xorm:"varchar(100) index not null default ''" json:"v2"`
V3 string `xorm:"varchar(100) index not null default ''" json:"v3"`
V4 string `xorm:"varchar(100) index not null default ''" json:"v4"`
V5 string `xorm:"varchar(100) index not null default ''" json:"v5"`
}
func GetPermissionCount(owner, field, value string) int {
@@ -158,78 +153,6 @@ func (permission *Permission) GetId() string {
return fmt.Sprintf("%s/%s", permission.Owner, permission.Name)
}
func getEnforcer(permission *Permission) *casbin.Enforcer {
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
adapter, err := xormadapter.NewAdapterWithTableName(conf.GetConfigString("driverName"), conf.GetBeegoConfDataSourceName()+conf.GetConfigString("dbName"), "permission_rule", tableNamePrefix, true)
if err != nil {
panic(err)
}
modelText := `
[request_definition]
r = sub, obj, act
[policy_definition]
p = permission, sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`
permissionModel := getModel(permission.Owner, permission.Model)
if permissionModel != nil {
modelText = permissionModel.ModelText
}
m, err := model.NewModelFromString(modelText)
if err != nil {
panic(err)
}
enforcer, err := casbin.NewEnforcer(m, adapter)
if err != nil {
panic(err)
}
err = enforcer.LoadFilteredPolicy(xormadapter.Filter{V0: []string{permission.GetId()}})
if err != nil {
panic(err)
}
return enforcer
}
func getPolicies(permission *Permission) [][]string {
var policies [][]string
for _, user := range permission.Users {
for _, resource := range permission.Resources {
for _, action := range permission.Actions {
policies = append(policies, []string{permission.GetId(), user, resource, strings.ToLower(action)})
}
}
}
return policies
}
func addPolicies(permission *Permission) {
enforcer := getEnforcer(permission)
policies := getPolicies(permission)
_, err := enforcer.AddPolicies(policies)
if err != nil {
panic(err)
}
}
func removePolicies(permission *Permission) {
enforcer := getEnforcer(permission)
_, err := enforcer.RemoveFilteredPolicy(0, permission.GetId())
if err != nil {
panic(err)
}
}
func GetPermissionsByUser(userId string) []*Permission {
permissions := []*Permission{}
err := adapter.Engine.Where("users like ?", "%"+userId+"%").Find(&permissions)

View File

@@ -0,0 +1,162 @@
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package object
import (
"strings"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
xormadapter "github.com/casbin/xorm-adapter/v2"
"github.com/casdoor/casdoor/conf"
)
func getEnforcer(permission *Permission) *casbin.Enforcer {
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
adapter, err := xormadapter.NewAdapterWithTableName(conf.GetConfigString("driverName"), conf.GetBeegoConfDataSourceName()+conf.GetConfigString("dbName"), "permission_rule", tableNamePrefix, true)
if err != nil {
panic(err)
}
modelText := `
[request_definition]
r = sub, obj, act
[policy_definition]
p = permission, sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`
permissionModel := getModel(permission.Owner, permission.Model)
if permissionModel != nil {
modelText = permissionModel.ModelText
}
m, err := model.NewModelFromString(modelText)
if err != nil {
panic(err)
}
enforcer, err := casbin.NewEnforcer(m, adapter)
if err != nil {
panic(err)
}
err = enforcer.LoadFilteredPolicy(xormadapter.Filter{V0: []string{permission.GetId()}})
if err != nil {
panic(err)
}
return enforcer
}
func getPolicies(permission *Permission) [][]string {
var policies [][]string
for _, user := range permission.Users {
for _, resource := range permission.Resources {
for _, action := range permission.Actions {
policies = append(policies, []string{permission.GetId(), user, resource, strings.ToLower(action)})
}
}
}
for _, role := range permission.Roles {
for _, resource := range permission.Resources {
for _, action := range permission.Actions {
policies = append(policies, []string{permission.GetId(), role, resource, strings.ToLower(action)})
}
}
}
return policies
}
func addPolicies(permission *Permission) {
enforcer := getEnforcer(permission)
policies := getPolicies(permission)
_, err := enforcer.AddPolicies(policies)
if err != nil {
panic(err)
}
}
func removePolicies(permission *Permission) {
enforcer := getEnforcer(permission)
_, err := enforcer.RemoveFilteredPolicy(0, permission.GetId())
if err != nil {
panic(err)
}
}
func Enforce(userId string, permissionRule *PermissionRule) bool {
permission := GetPermission(permissionRule.V0)
enforcer := getEnforcer(permission)
allow, err := enforcer.Enforce(userId, permissionRule.V2, permissionRule.V3)
if err != nil {
panic(err)
}
return allow
}
func BatchEnforce(userId string, permissionRules []PermissionRule) []bool {
var requests [][]interface{}
for _, permissionRule := range permissionRules {
requests = append(requests, []interface{}{userId, permissionRule.V2, permissionRule.V3})
}
permission := GetPermission(permissionRules[0].V0)
enforcer := getEnforcer(permission)
allow, err := enforcer.BatchEnforce(requests)
if err != nil {
panic(err)
}
return allow
}
func getAllValues(userId string, sec string, fieldIndex int) []string {
permissions := GetPermissionsByUser(userId)
var values []string
for _, permission := range permissions {
enforcer := getEnforcer(permission)
enforcer.ClearPolicy()
err := enforcer.LoadFilteredPolicy(xormadapter.Filter{V0: []string{permission.GetId()}, V1: []string{userId}})
if err != nil {
return nil
}
for _, value := range enforcer.GetModel().GetValuesForFieldInPolicyAllTypes(sec, fieldIndex) {
values = append(values, value)
}
}
return values
}
func GetAllObjects(userId string) []string {
return getAllValues(userId, "p", 2)
}
func GetAllActions(userId string) []string {
return getAllValues(userId, "p", 3)
}
func GetAllRoles(userId string) []string {
roles := GetRolesByUser(userId)
var res []string
for _, role := range roles {
res = append(res, role.Name)
}
return res
}

View File

@@ -43,10 +43,11 @@ type Provider struct {
CustomUserInfoUrl string `xorm:"varchar(200)" json:"customUserInfoUrl"`
CustomLogo string `xorm:"varchar(200)" json:"customLogo"`
Host string `xorm:"varchar(100)" json:"host"`
Port int `json:"port"`
Title string `xorm:"varchar(100)" json:"title"`
Content string `xorm:"varchar(1000)" json:"content"`
Host string `xorm:"varchar(100)" json:"host"`
Port int `json:"port"`
DisableSsl bool `json:"disableSsl"`
Title string `xorm:"varchar(100)" json:"title"`
Content string `xorm:"varchar(1000)" json:"content"`
RegionId string `xorm:"varchar(100)" json:"regionId"`
SignName string `xorm:"varchar(100)" json:"signName"`

View File

@@ -35,6 +35,7 @@ import (
uuid "github.com/satori/go.uuid"
)
// NewSamlResponse
// returns a saml2 response
func NewSamlResponse(user *User, host string, certificate string, destination string, iss string, requestId string, redirectUri []string) (*etree.Element, error) {
samlResponse := &etree.Element{
@@ -113,6 +114,7 @@ func (x X509Key) GetKeyPair() (privateKey *rsa.PrivateKey, cert []byte, err erro
return privateKey, cert, err
}
// IdpEntityDescriptor
// SAML METADATA
type IdpEntityDescriptor struct {
XMLName xml.Name `xml:"EntityDescriptor"`

View File

@@ -44,7 +44,7 @@ func ParseSamlResponse(samlResponse string, providerType string) (string, error)
func GenerateSamlLoginUrl(id, relayState string) (string, string, error) {
provider := GetProvider(id)
if provider.Category != "SAML" {
return "", "", fmt.Errorf("Provider %s's category is not SAML", provider.Name)
return "", "", fmt.Errorf("provider %s's category is not SAML", provider.Name)
}
sp, err := buildSp(provider, "")
if err != nil {

View File

@@ -27,14 +27,14 @@ import (
)
const (
hourSeconds = 3600
INVALID_REQUEST = "invalid_request"
INVALID_CLIENT = "invalid_client"
INVALID_GRANT = "invalid_grant"
UNAUTHORIZED_CLIENT = "unauthorized_client"
UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type"
INVALID_SCOPE = "invalid_scope"
ENDPOINT_ERROR = "endpoint_error"
hourSeconds = 3600
InvalidRequest = "invalid_request"
InvalidClient = "invalid_client"
InvalidGrant = "invalid_grant"
UnauthorizedClient = "unauthorized_client"
UnsupportedGrantType = "unsupported_grant_type"
InvalidScope = "invalid_scope"
EndpointError = "endpoint_error"
)
type Code struct {
@@ -200,7 +200,7 @@ func DeleteToken(token *Token) bool {
return affected != 0
}
func DeleteTokenByAceessToken(accessToken string) (bool, *Application) {
func DeleteTokenByAccessToken(accessToken string) (bool, *Application) {
token := Token{AccessToken: accessToken}
existed, err := adapter.Engine.Get(&token)
if err != nil {
@@ -325,7 +325,7 @@ func GetOAuthToken(grantType string, clientId string, clientSecret string, code
application := GetApplicationByClientId(clientId)
if application == nil {
return &TokenError{
Error: INVALID_CLIENT,
Error: InvalidClient,
ErrorDescription: "client_id is invalid",
}
}
@@ -334,7 +334,7 @@ func GetOAuthToken(grantType string, clientId string, clientSecret string, code
if !IsGrantTypeValid(grantType, application.GrantTypes) && tag == "" {
return &TokenError{
Error: UNSUPPORTED_GRANT_TYPE,
Error: UnsupportedGrantType,
ErrorDescription: fmt.Sprintf("grant_type: %s is not supported in this application", grantType),
}
}
@@ -377,20 +377,20 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
// check parameters
if grantType != "refresh_token" {
return &TokenError{
Error: UNSUPPORTED_GRANT_TYPE,
Error: UnsupportedGrantType,
ErrorDescription: "grant_type should be refresh_token",
}
}
application := GetApplicationByClientId(clientId)
if application == nil {
return &TokenError{
Error: INVALID_CLIENT,
Error: InvalidClient,
ErrorDescription: "client_id is invalid",
}
}
if clientSecret != "" && application.ClientSecret != clientSecret {
return &TokenError{
Error: INVALID_CLIENT,
Error: InvalidClient,
ErrorDescription: "client_secret is invalid",
}
}
@@ -399,7 +399,7 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
existed, err := adapter.Engine.Get(&token)
if err != nil || !existed {
return &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: "refresh token is invalid, expired or revoked",
}
}
@@ -408,7 +408,7 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
_, err = ParseJwtToken(refreshToken, cert)
if err != nil {
return &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: fmt.Sprintf("parse refresh token error: %s", err.Error()),
}
}
@@ -416,14 +416,14 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
user := getUser(application.Organization, token.User)
if user.IsForbidden {
return &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: "the user is forbidden to sign in, please contact the administrator",
}
}
newAccessToken, newRefreshToken, err := generateJwtToken(application, user, "", scope, host)
if err != nil {
return &TokenError{
Error: ENDPOINT_ERROR,
Error: EndpointError,
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
}
}
@@ -464,6 +464,7 @@ func pkceChallenge(verifier string) string {
return challenge
}
// IsGrantTypeValid
// Check if grantType is allowed in the current application
// authorization_code is allowed by default
func IsGrantTypeValid(method string, grantTypes []string) bool {
@@ -478,11 +479,12 @@ func IsGrantTypeValid(method string, grantTypes []string) bool {
return false
}
// GetAuthorizationCodeToken
// Authorization code flow
func GetAuthorizationCodeToken(application *Application, clientSecret string, code string, verifier string) (*Token, *TokenError) {
if code == "" {
return nil, &TokenError{
Error: INVALID_REQUEST,
Error: InvalidRequest,
ErrorDescription: "authorization code should not be empty",
}
}
@@ -490,21 +492,21 @@ func GetAuthorizationCodeToken(application *Application, clientSecret string, co
token := getTokenByCode(code)
if token == nil {
return nil, &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: "authorization code is invalid",
}
}
if token.CodeIsUsed {
// anti replay attacks
return nil, &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: "authorization code has been used",
}
}
if token.CodeChallenge != "" && pkceChallenge(verifier) != token.CodeChallenge {
return nil, &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: "verifier is invalid",
}
}
@@ -514,13 +516,13 @@ func GetAuthorizationCodeToken(application *Application, clientSecret string, co
// but if it is provided, it must be accurate.
if token.CodeChallenge == "" {
return nil, &TokenError{
Error: INVALID_CLIENT,
Error: InvalidClient,
ErrorDescription: "client_secret is invalid",
}
} else {
if clientSecret != "" {
return nil, &TokenError{
Error: INVALID_CLIENT,
Error: InvalidClient,
ErrorDescription: "client_secret is invalid",
}
}
@@ -529,7 +531,7 @@ func GetAuthorizationCodeToken(application *Application, clientSecret string, co
if application.Name != token.Application {
return nil, &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: "the token is for wrong application (client_id)",
}
}
@@ -537,39 +539,40 @@ func GetAuthorizationCodeToken(application *Application, clientSecret string, co
if time.Now().Unix() > token.CodeExpireIn {
// code must be used within 5 minutes
return nil, &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: "authorization code has expired",
}
}
return token, nil
}
// GetPasswordToken
// Resource Owner Password Credentials flow
func GetPasswordToken(application *Application, username string, password string, scope string, host string) (*Token, *TokenError) {
user := getUser(application.Organization, username)
if user == nil {
return nil, &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: "the user does not exist",
}
}
msg := CheckPassword(user, password)
if msg != "" {
return nil, &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: "invalid username or password",
}
}
if user.IsForbidden {
return nil, &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: "the user is forbidden to sign in, please contact the administrator",
}
}
accessToken, refreshToken, err := generateJwtToken(application, user, "", scope, host)
if err != nil {
return nil, &TokenError{
Error: ENDPOINT_ERROR,
Error: EndpointError,
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
}
}
@@ -592,11 +595,12 @@ func GetPasswordToken(application *Application, username string, password string
return token, nil
}
// GetClientCredentialsToken
// Client Credentials flow
func GetClientCredentialsToken(application *Application, clientSecret string, scope string, host string) (*Token, *TokenError) {
if application.ClientSecret != clientSecret {
return nil, &TokenError{
Error: INVALID_CLIENT,
Error: InvalidClient,
ErrorDescription: "client_secret is invalid",
}
}
@@ -608,7 +612,7 @@ func GetClientCredentialsToken(application *Application, clientSecret string, sc
accessToken, _, err := generateJwtToken(application, nullUser, "", scope, host)
if err != nil {
return nil, &TokenError{
Error: ENDPOINT_ERROR,
Error: EndpointError,
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
}
}
@@ -630,6 +634,7 @@ func GetClientCredentialsToken(application *Application, clientSecret string, sc
return token, nil
}
// GetTokenByUser
// Implicit flow
func GetTokenByUser(application *Application, user *User, scope string, host string) (*Token, error) {
accessToken, refreshToken, err := generateJwtToken(application, user, "", scope, host)
@@ -655,12 +660,13 @@ func GetTokenByUser(application *Application, user *User, scope string, host str
return token, nil
}
// GetWechatMiniProgramToken
// Wechat Mini Program flow
func GetWechatMiniProgramToken(application *Application, code string, host string, username string, avatar string) (*Token, *TokenError) {
mpProvider := GetWechatMiniProgramProvider(application)
if mpProvider == nil {
return nil, &TokenError{
Error: INVALID_CLIENT,
Error: InvalidClient,
ErrorDescription: "the application does not support wechat mini program",
}
}
@@ -669,14 +675,14 @@ func GetWechatMiniProgramToken(application *Application, code string, host strin
session, err := mpIdp.GetSessionByCode(code)
if err != nil {
return nil, &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: fmt.Sprintf("get wechat mini program session error: %s", err.Error()),
}
}
openId, unionId := session.Openid, session.Unionid
if openId == "" && unionId == "" {
return nil, &TokenError{
Error: INVALID_REQUEST,
Error: InvalidRequest,
ErrorDescription: "the wechat mini program session is invalid",
}
}
@@ -684,7 +690,7 @@ func GetWechatMiniProgramToken(application *Application, code string, host strin
if user == nil {
if !application.EnableSignUp {
return nil, &TokenError{
Error: INVALID_GRANT,
Error: InvalidGrant,
ErrorDescription: "the application does not allow to sign up new account",
}
}
@@ -703,13 +709,16 @@ func GetWechatMiniProgramToken(application *Application, code string, host strin
Avatar: avatar,
SignupApplication: application.Name,
WeChat: openId,
WeChatUnionId: unionId,
Type: "normal-user",
CreatedTime: util.GetCurrentTime(),
IsAdmin: false,
IsGlobalAdmin: false,
IsForbidden: false,
IsDeleted: false,
Properties: map[string]string{
UserPropertiesWechatOpenId: openId,
UserPropertiesWechatUnionId: unionId,
},
}
AddUser(user)
}
@@ -717,7 +726,7 @@ func GetWechatMiniProgramToken(application *Application, code string, host strin
accessToken, refreshToken, err := generateJwtToken(application, user, "", "", host)
if err != nil {
return nil, &TokenError{
Error: ENDPOINT_ERROR,
Error: EndpointError,
ErrorDescription: fmt.Sprintf("generate jwt token error: %s", err.Error()),
}
}

View File

@@ -136,6 +136,7 @@ func GenerateId() {
panic("unimplemented")
}
// GetCasTokenByPgt
/**
@ret1: whether a token is found
@ret2: token, nil if not found
@@ -150,6 +151,7 @@ func GetCasTokenByPgt(pgt string) (bool, *CasAuthenticationSuccess, string, stri
return false, nil, "", ""
}
// GetCasTokenByTicket
/**
@ret1: whether a token is found
@ret2: token, nil if not found
@@ -207,6 +209,7 @@ func GenerateCasToken(userId string, service string) (string, error) {
}
}
// GetValidationBySaml
/**
@ret1: saml response
@ret2: the service URL who requested to issue this token

View File

@@ -24,6 +24,11 @@ import (
"xorm.io/core"
)
const (
UserPropertiesWechatUnionId = "wechatUnionId"
UserPropertiesWechatOpenId = "wechatOpenId"
)
type User struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"`
@@ -73,32 +78,31 @@ type User struct {
LastSigninTime string `xorm:"varchar(100)" json:"lastSigninTime"`
LastSigninIp string `xorm:"varchar(100)" json:"lastSigninIp"`
GitHub string `xorm:"github varchar(100)" json:"github"`
Google string `xorm:"varchar(100)" json:"google"`
QQ string `xorm:"qq varchar(100)" json:"qq"`
WeChat string `xorm:"wechat varchar(100)" json:"wechat"`
WeChatUnionId string `xorm:"varchar(100)" json:"unionId"`
Facebook string `xorm:"facebook varchar(100)" json:"facebook"`
DingTalk string `xorm:"dingtalk varchar(100)" json:"dingtalk"`
Weibo string `xorm:"weibo varchar(100)" json:"weibo"`
Gitee string `xorm:"gitee varchar(100)" json:"gitee"`
LinkedIn string `xorm:"linkedin varchar(100)" json:"linkedin"`
Wecom string `xorm:"wecom varchar(100)" json:"wecom"`
Lark string `xorm:"lark varchar(100)" json:"lark"`
Gitlab string `xorm:"gitlab varchar(100)" json:"gitlab"`
Adfs string `xorm:"adfs varchar(100)" json:"adfs"`
Baidu string `xorm:"baidu varchar(100)" json:"baidu"`
Alipay string `xorm:"alipay varchar(100)" json:"alipay"`
Casdoor string `xorm:"casdoor varchar(100)" json:"casdoor"`
Infoflow string `xorm:"infoflow varchar(100)" json:"infoflow"`
Apple string `xorm:"apple varchar(100)" json:"apple"`
AzureAD string `xorm:"azuread varchar(100)" json:"azuread"`
Slack string `xorm:"slack varchar(100)" json:"slack"`
Steam string `xorm:"steam varchar(100)" json:"steam"`
Bilibili string `xorm:"bilibili varchar(100)" json:"bilibili"`
Okta string `xorm:"okta varchar(100)" json:"okta"`
Douyin string `xorm:"douyin varchar(100)" json:"douyin"`
Custom string `xorm:"custom varchar(100)" json:"custom"`
GitHub string `xorm:"github varchar(100)" json:"github"`
Google string `xorm:"varchar(100)" json:"google"`
QQ string `xorm:"qq varchar(100)" json:"qq"`
WeChat string `xorm:"wechat varchar(100)" json:"wechat"`
Facebook string `xorm:"facebook varchar(100)" json:"facebook"`
DingTalk string `xorm:"dingtalk varchar(100)" json:"dingtalk"`
Weibo string `xorm:"weibo varchar(100)" json:"weibo"`
Gitee string `xorm:"gitee varchar(100)" json:"gitee"`
LinkedIn string `xorm:"linkedin varchar(100)" json:"linkedin"`
Wecom string `xorm:"wecom varchar(100)" json:"wecom"`
Lark string `xorm:"lark varchar(100)" json:"lark"`
Gitlab string `xorm:"gitlab varchar(100)" json:"gitlab"`
Adfs string `xorm:"adfs varchar(100)" json:"adfs"`
Baidu string `xorm:"baidu varchar(100)" json:"baidu"`
Alipay string `xorm:"alipay varchar(100)" json:"alipay"`
Casdoor string `xorm:"casdoor varchar(100)" json:"casdoor"`
Infoflow string `xorm:"infoflow varchar(100)" json:"infoflow"`
Apple string `xorm:"apple varchar(100)" json:"apple"`
AzureAD string `xorm:"azuread varchar(100)" json:"azuread"`
Slack string `xorm:"slack varchar(100)" json:"slack"`
Steam string `xorm:"steam varchar(100)" json:"steam"`
Bilibili string `xorm:"bilibili varchar(100)" json:"bilibili"`
Okta string `xorm:"okta varchar(100)" json:"okta"`
Douyin string `xorm:"douyin varchar(100)" json:"douyin"`
Custom string `xorm:"custom varchar(100)" json:"custom"`
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
@@ -243,7 +247,7 @@ func getUserByWechatId(wechatOpenId string, wechatUnionId string) *User {
wechatUnionId = wechatOpenId
}
user := &User{}
existed, err := adapter.Engine.Where("wechat = ? OR wechat = ? OR unionid = ?", wechatOpenId, wechatUnionId, wechatUnionId).Get(user)
existed, err := adapter.Engine.Where("wechat = ? OR wechat = ?", wechatOpenId, wechatUnionId).Get(user)
if err != nil {
panic(err)
}

View File

@@ -50,30 +50,31 @@ func GetWebAuthnObject(host string) *webauthn.WebAuthn {
return webAuthn
}
// WebAuthnID
// implementation of webauthn.User interface
func (u *User) WebAuthnID() []byte {
return []byte(u.GetId())
func (user *User) WebAuthnID() []byte {
return []byte(user.GetId())
}
func (u *User) WebAuthnName() string {
return u.Name
func (user *User) WebAuthnName() string {
return user.Name
}
func (u *User) WebAuthnDisplayName() string {
return u.DisplayName
func (user *User) WebAuthnDisplayName() string {
return user.DisplayName
}
func (u *User) WebAuthnCredentials() []webauthn.Credential {
return u.WebauthnCredentials
func (user *User) WebAuthnCredentials() []webauthn.Credential {
return user.WebauthnCredentials
}
func (u *User) WebAuthnIcon() string {
return u.Avatar
func (user *User) WebAuthnIcon() string {
return user.Avatar
}
// CredentialExcludeList returns a CredentialDescriptor array filled with all the user's credentials
func (u *User) CredentialExcludeList() []protocol.CredentialDescriptor {
credentials := u.WebAuthnCredentials()
func (user *User) CredentialExcludeList() []protocol.CredentialDescriptor {
credentials := user.WebAuthnCredentials()
credentialExcludeList := []protocol.CredentialDescriptor{}
for _, cred := range credentials {
descriptor := protocol.CredentialDescriptor{
@@ -86,16 +87,16 @@ func (u *User) CredentialExcludeList() []protocol.CredentialDescriptor {
return credentialExcludeList
}
func (u *User) AddCredentials(credential webauthn.Credential, isGlobalAdmin bool) bool {
u.WebauthnCredentials = append(u.WebauthnCredentials, credential)
return UpdateUser(u.GetId(), u, []string{"webauthnCredentials"}, isGlobalAdmin)
func (user *User) AddCredentials(credential webauthn.Credential, isGlobalAdmin bool) bool {
user.WebauthnCredentials = append(user.WebauthnCredentials, credential)
return UpdateUser(user.GetId(), user, []string{"webauthnCredentials"}, isGlobalAdmin)
}
func (u *User) DeleteCredentials(credentialIdBase64 string) bool {
for i, credential := range u.WebauthnCredentials {
func (user *User) DeleteCredentials(credentialIdBase64 string) bool {
for i, credential := range user.WebauthnCredentials {
if base64.StdEncoding.EncodeToString(credential.ID) == credentialIdBase64 {
u.WebauthnCredentials = append(u.WebauthnCredentials[0:i], u.WebauthnCredentials[i+1:]...)
return UpdateUserForAllFields(u.GetId(), u)
user.WebauthnCredentials = append(user.WebauthnCredentials[0:i], user.WebauthnCredentials[i+1:]...)
return UpdateUserForAllFields(user.GetId(), user)
}
}
return false

View File

@@ -42,7 +42,7 @@ type VerificationRecord struct {
func SendVerificationCodeToEmail(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
if provider == nil {
return fmt.Errorf("Please set an Email provider first")
return fmt.Errorf("please set an Email provider first")
}
sender := organization.DisplayName
@@ -60,7 +60,7 @@ func SendVerificationCodeToEmail(organization *Organization, user *User, provide
func SendVerificationCodeToPhone(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
if provider == nil {
return errors.New("Please set a SMS provider first")
return errors.New("please set a SMS provider first")
}
code := getRandomCode(5)
@@ -85,7 +85,7 @@ func AddToVerificationRecord(user *User, provider *Provider, remoteAddr, recordT
now := time.Now().Unix()
if has && now-record.Time < 60 {
return errors.New("You can only send one code in 60s.")
return errors.New("you can only send one code in 60s")
}
record.Owner = provider.Owner

View File

@@ -20,7 +20,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
@@ -147,7 +146,7 @@ func (pp *GcPaymentProvider) doPost(postBytes []byte) ([]byte, error) {
}
}(resp.Body)
respBytes, err := ioutil.ReadAll(resp.Body)
respBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

View File

@@ -83,6 +83,12 @@ func initAPI() {
beego.Router("/api/add-permission", &controllers.ApiController{}, "POST:AddPermission")
beego.Router("/api/delete-permission", &controllers.ApiController{}, "POST:DeletePermission")
beego.Router("/api/enforce", &controllers.ApiController{}, "POST:Enforce")
beego.Router("/api/batch-enforce", &controllers.ApiController{}, "POST:BatchEnforce")
beego.Router("/api/get-all-objects", &controllers.ApiController{}, "GET:GetAllObjects")
beego.Router("/api/get-all-actions", &controllers.ApiController{}, "GET:GetAllActions")
beego.Router("/api/get-all-roles", &controllers.ApiController{}, "GET:GetAllRoles")
beego.Router("/api/get-models", &controllers.ApiController{}, "GET:GetModels")
beego.Router("/api/get-model", &controllers.ApiController{}, "GET:GetModel")
beego.Router("/api/update-model", &controllers.ApiController{}, "POST:UpdateModel")

View File

@@ -20,7 +20,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"time"
@@ -168,7 +168,7 @@ func GetMinLenStr(strs ...string) string {
}
func ReadStringFromPath(path string) string {
data, err := ioutil.ReadFile(path)
data, err := os.ReadFile(path)
if err != nil {
panic(err)
}
@@ -177,7 +177,7 @@ func ReadStringFromPath(path string) string {
}
func WriteStringToPath(s string, path string) {
err := ioutil.WriteFile(path, []byte(s), 0o644)
err := os.WriteFile(path, []byte(s), 0o644)
if err != nil {
panic(err)
}

View File

@@ -1 +0,0 @@
PUBLIC_URL=.

View File

@@ -42,7 +42,13 @@
"space-before-function-paren": ["error", "never"],
"no-trailing-spaces": ["error", { "ignoreComments": true }],
"eol-last": ["error", "always"],
// "no-var": ["error"],
"no-var": ["error"],
"prefer-const": [
"error",
{
"destructuring": "all"
}
],
"curly": ["error", "all"],
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
"no-mixed-spaces-and-tabs": "error",
@@ -89,7 +95,7 @@
// don't use strict mod now, otherwise there are a lot of errors in the codebase
"no-unused-vars": "off",
"react/no-deprecated": "warn",
"no-case-declarations": "warn",
"no-case-declarations": "off",
"react/jsx-key": "warn"
}
}

View File

@@ -63,6 +63,18 @@
"devDependencies": {
"cross-env": "^7.0.3",
"eslint": "^7.11.0",
"eslint-plugin-react": "^7.30.1"
"eslint-plugin-react": "^7.30.1",
"husky": "^4.3.8",
"lint-staged": "^13.0.3"
},
"lint-staged": {
"src/**/*.{js,jsx,css,sass,ts,tsx}": [
"yarn fix"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}
}

View File

@@ -38,7 +38,7 @@ class AccountTable extends React.Component {
}
addRow(table) {
let row = {name: Setting.getNewRowNameForTable(table, "Please select an account item"), visible: true, viewRule: "Public", modifyRule: "Self"};
const row = {name: Setting.getNewRowNameForTable(table, "Please select an account item"), visible: true, viewRule: "Public", modifyRule: "Self"};
if (table === undefined) {
table = [];
}
@@ -141,7 +141,7 @@ class AccountTable extends React.Component {
return null;
}
let options = [
const options = [
{id: "Public", name: "Public"},
{id: "Self", name: "Self"},
{id: "Admin", name: "Admin"},

View File

@@ -182,7 +182,7 @@ class App extends Component {
}
setLanguage(account) {
let language = account?.language;
const language = account?.language;
if (language !== "" && language !== i18next.language) {
Setting.setLanguage(language);
}
@@ -242,7 +242,7 @@ class App extends Component {
});
Setting.showMessage("success", "Logged out successfully");
let redirectUri = res.data2;
const redirectUri = res.data2;
if (redirectUri !== null && redirectUri !== undefined && redirectUri !== "") {
Setting.goToLink(redirectUri);
} else if (owner !== "built-in") {
@@ -322,7 +322,7 @@ class App extends Component {
}
renderAccount() {
let res = [];
const res = [];
if (this.state.account === undefined) {
return null;
@@ -349,7 +349,7 @@ class App extends Component {
}
renderMenu() {
let res = [];
const res = [];
if (this.state.account === null || this.state.account === undefined) {
return [];
@@ -669,26 +669,28 @@ class App extends Component {
if (this.isDoorPages()) {
return (
<div style={{position: "relative", minHeight: "100vh"}}>
<Switch>
<Route exact path="/signup" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} />)} />
<Route exact path="/signup/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />)} />
<Route exact path="/login" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage account={this.state.account} {...props} />)} />
<Route exact path="/login/:owner" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage account={this.state.account} {...props} />)} />
<Route exact path="/auto-signup/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signup"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
<Route exact path="/signup/oauth/authorize" render={(props) => <SignupPage account={this.state.account} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
<Route exact path="/login/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
<Route exact path="/login/saml/authorize/:owner/:applicationName" render={(props) => <LoginPage account={this.state.account} type={"saml"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
<Route exact path="/cas/:owner/:casApplicationName/logout" render={(props) => this.renderHomeIfLoggedIn(<CasLogout clearAccount={() => this.setState({account: null})} {...props} />)} />
<Route exact path="/cas/:owner/:casApplicationName/login" render={(props) => {return (<LoginPage type={"cas"} mode={"signup"} account={this.state.account} {...props} />);}} />
<Route exact path="/callback" component={AuthCallback} />
<Route exact path="/callback/saml" component={SamlCallback} />
<Route exact path="/forget" render={(props) => this.renderHomeIfLoggedIn(<SelfForgetPage {...props} />)} />
<Route exact path="/forget/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<ForgetPage {...props} />)} />
<Route exact path="/prompt" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage account={this.state.account} {...props} />)} />
<Route exact path="/prompt/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage account={this.state.account} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} {...props} />)} />
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
</Switch>
<div id="content-wrap" style={{flexDirection: "column"}}>
<Switch>
<Route exact path="/signup" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} />)} />
<Route exact path="/signup/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />)} />
<Route exact path="/login" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage account={this.state.account} {...props} />)} />
<Route exact path="/login/:owner" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage account={this.state.account} {...props} />)} />
<Route exact path="/auto-signup/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signup"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
<Route exact path="/signup/oauth/authorize" render={(props) => <SignupPage account={this.state.account} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
<Route exact path="/login/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
<Route exact path="/login/saml/authorize/:owner/:applicationName" render={(props) => <LoginPage account={this.state.account} type={"saml"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
<Route exact path="/cas/:owner/:casApplicationName/logout" render={(props) => this.renderHomeIfLoggedIn(<CasLogout clearAccount={() => this.setState({account: null})} {...props} />)} />
<Route exact path="/cas/:owner/:casApplicationName/login" render={(props) => {return (<LoginPage type={"cas"} mode={"signup"} account={this.state.account} {...props} />);}} />
<Route exact path="/callback" component={AuthCallback} />
<Route exact path="/callback/saml" component={SamlCallback} />
<Route exact path="/forget" render={(props) => this.renderHomeIfLoggedIn(<SelfForgetPage {...props} />)} />
<Route exact path="/forget/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<ForgetPage {...props} />)} />
<Route exact path="/prompt" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage account={this.state.account} {...props} />)} />
<Route exact path="/prompt/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage account={this.state.account} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} {...props} />)} />
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
</Switch>
</div>
{
this.renderFooter()
}

View File

@@ -120,7 +120,7 @@ class ApplicationEditPage extends React.Component {
updateApplicationField(key, value) {
value = this.parseApplicationField(key, value);
let application = this.state.application;
const application = this.state.application;
application[key] = value;
this.setState({
application: application,
@@ -566,8 +566,8 @@ class ApplicationEditPage extends React.Component {
renderSignupSigninPreview() {
let signUpUrl = `/signup/${this.state.application.name}`;
let signInUrl = `/login/oauth/authorize?client_id=${this.state.application.clientId}&response_type=code&redirect_uri=${this.state.application.redirectUris[0]}&scope=read&state=casdoor`;
let maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "100%", width: "100%", background: "rgba(0,0,0,0.4)"};
const signInUrl = `/login/oauth/authorize?client_id=${this.state.application.clientId}&response_type=code&redirect_uri=${this.state.application.redirectUris[0]}&scope=read&state=casdoor`;
const maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "100%", width: "100%", background: "rgba(0,0,0,0.4)"};
if (!this.state.application.enablePassword) {
signUpUrl = signInUrl.replace("/login/oauth/authorize", "/signup/oauth/authorize");
}
@@ -613,8 +613,8 @@ class ApplicationEditPage extends React.Component {
}
renderPromptPreview() {
let promptUrl = `/prompt/${this.state.application.name}`;
let maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "100%", width: "100%", background: "rgba(0,0,0,0.4)"};
const promptUrl = `/prompt/${this.state.application.name}`;
const maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "100%", width: "100%", background: "rgba(0,0,0,0.4)"};
return (
<Col span={11}>
<Button style={{marginBottom: "10px"}} type="primary" shape="round" icon={<CopyOutlined />} onClick={() => {
@@ -634,7 +634,7 @@ class ApplicationEditPage extends React.Component {
}
submitApplicationEdit(willExist) {
let application = Setting.deepCopy(this.state.application);
const application = Setting.deepCopy(this.state.application);
ApplicationBackend.updateApplication(this.state.application.owner, this.state.applicationName, application)
.then((res) => {
if (res.msg === "") {

View File

@@ -250,8 +250,8 @@ class ApplicationListPage extends BaseListPage {
}
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const field = params.searchedColumn, value = params.searchText;
const sortField = params.sortField, sortOrder = params.sortOrder;
this.setState({loading: true});
ApplicationBackend.getApplications("admin", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
.then((res) => {

View File

@@ -57,7 +57,7 @@ class CertEditPage extends React.Component {
updateCertField(key, value) {
value = this.parseCertField(key, value);
let cert = this.state.cert;
const cert = this.state.cert;
cert[key] = value;
this.setState({
cert: cert,
@@ -214,7 +214,7 @@ class CertEditPage extends React.Component {
}
submitCertEdit(willExist) {
let cert = Setting.deepCopy(this.state.cert);
const cert = Setting.deepCopy(this.state.cert);
CertBackend.updateCert(this.state.cert.owner, this.state.certName, cert)
.then((res) => {
if (res.msg === "") {

View File

@@ -198,7 +198,7 @@ class CertListPage extends BaseListPage {
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (params.category !== undefined && params.category !== null) {
field = "category";
value = params.category;

View File

@@ -103,7 +103,7 @@ export const CropperDiv = (props) => {
onCancel={handleCancel}
width={600}
footer={
[<Button block type="primary" onClick={handleOk}>{i18next.t("user:Set new profile picture")}</Button>]
[<Button block key="submit" type="primary" onClick={handleOk}>{i18next.t("user:Set new profile picture")}</Button>]
}
>
<Col style={{margin: "0px auto 40px auto", width: 1000, height: 300}}>

View File

@@ -35,7 +35,7 @@ class LdapSyncPage extends React.Component {
}
syncUsers() {
let selectedUsers = this.state.selectedUsers;
const selectedUsers = this.state.selectedUsers;
if (selectedUsers === null || selectedUsers.length === 0) {
Setting.showMessage("error", "Please select al least 1 user first");
return;
@@ -44,10 +44,10 @@ class LdapSyncPage extends React.Component {
LdapBackend.syncUsers(this.state.ldap.owner, this.state.ldap.id, selectedUsers)
.then((res => {
if (res.status === "ok") {
let exist = res.data.exist;
let failed = res.data.failed;
let existUser = [];
let failedUser = [];
const exist = res.data.exist;
const failed = res.data.failed;
const existUser = [];
const failedUser = [];
if ((!exist || exist.length === 0) && (!failed || failed.length === 0)) {
Setting.goToLink(`/organizations/${this.state.ldap.owner}/users`);
@@ -103,7 +103,7 @@ class LdapSyncPage extends React.Component {
}
getExistUsers(owner, users) {
let uuidArray = [];
const uuidArray = [];
users.forEach(elem => {
uuidArray.push(elem.uuid);
});
@@ -119,11 +119,11 @@ class LdapSyncPage extends React.Component {
}
buildValArray(data, key) {
let valTypesArray = [];
const valTypesArray = [];
if (data !== null && data.length > 0) {
data.forEach(elem => {
let val = elem[key];
const val = elem[key];
if (!valTypesArray.includes(val)) {
valTypesArray.push(val);
}
@@ -133,10 +133,10 @@ class LdapSyncPage extends React.Component {
}
buildFilter(data, key) {
let filterArray = [];
const filterArray = [];
if (data !== null && data.length > 0) {
let valArray = this.buildValArray(data, key);
const valArray = this.buildValArray(data, key);
valArray.forEach(elem => {
filterArray.push({
text: elem,

View File

@@ -81,7 +81,7 @@ class ModelEditPage extends React.Component {
updateModelField(key, value) {
value = this.parseModelField(key, value);
let model = this.state.model;
const model = this.state.model;
model[key] = value;
this.setState({
model: model,
@@ -155,7 +155,7 @@ class ModelEditPage extends React.Component {
}
submitModelEdit(willExist) {
let model = Setting.deepCopy(this.state.model);
const model = Setting.deepCopy(this.state.model);
ModelBackend.updateModel(this.state.organizationName, this.state.modelName, model)
.then((res) => {
if (res.msg === "") {

View File

@@ -174,7 +174,7 @@ class ModelListPage extends BaseListPage {
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (params.type !== undefined && params.type !== null) {
field = "type";
value = params.type;

View File

@@ -75,7 +75,7 @@ class OrganizationEditPage extends React.Component {
updateOrganizationField(key, value) {
value = this.parseOrganizationField(key, value);
let organization = this.state.organization;
const organization = this.state.organization;
organization[key] = value;
this.setState({
organization: organization,
@@ -283,7 +283,7 @@ class OrganizationEditPage extends React.Component {
}
submitOrganizationEdit(willExist) {
let organization = Setting.deepCopy(this.state.organization);
const organization = Setting.deepCopy(this.state.organization);
OrganizationBackend.updateOrganization(this.state.organization.owner, this.state.organizationName, organization)
.then((res) => {
if (res.msg === "") {

View File

@@ -266,7 +266,7 @@ class OrganizationListPage extends BaseListPage {
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (params.passwordType !== undefined && params.passwordType !== null) {
field = "passwordType";
value = params.passwordType;

View File

@@ -54,7 +54,7 @@ export const PasswordModal = (props) => {
});
};
let hasOldPassword = user.password !== "";
const hasOldPassword = user.password !== "";
return (
<Row>

View File

@@ -60,7 +60,7 @@ class PaymentEditPage extends React.Component {
updatePaymentField(key, value) {
value = this.parsePaymentField(key, value);
let payment = this.state.payment;
const payment = this.state.payment;
payment[key] = value;
this.setState({
payment: payment,
@@ -440,7 +440,7 @@ class PaymentEditPage extends React.Component {
return;
}
let payment = Setting.deepCopy(this.state.payment);
const payment = Setting.deepCopy(this.state.payment);
PaymentBackend.updatePayment(this.state.payment.owner, this.state.paymentName, payment)
.then((res) => {
if (res.msg === "") {

View File

@@ -250,7 +250,7 @@ class PaymentListPage extends BaseListPage {
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (params.type !== undefined && params.type !== null) {
field = "type";
value = params.type;

View File

@@ -83,7 +83,7 @@ class PaymentResultPage extends React.Component {
title={`${i18next.t("payment:The payment is still under processing")}: ${payment.productDisplayName}, ${i18next.t("payment:the current state is")}: ${payment.state}, ${i18next.t("payment:please wait for a few seconds...")}`}
subTitle={i18next.t("payment:Please click the below button to return to the original website")}
extra={[
<Spin size="large" tip={i18next.t("payment:Processing...")} />,
<Spin key="returnUrl" size="large" tip={i18next.t("payment:Processing...")} />,
]}
/>
</div>

View File

@@ -116,7 +116,7 @@ class PermissionEditPage extends React.Component {
updatePermissionField(key, value) {
value = this.parsePermissionField(key, value);
let permission = this.state.permission;
const permission = this.state.permission;
permission[key] = value;
this.setState({
permission: permission,
@@ -288,7 +288,7 @@ class PermissionEditPage extends React.Component {
}
submitPermissionEdit(willExist) {
let permission = Setting.deepCopy(this.state.permission);
const permission = Setting.deepCopy(this.state.permission);
PermissionBackend.updatePermission(this.state.organizationName, this.state.permissionName, permission)
.then((res) => {
if (res.msg === "") {

View File

@@ -243,7 +243,7 @@ class PermissionListPage extends BaseListPage {
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (params.type !== undefined && params.type !== null) {
field = "type";
value = params.type;

View File

@@ -69,7 +69,7 @@ class ProductEditPage extends React.Component {
updateProductField(key, value) {
value = this.parseProductField(key, value);
let product = this.state.product;
const product = this.state.product;
product[key] = value;
this.setState({
product: product,
@@ -252,7 +252,7 @@ class ProductEditPage extends React.Component {
}
renderPreview() {
let buyUrl = `/products/${this.state.product.name}/buy`;
const buyUrl = `/products/${this.state.product.name}/buy`;
return (
<Col span={22} style={{display: "flex", flexDirection: "column"}}>
<a style={{marginBottom: "10px", display: "flex"}} target="_blank" rel="noreferrer" href={buyUrl}>
@@ -268,7 +268,7 @@ class ProductEditPage extends React.Component {
}
submitProductEdit(willExist) {
let product = Setting.deepCopy(this.state.product);
const product = Setting.deepCopy(this.state.product);
ProductBackend.updateProduct(this.state.product.owner, this.state.productName, product)
.then((res) => {
if (res.msg === "") {

View File

@@ -269,7 +269,7 @@ class ProductListPage extends BaseListPage {
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (params.type !== undefined && params.type !== null) {
field = "type";
value = params.type;

View File

@@ -61,7 +61,7 @@ class ProviderEditPage extends React.Component {
updateProviderField(key, value) {
value = this.parseProviderField(key, value);
let provider = this.state.provider;
const provider = this.state.provider;
provider[key] = value;
this.setState({
provider: provider,
@@ -148,11 +148,11 @@ class ProviderEditPage extends React.Component {
}
loadSamlConfiguration() {
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(this.state.provider.metadata, "text/xml");
var cert = xmlDoc.getElementsByTagName("ds:X509Certificate")[0].childNodes[0].nodeValue;
var endpoint = xmlDoc.getElementsByTagName("md:SingleSignOnService")[0].getAttribute("Location");
var issuerUrl = xmlDoc.getElementsByTagName("md:EntityDescriptor")[0].getAttribute("entityID");
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(this.state.provider.metadata, "text/xml");
const cert = xmlDoc.getElementsByTagName("ds:X509Certificate")[0].childNodes[0].nodeValue;
const endpoint = xmlDoc.getElementsByTagName("md:SingleSignOnService")[0].getAttribute("Location");
const issuerUrl = xmlDoc.getElementsByTagName("md:EntityDescriptor")[0].getAttribute("entityID");
this.updateProviderField("idP", cert);
this.updateProviderField("endpoint", endpoint);
this.updateProviderField("issuerUrl", issuerUrl);
@@ -199,6 +199,7 @@ class ProviderEditPage extends React.Component {
this.updateProviderField("type", "GitHub");
} else if (value === "Email") {
this.updateProviderField("type", "Default");
this.updateProviderField("disableSsl", false);
this.updateProviderField("title", "Casdoor Verification Code");
this.updateProviderField("content", "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes.");
} else if (value === "SMS") {
@@ -510,6 +511,16 @@ class ProviderEditPage extends React.Component {
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:Disable SSL"), i18next.t("provider:Disable SSL - Tooltip"))} :
</Col>
<Col span={1} >
<Switch checked={this.state.provider.disableSsl} onChange={checked => {
this.updateProviderField("disableSsl", checked);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:Email Title"), i18next.t("provider:Email Title - Tooltip"))} :
@@ -717,7 +728,7 @@ class ProviderEditPage extends React.Component {
}
submitProviderEdit(willExist) {
let provider = Setting.deepCopy(this.state.provider);
const provider = Setting.deepCopy(this.state.provider);
ProviderBackend.updateProvider(this.state.provider.owner, this.state.providerName, provider)
.then((res) => {
if (res.msg === "") {

View File

@@ -215,7 +215,7 @@ class ProviderListPage extends BaseListPage {
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (params.category !== undefined && params.category !== null) {
field = "category";
value = params.category;

View File

@@ -39,7 +39,7 @@ class ProviderTable extends React.Component {
}
addRow(table) {
let row = {name: Setting.getNewRowNameForTable(table, "Please select a provider"), canSignUp: true, canSignIn: true, canUnlink: true, alertType: "None"};
const row = {name: Setting.getNewRowNameForTable(table, "Please select a provider"), canSignUp: true, canSignIn: true, canUnlink: true, alertType: "None"};
if (table === undefined) {
table = [];
}

View File

@@ -199,7 +199,7 @@ class RecordListPage extends BaseListPage {
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (params.method !== undefined && params.method !== null) {
field = "method";
value = params.method;

View File

@@ -291,8 +291,8 @@ class ResourceListPage extends BaseListPage {
}
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const field = params.searchedColumn, value = params.searchText;
const sortField = params.sortField, sortOrder = params.sortOrder;
this.setState({loading: true});
ResourceBackend.getResources(this.props.account.owner, this.props.account.name, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
.then((res) => {

View File

@@ -91,7 +91,7 @@ class RoleEditPage extends React.Component {
updateRoleField(key, value) {
value = this.parseRoleField(key, value);
let role = this.state.role;
const role = this.state.role;
role[key] = value;
this.setState({
role: role,
@@ -179,7 +179,7 @@ class RoleEditPage extends React.Component {
}
submitRoleEdit(willExist) {
let role = Setting.deepCopy(this.state.role);
const role = Setting.deepCopy(this.state.role);
RoleBackend.updateRole(this.state.organizationName, this.state.roleName, role)
.then((res) => {
if (res.msg === "") {

View File

@@ -194,7 +194,7 @@ class RoleListPage extends BaseListPage {
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (params.type !== undefined && params.type !== null) {
field = "type";
value = params.type;

View File

@@ -23,7 +23,7 @@ import {authConfig} from "./auth/Auth";
import {Helmet} from "react-helmet";
import * as Conf from "./Conf";
export let ServerUrl = "";
export const ServerUrl = "";
// export const StaticBaseUrl = "https://cdn.jsdelivr.net/gh/casbin/static";
export const StaticBaseUrl = "https://cdn.casbin.org";
@@ -136,11 +136,11 @@ export function getCountryRegionData() {
language = Conf.DefaultLanguage;
}
var countries = require("i18n-iso-countries");
const countries = require("i18n-iso-countries");
countries.registerLocale(require("i18n-iso-countries/langs/" + language + ".json"));
var data = countries.getNames(language, {select: "official"});
var result = [];
for (var i in data) {result.push({code: i, name: data[i]});}
const data = countries.getNames(language, {select: "official"});
const result = [];
for (const i in data) {result.push({code: i, name: data[i]});}
return result;
}
@@ -335,7 +335,7 @@ export function openLink(link) {
export function openLinkSafe(link) {
// Javascript window.open issue in safari
// https://stackoverflow.com/questions/45569893/javascript-window-open-issue-in-safari
let a = document.createElement("a");
const a = document.createElement("a");
a.href = link;
a.setAttribute("target", "_blank");
a.click();
@@ -445,9 +445,9 @@ export function getFriendlyFileSize(size) {
return size + " B";
}
let i = Math.floor(Math.log(size) / Math.log(1024));
const i = Math.floor(Math.log(size) / Math.log(1024));
let num = (size / Math.pow(1024, i));
let round = Math.round(num);
const round = Math.round(num);
num = round < 10 ? num.toFixed(2) : round < 100 ? num.toFixed(1) : round;
return `${num} ${"KMGTPEZY"[i - 1]}B`;
}
@@ -456,7 +456,7 @@ function getRandomInt(s) {
let hash = 0;
if (s.length !== 0) {
for (let i = 0; i < s.length; i++) {
let char = s.charCodeAt(i);
const char = s.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
@@ -772,7 +772,7 @@ export function getMaskedEmail(email) {
username = maskString(username);
const domain = tokens[1];
let domainTokens = domain.split(".");
const domainTokens = domain.split(".");
domainTokens[domainTokens.length - 2] = maskString(domainTokens[domainTokens.length - 2]);
return `${username}@${domainTokens.join(".")}`;
@@ -802,7 +802,7 @@ export function getTagColor(s) {
}
export function getTags(tags) {
let res = [];
const res = [];
if (!tags) {return res;}
tags.forEach((tag, i) => {
res.push(
@@ -840,7 +840,7 @@ export function getFromLink() {
export function scrollToDiv(divId) {
if (divId) {
let ele = document.getElementById(divId);
const ele = document.getElementById(divId);
if (ele) {
ele.scrollIntoView({behavior: "smooth"});
}

View File

@@ -38,7 +38,7 @@ class SignupTable extends React.Component {
}
addRow(table) {
let row = {name: Setting.getNewRowNameForTable(table, "Please select a signup item"), visible: true, required: true, rule: "None"};
const row = {name: Setting.getNewRowNameForTable(table, "Please select a signup item"), visible: true, required: true, rule: "None"};
if (table === undefined) {
table = [];
}

View File

@@ -73,7 +73,7 @@ class SyncerEditPage extends React.Component {
updateSyncerField(key, value) {
value = this.parseSyncerField(key, value);
let syncer = this.state.syncer;
const syncer = this.state.syncer;
syncer[key] = value;
this.setState({
syncer: syncer,
@@ -119,7 +119,7 @@ class SyncerEditPage extends React.Component {
<Col span={22} >
<Select virtual={false} style={{width: "100%"}} value={this.state.syncer.type} onChange={(value => {
this.updateSyncerField("type", value);
let syncer = this.state.syncer;
const syncer = this.state.syncer;
syncer["tableColumns"] = Setting.getSyncerTableColumns(this.state.syncer);
syncer.table = (value === "Keycloak") ? "user_entity" : this.state.syncer.table;
this.setState({
@@ -295,7 +295,7 @@ class SyncerEditPage extends React.Component {
}
submitSyncerEdit(willExist) {
let syncer = Setting.deepCopy(this.state.syncer);
const syncer = Setting.deepCopy(this.state.syncer);
SyncerBackend.updateSyncer(this.state.syncer.owner, this.state.syncerName, syncer)
.then((res) => {
if (res.msg === "") {

View File

@@ -262,7 +262,7 @@ class SyncerListPage extends BaseListPage {
fetch = (params = {}) => {
let field = params.searchedColumn, value = params.searchText;
let sortField = params.sortField, sortOrder = params.sortOrder;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (params.type !== undefined && params.type !== null) {
field = "type";
value = params.type;

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