mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-20 10:02:01 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c296e9b6f | ||
|
|
3d80ec721f | ||
|
|
43d849086f | ||
|
|
69b144d80f | ||
|
|
52a66ef044 | ||
|
|
ec0a8e16f7 | ||
|
|
80a8000057 | ||
|
|
77091a3ae5 | ||
|
|
983da685a2 |
@@ -19,6 +19,7 @@ origin =
|
||||
staticBaseUrl = "https://cdn.casbin.org"
|
||||
isDemoMode = false
|
||||
batchSize = 100
|
||||
enableGzip = true
|
||||
ldapServerPort = 389
|
||||
radiusServerPort = 1812
|
||||
radiusSecret = "secret"
|
||||
|
||||
@@ -37,6 +37,11 @@ func (c *ApiController) Enforce() {
|
||||
resourceId := c.Input().Get("resourceId")
|
||||
enforcerId := c.Input().Get("enforcerId")
|
||||
|
||||
if len(c.Ctx.Input.RequestBody) == 0 {
|
||||
c.ResponseError("The request body should not be empty")
|
||||
return
|
||||
}
|
||||
|
||||
var request object.CasbinRequest
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &request)
|
||||
if err != nil {
|
||||
|
||||
@@ -160,35 +160,47 @@ func (c *ApiController) GetUser() {
|
||||
id = util.GetId(userFromUserId.Owner, userFromUserId.Name)
|
||||
}
|
||||
|
||||
if owner == "" {
|
||||
owner = util.GetOwnerFromId(id)
|
||||
}
|
||||
var user *object.User
|
||||
|
||||
organization, err := object.GetOrganization(util.GetId("admin", owner))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
if id == "" && owner == "" {
|
||||
switch {
|
||||
case email != "":
|
||||
user, err = object.GetUserByEmailOnly(email)
|
||||
case phone != "":
|
||||
user, err = object.GetUserByPhoneOnly(phone)
|
||||
case userId != "":
|
||||
user, err = object.GetUserByUserIdOnly(userId)
|
||||
}
|
||||
} else {
|
||||
if owner == "" {
|
||||
owner = util.GetOwnerFromId(id)
|
||||
}
|
||||
|
||||
if !organization.IsProfilePublic {
|
||||
requestUserId := c.GetSessionUsername()
|
||||
hasPermission, err := object.CheckUserPermission(requestUserId, id, false, c.GetAcceptLanguage())
|
||||
if !hasPermission {
|
||||
organization, err := object.GetOrganization(util.GetId("admin", owner))
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var user *object.User
|
||||
switch {
|
||||
case email != "":
|
||||
user, err = object.GetUserByEmail(owner, email)
|
||||
case phone != "":
|
||||
user, err = object.GetUserByPhone(owner, phone)
|
||||
case userId != "":
|
||||
user = userFromUserId
|
||||
default:
|
||||
user, err = object.GetUser(id)
|
||||
if !organization.IsProfilePublic {
|
||||
requestUserId := c.GetSessionUsername()
|
||||
hasPermission, err := object.CheckUserPermission(requestUserId, id, false, c.GetAcceptLanguage())
|
||||
if !hasPermission {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case email != "":
|
||||
user, err = object.GetUserByEmail(owner, email)
|
||||
case phone != "":
|
||||
user, err = object.GetUserByPhone(owner, phone)
|
||||
case userId != "":
|
||||
user = userFromUserId
|
||||
default:
|
||||
user, err = object.GetUser(id)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
2
main.go
2
main.go
@@ -59,7 +59,7 @@ func main() {
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.CorsFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.ApiFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.PrometheusFilter)
|
||||
beego.InsertFilter("*", beego.AfterExec, routers.RecordMessage, false)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.RecordMessage)
|
||||
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id"
|
||||
|
||||
@@ -22,14 +22,15 @@ config: |
|
||||
dataSourceName = "file:ent?mode=memory&cache=shared&_fk=1"
|
||||
dbName = casdoor
|
||||
redisEndpoint =
|
||||
defaultStorageProvider =
|
||||
defaultStorageProvider =
|
||||
isCloudIntranet = false
|
||||
authState = "casdoor"
|
||||
socks5Proxy = ""
|
||||
verificationCodeTimeout = 10
|
||||
initScore = 2000
|
||||
initScore = 0
|
||||
logPostOnly = true
|
||||
origin = "https://door.casbin.com"
|
||||
origin =
|
||||
enableGzip = true
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
|
||||
@@ -361,6 +361,8 @@ func CheckLoginPermission(userId string, application *Application) (bool, error)
|
||||
return false, err
|
||||
}
|
||||
|
||||
allowPermissionCount := 0
|
||||
denyPermissionCount := 0
|
||||
allowCount := 0
|
||||
denyCount := 0
|
||||
for _, permission := range permissions {
|
||||
@@ -368,8 +370,13 @@ func CheckLoginPermission(userId string, application *Application) (bool, error)
|
||||
continue
|
||||
}
|
||||
|
||||
if permission.isUserHit(userId) {
|
||||
allowCount += 1
|
||||
if !permission.isUserHit(userId) {
|
||||
if permission.Effect == "Allow" {
|
||||
allowPermissionCount += 1
|
||||
} else {
|
||||
denyPermissionCount += 1
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
@@ -391,8 +398,18 @@ func CheckLoginPermission(userId string, application *Application) (bool, error)
|
||||
}
|
||||
}
|
||||
|
||||
// Deny-override, if one deny is found, then deny
|
||||
if denyCount > 0 {
|
||||
return false, nil
|
||||
} else if allowCount > 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// For no-allow and no-deny condition
|
||||
// If only allow permissions exist, we suppose it's Deny-by-default, aka no-allow means deny
|
||||
// Otherwise, it's Allow-by-default, aka no-deny means allow
|
||||
if allowPermissionCount > 0 && denyPermissionCount == 0 {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ func (enforcer *Enforcer) LoadModelCfg() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
model, err := GetModel(enforcer.Model)
|
||||
model, err := GetModelEx(enforcer.Model)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if model == nil {
|
||||
|
||||
@@ -84,6 +84,19 @@ func GetModel(id string) (*Model, error) {
|
||||
return getModel(owner, name)
|
||||
}
|
||||
|
||||
func GetModelEx(id string) (*Model, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
model, err := getModel(owner, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if model != nil {
|
||||
return model, nil
|
||||
}
|
||||
|
||||
return getModel("built-in", name)
|
||||
}
|
||||
|
||||
func UpdateModelWithCheck(id string, modelObj *Model) error {
|
||||
// check model grammar
|
||||
_, err := model.NewModelFromString(modelObj.ModelText)
|
||||
|
||||
@@ -151,17 +151,20 @@ func UpdatePermission(id string, permission *Permission) (bool, error) {
|
||||
}
|
||||
|
||||
if permission.ResourceType == "Application" {
|
||||
model, err := GetModel(util.GetId(owner, permission.Model))
|
||||
model, err := GetModelEx(util.GetId(owner, permission.Model))
|
||||
if err != nil {
|
||||
return false, err
|
||||
} else if model == nil {
|
||||
return false, fmt.Errorf("the model: %s for permission: %s is not found", permission.Model, permission.GetId())
|
||||
}
|
||||
|
||||
modelCfg, err := getModelCfg(model)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if len(strings.Split(modelCfg["p"], ",")) != 3 {
|
||||
return false, fmt.Errorf("the model: %s for permission: %s is not valid, application type resources need 3 size [policy_defination] model", permission.Model, permission.GetId())
|
||||
return false, fmt.Errorf("the model: %s for permission: %s is not valid, Casbin model's [policy_defination] section should have 3 elements", permission.Model, permission.GetId())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,10 +424,10 @@ func (p *Permission) GetId() string {
|
||||
}
|
||||
|
||||
func (p *Permission) isUserHit(name string) bool {
|
||||
targetOrg, _ := util.GetOwnerAndNameFromId(name)
|
||||
targetOrg, targetName := util.GetOwnerAndNameFromId(name)
|
||||
for _, user := range p.Users {
|
||||
userOrg, userName := util.GetOwnerAndNameFromId(user)
|
||||
if userOrg == targetOrg && userName == "*" {
|
||||
if userOrg == targetOrg && (userName == "*" || userName == targetName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -433,7 +436,7 @@ func (p *Permission) isUserHit(name string) bool {
|
||||
|
||||
func (p *Permission) isResourceHit(name string) bool {
|
||||
for _, resource := range p.Resources {
|
||||
if name == resource {
|
||||
if resource == "*" || resource == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,12 +93,8 @@ func AddRecord(record *casvisorsdk.Record) bool {
|
||||
return affected
|
||||
}
|
||||
|
||||
func SendWebhooks(record *casvisorsdk.Record) error {
|
||||
webhooks, err := getWebhooksByOrganization(record.Organization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func getFilteredWebhooks(webhooks []*Webhook, action string) []*Webhook {
|
||||
res := []*Webhook{}
|
||||
for _, webhook := range webhooks {
|
||||
if !webhook.IsEnabled {
|
||||
continue
|
||||
@@ -106,28 +102,56 @@ func SendWebhooks(record *casvisorsdk.Record) error {
|
||||
|
||||
matched := false
|
||||
for _, event := range webhook.Events {
|
||||
if record.Action == event {
|
||||
if action == event {
|
||||
matched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if matched {
|
||||
var user *User
|
||||
if webhook.IsUserExtended {
|
||||
user, err = getUser(record.Organization, record.User)
|
||||
user, err = GetMaskedUser(user, false, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res = append(res, webhook)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func SendWebhooks(record *casvisorsdk.Record) error {
|
||||
webhooks, err := getWebhooksByOrganization(record.Organization)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
errs := []error{}
|
||||
webhooks = getFilteredWebhooks(webhooks, record.Action)
|
||||
for _, webhook := range webhooks {
|
||||
var user *User
|
||||
if webhook.IsUserExtended {
|
||||
user, err = getUser(record.Organization, record.User)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
|
||||
err = sendWebhook(webhook, record, user)
|
||||
user, err = GetMaskedUser(user, false, err)
|
||||
if err != nil {
|
||||
return err
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
err = sendWebhook(webhook, record, user)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
errStrings := []string{}
|
||||
for _, err := range errs {
|
||||
errStrings = append(errStrings, err.Error())
|
||||
}
|
||||
return fmt.Errorf(strings.Join(errStrings, " | "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -372,6 +372,24 @@ func GetUserByEmail(owner string, email string) (*User, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func GetUserByEmailOnly(email string) (*User, error) {
|
||||
if email == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
user := User{Email: email}
|
||||
existed, err := ormer.Engine.Get(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existed {
|
||||
return &user, nil
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetUserByPhone(owner string, phone string) (*User, error) {
|
||||
if owner == "" || phone == "" {
|
||||
return nil, nil
|
||||
@@ -390,6 +408,24 @@ func GetUserByPhone(owner string, phone string) (*User, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func GetUserByPhoneOnly(phone string) (*User, error) {
|
||||
if phone == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
user := User{Phone: phone}
|
||||
existed, err := ormer.Engine.Get(&user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existed {
|
||||
return &user, nil
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetUserByUserId(owner string, userId string) (*User, error) {
|
||||
if owner == "" || userId == "" {
|
||||
return nil, nil
|
||||
|
||||
@@ -190,5 +190,5 @@ func isHostIntranet(s string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return ip.IsPrivate()
|
||||
return ip.IsPrivate() || ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast()
|
||||
}
|
||||
|
||||
@@ -96,10 +96,13 @@ func buildExternalId(user *object.User) optional.String {
|
||||
func buildMeta(user *object.User) scim.Meta {
|
||||
createdTime := util.String2Time(user.CreatedTime)
|
||||
updatedTime := util.String2Time(user.UpdatedTime)
|
||||
if user.UpdatedTime == "" {
|
||||
updatedTime = createdTime
|
||||
}
|
||||
return scim.Meta{
|
||||
Created: &createdTime,
|
||||
LastModified: &updatedTime,
|
||||
Version: user.Id,
|
||||
Version: util.Time2String(updatedTime),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,10 @@ func String2Time(timestamp string) time.Time {
|
||||
return parseTime
|
||||
}
|
||||
|
||||
func Time2String(timestamp time.Time) string {
|
||||
return timestamp.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
func IsTokenExpired(createdTime string, expiresIn int) bool {
|
||||
createdTimeObj, _ := time.Parse(time.RFC3339, createdTime)
|
||||
expiresAtObj := createdTimeObj.Add(time.Duration(expiresIn) * time.Second)
|
||||
|
||||
@@ -277,7 +277,10 @@ class PermissionEditPage extends React.Component {
|
||||
<Col span={22} >
|
||||
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.permission.users}
|
||||
onChange={(value => {this.updatePermissionField("users", value);})}
|
||||
options={this.state.users.map((user) => Setting.getOption(`${user.owner}/${user.name}`, `${user.owner}/${user.name}`))}
|
||||
options={[
|
||||
Setting.getOption(i18next.t("organization:All"), "*"),
|
||||
...this.state.users.map((user) => Setting.getOption(`${user.owner}/${user.name}`, `${user.owner}/${user.name}`)),
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -288,7 +291,10 @@ class PermissionEditPage extends React.Component {
|
||||
<Col span={22} >
|
||||
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.permission.groups}
|
||||
onChange={(value => {this.updatePermissionField("groups", value);})}
|
||||
options={this.state.groups.map((group) => Setting.getOption(`${group.owner}/${group.name}`, `${group.owner}/${group.name}`))}
|
||||
options={[
|
||||
Setting.getOption(i18next.t("organization:All"), "*"),
|
||||
...this.state.groups.map((group) => Setting.getOption(`${group.owner}/${group.name}`, `${group.owner}/${group.name}`)),
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -299,8 +305,11 @@ class PermissionEditPage extends React.Component {
|
||||
<Col span={22} >
|
||||
<Select disabled={!this.hasRoleDefinition(this.state.model)} virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.permission.roles}
|
||||
onChange={(value => {this.updatePermissionField("roles", value);})}
|
||||
options={this.state.roles.filter(roles => (roles.owner !== this.state.roles.owner || roles.name !== this.state.roles.name)).map((permission) => Setting.getOption(`${permission.owner}/${permission.name}`, `${permission.owner}/${permission.name}`))
|
||||
} />
|
||||
options={[
|
||||
Setting.getOption(i18next.t("organization:All"), "*"),
|
||||
...this.state.roles.filter(roles => (roles.owner !== this.state.roles.owner || roles.name !== this.state.roles.name)).map((permission) => Setting.getOption(`${permission.owner}/${permission.name}`, `${permission.owner}/${permission.name}`)),
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
@@ -312,8 +321,11 @@ class PermissionEditPage extends React.Component {
|
||||
onChange={(value => {
|
||||
this.updatePermissionField("domains", value);
|
||||
})}
|
||||
options={this.state.permission.domains.map((domain) => Setting.getOption(domain, domain))
|
||||
} />
|
||||
options={[
|
||||
Setting.getOption(i18next.t("organization:All"), "*"),
|
||||
...this.state.permission.domains.map((domain) => Setting.getOption(domain, domain)),
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
@@ -340,8 +352,11 @@ class PermissionEditPage extends React.Component {
|
||||
<Col span={22} >
|
||||
<Select virtual={false} mode={(this.state.permission.resourceType === "Custom") ? "tags" : "multiple"} style={{width: "100%"}} value={this.state.permission.resources}
|
||||
onChange={(value => {this.updatePermissionField("resources", value);})}
|
||||
options={this.state.resources.map((resource) => Setting.getOption(`${resource.name}`, `${resource.name}`))
|
||||
} />
|
||||
options={[
|
||||
Setting.getOption(i18next.t("organization:All"), "*"),
|
||||
...this.state.resources.map((resource) => Setting.getOption(`${resource.name}`, `${resource.name}`)),
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
|
||||
Reference in New Issue
Block a user