* feat: Casdoor storage API * chore: fmt casdoor.go using gofumpt * feat: add global casdoor config variablesHEAD
@@ -23,8 +23,9 @@ import ( | |||
) | |||
var ( | |||
adapter *Adapter = nil | |||
CasdoorOrganization string | |||
adapter *Adapter = nil | |||
Organization string | |||
Application string | |||
) | |||
type Session struct { | |||
@@ -41,7 +42,8 @@ func InitCasdoorAdapter() { | |||
adapter = NewAdapter(beego.AppConfig.String("driverName"), beego.AppConfig.String("dataSourceName"), beego.AppConfig.String("casdoorDbName")) | |||
CasdoorOrganization = beego.AppConfig.String("casdoorOrganization") | |||
Organization = beego.AppConfig.String("casdoorOrganization") | |||
Application = beego.AppConfig.String("casdoorApplication") | |||
} | |||
// Adapter represents the MySQL adapter for policy storage. | |||
@@ -0,0 +1,38 @@ | |||
package casdoor | |||
import ( | |||
"fmt" | |||
"github.com/astaxie/beego" | |||
"github.com/casbin/casibase/util" | |||
"github.com/casdoor/casdoor-go-sdk/casdoorsdk" | |||
) | |||
func ListResources(prefix string) ([]*casdoorsdk.Resource, error) { | |||
prefix = util.GetIdFromOwnerAndName(fmt.Sprintf("/resource/%s/%s/casibase", | |||
beego.AppConfig.String("casdoorOrganization"), | |||
beego.AppConfig.String("casdoorApplication")), prefix) | |||
result := make([]*casdoorsdk.Resource, 0) | |||
err := adapter.Engine.Where("name like ?", prefix+"%").Find(&result) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return result, nil | |||
} | |||
func GetResource(key string) (*casdoorsdk.Resource, error) { | |||
id := fmt.Sprintf("/resource/%s/%s/casibase/%s", Organization, Application, key) | |||
resource := casdoorsdk.Resource{Owner: Organization, Name: id} | |||
existed, err := adapter.Engine.Get(&resource) | |||
if err != nil { | |||
return nil, err | |||
} | |||
if existed { | |||
return &resource, nil | |||
} else { | |||
return nil, fmt.Errorf("resource %s not found", key) | |||
} | |||
} |
@@ -7,7 +7,7 @@ require ( | |||
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible | |||
github.com/astaxie/beego v1.12.3 | |||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect | |||
github.com/casdoor/casdoor-go-sdk v0.9.1 | |||
github.com/casdoor/casdoor-go-sdk v0.25.0 | |||
github.com/danaugrs/go-tsne/tsne v0.0.0-20220306155740-2250969e057f | |||
github.com/go-sql-driver/mysql v1.6.0 | |||
github.com/google/uuid v1.3.0 | |||
@@ -705,8 +705,8 @@ github.com/calebcase/tmpfile v1.0.3 h1:BZrOWZ79gJqQ3XbAQlihYZf/YCV0H4KPIdM5K5oMp | |||
github.com/calebcase/tmpfile v1.0.3/go.mod h1:UAUc01aHeC+pudPagY/lWvt2qS9ZO5Zzof6/tIUzqeI= | |||
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE= | |||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= | |||
github.com/casdoor/casdoor-go-sdk v0.9.1 h1:z+5nJ4IvP9cNUodLf8wS42AYtDoUCvN6McRB5M+1SAQ= | |||
github.com/casdoor/casdoor-go-sdk v0.9.1/go.mod h1:MBed3ISHQfXTtoOCAk5T8l5lt4wFvsyynrw0awggydY= | |||
github.com/casdoor/casdoor-go-sdk v0.25.0 h1:hrx10mgpLgWqNsgFKQN/ljJsnD1i0cytW+S+2XxmxyQ= | |||
github.com/casdoor/casdoor-go-sdk v0.25.0/go.mod h1:MBed3ISHQfXTtoOCAk5T8l5lt4wFvsyynrw0awggydY= | |||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= | |||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= | |||
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= | |||
@@ -0,0 +1,75 @@ | |||
package storage | |||
import ( | |||
"fmt" | |||
"io" | |||
"net/http" | |||
"time" | |||
"github.com/astaxie/beego" | |||
"github.com/casbin/casibase/casdoor" | |||
"github.com/casbin/casibase/util" | |||
"github.com/casdoor/casdoor-go-sdk/casdoorsdk" | |||
) | |||
type casdoorClient struct { | |||
Storage | |||
} | |||
func NewCasdoorStorage() Storage { | |||
return &casdoorClient{} | |||
} | |||
func (s *casdoorClient) Get(key string) (io.ReadCloser, error) { | |||
res, err := casdoor.GetResource(key) | |||
if err != nil { | |||
return nil, err | |||
} | |||
response, err := http.Get(res.Url) | |||
if err != nil { | |||
return nil, err | |||
} | |||
return response.Body, nil | |||
} | |||
func (s *casdoorClient) Put(user, key string, bytes []byte) error { | |||
_, _, err := casdoorsdk.UploadResource(user, "Casibase", "Casibase", | |||
fmt.Sprintf("/resource/%s/%s/%s", | |||
casdoor.Organization, casdoor.Application, key), | |||
bytes) | |||
if err != nil { | |||
return err | |||
} | |||
return nil | |||
} | |||
func (s *casdoorClient) Delete(key string) error { | |||
_, err := casdoorsdk.DeleteResource(util.GetIdFromOwnerAndName(fmt.Sprintf("/resource/%s/%s/casibase", | |||
beego.AppConfig.String("casdoorOrganization"), | |||
beego.AppConfig.String("casdoorApplication")), key)) | |||
if err != nil { | |||
return err | |||
} | |||
return nil | |||
} | |||
func (s *casdoorClient) List(prefix string) ([]*Object, error) { | |||
res, err := casdoor.ListResources(prefix) | |||
if err != nil { | |||
return nil, err | |||
} | |||
result := make([]*Object, 0) | |||
for _, r := range res { | |||
created, _ := time.Parse(time.RFC3339, r.CreatedTime) | |||
result = append(result, &Object{ | |||
Key: util.GetNameFromIdNoCheck(r.Name), | |||
LastModified: &created, | |||
Storage: s, | |||
}) | |||
} | |||
return result, nil | |||
} |
@@ -0,0 +1,28 @@ | |||
package storage | |||
import ( | |||
"io" | |||
"time" | |||
) | |||
type Storage interface { | |||
Get(key string) (io.ReadCloser, error) | |||
Put(user, key string, bytes []byte) error | |||
Delete(key string) error | |||
List(prefix string) ([]*Object, error) | |||
} | |||
type Object struct { | |||
Key string | |||
LastModified *time.Time | |||
Storage Storage | |||
} | |||
func NewStorageProvider(provider string) Storage { | |||
switch provider { | |||
case "casdoor": | |||
return NewCasdoorStorage() | |||
default: | |||
return nil | |||
} | |||
} |
@@ -15,13 +15,70 @@ | |||
//go:build !skipCi | |||
// +build !skipCi | |||
package storage | |||
package storage_test | |||
import "testing" | |||
import ( | |||
"io" | |||
"testing" | |||
"github.com/casbin/casibase/casdoor" | |||
"github.com/casbin/casibase/controllers" | |||
"github.com/casbin/casibase/storage" | |||
) | |||
func TestStorage(t *testing.T) { | |||
_, err := ListObjects("casibase", "") | |||
_, err := storage.ListObjects("casibase", "") | |||
if err != nil { | |||
panic(err) | |||
} | |||
} | |||
func TestCasdoor(t *testing.T) { | |||
controllers.InitAuthConfig() | |||
casdoor.InitCasdoorAdapter() | |||
s := storage.NewCasdoorStorage() | |||
// Test Put | |||
err := s.Put("admin", "test", []byte("test")) | |||
if err != nil { | |||
t.Error(err) | |||
} | |||
// Test List | |||
objs, err := s.List("admin") | |||
if err != nil { | |||
t.Error(err) | |||
} | |||
for _, obj := range objs { | |||
t.Log(obj) | |||
} | |||
// Test Get | |||
in, err := s.Get("test") | |||
if err != nil { | |||
t.Error(err) | |||
} | |||
bytes, err := io.ReadAll(in) | |||
if err != nil { | |||
t.Error(err) | |||
} | |||
t.Log(string(bytes)) | |||
// Test Delete | |||
err = s.Delete("test") | |||
if err != nil { | |||
t.Error(err) | |||
} | |||
objs, err = s.List("test") | |||
if err != nil { | |||
t.Error(err) | |||
} | |||
for _, obj := range objs { | |||
t.Log(obj) | |||
} | |||
} |
@@ -93,6 +93,12 @@ func GetOwnerAndNameFromId3New(id string) (string, string, string) { | |||
return tokens[0], tokens[1], tokens[2] | |||
} | |||
func GetNameFromIdNoCheck(id string) string { | |||
tokens := strings.Split(id, "/") | |||
return tokens[len(tokens)-1] | |||
} | |||
func GetIdFromOwnerAndName(owner string, name string) string { | |||
return fmt.Sprintf("%s/%s", owner, name) | |||
} | |||