mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-17 21:24:53 +08:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
aab6a799fe | ||
![]() |
b94d06fb07 | ||
![]() |
f9cc6ed064 | ||
![]() |
4cc9137637 | ||
![]() |
d145ab780c | ||
![]() |
687830697e | ||
![]() |
111d1a5786 | ||
![]() |
775dd9eb57 |
@@ -20,6 +20,7 @@ staticBaseUrl = "https://cdn.casbin.org"
|
||||
isDemoMode = false
|
||||
batchSize = 100
|
||||
ldapServerPort = 389
|
||||
radiusServerPort = 1812
|
||||
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
||||
logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
|
||||
initDataFile = "./init_data.json"
|
@@ -615,11 +615,16 @@ func (c *ApiController) Login() {
|
||||
return
|
||||
}
|
||||
|
||||
userId := userInfo.Id
|
||||
if userId == "" {
|
||||
userId = util.GenerateId()
|
||||
}
|
||||
|
||||
user = &object.User{
|
||||
Owner: application.Organization,
|
||||
Name: userInfo.Username,
|
||||
CreatedTime: util.GetCurrentTime(),
|
||||
Id: util.GenerateId(),
|
||||
Id: userId,
|
||||
Type: "normal-user",
|
||||
DisplayName: userInfo.DisplayName,
|
||||
Avatar: userInfo.AvatarUrl,
|
||||
|
@@ -123,7 +123,9 @@ func (a *AzureACSEmailProvider) sendEmail(e *Email) error {
|
||||
|
||||
bodyBuffer := bytes.NewBuffer(postBody)
|
||||
|
||||
req, err := http.NewRequest("POST", a.Endpoint+sendEmailEndpoint+"?api-version="+apiVersion, bodyBuffer)
|
||||
endpoint := strings.TrimSuffix(a.Endpoint, "/")
|
||||
url := fmt.Sprintf("%s/emails:send?api-version=2023-03-31", endpoint)
|
||||
req, err := http.NewRequest("POST", url, bodyBuffer)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating AzureACS API request: %s", err)
|
||||
}
|
||||
@@ -149,7 +151,7 @@ func (a *AzureACSEmailProvider) sendEmail(e *Email) error {
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Response error Handling
|
||||
if resp.StatusCode == http.StatusBadRequest {
|
||||
if resp.StatusCode == http.StatusBadRequest || resp.StatusCode == http.StatusUnauthorized {
|
||||
commError := ErrorResponse{}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&commError)
|
||||
|
@@ -18,9 +18,9 @@ type EmailProvider interface {
|
||||
Send(fromAddress string, fromName, toAddress string, subject string, content string) error
|
||||
}
|
||||
|
||||
func GetEmailProvider(typ string, clientId string, clientSecret string, appId string, host string, port int, disableSsl bool) EmailProvider {
|
||||
func GetEmailProvider(typ string, clientId string, clientSecret string, host string, port int, disableSsl bool) EmailProvider {
|
||||
if typ == "Azure ACS" {
|
||||
return NewAzureACSEmailProvider(appId, host)
|
||||
return NewAzureACSEmailProvider(clientSecret, host)
|
||||
} else {
|
||||
return NewSmtpEmailProvider(clientId, clientSecret, host, port, typ, disableSsl)
|
||||
}
|
||||
|
1
go.mod
1
go.mod
@@ -66,6 +66,7 @@ require (
|
||||
google.golang.org/api v0.138.0
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0
|
||||
layeh.com/radius v0.0.0-20221205141417-e7fbddd11d68 // indirect
|
||||
maunium.net/go/mautrix v0.16.0
|
||||
modernc.org/sqlite v1.18.2
|
||||
)
|
||||
|
3
go.sum
3
go.sum
@@ -1912,6 +1912,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
@@ -2768,6 +2769,8 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
||||
layeh.com/radius v0.0.0-20221205141417-e7fbddd11d68 h1:2NDro2Jzkrqfngy/sA5GVnChs7fx8EzcQKFi/lI2cfg=
|
||||
layeh.com/radius v0.0.0-20221205141417-e7fbddd11d68/go.mod h1:pFWM9De99EY9TPVyHIyA56QmoRViVck/x41WFkUlc9A=
|
||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
|
2
main.go
2
main.go
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/casdoor/casdoor/ldap"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/proxy"
|
||||
"github.com/casdoor/casdoor/radius"
|
||||
"github.com/casdoor/casdoor/routers"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
@@ -81,6 +82,7 @@ func main() {
|
||||
logs.SetLogFuncCall(false)
|
||||
|
||||
go ldap.StartLdapServer()
|
||||
go radius.StartRadiusServer()
|
||||
go object.ClearThroughputPerSecond()
|
||||
|
||||
beego.Run(fmt.Sprintf(":%v", port))
|
||||
|
@@ -21,7 +21,7 @@ import (
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
func NewMatrixProvider(userId string, roomId string, accessToken string, homeServer string) (*notify.Notify, error) {
|
||||
func NewMatrixProvider(userId string, accessToken string, roomId string, homeServer string) (*notify.Notify, error) {
|
||||
matrixSrv, err := matrix.New(id.UserID(userId), id.RoomID(roomId), homeServer, accessToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -18,27 +18,27 @@ import "github.com/casdoor/notify"
|
||||
|
||||
func GetNotificationProvider(typ string, clientId string, clientSecret string, clientId2 string, clientSecret2 string, appId string, receiver string, method string, title string, metaData string) (notify.Notifier, error) {
|
||||
if typ == "Telegram" {
|
||||
return NewTelegramProvider(appId, receiver)
|
||||
return NewTelegramProvider(clientSecret, receiver)
|
||||
} else if typ == "Custom HTTP" {
|
||||
return NewCustomHttpProvider(receiver, method, title)
|
||||
} else if typ == "DingTalk" {
|
||||
return NewDingTalkProvider(appId, receiver)
|
||||
return NewDingTalkProvider(clientId, clientSecret)
|
||||
} else if typ == "Lark" {
|
||||
return NewLarkProvider(receiver)
|
||||
return NewLarkProvider(clientSecret)
|
||||
} else if typ == "Microsoft Teams" {
|
||||
return NewMicrosoftTeamsProvider(receiver)
|
||||
return NewMicrosoftTeamsProvider(clientSecret)
|
||||
} else if typ == "Bark" {
|
||||
return NewBarkProvider(receiver)
|
||||
return NewBarkProvider(clientSecret)
|
||||
} else if typ == "Pushover" {
|
||||
return NewPushoverProvider(appId, receiver)
|
||||
return NewPushoverProvider(clientSecret, receiver)
|
||||
} else if typ == "Pushbullet" {
|
||||
return NewPushbulletProvider(appId, receiver)
|
||||
return NewPushbulletProvider(clientSecret, receiver)
|
||||
} else if typ == "Slack" {
|
||||
return NewSlackProvider(appId, receiver)
|
||||
return NewSlackProvider(clientSecret, receiver)
|
||||
} else if typ == "Webpush" {
|
||||
return NewWebpushProvider(clientId, clientSecret, receiver)
|
||||
} else if typ == "Discord" {
|
||||
return NewDiscordProvider(appId, receiver)
|
||||
return NewDiscordProvider(clientSecret, receiver)
|
||||
} else if typ == "Google Chat" {
|
||||
return NewGoogleChatProvider(metaData)
|
||||
} else if typ == "Line" {
|
||||
|
@@ -36,7 +36,7 @@ func getDialer(provider *Provider) *gomail.Dialer {
|
||||
}
|
||||
|
||||
func SendEmail(provider *Provider, title string, content string, dest string, sender string) error {
|
||||
emailProvider := email.GetEmailProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.AppId, provider.Host, provider.Port, provider.DisableSsl)
|
||||
emailProvider := email.GetEmailProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, provider.Port, provider.DisableSsl)
|
||||
|
||||
fromAddress := provider.ClientId2
|
||||
if fromAddress == "" {
|
||||
|
@@ -226,7 +226,7 @@ func GetGroupUserCount(groupId string, field, value string) (int64, error) {
|
||||
} else {
|
||||
return ormer.Engine.Table("user").
|
||||
Where("owner = ?", owner).In("name", names).
|
||||
And(fmt.Sprintf("user.%s LIKE ?", util.CamelToSnakeCase(field)), "%"+value+"%").
|
||||
And(fmt.Sprintf("user.%s like ?", util.CamelToSnakeCase(field)), "%"+value+"%").
|
||||
Count()
|
||||
}
|
||||
}
|
||||
@@ -247,7 +247,7 @@ func GetPaginationGroupUsers(groupId string, offset, limit int, field, value, so
|
||||
}
|
||||
|
||||
if field != "" && value != "" {
|
||||
session = session.And(fmt.Sprintf("user.%s LIKE ?", util.CamelToSnakeCase(field)), "%"+value+"%")
|
||||
session = session.And(fmt.Sprintf("user.%s like ?", util.CamelToSnakeCase(field)), "%"+value+"%")
|
||||
}
|
||||
|
||||
if sortField == "" || sortOrder == "" {
|
||||
|
@@ -258,9 +258,59 @@ func DeletePermission(permission *Permission) (bool, error) {
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error) {
|
||||
func getPermissionsByUser(userId string) ([]*Permission, error) {
|
||||
permissions := []*Permission{}
|
||||
err := ormer.Engine.Where("users like ?", "%"+userId+"\"%").Find(&permissions)
|
||||
if err != nil {
|
||||
return permissions, err
|
||||
}
|
||||
|
||||
res := []*Permission{}
|
||||
for _, permission := range permissions {
|
||||
if util.InSlice(permission.Users, userId) {
|
||||
res = append(res, permission)
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func GetPermissionsByRole(roleId string) ([]*Permission, error) {
|
||||
permissions := []*Permission{}
|
||||
err := ormer.Engine.Where("roles like ?", "%"+roleId+"\"%").Find(&permissions)
|
||||
if err != nil {
|
||||
return permissions, err
|
||||
}
|
||||
|
||||
res := []*Permission{}
|
||||
for _, permission := range permissions {
|
||||
if util.InSlice(permission.Roles, roleId) {
|
||||
res = append(res, permission)
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func GetPermissionsByResource(resourceId string) ([]*Permission, error) {
|
||||
permissions := []*Permission{}
|
||||
err := ormer.Engine.Where("resources like ?", "%"+resourceId+"\"%").Find(&permissions)
|
||||
if err != nil {
|
||||
return permissions, err
|
||||
}
|
||||
|
||||
res := []*Permission{}
|
||||
for _, permission := range permissions {
|
||||
if util.InSlice(permission.Resources, resourceId) {
|
||||
res = append(res, permission)
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func getPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error) {
|
||||
permissions, err := getPermissionsByUser(userId)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -277,14 +327,13 @@ func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error)
|
||||
|
||||
permFromRoles := []*Permission{}
|
||||
|
||||
roles, err := GetRolesByUser(userId)
|
||||
roles, err := getRolesByUser(userId)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for _, role := range roles {
|
||||
perms := []*Permission{}
|
||||
err := ormer.Engine.Where("roles like ?", "%"+role.GetId()+"\"%").Find(&perms)
|
||||
perms, err := GetPermissionsByRole(role.GetId())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -302,26 +351,6 @@ func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error)
|
||||
return permissions, roles, nil
|
||||
}
|
||||
|
||||
func GetPermissionsByRole(roleId string) ([]*Permission, error) {
|
||||
permissions := []*Permission{}
|
||||
err := ormer.Engine.Where("roles like ?", "%"+roleId+"\"%").Find(&permissions)
|
||||
if err != nil {
|
||||
return permissions, err
|
||||
}
|
||||
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
func GetPermissionsByResource(resourceId string) ([]*Permission, error) {
|
||||
permissions := []*Permission{}
|
||||
err := ormer.Engine.Where("resources like ?", "%"+resourceId+"\"%").Find(&permissions)
|
||||
if err != nil {
|
||||
return permissions, err
|
||||
}
|
||||
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
func GetPermissionsBySubmitter(owner string, submitter string) ([]*Permission, error) {
|
||||
permissions := []*Permission{}
|
||||
err := ormer.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Submitter: submitter})
|
||||
|
@@ -258,7 +258,7 @@ func BatchEnforce(permission *Permission, requests *[]CasbinRequest, permissionI
|
||||
}
|
||||
|
||||
func getAllValues(userId string, fn func(enforcer *casbin.Enforcer) []string) []string {
|
||||
permissions, _, err := GetPermissionsAndRolesByUser(userId)
|
||||
permissions, _, err := getPermissionsAndRolesByUser(userId)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -293,7 +293,7 @@ func GetAllActions(userId string) []string {
|
||||
}
|
||||
|
||||
func GetAllRoles(userId string) []string {
|
||||
roles, err := GetRolesByUser(userId)
|
||||
roles, err := getRolesByUser(userId)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@@ -32,6 +32,7 @@ type Role struct {
|
||||
Description string `xorm:"varchar(100)" json:"description"`
|
||||
|
||||
Users []string `xorm:"mediumtext" json:"users"`
|
||||
Groups []string `xorm:"mediumtext" json:"groups"`
|
||||
Roles []string `xorm:"mediumtext" json:"roles"`
|
||||
Domains []string `xorm:"mediumtext" json:"domains"`
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
@@ -252,15 +253,30 @@ func (role *Role) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", role.Owner, role.Name)
|
||||
}
|
||||
|
||||
func GetRolesByUser(userId string) ([]*Role, error) {
|
||||
func getRolesByUserInternal(userId string) ([]*Role, error) {
|
||||
roles := []*Role{}
|
||||
err := ormer.Engine.Where("users like ?", "%"+userId+"\"%").Find(&roles)
|
||||
if err != nil {
|
||||
return roles, err
|
||||
}
|
||||
|
||||
allRolesIds := make([]string, 0, len(roles))
|
||||
res := []*Role{}
|
||||
for _, role := range roles {
|
||||
if util.InSlice(role.Users, userId) {
|
||||
res = append(res, role)
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func getRolesByUser(userId string) ([]*Role, error) {
|
||||
roles, err := getRolesByUserInternal(userId)
|
||||
if err != nil {
|
||||
return roles, err
|
||||
}
|
||||
|
||||
allRolesIds := []string{}
|
||||
for _, role := range roles {
|
||||
allRolesIds = append(allRolesIds, role.GetId())
|
||||
}
|
||||
@@ -336,16 +352,6 @@ func GetMaskedRoles(roles []*Role) []*Role {
|
||||
return roles
|
||||
}
|
||||
|
||||
func GetRolesByNamePrefix(owner string, prefix string) ([]*Role, error) {
|
||||
roles := []*Role{}
|
||||
err := ormer.Engine.Where("owner=? and name like ?", owner, prefix+"%").Find(&roles)
|
||||
if err != nil {
|
||||
return roles, err
|
||||
}
|
||||
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
// GetAncestorRoles returns a list of roles that contain the given roleIds
|
||||
func GetAncestorRoles(roleIds ...string) ([]*Role, error) {
|
||||
var (
|
||||
|
@@ -796,7 +796,7 @@ func ExtendUserWithRolesAndPermissions(user *User) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
user.Permissions, user.Roles, err = GetPermissionsAndRolesByUser(user.GetId())
|
||||
user.Permissions, user.Roles, err = getPermissionsAndRolesByUser(user.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
67
radius/server.go
Normal file
67
radius/server.go
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package radius
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"layeh.com/radius"
|
||||
"layeh.com/radius/rfc2865"
|
||||
)
|
||||
|
||||
// https://support.huawei.com/enterprise/zh/doc/EDOC1000178159/35071f9a#tab_3
|
||||
func StartRadiusServer() {
|
||||
server := radius.PacketServer{
|
||||
Addr: "0.0.0.0:" + conf.GetConfigString("radiusServerPort"),
|
||||
Handler: radius.HandlerFunc(handlerRadius),
|
||||
SecretSource: radius.StaticSecretSource([]byte(`secret`)),
|
||||
}
|
||||
log.Printf("Starting Radius server on %s", server.Addr)
|
||||
if err := server.ListenAndServe(); err != nil {
|
||||
log.Fatalf("StartRadiusServer() failed, err = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func handlerRadius(w radius.ResponseWriter, r *radius.Request) {
|
||||
switch r.Code {
|
||||
case radius.CodeAccessRequest:
|
||||
handleAccessRequest(w, r)
|
||||
default:
|
||||
log.Printf("radius message, code = %d", r.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func handleAccessRequest(w radius.ResponseWriter, r *radius.Request) {
|
||||
username := rfc2865.UserName_GetString(r.Packet)
|
||||
password := rfc2865.UserPassword_GetString(r.Packet)
|
||||
organization := parseOrganization(r.Packet)
|
||||
code := radius.CodeAccessAccept
|
||||
|
||||
log.Printf("username=%v, password=%v, code=%v, org=%v", username, password, code, organization)
|
||||
if organization == "" {
|
||||
code = radius.CodeAccessReject
|
||||
w.Write(r.Response(code))
|
||||
return
|
||||
}
|
||||
_, msg := object.CheckUserPassword(organization, username, password, "en")
|
||||
if msg != "" {
|
||||
code = radius.CodeAccessReject
|
||||
w.Write(r.Response(code))
|
||||
return
|
||||
}
|
||||
w.Write(r.Response(code))
|
||||
}
|
62
radius/server_test.go
Normal file
62
radius/server_test.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !skipCi
|
||||
// +build !skipCi
|
||||
|
||||
package radius
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"layeh.com/radius"
|
||||
"layeh.com/radius/rfc2865"
|
||||
)
|
||||
|
||||
func TestAccessRequestRejected(t *testing.T) {
|
||||
packet := radius.New(radius.CodeAccessRequest, []byte(`secret`))
|
||||
rfc2865.UserName_SetString(packet, "admin")
|
||||
rfc2865.UserPassword_SetString(packet, "12345")
|
||||
vsa, err := radius.NewVendorSpecific(OrganizationVendorID, []byte("built-in"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
packet.Add(rfc2865.VendorSpecific_Type, vsa)
|
||||
response, err := radius.Exchange(context.Background(), packet, "localhost:1812")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if response.Code != radius.CodeAccessReject {
|
||||
t.Fatalf("Expected %v, got %v", radius.CodeAccessReject, response.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccessRequestAccepted(t *testing.T) {
|
||||
packet := radius.New(radius.CodeAccessRequest, []byte(`secret`))
|
||||
rfc2865.UserName_SetString(packet, "admin")
|
||||
rfc2865.UserPassword_SetString(packet, "123")
|
||||
vsa, err := radius.NewVendorSpecific(OrganizationVendorID, []byte("built-in"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
packet.Add(rfc2865.VendorSpecific_Type, vsa)
|
||||
response, err := radius.Exchange(context.Background(), packet, "localhost:1812")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if response.Code != radius.CodeAccessAccept {
|
||||
t.Fatalf("Expected %v, got %v", radius.CodeAccessAccept, response.Code)
|
||||
}
|
||||
}
|
40
radius/util.go
Normal file
40
radius/util.go
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package radius
|
||||
|
||||
import (
|
||||
"layeh.com/radius"
|
||||
"layeh.com/radius/rfc2865"
|
||||
)
|
||||
|
||||
const (
|
||||
OrganizationVendorID = uint32(100)
|
||||
)
|
||||
|
||||
func parseOrganization(p *radius.Packet) string {
|
||||
for _, avp := range p.Attributes {
|
||||
if avp.Type == rfc2865.VendorSpecific_Type {
|
||||
attr := avp.Attribute
|
||||
vendorId, value, err := radius.VendorSpecific(attr)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
if vendorId == OrganizationVendorID {
|
||||
return string(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
@@ -227,7 +227,7 @@ class AdapterEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:DB Test"), i18next.t("provider:DB Test - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("provider:DB test"), i18next.t("provider:DB test - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={2} >
|
||||
<Button type={"primary"} onClick={() => {
|
||||
|
@@ -129,6 +129,13 @@ class AdapterListPage extends BaseListPage {
|
||||
{text: "Database", value: "Database"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18next.t("syncer:Database type"),
|
||||
dataIndex: "databaseType",
|
||||
key: "databaseType",
|
||||
width: "120px",
|
||||
sorter: (a, b) => a.databaseType.localeCompare(b.databaseType),
|
||||
},
|
||||
{
|
||||
title: i18next.t("provider:Host"),
|
||||
dataIndex: "host",
|
||||
@@ -144,6 +151,12 @@ class AdapterListPage extends BaseListPage {
|
||||
width: "100px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("port"),
|
||||
render: (text, record, index) => {
|
||||
if (text === 0) {
|
||||
return "";
|
||||
}
|
||||
return text;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:User"),
|
||||
@@ -161,13 +174,6 @@ class AdapterListPage extends BaseListPage {
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("password"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("syncer:Database type"),
|
||||
dataIndex: "databaseType",
|
||||
key: "databaseType",
|
||||
width: "120px",
|
||||
sorter: (a, b) => a.databaseType.localeCompare(b.databaseType),
|
||||
},
|
||||
{
|
||||
title: i18next.t("syncer:Database"),
|
||||
dataIndex: "database",
|
||||
|
@@ -298,6 +298,13 @@ class PermissionListPage extends BaseListPage {
|
||||
filterMultiple: false,
|
||||
width: "120px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/users/${record.owner}/${encodeURIComponent(text)}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("permission:Approver"),
|
||||
@@ -306,6 +313,13 @@ class PermissionListPage extends BaseListPage {
|
||||
filterMultiple: false,
|
||||
width: "120px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/users/${record.owner}/${encodeURIComponent(text)}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("permission:Approve time"),
|
||||
|
@@ -172,6 +172,12 @@ class ProviderEditPage extends React.Component {
|
||||
} else {
|
||||
return Setting.getLabel(i18next.t("provider:Site key"), i18next.t("provider:Site key - Tooltip"));
|
||||
}
|
||||
case "Notification":
|
||||
if (provider.type === "DingTalk") {
|
||||
return Setting.getLabel(i18next.t("provider:Access key"), i18next.t("provider:Access key - Tooltip"));
|
||||
} else {
|
||||
return Setting.getLabel(i18next.t("provider:Client ID"), i18next.t("provider:Client ID - Tooltip"));
|
||||
}
|
||||
default:
|
||||
return Setting.getLabel(i18next.t("provider:Client ID"), i18next.t("provider:Client ID - Tooltip"));
|
||||
}
|
||||
@@ -180,7 +186,11 @@ class ProviderEditPage extends React.Component {
|
||||
getClientSecretLabel(provider) {
|
||||
switch (provider.category) {
|
||||
case "Email":
|
||||
return Setting.getLabel(i18next.t("general:Password"), i18next.t("general:Password - Tooltip"));
|
||||
if (provider.type === "Azure ACS") {
|
||||
return Setting.getLabel(i18next.t("provider:Secret key"), i18next.t("provider:Secret key - Tooltip"));
|
||||
} else {
|
||||
return Setting.getLabel(i18next.t("general:Password"), i18next.t("general:Password - Tooltip"));
|
||||
}
|
||||
case "SMS":
|
||||
if (provider.type === "Volc Engine SMS" || provider.type === "Amazon SNS" || provider.type === "Baidu Cloud SMS") {
|
||||
return Setting.getLabel(i18next.t("provider:Secret access key"), i18next.t("provider:Secret access key - Tooltip"));
|
||||
@@ -202,8 +212,10 @@ class ProviderEditPage extends React.Component {
|
||||
return Setting.getLabel(i18next.t("provider:Secret key"), i18next.t("provider:Secret key - Tooltip"));
|
||||
}
|
||||
case "Notification":
|
||||
if (provider.type === "Line") {
|
||||
if (provider.type === "Line" || provider.type === "Telegram" || provider.type === "Bark" || provider.type === "DingTalk" || provider.type === "Discord" || provider.type === "Slack" || provider.type === "Pushover" || provider.type === "Pushbullet") {
|
||||
return Setting.getLabel(i18next.t("provider:Secret key"), i18next.t("provider:Secret key - Tooltip"));
|
||||
} else if (provider.type === "Lark" || provider.type === "Microsoft Teams") {
|
||||
return Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:Endpoint - Tooltip"));
|
||||
} else {
|
||||
return Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:Client secret - Tooltip"));
|
||||
}
|
||||
@@ -297,7 +309,7 @@ class ProviderEditPage extends React.Component {
|
||||
tooltip = i18next.t("provider:Project Id - Tooltip");
|
||||
}
|
||||
} else if (provider.category === "Email") {
|
||||
if (provider.type === "SUBMAIL" || provider.type === "Azure ACS") {
|
||||
if (provider.type === "SUBMAIL") {
|
||||
text = i18next.t("provider:App ID");
|
||||
tooltip = i18next.t("provider:App ID - Tooltip");
|
||||
}
|
||||
@@ -305,7 +317,7 @@ class ProviderEditPage extends React.Component {
|
||||
if (provider.type === "Viber") {
|
||||
text = i18next.t("provider:Domain");
|
||||
tooltip = i18next.t("provider:Domain - Tooltip");
|
||||
} else if (provider.type === "Telegram" || provider.type === "DingTalk" || provider.type === "Pushover" || provider.type === "Pushbullet" || provider.type === "Slack" || provider.type === "Discord" || provider.type === "Line" || provider.type === "Matrix" || provider.type === "Rocket Chat") {
|
||||
} else if (provider.type === "Line" || provider.type === "Matrix" || provider.type === "Rocket Chat") {
|
||||
text = i18next.t("provider:App Key");
|
||||
tooltip = i18next.t("provider:App Key - Tooltip");
|
||||
}
|
||||
@@ -336,12 +348,9 @@ class ProviderEditPage extends React.Component {
|
||||
if (provider.type === "Telegram" || provider.type === "Pushover" || provider.type === "Pushbullet" || provider.type === "Slack" || provider.type === "Discord" || provider.type === "Line" || provider.type === "Twitter" || provider.type === "Reddit" || provider.type === "Rocket Chat" || provider.type === "Viber") {
|
||||
text = i18next.t("provider:Chat ID");
|
||||
tooltip = i18next.t("provider:Chat ID - Tooltip");
|
||||
} else if (provider.type === "Custom HTTP" || provider.type === "Lark" || provider.type === "Microsoft Teams" || provider.type === "Webpush" || provider.type === "Matrix") {
|
||||
} else if (provider.type === "Custom HTTP" || provider.type === "Webpush" || provider.type === "Matrix") {
|
||||
text = i18next.t("provider:Endpoint");
|
||||
tooltip = i18next.t("provider:Endpoint - Tooltip");
|
||||
} else if (provider.type === "DingTalk" || provider.type === "Bark") {
|
||||
text = i18next.t("provider:Secret Key");
|
||||
tooltip = i18next.t("provider:Secret Key - Tooltip");
|
||||
}
|
||||
|
||||
if (text === "" && tooltip === "") {
|
||||
@@ -626,24 +635,24 @@ class ProviderEditPage extends React.Component {
|
||||
}
|
||||
{
|
||||
(this.state.provider.category === "Captcha" && this.state.provider.type === "Default") ||
|
||||
(this.state.provider.category === "Email" && this.state.provider.type === "Azure ACS") ||
|
||||
(this.state.provider.category === "Web3") ||
|
||||
(this.state.provider.category === "Storage" && this.state.provider.type === "Local File System" ||
|
||||
(this.state.provider.category === "Notification" && this.state.provider.type !== "Webpush" && this.state.provider.type !== "Line" && this.state.provider.type !== "Matrix" && this.state.provider.type !== "Twitter" && this.state.provider.type !== "Reddit" && this.state.provider.type !== "Rocket Chat" && this.state.provider.type !== "Viber")) ? null : (
|
||||
(this.state.provider.category === "Storage" && this.state.provider.type === "Local File System") ||
|
||||
(this.state.provider.category === "Notification" && (this.state.provider.type === "Google Chat" || this.state.provider.type === "Custom HTTP")) ? null : (
|
||||
<React.Fragment>
|
||||
{
|
||||
this.state.provider.type === "Line" ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{this.getClientIdLabel(this.state.provider)} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.clientId} onChange={e => {
|
||||
this.updateProviderField("clientId", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
(this.state.provider.category === "Email" && this.state.provider.type === "Azure ACS") ||
|
||||
(this.state.provider.category === "Notification" && (this.state.provider.type === "Line" || this.state.provider.type === "Telegram" || this.state.provider.type === "Bark" || this.state.provider.type === "Discord" || this.state.provider.type === "Slack" || this.state.provider.type === "Pushbullet" || this.state.provider.type === "Pushover" || this.state.provider.type === "Lark" || this.state.provider.type === "Microsoft Teams")) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{this.getClientIdLabel(this.state.provider)} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.clientId} onChange={e => {
|
||||
this.updateProviderField("clientId", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
|
@@ -14,11 +14,12 @@
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row, Select, Switch} from "antd";
|
||||
import * as RoleBackend from "./backend/RoleBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
import * as GroupBackend from "./backend/GroupBackend";
|
||||
import * as RoleBackend from "./backend/RoleBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
|
||||
class RoleEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -30,6 +31,7 @@ class RoleEditPage extends React.Component {
|
||||
role: null,
|
||||
organizations: [],
|
||||
users: [],
|
||||
groups: [],
|
||||
roles: [],
|
||||
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
||||
};
|
||||
@@ -57,6 +59,7 @@ class RoleEditPage extends React.Component {
|
||||
});
|
||||
|
||||
this.getUsers(this.state.organizationName);
|
||||
this.getGroups(this.state.organizationName);
|
||||
this.getRoles(this.state.organizationName);
|
||||
});
|
||||
}
|
||||
@@ -84,6 +87,20 @@ class RoleEditPage extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
getGroups(organizationName) {
|
||||
GroupBackend.getGroups(organizationName)
|
||||
.then((res) => {
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
groups: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getRoles(organizationName) {
|
||||
RoleBackend.getRoles(organizationName)
|
||||
.then((res) => {
|
||||
@@ -176,6 +193,17 @@ class RoleEditPage extends React.Component {
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("role:Sub groups"), i18next.t("role:Sub groups - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.role.groups}
|
||||
onChange={(value => {this.updateRoleField("groups", value);})}
|
||||
options={this.state.groups.map((group) => Setting.getOption(`${group.owner}/${group.name}`, `${group.owner}/${group.name}`))}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("role:Sub roles"), i18next.t("role:Sub roles - Tooltip"))} :
|
||||
|
@@ -33,6 +33,7 @@ class RoleListPage extends BaseListPage {
|
||||
createdTime: moment().format(),
|
||||
displayName: `New Role - ${randomName}`,
|
||||
users: [],
|
||||
groups: [],
|
||||
roles: [],
|
||||
domains: [],
|
||||
isEnabled: true,
|
||||
@@ -171,6 +172,17 @@ class RoleListPage extends BaseListPage {
|
||||
return Setting.getTags(text, "users");
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("role:Sub groups"),
|
||||
dataIndex: "groups",
|
||||
key: "groups",
|
||||
// width: '100px',
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("groups"),
|
||||
render: (text, record, index) => {
|
||||
return Setting.getTags(text, "groups");
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("role:Sub roles"),
|
||||
dataIndex: "roles",
|
||||
|
@@ -749,7 +749,7 @@ export function isMobile() {
|
||||
}
|
||||
|
||||
export function getFormattedDate(date) {
|
||||
if (date === undefined) {
|
||||
if (!date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user