Add role service and manager

This commit is contained in:
Benedikt Kulmann
2020-08-19 12:42:15 +02:00
parent 143bf118fa
commit 65d71bd6fd
16 changed files with 2940 additions and 409 deletions

View File

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@ package proto
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
empty "github.com/golang/protobuf/ptypes/empty"
_ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger/options"
_ "google.golang.org/genproto/googleapis/api/annotations"
math "math"
@@ -60,6 +61,20 @@ func NewBundleServiceEndpoints() []*api.Endpoint {
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "BundleService.AddSettingToBundle",
Path: []string{"/api/v0/settings/bundles-add-setting"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "BundleService.RemoveSettingFromBundle",
Path: []string{"/api/v0/settings/bundles-remove-setting"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
}
}
@@ -69,6 +84,8 @@ type BundleService interface {
SaveBundle(ctx context.Context, in *SaveBundleRequest, opts ...client.CallOption) (*SaveBundleResponse, error)
GetBundle(ctx context.Context, in *GetBundleRequest, opts ...client.CallOption) (*GetBundleResponse, error)
ListBundles(ctx context.Context, in *ListBundlesRequest, opts ...client.CallOption) (*ListBundlesResponse, error)
AddSettingToBundle(ctx context.Context, in *AddSettingToBundleRequest, opts ...client.CallOption) (*AddSettingToBundleResponse, error)
RemoveSettingFromBundle(ctx context.Context, in *RemoveSettingFromBundleRequest, opts ...client.CallOption) (*empty.Empty, error)
}
type bundleService struct {
@@ -113,12 +130,34 @@ func (c *bundleService) ListBundles(ctx context.Context, in *ListBundlesRequest,
return out, nil
}
func (c *bundleService) AddSettingToBundle(ctx context.Context, in *AddSettingToBundleRequest, opts ...client.CallOption) (*AddSettingToBundleResponse, error) {
req := c.c.NewRequest(c.name, "BundleService.AddSettingToBundle", in)
out := new(AddSettingToBundleResponse)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *bundleService) RemoveSettingFromBundle(ctx context.Context, in *RemoveSettingFromBundleRequest, opts ...client.CallOption) (*empty.Empty, error) {
req := c.c.NewRequest(c.name, "BundleService.RemoveSettingFromBundle", in)
out := new(empty.Empty)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for BundleService service
type BundleServiceHandler interface {
SaveBundle(context.Context, *SaveBundleRequest, *SaveBundleResponse) error
GetBundle(context.Context, *GetBundleRequest, *GetBundleResponse) error
ListBundles(context.Context, *ListBundlesRequest, *ListBundlesResponse) error
AddSettingToBundle(context.Context, *AddSettingToBundleRequest, *AddSettingToBundleResponse) error
RemoveSettingFromBundle(context.Context, *RemoveSettingFromBundleRequest, *empty.Empty) error
}
func RegisterBundleServiceHandler(s server.Server, hdlr BundleServiceHandler, opts ...server.HandlerOption) error {
@@ -126,6 +165,8 @@ func RegisterBundleServiceHandler(s server.Server, hdlr BundleServiceHandler, op
SaveBundle(ctx context.Context, in *SaveBundleRequest, out *SaveBundleResponse) error
GetBundle(ctx context.Context, in *GetBundleRequest, out *GetBundleResponse) error
ListBundles(ctx context.Context, in *ListBundlesRequest, out *ListBundlesResponse) error
AddSettingToBundle(ctx context.Context, in *AddSettingToBundleRequest, out *AddSettingToBundleResponse) error
RemoveSettingFromBundle(ctx context.Context, in *RemoveSettingFromBundleRequest, out *empty.Empty) error
}
type BundleService struct {
bundleService
@@ -152,6 +193,20 @@ func RegisterBundleServiceHandler(s server.Server, hdlr BundleServiceHandler, op
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "BundleService.AddSettingToBundle",
Path: []string{"/api/v0/settings/bundles-add-setting"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "BundleService.RemoveSettingFromBundle",
Path: []string{"/api/v0/settings/bundles-remove-setting"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
return s.Handle(s.NewHandler(&BundleService{h}, opts...))
}
@@ -171,6 +226,14 @@ func (h *bundleServiceHandler) ListBundles(ctx context.Context, in *ListBundlesR
return h.BundleServiceHandler.ListBundles(ctx, in, out)
}
func (h *bundleServiceHandler) AddSettingToBundle(ctx context.Context, in *AddSettingToBundleRequest, out *AddSettingToBundleResponse) error {
return h.BundleServiceHandler.AddSettingToBundle(ctx, in, out)
}
func (h *bundleServiceHandler) RemoveSettingFromBundle(ctx context.Context, in *RemoveSettingFromBundleRequest, out *empty.Empty) error {
return h.BundleServiceHandler.RemoveSettingFromBundle(ctx, in, out)
}
// Api Endpoints for ValueService service
func NewValueServiceEndpoints() []*api.Endpoint {
@@ -337,3 +400,170 @@ func (h *valueServiceHandler) ListValues(ctx context.Context, in *ListValuesRequ
func (h *valueServiceHandler) GetValueByUniqueIdentifiers(ctx context.Context, in *GetValueByUniqueIdentifiersRequest, out *GetValueResponse) error {
return h.ValueServiceHandler.GetValueByUniqueIdentifiers(ctx, in, out)
}
// Api Endpoints for RoleService service
func NewRoleServiceEndpoints() []*api.Endpoint {
return []*api.Endpoint{
&api.Endpoint{
Name: "RoleService.ListRoles",
Path: []string{"/api/v0/settings/roles-list"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "RoleService.ListRoleAssignments",
Path: []string{"/api/v0/settings/assignments-list"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "RoleService.AssignRoleToUser",
Path: []string{"/api/v0/settings/assignments-add"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
&api.Endpoint{
Name: "RoleService.RemoveRoleFromUser",
Path: []string{"/api/v0/settings/assignments-remove"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
},
}
}
// Client API for RoleService service
type RoleService interface {
ListRoles(ctx context.Context, in *ListBundlesRequest, opts ...client.CallOption) (*ListBundlesResponse, error)
ListRoleAssignments(ctx context.Context, in *ListRoleAssignmentsRequest, opts ...client.CallOption) (*ListRoleAssignmentsResponse, error)
AssignRoleToUser(ctx context.Context, in *AssignRoleToUserRequest, opts ...client.CallOption) (*AssignRoleToUserResponse, error)
RemoveRoleFromUser(ctx context.Context, in *RemoveRoleFromUserRequest, opts ...client.CallOption) (*empty.Empty, error)
}
type roleService struct {
c client.Client
name string
}
func NewRoleService(name string, c client.Client) RoleService {
return &roleService{
c: c,
name: name,
}
}
func (c *roleService) ListRoles(ctx context.Context, in *ListBundlesRequest, opts ...client.CallOption) (*ListBundlesResponse, error) {
req := c.c.NewRequest(c.name, "RoleService.ListRoles", in)
out := new(ListBundlesResponse)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *roleService) ListRoleAssignments(ctx context.Context, in *ListRoleAssignmentsRequest, opts ...client.CallOption) (*ListRoleAssignmentsResponse, error) {
req := c.c.NewRequest(c.name, "RoleService.ListRoleAssignments", in)
out := new(ListRoleAssignmentsResponse)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *roleService) AssignRoleToUser(ctx context.Context, in *AssignRoleToUserRequest, opts ...client.CallOption) (*AssignRoleToUserResponse, error) {
req := c.c.NewRequest(c.name, "RoleService.AssignRoleToUser", in)
out := new(AssignRoleToUserResponse)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *roleService) RemoveRoleFromUser(ctx context.Context, in *RemoveRoleFromUserRequest, opts ...client.CallOption) (*empty.Empty, error) {
req := c.c.NewRequest(c.name, "RoleService.RemoveRoleFromUser", in)
out := new(empty.Empty)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for RoleService service
type RoleServiceHandler interface {
ListRoles(context.Context, *ListBundlesRequest, *ListBundlesResponse) error
ListRoleAssignments(context.Context, *ListRoleAssignmentsRequest, *ListRoleAssignmentsResponse) error
AssignRoleToUser(context.Context, *AssignRoleToUserRequest, *AssignRoleToUserResponse) error
RemoveRoleFromUser(context.Context, *RemoveRoleFromUserRequest, *empty.Empty) error
}
func RegisterRoleServiceHandler(s server.Server, hdlr RoleServiceHandler, opts ...server.HandlerOption) error {
type roleService interface {
ListRoles(ctx context.Context, in *ListBundlesRequest, out *ListBundlesResponse) error
ListRoleAssignments(ctx context.Context, in *ListRoleAssignmentsRequest, out *ListRoleAssignmentsResponse) error
AssignRoleToUser(ctx context.Context, in *AssignRoleToUserRequest, out *AssignRoleToUserResponse) error
RemoveRoleFromUser(ctx context.Context, in *RemoveRoleFromUserRequest, out *empty.Empty) error
}
type RoleService struct {
roleService
}
h := &roleServiceHandler{hdlr}
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "RoleService.ListRoles",
Path: []string{"/api/v0/settings/roles-list"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "RoleService.ListRoleAssignments",
Path: []string{"/api/v0/settings/assignments-list"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "RoleService.AssignRoleToUser",
Path: []string{"/api/v0/settings/assignments-add"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
opts = append(opts, api.WithEndpoint(&api.Endpoint{
Name: "RoleService.RemoveRoleFromUser",
Path: []string{"/api/v0/settings/assignments-remove"},
Method: []string{"POST"},
Body: "*",
Handler: "rpc",
}))
return s.Handle(s.NewHandler(&RoleService{h}, opts...))
}
type roleServiceHandler struct {
RoleServiceHandler
}
func (h *roleServiceHandler) ListRoles(ctx context.Context, in *ListBundlesRequest, out *ListBundlesResponse) error {
return h.RoleServiceHandler.ListRoles(ctx, in, out)
}
func (h *roleServiceHandler) ListRoleAssignments(ctx context.Context, in *ListRoleAssignmentsRequest, out *ListRoleAssignmentsResponse) error {
return h.RoleServiceHandler.ListRoleAssignments(ctx, in, out)
}
func (h *roleServiceHandler) AssignRoleToUser(ctx context.Context, in *AssignRoleToUserRequest, out *AssignRoleToUserResponse) error {
return h.RoleServiceHandler.AssignRoleToUser(ctx, in, out)
}
func (h *roleServiceHandler) RemoveRoleFromUser(ctx context.Context, in *RemoveRoleFromUserRequest, out *empty.Empty) error {
return h.RoleServiceHandler.RemoveRoleFromUser(ctx, in, out)
}

View File

@@ -3,10 +3,12 @@ package proto_test
import (
"context"
"encoding/json"
fmt "fmt"
"log"
"os"
"testing"
mgrpc "github.com/micro/go-micro/v2/client/grpc"
ocislog "github.com/owncloud/ocis-pkg/v2/log"
"github.com/owncloud/ocis-pkg/v2/service/grpc"
"github.com/owncloud/ocis-settings/pkg/config"
@@ -59,6 +61,10 @@ func init() {
if err != nil {
log.Fatalf("could not register ValueServiceHandler: %v", err)
}
err = proto.RegisterRoleServiceHandler(service.Server(), svc.NewService(cfg, ocislog.NewLogger(ocislog.Color(true), ocislog.Pretty(true))))
if err != nil {
log.Fatalf("could not register RegisterRoleServiceHandler: %v", err)
}
if err = service.Server().Start(); err != nil {
log.Fatalf("could not start server: %v", err)
@@ -627,6 +633,52 @@ func TestGetSettingsBundleCreatesFolder(t *testing.T) {
os.RemoveAll(dataStore)
}
// TODO non-deterministic. Fix.
func TestCreateRoleAndAssign(t *testing.T) {
c := mgrpc.NewClient()
bundleC := proto.NewBundleService("com.owncloud.api.settings", c)
res, err := bundleC.SaveBundle(context.Background(), &proto.SaveBundleRequest{
Bundle: &proto.Bundle{
// Id: "f36db5e6-a03c-40df-8413-711c67e40b47", // bug: providing the ID ignores its value for the filename.
Type: proto.Bundle_TYPE_ROLE,
DisplayName: "test role - update",
Name: "TEST_ROLE",
Extension: "ocis-settings",
Settings: []*proto.Setting{
{
Name: "settingName",
Resource: &proto.Resource{
Id: settingsStub[0].Id,
Type: proto.Resource_TYPE_SETTING,
},
Value: &proto.Setting_PermissionValue{
&proto.Permission{
Operation: proto.Permission_OPERATION_UPDATE,
Constraint: proto.Permission_CONSTRAINT_OWN,
},
},
},
},
Resource: &proto.Resource{
Type: proto.Resource_TYPE_SYSTEM,
},
},
})
if err == nil {
rolesC := proto.NewRoleService("com.owncloud.api.settings", c)
_, err = rolesC.AssignRoleToUser(context.Background(), &proto.AssignRoleToUserRequest{
AccountUuid: "4c510ada-c86b-4815-8820-42cdf82c3d51",
RoleId: res.Bundle.Id,
})
if err != nil {
fmt.Println(err)
}
assert.NoError(t, err)
}
os.RemoveAll(dataStore)
}
// // TODO this tests are non-deterministic at least on my machine. Find a way to make them deterministic.
// func TestListBudlesOnAuthorizedUser(t *testing.T) {
// client := service.Client()

View File

@@ -11,6 +11,8 @@ import (
"github.com/go-chi/chi"
"github.com/go-chi/render"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/ptypes/empty"
)
type webBundleServiceHandler struct {
@@ -94,6 +96,53 @@ func (h *webBundleServiceHandler) ListBundles(w http.ResponseWriter, r *http.Req
render.JSON(w, r, resp)
}
func (h *webBundleServiceHandler) AddSettingToBundle(w http.ResponseWriter, r *http.Request) {
req := &AddSettingToBundleRequest{}
resp := &AddSettingToBundleResponse{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusPreconditionFailed)
return
}
if err := h.h.AddSettingToBundle(
r.Context(),
req,
resp,
); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
render.Status(r, http.StatusCreated)
render.JSON(w, r, resp)
}
func (h *webBundleServiceHandler) RemoveSettingFromBundle(w http.ResponseWriter, r *http.Request) {
req := &RemoveSettingFromBundleRequest{}
resp := &empty.Empty{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusPreconditionFailed)
return
}
if err := h.h.RemoveSettingFromBundle(
r.Context(),
req,
resp,
); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
render.Status(r, http.StatusNoContent)
render.NoContent(w, r)
}
func RegisterBundleServiceWeb(r chi.Router, i BundleServiceHandler, middlewares ...func(http.Handler) http.Handler) {
handler := &webBundleServiceHandler{
r: r,
@@ -103,6 +152,8 @@ func RegisterBundleServiceWeb(r chi.Router, i BundleServiceHandler, middlewares
r.MethodFunc("POST", "/api/v0/settings/bundle-save", handler.SaveBundle)
r.MethodFunc("POST", "/api/v0/settings/bundle-get", handler.GetBundle)
r.MethodFunc("POST", "/api/v0/settings/bundles-list", handler.ListBundles)
r.MethodFunc("POST", "/api/v0/settings/bundles-add-setting", handler.AddSettingToBundle)
r.MethodFunc("POST", "/api/v0/settings/bundles-remove-setting", handler.RemoveSettingFromBundle)
}
type webValueServiceHandler struct {
@@ -222,6 +273,122 @@ func RegisterValueServiceWeb(r chi.Router, i ValueServiceHandler, middlewares ..
r.MethodFunc("POST", "/api/v0/settings/values-get-by-unique-identifiers", handler.GetValueByUniqueIdentifiers)
}
type webRoleServiceHandler struct {
r chi.Router
h RoleServiceHandler
}
func (h *webRoleServiceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.r.ServeHTTP(w, r)
}
func (h *webRoleServiceHandler) ListRoles(w http.ResponseWriter, r *http.Request) {
req := &ListBundlesRequest{}
resp := &ListBundlesResponse{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusPreconditionFailed)
return
}
if err := h.h.ListRoles(
r.Context(),
req,
resp,
); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
render.Status(r, http.StatusCreated)
render.JSON(w, r, resp)
}
func (h *webRoleServiceHandler) ListRoleAssignments(w http.ResponseWriter, r *http.Request) {
req := &ListRoleAssignmentsRequest{}
resp := &ListRoleAssignmentsResponse{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusPreconditionFailed)
return
}
if err := h.h.ListRoleAssignments(
r.Context(),
req,
resp,
); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
render.Status(r, http.StatusCreated)
render.JSON(w, r, resp)
}
func (h *webRoleServiceHandler) AssignRoleToUser(w http.ResponseWriter, r *http.Request) {
req := &AssignRoleToUserRequest{}
resp := &AssignRoleToUserResponse{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusPreconditionFailed)
return
}
if err := h.h.AssignRoleToUser(
r.Context(),
req,
resp,
); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
render.Status(r, http.StatusCreated)
render.JSON(w, r, resp)
}
func (h *webRoleServiceHandler) RemoveRoleFromUser(w http.ResponseWriter, r *http.Request) {
req := &RemoveRoleFromUserRequest{}
resp := &empty.Empty{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusPreconditionFailed)
return
}
if err := h.h.RemoveRoleFromUser(
r.Context(),
req,
resp,
); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
render.Status(r, http.StatusNoContent)
render.NoContent(w, r)
}
func RegisterRoleServiceWeb(r chi.Router, i RoleServiceHandler, middlewares ...func(http.Handler) http.Handler) {
handler := &webRoleServiceHandler{
r: r,
h: i,
}
r.MethodFunc("POST", "/api/v0/settings/roles-list", handler.ListRoles)
r.MethodFunc("POST", "/api/v0/settings/assignments-list", handler.ListRoleAssignments)
r.MethodFunc("POST", "/api/v0/settings/assignments-add", handler.AssignRoleToUser)
r.MethodFunc("POST", "/api/v0/settings/assignments-remove", handler.RemoveRoleFromUser)
}
// SaveBundleRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of SaveBundleRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
@@ -438,6 +605,114 @@ func (m *ListBundlesResponse) UnmarshalJSON(b []byte) error {
var _ json.Unmarshaler = (*ListBundlesResponse)(nil)
// AddSettingToBundleRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of AddSettingToBundleRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
var AddSettingToBundleRequestJSONMarshaler = new(jsonpb.Marshaler)
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
// uses the more correct jsonpb package to correctly marshal the message.
func (m *AddSettingToBundleRequest) MarshalJSON() ([]byte, error) {
if m == nil {
return json.Marshal(nil)
}
buf := &bytes.Buffer{}
if err := AddSettingToBundleRequestJSONMarshaler.Marshal(buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var _ json.Marshaler = (*AddSettingToBundleRequest)(nil)
// AddSettingToBundleRequestJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
// instances of AddSettingToBundleRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
var AddSettingToBundleRequestJSONUnmarshaler = new(jsonpb.Unmarshaler)
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
// uses the more correct jsonpb package to correctly unmarshal the message.
func (m *AddSettingToBundleRequest) UnmarshalJSON(b []byte) error {
return AddSettingToBundleRequestJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
}
var _ json.Unmarshaler = (*AddSettingToBundleRequest)(nil)
// AddSettingToBundleResponseJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of AddSettingToBundleResponse. This struct is safe to replace or modify but
// should not be done so concurrently.
var AddSettingToBundleResponseJSONMarshaler = new(jsonpb.Marshaler)
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
// uses the more correct jsonpb package to correctly marshal the message.
func (m *AddSettingToBundleResponse) MarshalJSON() ([]byte, error) {
if m == nil {
return json.Marshal(nil)
}
buf := &bytes.Buffer{}
if err := AddSettingToBundleResponseJSONMarshaler.Marshal(buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var _ json.Marshaler = (*AddSettingToBundleResponse)(nil)
// AddSettingToBundleResponseJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
// instances of AddSettingToBundleResponse. This struct is safe to replace or modify but
// should not be done so concurrently.
var AddSettingToBundleResponseJSONUnmarshaler = new(jsonpb.Unmarshaler)
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
// uses the more correct jsonpb package to correctly unmarshal the message.
func (m *AddSettingToBundleResponse) UnmarshalJSON(b []byte) error {
return AddSettingToBundleResponseJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
}
var _ json.Unmarshaler = (*AddSettingToBundleResponse)(nil)
// RemoveSettingFromBundleRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of RemoveSettingFromBundleRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
var RemoveSettingFromBundleRequestJSONMarshaler = new(jsonpb.Marshaler)
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
// uses the more correct jsonpb package to correctly marshal the message.
func (m *RemoveSettingFromBundleRequest) MarshalJSON() ([]byte, error) {
if m == nil {
return json.Marshal(nil)
}
buf := &bytes.Buffer{}
if err := RemoveSettingFromBundleRequestJSONMarshaler.Marshal(buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var _ json.Marshaler = (*RemoveSettingFromBundleRequest)(nil)
// RemoveSettingFromBundleRequestJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
// instances of RemoveSettingFromBundleRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
var RemoveSettingFromBundleRequestJSONUnmarshaler = new(jsonpb.Unmarshaler)
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
// uses the more correct jsonpb package to correctly unmarshal the message.
func (m *RemoveSettingFromBundleRequest) UnmarshalJSON(b []byte) error {
return RemoveSettingFromBundleRequestJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
}
var _ json.Unmarshaler = (*RemoveSettingFromBundleRequest)(nil)
// SaveValueRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of SaveValueRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
@@ -762,6 +1037,222 @@ func (m *Identifier) UnmarshalJSON(b []byte) error {
var _ json.Unmarshaler = (*Identifier)(nil)
// ListRoleAssignmentsRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of ListRoleAssignmentsRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
var ListRoleAssignmentsRequestJSONMarshaler = new(jsonpb.Marshaler)
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
// uses the more correct jsonpb package to correctly marshal the message.
func (m *ListRoleAssignmentsRequest) MarshalJSON() ([]byte, error) {
if m == nil {
return json.Marshal(nil)
}
buf := &bytes.Buffer{}
if err := ListRoleAssignmentsRequestJSONMarshaler.Marshal(buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var _ json.Marshaler = (*ListRoleAssignmentsRequest)(nil)
// ListRoleAssignmentsRequestJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
// instances of ListRoleAssignmentsRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
var ListRoleAssignmentsRequestJSONUnmarshaler = new(jsonpb.Unmarshaler)
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
// uses the more correct jsonpb package to correctly unmarshal the message.
func (m *ListRoleAssignmentsRequest) UnmarshalJSON(b []byte) error {
return ListRoleAssignmentsRequestJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
}
var _ json.Unmarshaler = (*ListRoleAssignmentsRequest)(nil)
// ListRoleAssignmentsResponseJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of ListRoleAssignmentsResponse. This struct is safe to replace or modify but
// should not be done so concurrently.
var ListRoleAssignmentsResponseJSONMarshaler = new(jsonpb.Marshaler)
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
// uses the more correct jsonpb package to correctly marshal the message.
func (m *ListRoleAssignmentsResponse) MarshalJSON() ([]byte, error) {
if m == nil {
return json.Marshal(nil)
}
buf := &bytes.Buffer{}
if err := ListRoleAssignmentsResponseJSONMarshaler.Marshal(buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var _ json.Marshaler = (*ListRoleAssignmentsResponse)(nil)
// ListRoleAssignmentsResponseJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
// instances of ListRoleAssignmentsResponse. This struct is safe to replace or modify but
// should not be done so concurrently.
var ListRoleAssignmentsResponseJSONUnmarshaler = new(jsonpb.Unmarshaler)
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
// uses the more correct jsonpb package to correctly unmarshal the message.
func (m *ListRoleAssignmentsResponse) UnmarshalJSON(b []byte) error {
return ListRoleAssignmentsResponseJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
}
var _ json.Unmarshaler = (*ListRoleAssignmentsResponse)(nil)
// AssignRoleToUserRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of AssignRoleToUserRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
var AssignRoleToUserRequestJSONMarshaler = new(jsonpb.Marshaler)
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
// uses the more correct jsonpb package to correctly marshal the message.
func (m *AssignRoleToUserRequest) MarshalJSON() ([]byte, error) {
if m == nil {
return json.Marshal(nil)
}
buf := &bytes.Buffer{}
if err := AssignRoleToUserRequestJSONMarshaler.Marshal(buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var _ json.Marshaler = (*AssignRoleToUserRequest)(nil)
// AssignRoleToUserRequestJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
// instances of AssignRoleToUserRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
var AssignRoleToUserRequestJSONUnmarshaler = new(jsonpb.Unmarshaler)
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
// uses the more correct jsonpb package to correctly unmarshal the message.
func (m *AssignRoleToUserRequest) UnmarshalJSON(b []byte) error {
return AssignRoleToUserRequestJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
}
var _ json.Unmarshaler = (*AssignRoleToUserRequest)(nil)
// AssignRoleToUserResponseJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of AssignRoleToUserResponse. This struct is safe to replace or modify but
// should not be done so concurrently.
var AssignRoleToUserResponseJSONMarshaler = new(jsonpb.Marshaler)
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
// uses the more correct jsonpb package to correctly marshal the message.
func (m *AssignRoleToUserResponse) MarshalJSON() ([]byte, error) {
if m == nil {
return json.Marshal(nil)
}
buf := &bytes.Buffer{}
if err := AssignRoleToUserResponseJSONMarshaler.Marshal(buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var _ json.Marshaler = (*AssignRoleToUserResponse)(nil)
// AssignRoleToUserResponseJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
// instances of AssignRoleToUserResponse. This struct is safe to replace or modify but
// should not be done so concurrently.
var AssignRoleToUserResponseJSONUnmarshaler = new(jsonpb.Unmarshaler)
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
// uses the more correct jsonpb package to correctly unmarshal the message.
func (m *AssignRoleToUserResponse) UnmarshalJSON(b []byte) error {
return AssignRoleToUserResponseJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
}
var _ json.Unmarshaler = (*AssignRoleToUserResponse)(nil)
// RemoveRoleFromUserRequestJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of RemoveRoleFromUserRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
var RemoveRoleFromUserRequestJSONMarshaler = new(jsonpb.Marshaler)
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
// uses the more correct jsonpb package to correctly marshal the message.
func (m *RemoveRoleFromUserRequest) MarshalJSON() ([]byte, error) {
if m == nil {
return json.Marshal(nil)
}
buf := &bytes.Buffer{}
if err := RemoveRoleFromUserRequestJSONMarshaler.Marshal(buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var _ json.Marshaler = (*RemoveRoleFromUserRequest)(nil)
// RemoveRoleFromUserRequestJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
// instances of RemoveRoleFromUserRequest. This struct is safe to replace or modify but
// should not be done so concurrently.
var RemoveRoleFromUserRequestJSONUnmarshaler = new(jsonpb.Unmarshaler)
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
// uses the more correct jsonpb package to correctly unmarshal the message.
func (m *RemoveRoleFromUserRequest) UnmarshalJSON(b []byte) error {
return RemoveRoleFromUserRequestJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
}
var _ json.Unmarshaler = (*RemoveRoleFromUserRequest)(nil)
// UserRoleAssignmentJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of UserRoleAssignment. This struct is safe to replace or modify but
// should not be done so concurrently.
var UserRoleAssignmentJSONMarshaler = new(jsonpb.Marshaler)
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
// uses the more correct jsonpb package to correctly marshal the message.
func (m *UserRoleAssignment) MarshalJSON() ([]byte, error) {
if m == nil {
return json.Marshal(nil)
}
buf := &bytes.Buffer{}
if err := UserRoleAssignmentJSONMarshaler.Marshal(buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var _ json.Marshaler = (*UserRoleAssignment)(nil)
// UserRoleAssignmentJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
// instances of UserRoleAssignment. This struct is safe to replace or modify but
// should not be done so concurrently.
var UserRoleAssignmentJSONUnmarshaler = new(jsonpb.Unmarshaler)
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
// uses the more correct jsonpb package to correctly unmarshal the message.
func (m *UserRoleAssignment) UnmarshalJSON(b []byte) error {
return UserRoleAssignmentJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
}
var _ json.Unmarshaler = (*UserRoleAssignment)(nil)
// ResourceJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of Resource. This struct is safe to replace or modify but
// should not be done so concurrently.
@@ -1086,6 +1577,42 @@ func (m *ListOption) UnmarshalJSON(b []byte) error {
var _ json.Unmarshaler = (*ListOption)(nil)
// PermissionJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of Permission. This struct is safe to replace or modify but
// should not be done so concurrently.
var PermissionJSONMarshaler = new(jsonpb.Marshaler)
// MarshalJSON satisfies the encoding/json Marshaler interface. This method
// uses the more correct jsonpb package to correctly marshal the message.
func (m *Permission) MarshalJSON() ([]byte, error) {
if m == nil {
return json.Marshal(nil)
}
buf := &bytes.Buffer{}
if err := PermissionJSONMarshaler.Marshal(buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var _ json.Marshaler = (*Permission)(nil)
// PermissionJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
// instances of Permission. This struct is safe to replace or modify but
// should not be done so concurrently.
var PermissionJSONUnmarshaler = new(jsonpb.Unmarshaler)
// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method
// uses the more correct jsonpb package to correctly unmarshal the message.
func (m *Permission) UnmarshalJSON(b []byte) error {
return PermissionJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
}
var _ json.Unmarshaler = (*Permission)(nil)
// ValueJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of Value. This struct is safe to replace or modify but
// should not be done so concurrently.

View File

@@ -24,6 +24,102 @@
"application/json"
],
"paths": {
"/api/v0/settings/assignments-add": {
"post": {
"operationId": "RoleService_AssignRoleToUser",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/protoAssignRoleToUserResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/protoAssignRoleToUserRequest"
}
}
],
"tags": [
"RoleService"
]
}
},
"/api/v0/settings/assignments-list": {
"post": {
"operationId": "RoleService_ListRoleAssignments",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/protoListRoleAssignmentsResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/protoListRoleAssignmentsRequest"
}
}
],
"tags": [
"RoleService"
]
}
},
"/api/v0/settings/assignments-remove": {
"post": {
"operationId": "RoleService_RemoveRoleFromUser",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"properties": {}
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/protoRemoveRoleFromUserRequest"
}
}
],
"tags": [
"RoleService"
]
}
},
"/api/v0/settings/bundle-get": {
"post": {
"operationId": "BundleService_GetBundle",
@@ -88,6 +184,38 @@
]
}
},
"/api/v0/settings/bundles-add-setting": {
"post": {
"operationId": "BundleService_AddSettingToBundle",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/protoAddSettingToBundleResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/protoAddSettingToBundleRequest"
}
}
],
"tags": [
"BundleService"
]
}
},
"/api/v0/settings/bundles-list": {
"post": {
"operationId": "BundleService_ListBundles",
@@ -120,6 +248,70 @@
]
}
},
"/api/v0/settings/bundles-remove-setting": {
"post": {
"operationId": "BundleService_RemoveSettingFromBundle",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"properties": {}
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/protoRemoveSettingFromBundleRequest"
}
}
],
"tags": [
"BundleService"
]
}
},
"/api/v0/settings/roles-list": {
"post": {
"operationId": "RoleService_ListRoles",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/protoListBundlesResponse"
}
},
"default": {
"description": "An unexpected error response",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/protoListBundlesRequest"
}
}
],
"tags": [
"RoleService"
]
}
},
"/api/v0/settings/value-get": {
"post": {
"operationId": "ValueService_GetValue",
@@ -250,6 +442,55 @@
}
},
"definitions": {
"PermissionConstraint": {
"type": "string",
"enum": [
"CONSTRAINT_UNKNOWN",
"CONSTRAINT_OWN",
"CONSTRAINT_SHARED",
"CONSTRAINT_ALL"
],
"default": "CONSTRAINT_UNKNOWN"
},
"protoAddSettingToBundleRequest": {
"type": "object",
"properties": {
"bundle_id": {
"type": "string"
},
"setting": {
"$ref": "#/definitions/protoSetting"
}
}
},
"protoAddSettingToBundleResponse": {
"type": "object",
"properties": {
"setting": {
"$ref": "#/definitions/protoSetting"
}
}
},
"protoAssignRoleToUserRequest": {
"type": "object",
"properties": {
"account_uuid": {
"type": "string"
},
"role_id": {
"type": "string",
"title": "the role_id is a bundle_id internally"
}
}
},
"protoAssignRoleToUserResponse": {
"type": "object",
"properties": {
"assignment": {
"$ref": "#/definitions/protoUserRoleAssignment"
}
}
},
"protoBool": {
"type": "object",
"properties": {
@@ -427,6 +668,25 @@
}
}
},
"protoListRoleAssignmentsRequest": {
"type": "object",
"properties": {
"account_uuid": {
"type": "string"
}
}
},
"protoListRoleAssignmentsResponse": {
"type": "object",
"properties": {
"assignments": {
"type": "array",
"items": {
"$ref": "#/definitions/protoUserRoleAssignment"
}
}
}
},
"protoListValue": {
"type": "object",
"properties": {
@@ -471,6 +731,47 @@
}
}
},
"protoPermission": {
"type": "object",
"properties": {
"operation": {
"$ref": "#/definitions/protoPermissionOperation"
},
"constraint": {
"$ref": "#/definitions/PermissionConstraint"
}
}
},
"protoPermissionOperation": {
"type": "string",
"enum": [
"OPERATION_UNKNOWN",
"OPERATION_CREATE",
"OPERATION_READ",
"OPERATION_UPDATE",
"OPERATION_DELETE"
],
"default": "OPERATION_UNKNOWN"
},
"protoRemoveRoleFromUserRequest": {
"type": "object",
"properties": {
"id": {
"type": "string"
}
}
},
"protoRemoveSettingFromBundleRequest": {
"type": "object",
"properties": {
"bundle_id": {
"type": "string"
},
"setting_id": {
"type": "string"
}
}
},
"protoResource": {
"type": "object",
"properties": {
@@ -519,8 +820,7 @@
"value": {
"$ref": "#/definitions/protoValue"
}
},
"title": "requests and responses for settings values"
}
},
"protoSaveValueResponse": {
"type": "object",
@@ -560,6 +860,9 @@
"multi_choice_value": {
"$ref": "#/definitions/protoMultiChoiceList"
},
"permission_value": {
"$ref": "#/definitions/protoPermission"
},
"resource": {
"$ref": "#/definitions/protoResource"
}
@@ -599,6 +902,22 @@
}
}
},
"protoUserRoleAssignment": {
"type": "object",
"properties": {
"id": {
"type": "string",
"title": "id is generated upon saving the assignment"
},
"account_uuid": {
"type": "string"
},
"role_id": {
"type": "string",
"title": "the role_id is a bundle_id internally"
}
}
},
"protoValue": {
"type": "object",
"properties": {

View File

@@ -28,6 +28,9 @@ func Server(opts ...Option) grpc.Service {
if err := proto.RegisterValueServiceHandler(service.Server(), handle); err != nil {
options.Logger.Fatal().Err(err).Msg("could not register SettingsValues service handler")
}
if err := proto.RegisterRoleServiceHandler(service.Server(), handle); err != nil {
options.Logger.Fatal().Err(err).Msg("could not register SettingsRoles service handler")
}
service.Init()
return service

View File

@@ -65,6 +65,7 @@ func Server(opts ...Option) http.Service {
mux.Route(options.Config.HTTP.Root, func(r chi.Router) {
proto.RegisterBundleServiceWeb(r, handle)
proto.RegisterValueServiceWeb(r, handle)
proto.RegisterRoleServiceWeb(r, handle)
})
service.Handle(

View File

@@ -2,6 +2,7 @@ package svc
import (
"context"
"github.com/golang/protobuf/ptypes/empty"
"github.com/owncloud/ocis-pkg/v2/log"
"github.com/owncloud/ocis-pkg/v2/middleware"
@@ -69,6 +70,28 @@ func (g Service) ListBundles(c context.Context, req *proto.ListBundlesRequest, r
return nil
}
// AddSettingToBundle implements the BundleServiceHandler interface
func (g Service) AddSettingToBundle(c context.Context, req *proto.AddSettingToBundleRequest, res *proto.AddSettingToBundleResponse) error {
cleanUpResource(c, req.Setting.Resource)
if validationError := validateAddSettingToBundle(req); validationError != nil {
return validationError
}
r, err := g.manager.AddSettingToBundle(req.BundleId, req.Setting)
if err != nil {
return err
}
res.Setting = r
return nil
}
// RemoveSettingFromBundle implements the BundleServiceHandler interface
func (g Service) RemoveSettingFromBundle(c context.Context, req *proto.RemoveSettingFromBundleRequest, _ *empty.Empty) error {
if validationError := validateRemoveSettingFromBundle(req); validationError != nil {
return validationError
}
return g.manager.RemoveSettingFromBundle(req.BundleId, req.SettingId)
}
// SaveValue implements the ValueServiceHandler interface
func (g Service) SaveValue(c context.Context, req *proto.SaveValueRequest, res *proto.SaveValueResponse) error {
req.Value.AccountUuid = getValidatedAccountUUID(c, req.Value.AccountUuid)
@@ -164,6 +187,56 @@ func (g Service) getValueWithIdentifier(value *proto.Value) (*proto.ValueWithIde
}, nil
}
// ListRoles implements the RoleServiceHandler interface
func (g Service) ListRoles(c context.Context, req *proto.ListBundlesRequest, res *proto.ListBundlesResponse) error {
req.AccountUuid = getValidatedAccountUUID(c, req.AccountUuid)
if validationError := validateListRoles(req); validationError != nil {
return validationError
}
r, err := g.manager.ListBundles(proto.Bundle_TYPE_ROLE)
if err != nil {
return err
}
res.Bundles = r
return nil
}
// ListRoleAssignments implements the RoleServiceHandler interface
func (g Service) ListRoleAssignments(c context.Context, req *proto.ListRoleAssignmentsRequest, res *proto.ListRoleAssignmentsResponse) error {
req.AccountUuid = getValidatedAccountUUID(c, req.AccountUuid)
if validationError := validateListRoleAssignments(req); validationError != nil {
return validationError
}
r, err := g.manager.ListRoleAssignments(req.AccountUuid)
if err != nil {
return err
}
res.Assignments = r
return nil
}
// AssignRoleToUser implements the RoleServiceHandler interface
func (g Service) AssignRoleToUser(c context.Context, req *proto.AssignRoleToUserRequest, res *proto.AssignRoleToUserResponse) error {
req.AccountUuid = getValidatedAccountUUID(c, req.AccountUuid)
if validationError := validateAssignRoleToUser(req); validationError != nil {
return validationError
}
r, err := g.manager.WriteRoleAssignment(req.AccountUuid, req.RoleId)
if err != nil {
return err
}
res.Assignment = r
return nil
}
// RemoveRoleFromUser implements the RoleServiceHandler interface
func (g Service) RemoveRoleFromUser(c context.Context, req *proto.RemoveRoleFromUserRequest, _ *empty.Empty) error {
if validationError := validateRemoveRoleFromUser(req); validationError != nil {
return validationError
}
return g.manager.RemoveRoleAssignment(req.Id)
}
// cleanUpResource makes sure that the account uuid of the authenticated user is injected if needed.
func cleanUpResource(c context.Context, resource *proto.Resource) {
if resource != nil && resource.Type == proto.Resource_TYPE_USER {

View File

@@ -11,7 +11,7 @@ import (
var (
regexForAccountUUID = regexp.MustCompile(`^[A-Za-z0-9\-_.+@]+$`)
requireAccountID = []validation.Rule{
validation.Required, // use rule for validation error message consistency (".. must not be blank" on empty strings)
validation.Required,// use rule for validation error message consistency (".. must not be blank" on empty strings)
validation.Match(regexForAccountUUID),
}
regexForKeys = regexp.MustCompile(`^[A-Za-z0-9\-_]*$`)
@@ -52,6 +52,24 @@ func validateListBundles(req *proto.ListBundlesRequest) error {
return validation.Validate(&req.AccountUuid, requireAccountID...)
}
func validateAddSettingToBundle(req *proto.AddSettingToBundleRequest) error {
if err := validation.ValidateStruct(
req,
validation.Field(&req.BundleId, is.UUID),
); err != nil {
return err
}
return validateSetting(req.Setting)
}
func validateRemoveSettingFromBundle(req *proto.RemoveSettingFromBundleRequest) error {
return validation.ValidateStruct(
req,
validation.Field(&req.BundleId, is.UUID),
validation.Field(&req.SettingId, is.UUID),
)
}
func validateSaveValue(req *proto.SaveValueRequest) error {
if err := validation.ValidateStruct(
req.Value,
@@ -83,6 +101,29 @@ func validateListValues(req *proto.ListValuesRequest) error {
)
}
func validateListRoles(req *proto.ListBundlesRequest) error {
return validation.Validate(&req.AccountUuid, requireAccountID...)
}
func validateListRoleAssignments(req *proto.ListRoleAssignmentsRequest) error {
return validation.Validate(req.AccountUuid, requireAccountID...)
}
func validateAssignRoleToUser(req *proto.AssignRoleToUserRequest) error {
return validation.ValidateStruct(
req,
validation.Field(&req.AccountUuid, requireAccountID...),
validation.Field(&req.RoleId, is.UUID),
)
}
func validateRemoveRoleFromUser(req *proto.RemoveRoleFromUserRequest) error {
return validation.ValidateStruct(
req,
validation.Field(&req.Id, is.UUID),
)
}
// validateResource is an internal helper for validating the content of a resource.
func validateResource(resource *proto.Resource) error {
if err := validation.Validate(&resource, validation.Required); err != nil {

View File

@@ -17,6 +17,7 @@ type RegisterFunc func(*config.Config) Manager
type Manager interface {
BundleManager
ValueManager
RoleAssignmentManager
}
// BundleManager is a bundle service interface for abstraction of storage implementations
@@ -25,6 +26,8 @@ type BundleManager interface {
ReadBundle(bundleID string) (*proto.Bundle, error)
WriteBundle(bundle *proto.Bundle) (*proto.Bundle, error)
ReadSetting(settingID string) (*proto.Setting, error)
AddSettingToBundle(bundleID string, setting *proto.Setting) (*proto.Setting, error)
RemoveSettingFromBundle(bundleID, settingID string) error
}
// ValueManager is a value service interface for abstraction of storage implementations
@@ -34,3 +37,10 @@ type ValueManager interface {
ReadValueByUniqueIdentifiers(accountUUID, settingID string) (*proto.Value, error)
WriteValue(value *proto.Value) (*proto.Value, error)
}
// RoleAssignmentManager is a role assignment service interface for abstraction of storage implementations
type RoleAssignmentManager interface {
ListRoleAssignments(accountUUID string) ([]*proto.UserRoleAssignment, error)
WriteRoleAssignment(accountUUID, roleID string) (*proto.UserRoleAssignment, error)
RemoveRoleAssignment(assignmentID string) error
}

View File

@@ -0,0 +1,68 @@
// Package store implements the go-micro store interface
package store
import (
"io/ioutil"
"os"
"path/filepath"
"github.com/gofrs/uuid"
"github.com/owncloud/ocis-settings/pkg/proto/v0"
)
// ListRoleAssignments loads and returns all role assignments matching the given assignment identifier.
func (s Store) ListRoleAssignments(accountUUID string) ([]*proto.UserRoleAssignment, error) {
var records []*proto.UserRoleAssignment
assignmentsFolder := s.buildFolderPathForRoleAssignments(false)
assignmentFiles, err := ioutil.ReadDir(assignmentsFolder)
if err != nil {
s.Logger.Error().Err(err).Str("assignmentFiles", assignmentsFolder).Msg("error reading assignment file")
return records, nil
}
for _, assignmentFile := range assignmentFiles {
record := proto.UserRoleAssignment{}
err = s.parseRecordFromFile(&record, filepath.Join(assignmentsFolder, assignmentFile.Name()))
if err == nil {
if record.AccountUuid == accountUUID {
records = append(records, &record)
}
}
}
return records, nil
}
// WriteRoleAssignment appends the given role assignment to the existing assignments of the respective account.
func (s Store) WriteRoleAssignment(accountUUID, roleID string) (*proto.UserRoleAssignment, error) {
// as per https://jira.owncloud.com/browse/OCIS-117 "Each user can have exactly one role"
list, err := s.ListRoleAssignments(accountUUID)
if err != nil {
return nil, err
}
if len(list) > 0 {
filePath := s.buildFilePathForRoleAssignment(list[0].Id, true)
if err := os.Remove(filePath); err != nil {
return nil, err
}
}
assignment := &proto.UserRoleAssignment{
Id: uuid.Must(uuid.NewV4()).String(),
AccountUuid: accountUUID,
RoleId: roleID,
}
filePath := s.buildFilePathForRoleAssignment(assignment.Id, true)
if err := s.writeRecordToFile(assignment, filePath); err != nil {
return nil, err
}
s.Logger.Debug().Msgf("request contents written to file: %v", filePath)
return assignment, nil
}
// RemoveRoleAssignment deletes the given role assignment from the existing assignments of the respective account.
func (s Store) RemoveRoleAssignment(assignmentID string) error {
filePath := s.buildFilePathForRoleAssignment(assignmentID, false)
return os.Remove(filePath)
}

View File

@@ -0,0 +1,178 @@
package store
import (
"errors"
"log"
"os"
"path/filepath"
"testing"
olog "github.com/owncloud/ocis-pkg/v2/log"
"github.com/owncloud/ocis-settings/pkg/proto/v0"
"github.com/stretchr/testify/assert"
)
var (
einstein = "a4d07560-a670-4be9-8d60-9b547751a208"
marie = "3c054db3-eec1-4ca4-b985-bc56dcf560cb"
s = Store{
dataPath: dataRoot,
Logger: logger,
}
logger = olog.NewLogger(
olog.Color(true),
olog.Pretty(true),
olog.Level("info"),
)
bundles = []*proto.Bundle{
{
Id: "f36db5e6-a03c-40df-8413-711c67e40b47",
Type: proto.Bundle_TYPE_ROLE,
DisplayName: "test role - reads | update",
Name: "TEST_ROLE",
Extension: "ocis-settings",
Resource: &proto.Resource{
Type: proto.Resource_TYPE_BUNDLE,
},
Settings: []*proto.Setting{
{
Name: "update",
Value: &proto.Setting_PermissionValue{
PermissionValue: &proto.Permission{
Operation: proto.Permission_OPERATION_UPDATE,
},
},
},
{
Name: "read",
Value: &proto.Setting_PermissionValue{
PermissionValue: &proto.Permission{
Operation: proto.Permission_OPERATION_READ,
},
},
},
},
},
{
Id: "44f1a664-0a7f-461a-b0be-5b59e46bbc7a",
Type: proto.Bundle_TYPE_ROLE,
DisplayName: "another",
Name: "ANOTHER_TEST_ROLE",
Extension: "ocis-settings",
Resource: &proto.Resource{
Type: proto.Resource_TYPE_BUNDLE,
},
Settings: []*proto.Setting{
{
Name: "read",
Value: &proto.Setting_PermissionValue{
PermissionValue: &proto.Permission{
Operation: proto.Permission_OPERATION_READ,
},
},
},
},
},
}
)
func init() {
setupRoles()
}
func setupRoles() {
for i := range bundles {
if _, err := s.WriteBundle(bundles[i]); err != nil {
log.Fatal(err)
}
}
}
func TestAssignmentUniqueness(t *testing.T) {
var scenarios = []struct {
name string
userID string
firstRole string
secondRole string
}{
{
"roles assignments",
einstein,
"f36db5e6-a03c-40df-8413-711c67e40b47",
"44f1a664-0a7f-461a-b0be-5b59e46bbc7a",
},
}
for _, scenario := range scenarios {
scenario := scenario
t.Run(scenario.name, func(t *testing.T) {
firstAssignment, err := s.WriteRoleAssignment(scenario.userID, scenario.firstRole)
assert.NoError(t, err)
assert.Equal(t, firstAssignment.RoleId, scenario.firstRole)
assert.FileExists(t, filepath.Join(dataRoot, "assignments", firstAssignment.Id+".json"))
list, err := s.ListRoleAssignments(scenario.userID)
assert.NoError(t, err)
assert.Equal(t, 1, len(list))
// creating another assignment shouldn't add another entry, as we support max one role per user.
secondAssignment, err := s.WriteRoleAssignment(scenario.userID, scenario.secondRole)
assert.NoError(t, err)
assert.Equal(t, 1, len(list))
// assigning the second role should remove the old file and create a new one.
list, err = s.ListRoleAssignments(scenario.userID)
assert.NoError(t, err)
assert.Equal(t, 1, len(list))
assert.Equal(t, secondAssignment.RoleId, scenario.secondRole)
assert.NoFileExists(t, filepath.Join(dataRoot, "assignments", firstAssignment.Id+".json"))
assert.FileExists(t, filepath.Join(dataRoot, "assignments", secondAssignment.Id+".json"))
})
}
burnRoot()
}
func TestDeleteAssignment(t *testing.T) {
var scenarios = []struct {
name string
userID string
firstRole string
secondRole string
}{
{
"roles assignments",
einstein,
"f36db5e6-a03c-40df-8413-711c67e40b47",
"44f1a664-0a7f-461a-b0be-5b59e46bbc7a",
},
}
for _, scenario := range scenarios {
scenario := scenario
t.Run(scenario.name, func(t *testing.T) {
assignment, err := s.WriteRoleAssignment(scenario.userID, scenario.firstRole)
assert.NoError(t, err)
assert.Equal(t, assignment.RoleId, scenario.firstRole)
assert.FileExists(t, filepath.Join(dataRoot, "assignments", assignment.Id+".json"))
list, err := s.ListRoleAssignments(scenario.userID)
assert.NoError(t, err)
assert.Equal(t, 1, len(list))
err = s.RemoveRoleAssignment(assignment.Id)
assert.NoError(t, err)
list, err = s.ListRoleAssignments(scenario.userID)
assert.NoError(t, err)
assert.Equal(t, 0, len(list))
err = s.RemoveRoleAssignment(assignment.Id)
merr := &os.PathError{}
assert.Equal(t, true, errors.As(err, &merr))
})
}
burnRoot()
}

View File

@@ -95,3 +95,67 @@ func (s Store) WriteBundle(record *proto.Bundle) (*proto.Bundle, error) {
s.Logger.Debug().Msgf("request contents written to file: %v", filePath)
return record, nil
}
// AddSettingToBundle adds the given setting to the bundle with the given bundleID.
func (s Store) AddSettingToBundle(bundleID string, setting *proto.Setting) (*proto.Setting, error) {
bundle, err := s.ReadBundle(bundleID)
if err != nil {
return nil, err
}
if setting.Id == "" {
setting.Id = uuid.Must(uuid.NewV4()).String()
}
setSetting(bundle, setting)
_, err = s.WriteBundle(bundle)
if err != nil {
return nil, err
}
return setting, nil
}
// RemoveSettingFromBundle removes the setting from the bundle with the given ids.
func (s Store) RemoveSettingFromBundle(bundleID string, settingID string) error {
bundle, err := s.ReadBundle(bundleID)
if err != nil {
return nil
}
removeSetting(bundle, settingID)
_, err = s.WriteBundle(bundle)
return err
}
// indexOfSetting finds the index of the given setting within the given bundle.
// returns -1 if the setting was not found.
func indexOfSetting(bundle *proto.Bundle, settingID string) int {
for index := range bundle.Settings {
s := bundle.Settings[index]
if s.Id == settingID {
return index
}
}
return -1
}
// setSetting will append or overwrite the given setting within the given bundle
func setSetting(bundle *proto.Bundle, setting *proto.Setting) {
m.Lock()
defer m.Unlock()
index := indexOfSetting(bundle, setting.Id)
if index == -1 {
bundle.Settings = append(bundle.Settings, setting)
} else {
bundle.Settings[index] = setting
}
}
// removeSetting will remove the given setting from the given bundle
func removeSetting(bundle *proto.Bundle, settingID string) bool {
m.Lock()
defer m.Unlock()
index := indexOfSetting(bundle, settingID)
if index == -1 {
return false
}
bundle.Settings = append(bundle.Settings[:index], bundle.Settings[index+1:]...)
return true
}

View File

@@ -70,6 +70,35 @@ var bundleScenarios = []struct {
},
},
},
{
name: "generic-test-role-bundle",
bundle: &proto.Bundle{
Id: bundle3,
Type: proto.Bundle_TYPE_ROLE,
Extension: extension1,
DisplayName: "Role1",
Resource: &proto.Resource{
Type: proto.Resource_TYPE_SYSTEM,
},
Settings: []*proto.Setting{
{
Id: setting3,
Description: "test-desc-3",
DisplayName: "test-displayname-3",
Resource: &proto.Resource{
Type: proto.Resource_TYPE_SETTING,
Id: setting1,
},
Value: &proto.Setting_PermissionValue{
PermissionValue: &proto.Permission{
Operation: proto.Permission_OPERATION_READ,
Constraint: proto.Permission_CONSTRAINT_OWN,
},
},
},
},
},
},
}
func TestBundles(t *testing.T) {

View File

@@ -7,6 +7,7 @@ import (
const folderNameBundles = "bundles"
const folderNameValues = "values"
const folderNameAssignments = "assignments"
// buildFolderPathForBundles builds the folder path for storing settings bundles. If mkdir is true, folders in the path will be created if necessary.
func (s Store) buildFolderPathForBundles(mkdir bool) string {
@@ -38,6 +39,21 @@ func (s Store) buildFilePathForValue(valueID string, mkdir bool) string {
return filepath.Join(extensionFolder, valueID+".json")
}
// buildFolderPathForRoleAssignments builds the folder path for storing role assignments. If mkdir is true, folders in the path will be created if necessary.
func (s Store) buildFolderPathForRoleAssignments(mkdir bool) string {
roleAssignmentsFolder := filepath.Join(s.dataPath, folderNameAssignments)
if mkdir {
s.ensureFolderExists(roleAssignmentsFolder)
}
return roleAssignmentsFolder
}
// buildFilePathForRoleAssignment builds a unique file name from the given params. If mkdir is true, folders in the path will be created if necessary.
func (s Store) buildFilePathForRoleAssignment(assignmentID string, mkdir bool) string {
roleAssignmentsFolder := s.buildFolderPathForRoleAssignments(mkdir)
return filepath.Join(roleAssignmentsFolder, assignmentID+".json")
}
// ensureFolderExists checks if the given path is an existing folder and creates one if not existing
func (s Store) ensureFolderExists(path string) {
if _, err := os.Stat(path); os.IsNotExist(err) {

View File

@@ -18,12 +18,12 @@ const (
// bundle ids
bundle1 = "2f06addf-4fd2-49d5-8f71-00fbd3a3ec47"
bundle2 = "2d745744-749c-4286-8e92-74a24d8331c5"
//bundle3 = "d8fd27d1-c00b-4794-a658-416b756a72ff"
bundle3 = "d8fd27d1-c00b-4794-a658-416b756a72ff"
// setting ids
setting1 = "c7ebbc8b-d15a-4f2e-9d7d-d6a4cf858d1a"
setting2 = "3fd9a3d9-20b7-40d4-9294-b22bb5868c10"
//setting3 = "24bb9535-3df4-42f1-a622-7c0562bec99f"
setting3 = "24bb9535-3df4-42f1-a622-7c0562bec99f"
// value ids
value1 = "fd3b6221-dc13-4a22-824d-2480495f1cdb"