diff --git a/controllers/account.go b/controllers/account.go index d7334839..253a9353 100644 --- a/controllers/account.go +++ b/controllers/account.go @@ -15,10 +15,8 @@ package controllers import ( - "bytes" "encoding/json" "fmt" - "io" "strconv" "github.com/casbin/casdoor/object" @@ -212,67 +210,6 @@ func (c *ApiController) GetAccount() { c.ResponseOk(user, organization) } -// UploadFile -// @Title UploadFile -// @Description upload file -// @Param owner query string true "The owner" -// @Param tag query string true "The tag" -// @Param fullFilePath query string true "The full file path" -// @Param file query string true "The file" -// @Success 200 {object} controllers.Response The Response object -// @router /upload-file [post] -func (c *ApiController) UploadFile() { - userId, ok := c.RequireSignedIn() - if !ok { - return - } - - //owner := c.Input().Get("owner") - tag := c.Input().Get("tag") - parent := c.Input().Get("parent") - fullFilePath := c.Input().Get("fullFilePath") - - file, _, err := c.GetFile("file") - defer file.Close() - if err != nil { - c.ResponseError(err.Error()) - return - } - - fileBuffer := bytes.NewBuffer(nil) - if _, err = io.Copy(fileBuffer, file); err != nil { - c.ResponseError(err.Error()) - return - } - - user := object.GetUser(userId) - application := object.GetApplicationByUser(user) - provider := application.GetStorageProvider() - if provider == nil { - c.ResponseError("No storage provider is found") - return - } - - fileUrl, err := object.UploadFile(provider, fullFilePath, fileBuffer) - if err != nil { - c.ResponseError(err.Error()) - return - } - - switch tag { - case "avatar": - user.Avatar = fileUrl - object.UpdateUser(user.GetId(), user) - case "termsOfUse": - applicationId := fmt.Sprintf("admin/%s", parent) - app := object.GetApplication(applicationId) - app.TermsOfUse = fileUrl - object.UpdateApplication(applicationId, app) - } - - c.ResponseOk(fileUrl) -} - // GetHumanCheck ... func (c *ApiController) GetHumanCheck() { c.Data["json"] = HumanCheck{Type: "none"} diff --git a/controllers/resource.go b/controllers/resource.go new file mode 100644 index 00000000..5f7e16d1 --- /dev/null +++ b/controllers/resource.go @@ -0,0 +1,152 @@ +// Copyright 2021 The casbin 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 controllers + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "path/filepath" + "strings" + + "github.com/casbin/casdoor/object" + "github.com/casbin/casdoor/util" +) + +func (c *ApiController) GetResources() { + owner := c.Input().Get("owner") + + c.Data["json"] = object.GetResources(owner) + c.ServeJSON() +} + +func (c *ApiController) GetResource() { + id := c.Input().Get("id") + + c.Data["json"] = object.GetResource(id) + c.ServeJSON() +} + +func (c *ApiController) UpdateResource() { + id := c.Input().Get("id") + + var resource object.Resource + err := json.Unmarshal(c.Ctx.Input.RequestBody, &resource) + if err != nil { + panic(err) + } + + c.Data["json"] = wrapActionResponse(object.UpdateResource(id, &resource)) + c.ServeJSON() +} + +func (c *ApiController) AddResource() { + var resource object.Resource + err := json.Unmarshal(c.Ctx.Input.RequestBody, &resource) + if err != nil { + panic(err) + } + + c.Data["json"] = wrapActionResponse(object.AddResource(&resource)) + c.ServeJSON() +} + +func (c *ApiController) DeleteResource() { + var resource object.Resource + err := json.Unmarshal(c.Ctx.Input.RequestBody, &resource) + if err != nil { + panic(err) + } + + c.Data["json"] = wrapActionResponse(object.DeleteResource(&resource)) + c.ServeJSON() +} + +func (c *ApiController) UploadResource() { + userId, ok := c.RequireSignedIn() + if !ok { + return + } + + owner := c.Input().Get("owner") + tag := c.Input().Get("tag") + parent := c.Input().Get("parent") + fullFilePath := c.Input().Get("fullFilePath") + + file, header, err := c.GetFile("file") + defer file.Close() + if err != nil { + c.ResponseError(err.Error()) + return + } + + filename := filepath.Base(fullFilePath) + fileBuffer := bytes.NewBuffer(nil) + if _, err = io.Copy(fileBuffer, file); err != nil { + c.ResponseError(err.Error()) + return + } + + user := object.GetUser(userId) + application := object.GetApplicationByUser(user) + provider := application.GetStorageProvider() + if provider == nil { + c.ResponseError("No storage provider is found") + return + } + + fileUrl, objectKey, err := object.UploadFile(provider, fullFilePath, fileBuffer) + if err != nil { + c.ResponseError(err.Error()) + return + } + + fileType := "unknown" + fileFormat := filepath.Ext(fullFilePath) + if strings.Contains(".png|.jpg|.bmp", fileFormat) { + fileType = "image" + } else if strings.Contains(".mp4|.avi", fileFormat) { + fileType = "video" + } + + fileSize := int(header.Size) + resource := &object.Resource{ + Owner: owner, + Name: filename, + CreatedTime: util.GetCurrentTime(), + Tag: tag, + Parent: parent, + FileType: fileType, + FileFormat: fileFormat, + FileSize: fileSize, + Url: fileUrl, + ObjectKey: objectKey, + } + object.AddOrUpdateResource(resource) + + switch tag { + case "avatar": + user.Avatar = fileUrl + object.UpdateUser(user.GetId(), user) + case "termsOfUse": + applicationId := fmt.Sprintf("admin/%s", parent) + app := object.GetApplication(applicationId) + app.TermsOfUse = fileUrl + object.UpdateApplication(applicationId, app) + } + + c.ResponseOk(fileUrl) +} diff --git a/object/adapter.go b/object/adapter.go index 35cb7257..2f62fec7 100644 --- a/object/adapter.go +++ b/object/adapter.go @@ -124,6 +124,11 @@ func (a *Adapter) createTable() { panic(err) } + err = a.Engine.Sync2(new(Resource)) + if err != nil { + panic(err) + } + err = a.Engine.Sync2(new(Token)) if err != nil { panic(err) diff --git a/object/resource.go b/object/resource.go new file mode 100644 index 00000000..9e403f42 --- /dev/null +++ b/object/resource.go @@ -0,0 +1,110 @@ +// Copyright 2021 The casbin 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 object + +import ( + "fmt" + "xorm.io/core" + + "github.com/casbin/casdoor/util" +) + +type Resource struct { + Owner string `xorm:"varchar(100) notnull pk" json:"owner"` + Name string `xorm:"varchar(100) notnull pk" json:"name"` + CreatedTime string `xorm:"varchar(100)" json:"createdTime"` + + Tag string `xorm:"varchar(100)" json:"tag"` + Parent string `xorm:"varchar(100)" json:"parent"` + FileType string `xorm:"varchar(100)" json:"fileType"` + FileFormat string `xorm:"varchar(100)" json:"fileFormat"` + FileSize int `json:"fileSize"` + Url string `xorm:"varchar(100)" json:"url"` + ObjectKey string `xorm:"varchar(100)" json:"objectKey"` +} + +func GetResources(owner string) []*Resource { + resources := []*Resource{} + err := adapter.Engine.Desc("created_time").Find(&resources, &Resource{Owner: owner}) + if err != nil { + panic(err) + } + + return resources +} + +func getResource(owner string, name string) *Resource { + resource := Resource{Owner: owner, Name: name} + existed, err := adapter.Engine.Get(&resource) + if err != nil { + panic(err) + } + + if existed { + return &resource + } else { + return nil + } +} + +func GetResource(id string) *Resource { + owner, name := util.GetOwnerAndNameFromId(id) + return getResource(owner, name) +} + +func UpdateResource(id string, resource *Resource) bool { + owner, name := util.GetOwnerAndNameFromId(id) + if getResource(owner, name) == nil { + return false + } + + _, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(resource) + if err != nil { + panic(err) + } + + //return affected != 0 + return true +} + +func AddResource(resource *Resource) bool { + affected, err := adapter.Engine.Insert(resource) + if err != nil { + panic(err) + } + + return affected != 0 +} + +func DeleteResource(resource *Resource) bool { + affected, err := adapter.Engine.ID(core.PK{resource.Owner, resource.Name}).Delete(&Resource{}) + if err != nil { + panic(err) + } + + return affected != 0 +} + +func (resource *Resource) GetId() string { + return fmt.Sprintf("%s/%s", resource.Owner, resource.Name) +} + +func AddOrUpdateResource(resource *Resource) bool { + if getResource(resource.Owner, resource.Name) == nil { + return AddResource(resource) + } else { + return UpdateResource(resource.GetId(), resource) + } +} diff --git a/object/storage.go b/object/storage.go index e87a8113..0ba79735 100644 --- a/object/storage.go +++ b/object/storage.go @@ -23,10 +23,10 @@ import ( "github.com/casbin/casdoor/util" ) -func UploadFile(provider *Provider, fullFilePath string, fileBuffer *bytes.Buffer) (string, error) { +func UploadFile(provider *Provider, fullFilePath string, fileBuffer *bytes.Buffer) (string, string, error) { storageProvider := storage.GetStorageProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.RegionId, provider.Bucket, provider.Endpoint) if storageProvider == nil { - return "", fmt.Errorf("the provider type: %s is not supported", provider.Type) + return "", "", fmt.Errorf("the provider type: %s is not supported", provider.Type) } if provider.Domain == "" { @@ -34,10 +34,10 @@ func UploadFile(provider *Provider, fullFilePath string, fileBuffer *bytes.Buffe UpdateProvider(provider.GetId(), provider) } - path := util.UrlJoin(util.GetUrlPath(provider.Domain), fullFilePath) - _, err := storageProvider.Put(path, fileBuffer) + objectKey := util.UrlJoin(util.GetUrlPath(provider.Domain), fullFilePath) + _, err := storageProvider.Put(objectKey, fileBuffer) if err != nil { - return "", err + return "", "", err } host := "" @@ -52,6 +52,6 @@ func UploadFile(provider *Provider, fullFilePath string, fileBuffer *bytes.Buffe host = util.UrlJoin(provider.Domain, "/files") } - fileUrl := fmt.Sprintf("%s?time=%s", util.UrlJoin(host, path), util.GetCurrentUnixTime()) - return fileUrl, nil + fileUrl := fmt.Sprintf("%s?time=%s", util.UrlJoin(host, objectKey), util.GetCurrentUnixTime()) + return fileUrl, objectKey, nil } diff --git a/routers/router.go b/routers/router.go index 54b91f12..d9e335a0 100644 --- a/routers/router.go +++ b/routers/router.go @@ -59,12 +59,13 @@ func initAPI() { beego.Router("/api/update-user", &controllers.ApiController{}, "POST:UpdateUser") beego.Router("/api/add-user", &controllers.ApiController{}, "POST:AddUser") beego.Router("/api/delete-user", &controllers.ApiController{}, "POST:DeleteUser") - beego.Router("/api/upload-file", &controllers.ApiController{}, "POST:UploadFile") + beego.Router("/api/set-password", &controllers.ApiController{}, "POST:SetPassword") beego.Router("/api/get-email-and-phone", &controllers.ApiController{}, "POST:GetEmailAndPhone") beego.Router("/api/send-verification-code", &controllers.ApiController{}, "POST:SendVerificationCode") beego.Router("/api/reset-email-or-phone", &controllers.ApiController{}, "POST:ResetEmailOrPhone") beego.Router("/api/get-human-check", &controllers.ApiController{}, "GET:GetHumanCheck") + beego.Router("/api/get-ldap-user", &controllers.ApiController{}, "POST:GetLdapUser") beego.Router("/api/get-ldaps", &controllers.ApiController{}, "POST:GetLdaps") beego.Router("/api/get-ldap", &controllers.ApiController{}, "POST:GetLdap") @@ -87,6 +88,13 @@ func initAPI() { beego.Router("/api/add-application", &controllers.ApiController{}, "POST:AddApplication") beego.Router("/api/delete-application", &controllers.ApiController{}, "POST:DeleteApplication") + beego.Router("/api/get-resources", &controllers.ApiController{}, "GET:GetResources") + beego.Router("/api/get-resource", &controllers.ApiController{}, "GET:GetResource") + beego.Router("/api/update-resource", &controllers.ApiController{}, "POST:UpdateResource") + beego.Router("/api/add-resource", &controllers.ApiController{}, "POST:AddResource") + beego.Router("/api/delete-resource", &controllers.ApiController{}, "POST:DeleteResource") + beego.Router("/api/upload-resource", &controllers.ApiController{}, "POST:UploadResource") + beego.Router("/api/get-tokens", &controllers.ApiController{}, "GET:GetTokens") beego.Router("/api/get-token", &controllers.ApiController{}, "GET:GetToken") beego.Router("/api/update-token", &controllers.ApiController{}, "POST:UpdateToken") diff --git a/web/src/App.js b/web/src/App.js index e2e62e28..376e4ee5 100644 --- a/web/src/App.js +++ b/web/src/App.js @@ -27,6 +27,8 @@ import ProviderListPage from "./ProviderListPage"; import ProviderEditPage from "./ProviderEditPage"; import ApplicationListPage from "./ApplicationListPage"; import ApplicationEditPage from "./ApplicationEditPage"; +import ResourceListPage from "./ResourceListPage"; +// import ResourceEditPage from "./ResourceEditPage"; import LdapEditPage from "./LdapEditPage"; import LdapSyncPage from "./LdapSyncPage"; import TokenListPage from "./TokenListPage"; @@ -99,6 +101,8 @@ class App extends Component { this.setState({ selectedMenuKey: '/providers' }); } else if (uri.includes('/applications')) { this.setState({ selectedMenuKey: '/applications' }); + } else if (uri.includes('/resources')) { + this.setState({ selectedMenuKey: '/resources' }); } else if (uri.includes('/tokens')) { this.setState({ selectedMenuKey: '/tokens' }); } else if (uri.includes('/records')) { @@ -317,6 +321,13 @@ class App extends Component { ); + res.push( +