diff --git a/casdoorsdk/policy.go b/casdoorsdk/policy.go new file mode 100644 index 0000000..47d8343 --- /dev/null +++ b/casdoorsdk/policy.go @@ -0,0 +1,79 @@ +// Copyright 2024 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 casdoorsdk + +import ( + "encoding/json" + "fmt" +) + +type CasbinRule struct { + Id int64 `xorm:"pk autoincr"` + 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 ''"` + + tableName string `xorm:"-"` +} + +func (c *Client) AddPolicy(enforcer *Enforcer, policy *CasbinRule) (bool, error) { + var policies []*CasbinRule + policies = make([]*CasbinRule, 1) + policies[0] = policy + _, affected, err := c.modifyPolicy("add-policy", enforcer, policies, nil) + return affected, err +} + +func (c *Client) UpdatePolicy(enforcer *Enforcer, oldpolicy *CasbinRule, newpolicy *CasbinRule) (bool, error) { + var policies []*CasbinRule + policies = make([]*CasbinRule, 2) + policies[0] = oldpolicy + policies[1] = newpolicy + _, affected, err := c.modifyPolicy("update-policy", enforcer, policies, nil) + return affected, err +} + +func (c *Client) RemovePolicy(enforcer *Enforcer, policy *CasbinRule) (bool, error) { + var policies []*CasbinRule + policies = make([]*CasbinRule, 1) + policies[0] = policy + _, affected, err := c.modifyPolicy("remove-policy", enforcer, policies, nil) + return affected, err +} + +func (c *Client) GetPolicies(enforcerName string, adapterId string) ([]*CasbinRule, error) { + queryMap := map[string]string{ + "id": fmt.Sprintf("%s/%s", c.OrganizationName, enforcerName), + "adapterId": adapterId, + } + + url := c.GetUrl("get-policies", queryMap) + + bytes, err := c.DoGetBytes(url) + if err != nil { + return nil, err + } + + var policies []*CasbinRule + err = json.Unmarshal(bytes, &policies) + if err != nil { + return nil, err + } + return policies, nil +} diff --git a/casdoorsdk/policy_global.go b/casdoorsdk/policy_global.go new file mode 100644 index 0000000..070ff5b --- /dev/null +++ b/casdoorsdk/policy_global.go @@ -0,0 +1,31 @@ +// Copyright 2024 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 casdoorsdk + +func AddPolicy(enforcer *Enforcer, policy *CasbinRule) (bool, error) { + return globalClient.AddPolicy(enforcer, policy) +} + +func UpdatePolicy(enforcer *Enforcer, oldpolicy *CasbinRule, newpolicy *CasbinRule) (bool, error) { + return globalClient.UpdatePolicy(enforcer, oldpolicy, newpolicy) +} + +func RemovePolicy(enforcer *Enforcer, policy *CasbinRule) (bool, error) { + return globalClient.RemovePolicy(enforcer, policy) +} + +func GetPolicies(enforcerName string, adapterId string) ([]*CasbinRule, error) { + return globalClient.GetPolicies(enforcerName, adapterId) +} diff --git a/casdoorsdk/policy_test.go b/casdoorsdk/policy_test.go new file mode 100644 index 0000000..20eed9f --- /dev/null +++ b/casdoorsdk/policy_test.go @@ -0,0 +1,118 @@ +// Copyright 2024 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 casdoorsdk + +import "testing" + +func TestPolicy(t *testing.T) { + InitConfig(TestCasdoorEndpoint, TestClientId, TestClientSecret, TestJwtPublicKey, TestCasdoorOrganization, TestCasdoorApplication) + + name := getRandomName("Enforcer") + + // Add a new object + enforcer := &Enforcer{ + Owner: "admin", + Name: name, + CreatedTime: GetCurrentTime(), + DisplayName: name, + Model: "built-in/user-model-built-in", + Adapter: "built-in/user-adapter-built-in", + Description: "Casdoor Website", + } + _, err := AddEnforcer(enforcer) + if err != nil { + t.Fatalf("Failed to add object: %v", err) + } + + //Add a new policy + policy := &CasbinRule{ + Ptype: "p", + V0: "1", + V1: "2", + V2: "4", + } + _, err = AddPolicy(enforcer, policy) + if err != nil { + t.Fatalf("Failed to add policy: %v", err) + } + // + // Get all objects, check if our added object is inside the list + Policies, err := GetPolicies(name, "") + if err != nil { + t.Fatalf("Failed to get objects: %v", err) + } + found := false + for _, item := range Policies { + if item.Ptype == "p" && item.V2 == "4" { + found = true + break + } + } + if !found { + t.Fatalf("Added object not found in list") + } + + newPolicy := &CasbinRule{ + Ptype: "p", + V0: "1", + V1: "2", + V2: "5", + } + + // Update the object + _, err = UpdatePolicy(enforcer, policy, newPolicy) + if err != nil { + t.Fatalf("Failed to update object: %v", err) + } + + // Validate the update + Policies, err = GetPolicies(name, "") + if err != nil { + t.Fatalf("Failed to get updated object: %v", err) + } + found = false + for _, item := range Policies { + if item.Ptype == "p" && item.V2 == "5" { + found = true + break + } + } + if !found { + t.Fatalf("Update object not found in list") + } + + // Delete the object + _, err = RemovePolicy(enforcer, newPolicy) + if err != nil { + t.Fatalf("Failed to delete object: %v", err) + } + + // Validate the deletion + Policies, err = GetPolicies(name, "") + if err != nil { + t.Fatalf("Failed to get updated object: %v", err) + } + found = false + for _, item := range Policies { + if item.Ptype == "p" && item.V2 == "3" { + found = true + break + } + } + if found { + t.Fatalf("Delete object found in list") + } + +} diff --git a/casdoorsdk/util_modify.go b/casdoorsdk/util_modify.go index 8fe6ccf..0f4ccb4 100644 --- a/casdoorsdk/util_modify.go +++ b/casdoorsdk/util_modify.go @@ -250,6 +250,37 @@ func (c *Client) modifyEnforcer(action string, enforcer *Enforcer, columns []str return resp, resp.Data == "Affected", nil } +// modifyPolicy is an encapsulation of cert CUD(Create, Update, Delete) operations. +func (c *Client) modifyPolicy(action string, enforcer *Enforcer, policies []*CasbinRule, columns []string) (*Response, bool, error) { + enforcer.Owner = c.OrganizationName + queryMap := map[string]string{ + "id": fmt.Sprintf("%s/%s", enforcer.Owner, enforcer.Name), + } + + if len(columns) != 0 { + queryMap["columns"] = strings.Join(columns, ",") + } + + var postBytes []byte + var err error + if action == "update-policy" { + postBytes, err = json.Marshal(policies) + } else { + postBytes, err = json.Marshal(policies[0]) + } + + if err != nil { + return nil, false, err + } + + resp, err := c.DoPost(action, queryMap, postBytes, false, false) + if err != nil { + return nil, false, err + } + + return resp, resp.Data == "Affected", nil +} + // modifyEnforcer is an encapsulation of cert CUD(Create, Update, Delete) operations. // possible actions are `add-group`, `update-group`, `delete-group`, func (c *Client) modifyGroup(action string, group *Group, columns []string) (*Response, bool, error) {