diff --git a/controllers/auth.go b/controllers/auth.go
index 70c73a9ed..d0db8a981 100644
--- a/controllers/auth.go
+++ b/controllers/auth.go
@@ -50,6 +50,17 @@ func tokenToResponse(token *object.Token) *Response {
// HandleLoggedIn ...
func (c *ApiController) HandleLoggedIn(application *object.Application, user *object.User, form *RequestForm) (resp *Response) {
userId := user.GetId()
+
+ allowed, err := object.CheckPermission(userId, application)
+ if err != nil {
+ c.ResponseError(err.Error(), nil)
+ return
+ }
+ if !allowed {
+ c.ResponseError("Unauthorized operation")
+ return
+ }
+
if form.Type == ResponseTypeLogin {
c.SetSessionUsername(userId)
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
diff --git a/object/adapter.go b/object/adapter.go
index 0394ba544..781151689 100644
--- a/object/adapter.go
+++ b/object/adapter.go
@@ -203,6 +203,11 @@ func (a *Adapter) createTable() {
if err != nil {
panic(err)
}
+
+ err = a.Engine.Sync2(new(PermissionRule))
+ if err != nil {
+ panic(err)
+ }
}
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
diff --git a/object/check.go b/object/check.go
index 649d8b333..230f9cec5 100644
--- a/object/check.go
+++ b/object/check.go
@@ -229,4 +229,21 @@ func CheckUserPermission(requestUserId, userId string, strict bool) (bool, error
}
return hasPermission, fmt.Errorf("you don't have the permission to do this")
+}
+
+func CheckPermission(userId string, application *Application) (bool, error) {
+ permissions := GetPermissions(application.Organization)
+ allow := true
+ var err error
+ for _, permission := range permissions {
+ if permission.IsEnabled {
+ for _, resource := range permission.Resources {
+ if resource == application.Name {
+ enforcer := getEnforcer(permission)
+ allow, err = enforcer.Enforce(userId, application.Name, "read")
+ }
+ }
+ }
+ }
+ return allow, err
}
\ No newline at end of file
diff --git a/object/permission.go b/object/permission.go
index e60c24838..de87b2356 100644
--- a/object/permission.go
+++ b/object/permission.go
@@ -16,7 +16,12 @@ 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"
)
@@ -39,6 +44,16 @@ type Permission struct {
IsEnabled bool `json:"isEnabled"`
}
+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 ''"`
+}
+
func GetPermissionCount(owner, field, value string) int {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Permission{})
@@ -95,7 +110,8 @@ func GetPermission(id string) *Permission {
func UpdatePermission(id string, permission *Permission) bool {
owner, name := util.GetOwnerAndNameFromId(id)
- if getPermission(owner, name) == nil {
+ oldPermission := getPermission(owner, name)
+ if oldPermission == nil {
return false
}
@@ -104,6 +120,11 @@ func UpdatePermission(id string, permission *Permission) bool {
panic(err)
}
+ if affected != 0 {
+ removePolicies(oldPermission)
+ addPolicies(permission)
+ }
+
return affected != 0
}
@@ -113,6 +134,10 @@ func AddPermission(permission *Permission) bool {
panic(err)
}
+ if affected != 0 {
+ addPolicies(permission)
+ }
+
return affected != 0
}
@@ -122,9 +147,85 @@ func DeletePermission(permission *Permission) bool {
panic(err)
}
+ if affected != 0 {
+ removePolicies(permission)
+ }
+
return affected != 0
}
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)
+ }
+}
diff --git a/web/src/PermissionEditPage.js b/web/src/PermissionEditPage.js
index 55cd4321a..052ae2c78 100644
--- a/web/src/PermissionEditPage.js
+++ b/web/src/PermissionEditPage.js
@@ -21,6 +21,7 @@ import * as Setting from "./Setting";
import i18next from "i18next";
import * as RoleBackend from "./backend/RoleBackend";
import * as ModelBackend from "./backend/ModelBackend";
+import * as ApplicationBackend from "./backend/ApplicationBackend";
const {Option} = Select;
@@ -36,6 +37,7 @@ class PermissionEditPage extends React.Component {
users: [],
roles: [],
models: [],
+ resources: [],
mode: props.location.mode !== undefined ? props.location.mode : "edit",
};
}
@@ -55,6 +57,7 @@ class PermissionEditPage extends React.Component {
this.getUsers(permission.owner);
this.getRoles(permission.owner);
this.getModels(permission.owner);
+ this.getResources(permission.owner);
});
}
@@ -94,6 +97,15 @@ class PermissionEditPage extends React.Component {
});
}
+ getResources(organizationName) {
+ ApplicationBackend.getApplicationsByOrganization("admin", organizationName)
+ .then((res) => {
+ this.setState({
+ resources: (res.msg === undefined) ? res : [],
+ });
+ });
+ }
+
parsePermissionField(key, value) {
if ([""].includes(key)) {
value = Setting.myParseInt(value);
@@ -212,6 +224,18 @@ class PermissionEditPage extends React.Component {
+
+
+ {Setting.getLabel(i18next.t("permission:Resources"), i18next.t("permission:Resources - Tooltip"))} :
+
+
+
+
+
{Setting.getLabel(i18next.t("permission:Actions"), i18next.t("permission:Actions - Tooltip"))} :