fix: remove model in adapter page (#2161)

This commit is contained in:
Yaodong Yu 2023-07-29 23:42:08 +08:00 committed by GitHub
parent ea10f8e615
commit 026fb207b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 53 additions and 121 deletions

View File

@ -145,7 +145,7 @@ func (c *ApiController) DeleteAdapter() {
c.ServeJSON() c.ServeJSON()
} }
func (c *ApiController) SyncPolicies() { func (c *ApiController) GetPolicies() {
id := c.Input().Get("id") id := c.Input().Get("id")
adapter, err := object.GetAdapter(id) adapter, err := object.GetAdapter(id)
if err != nil { if err != nil {
@ -153,7 +153,7 @@ func (c *ApiController) SyncPolicies() {
return return
} }
policies, err := object.SyncPolicies(adapter) policies, err := object.GetPolicies(adapter)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return

View File

@ -18,7 +18,6 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model" "github.com/casbin/casbin/v2/model"
"github.com/casdoor/casdoor/conf" "github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util" "github.com/casdoor/casdoor/util"
@ -31,9 +30,7 @@ type Adapter struct {
Name string `xorm:"varchar(100) notnull pk" json:"name"` Name string `xorm:"varchar(100) notnull pk" json:"name"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"` CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
Type string `xorm:"varchar(100)" json:"type"` Type string `xorm:"varchar(100)" json:"type"`
Model string `xorm:"varchar(100)" json:"model"`
DatabaseType string `xorm:"varchar(100)" json:"databaseType"` DatabaseType string `xorm:"varchar(100)" json:"databaseType"`
Host string `xorm:"varchar(100)" json:"host"` Host string `xorm:"varchar(100)" json:"host"`
Port string `xorm:"varchar(20)" json:"port"` Port string `xorm:"varchar(20)" json:"port"`
@ -46,7 +43,7 @@ type Adapter struct {
IsEnabled bool `json:"isEnabled"` IsEnabled bool `json:"isEnabled"`
Adapter *xormadapter.Adapter `xorm:"-" json:"-"` *xormadapter.Adapter `xorm:"-" json:"-"`
} }
func GetAdapterCount(owner, field, value string) (int64, error) { func GetAdapterCount(owner, field, value string) (int64, error) {
@ -153,46 +150,7 @@ func (adapter *Adapter) getTable() string {
} }
} }
func initEnforcer(modelObj *Model, adapter *Adapter) (*casbin.Enforcer, error) { func (adapter *Adapter) initAdapter() error {
// init Adapter
if adapter.Adapter == nil {
var dataSourceName string
if adapter.DatabaseType == "mssql" {
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%s?database=%s", adapter.User, adapter.Password, adapter.Host, adapter.Port, adapter.Database)
} else if adapter.DatabaseType == "postgres" {
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%s sslmode=disable dbname=%s", adapter.User, adapter.Password, adapter.Host, adapter.Port, adapter.Database)
} else {
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%s)/", adapter.User, adapter.Password, adapter.Host, adapter.Port)
}
if !isCloudIntranet {
dataSourceName = strings.ReplaceAll(dataSourceName, "dbi.", "db.")
}
var err error
adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(NewAdapter(adapter.DatabaseType, dataSourceName, adapter.Database).Engine, adapter.getTable(), "")
if err != nil {
return nil, err
}
}
// init Model
m, err := model.NewModelFromString(modelObj.ModelText)
if err != nil {
return nil, err
}
// init Enforcer
enforcer, err := casbin.NewEnforcer(m, adapter.Adapter)
if err != nil {
return nil, err
}
return enforcer, nil
}
func (adapter *Adapter) initAdapter() (*xormadapter.Adapter, error) {
// init Adapter
if adapter.Adapter == nil { if adapter.Adapter == nil {
var dataSourceName string var dataSourceName string
@ -215,7 +173,7 @@ func (adapter *Adapter) initAdapter() (*xormadapter.Adapter, error) {
case "sqlite3": case "sqlite3":
dataSourceName = fmt.Sprintf("file:%s", adapter.File) dataSourceName = fmt.Sprintf("file:%s", adapter.File)
default: default:
return nil, fmt.Errorf("unsupported database type: %s", adapter.DatabaseType) return fmt.Errorf("unsupported database type: %s", adapter.DatabaseType)
} }
} }
@ -226,10 +184,10 @@ func (adapter *Adapter) initAdapter() (*xormadapter.Adapter, error) {
var err error var err error
adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(NewAdapter(adapter.DatabaseType, dataSourceName, adapter.Database).Engine, adapter.getTable(), adapter.TableNamePrefix) adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(NewAdapter(adapter.DatabaseType, dataSourceName, adapter.Database).Engine, adapter.getTable(), adapter.TableNamePrefix)
if err != nil { if err != nil {
return nil, err return err
} }
} }
return adapter.Adapter, nil return nil
} }
func adapterChangeTrigger(oldName string, newName string) error { func adapterChangeTrigger(oldName string, newName string) error {
@ -279,41 +237,36 @@ func matrixToCasbinRules(Ptype string, policies [][]string) []*xormadapter.Casbi
return res return res
} }
func SyncPolicies(adapter *Adapter) ([]*xormadapter.CasbinRule, error) { func GetPolicies(adapter *Adapter) ([]*xormadapter.CasbinRule, error) {
modelObj, err := getModel(adapter.Owner, adapter.Model) err := adapter.initAdapter()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if modelObj == nil { casbinModel := getModelDef()
return nil, fmt.Errorf("The model: %s does not exist", util.GetId(adapter.Owner, adapter.Model)) err = adapter.LoadPolicy(casbinModel)
}
enforcer, err := initEnforcer(modelObj, adapter)
if err != nil { if err != nil {
return nil, err return nil, err
} }
policies := matrixToCasbinRules("p", enforcer.GetPolicy()) policies := matrixToCasbinRules("p", casbinModel.GetPolicy("p", "p"))
if strings.Contains(modelObj.ModelText, "[role_definition]") { policies = append(policies, matrixToCasbinRules("g", casbinModel.GetPolicy("g", "g"))...)
policies = append(policies, matrixToCasbinRules("g", enforcer.GetGroupingPolicy())...)
}
return policies, nil return policies, nil
} }
func UpdatePolicy(oldPolicy, newPolicy []string, adapter *Adapter) (bool, error) { func UpdatePolicy(oldPolicy, newPolicy []string, adapter *Adapter) (bool, error) {
modelObj, err := getModel(adapter.Owner, adapter.Model) err := adapter.initAdapter()
if err != nil { if err != nil {
return false, err return false, err
} }
enforcer, err := initEnforcer(modelObj, adapter) casbinModel := getModelDef()
err = adapter.LoadPolicy(casbinModel)
if err != nil { if err != nil {
return false, err return false, err
} }
affected, err := enforcer.UpdatePolicy(oldPolicy, newPolicy) affected := casbinModel.UpdatePolicy("p", "p", oldPolicy, newPolicy)
if err != nil { if err != nil {
return affected, err return affected, err
} }
@ -321,39 +274,38 @@ func UpdatePolicy(oldPolicy, newPolicy []string, adapter *Adapter) (bool, error)
} }
func AddPolicy(policy []string, adapter *Adapter) (bool, error) { func AddPolicy(policy []string, adapter *Adapter) (bool, error) {
modelObj, err := getModel(adapter.Owner, adapter.Model) err := adapter.initAdapter()
if err != nil { if err != nil {
return false, err return false, err
} }
enforcer, err := initEnforcer(modelObj, adapter) casbinModel := getModelDef()
err = adapter.LoadPolicy(casbinModel)
if err != nil { if err != nil {
return false, err return false, err
} }
affected, err := enforcer.AddPolicy(policy) casbinModel.AddPolicy("p", "p", policy)
if err != nil {
return affected, err return true, nil
}
return affected, nil
} }
func RemovePolicy(policy []string, adapter *Adapter) (bool, error) { func RemovePolicy(policy []string, adapter *Adapter) (bool, error) {
modelObj, err := getModel(adapter.Owner, adapter.Model) err := adapter.initAdapter()
if err != nil { if err != nil {
return false, err return false, err
} }
enforcer, err := initEnforcer(modelObj, adapter) casbinModel := getModelDef()
err = adapter.LoadPolicy(casbinModel)
if err != nil { if err != nil {
return false, err return false, err
} }
affected, err := enforcer.RemovePolicy(policy) affected := casbinModel.RemovePolicy("p", "p", policy)
if err != nil { if err != nil {
return affected, err return affected, err
} }
return affected, nil return affected, nil
} }
@ -364,3 +316,10 @@ func (adapter *Adapter) buildInAdapter() bool {
return adapter.Name == "permission-adapter-built-in" || adapter.Name == "api-adapter-built-in" return adapter.Name == "permission-adapter-built-in" || adapter.Name == "api-adapter-built-in"
} }
func getModelDef() model.Model {
casbinModel := model.NewModel()
casbinModel.AddDef("p", "p", "_, _, _, _, _, _")
casbinModel.AddDef("g", "g", "_, _, _, _, _, _")
return casbinModel
}

View File

@ -144,17 +144,17 @@ func (enforcer *Enforcer) InitEnforcer() (*casbin.Enforcer, error) {
return nil, errors.New("adapter not found") return nil, errors.New("adapter not found")
} }
casbinModel, err := m.initModel() err = m.initModel()
if err != nil { if err != nil {
return nil, err return nil, err
} }
adapter, err := a.initAdapter() err = a.initAdapter()
if err != nil { if err != nil {
return nil, err return nil, err
} }
e, err := casbin.NewEnforcer(casbinModel, adapter) e, err := casbin.NewEnforcer(m.Model, a.Adapter)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -31,6 +31,8 @@ type Model struct {
ModelText string `xorm:"mediumtext" json:"modelText"` ModelText string `xorm:"mediumtext" json:"modelText"`
IsEnabled bool `json:"isEnabled"` IsEnabled bool `json:"isEnabled"`
model.Model `xorm:"-" json:"-"`
} }
func GetModelCount(owner, field, value string) (int64, error) { func GetModelCount(owner, field, value string) (int64, error) {
@ -176,10 +178,14 @@ func HasRoleDefinition(m model.Model) bool {
return m["g"] != nil return m["g"] != nil
} }
func (m *Model) initModel() (model.Model, error) { func (m *Model) initModel() error {
casbinModel, err := model.NewModelFromString(m.ModelText) if m.Model == nil {
if err != nil { casbinModel, err := model.NewModelFromString(m.ModelText)
return nil, err if err != nil {
return err
}
m.Model = casbinModel
} }
return casbinModel, nil
return nil
} }

View File

@ -122,7 +122,7 @@ func initAPI() {
beego.Router("/api/update-adapter", &controllers.ApiController{}, "POST:UpdateAdapter") beego.Router("/api/update-adapter", &controllers.ApiController{}, "POST:UpdateAdapter")
beego.Router("/api/add-adapter", &controllers.ApiController{}, "POST:AddAdapter") beego.Router("/api/add-adapter", &controllers.ApiController{}, "POST:AddAdapter")
beego.Router("/api/delete-adapter", &controllers.ApiController{}, "POST:DeleteAdapter") beego.Router("/api/delete-adapter", &controllers.ApiController{}, "POST:DeleteAdapter")
beego.Router("/api/sync-policies", &controllers.ApiController{}, "GET:SyncPolicies") beego.Router("/api/get-policies", &controllers.ApiController{}, "GET:GetPolicies")
beego.Router("/api/update-policy", &controllers.ApiController{}, "POST:UpdatePolicy") beego.Router("/api/update-policy", &controllers.ApiController{}, "POST:UpdatePolicy")
beego.Router("/api/add-policy", &controllers.ApiController{}, "POST:AddPolicy") beego.Router("/api/add-policy", &controllers.ApiController{}, "POST:AddPolicy")
beego.Router("/api/remove-policy", &controllers.ApiController{}, "POST:RemovePolicy") beego.Router("/api/remove-policy", &controllers.ApiController{}, "POST:RemovePolicy")

View File

@ -20,7 +20,6 @@ import * as Setting from "./Setting";
import i18next from "i18next"; import i18next from "i18next";
import "codemirror/lib/codemirror.css"; import "codemirror/lib/codemirror.css";
import * as ModelBackend from "./backend/ModelBackend";
import PolicyTable from "./table/PoliciyTable"; import PolicyTable from "./table/PoliciyTable";
require("codemirror/theme/material-darker.css"); require("codemirror/theme/material-darker.css");
require("codemirror/mode/javascript/javascript"); require("codemirror/mode/javascript/javascript");
@ -36,7 +35,6 @@ class AdapterEditPage extends React.Component {
adapterName: props.match.params.adapterName, adapterName: props.match.params.adapterName,
adapter: null, adapter: null,
organizations: [], organizations: [],
models: [],
mode: props.location.mode !== undefined ? props.location.mode : "edit", mode: props.location.mode !== undefined ? props.location.mode : "edit",
}; };
} }
@ -58,8 +56,6 @@ class AdapterEditPage extends React.Component {
this.setState({ this.setState({
adapter: res.data, adapter: res.data,
}); });
this.getModels(this.state.organizationName);
} }
}); });
} }
@ -73,20 +69,6 @@ class AdapterEditPage extends React.Component {
}); });
} }
getModels(organizationName) {
ModelBackend.getModels(organizationName)
.then((res) => {
if (res.status === "error") {
Setting.showMessage("error", res.msg);
return;
}
this.setState({
models: res.data,
});
});
}
parseAdapterField(key, value) { parseAdapterField(key, value) {
// if ([].includes(key)) { // if ([].includes(key)) {
// value = Setting.myParseInt(value); // value = Setting.myParseInt(value);
@ -187,7 +169,6 @@ class AdapterEditPage extends React.Component {
</Col> </Col>
<Col span={22} > <Col span={22} >
<Select virtual={false} style={{width: "100%"}} disabled={!Setting.isAdminUser(this.props.account) || Setting.builtInObject(this.state.adapter)} value={this.state.adapter.owner} onChange={(value => { <Select virtual={false} style={{width: "100%"}} disabled={!Setting.isAdminUser(this.props.account) || Setting.builtInObject(this.state.adapter)} value={this.state.adapter.owner} onChange={(value => {
this.getModels(value);
this.updateAdapterField("owner", value); this.updateAdapterField("owner", value);
})}> })}>
{ {
@ -266,20 +247,6 @@ class AdapterEditPage extends React.Component {
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Model"), i18next.t("general:Model - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} style={{width: "100%"}} value={this.state.adapter.model} onChange={(model => {
this.updateAdapterField("model", model);
})}>
{
this.state.models.map((model, index) => <Option key={index} value={model.name}>{model.name}</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: "20px"}} > <Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("adapter:Policies"), i18next.t("adapter:Policies - Tooltip"))} : {Setting.getLabel(i18next.t("adapter:Policies"), i18next.t("adapter:Policies - Tooltip"))} :

View File

@ -103,8 +103,8 @@ export function RemovePolicy(owner, name, policy) {
}).then(res => res.json()); }).then(res => res.json());
} }
export function syncPolicies(owner, name) { export function getPolicies(owner, name) {
return fetch(`${Setting.ServerUrl}/api/sync-policies?id=${owner}/${encodeURIComponent(name)}`, { return fetch(`${Setting.ServerUrl}/api/get-policies?id=${owner}/${encodeURIComponent(name)}`, {
method: "GET", method: "GET",
credentials: "include", credentials: "include",
headers: { headers: {

View File

@ -102,7 +102,7 @@ class PolicyTable extends React.Component {
synPolicies() { synPolicies() {
this.setState({loading: true}); this.setState({loading: true});
AdapterBackend.syncPolicies(this.props.owner, this.props.name) AdapterBackend.getPolicies(this.props.owner, this.props.name)
.then((res) => { .then((res) => {
if (res.status === "ok") { if (res.status === "ok") {
Setting.showMessage("success", i18next.t("adapter:Sync policies successfully")); Setting.showMessage("success", i18next.t("adapter:Sync policies successfully"));