Open arvindh123 opened 6 months ago
@felixgateru We can achieve this Ticket with following changes
Changing the spiceDB definition for things like given below
File location : docker/spicedb/schema.zed
definition thing {
relation administrator: user
- relation group: group
+ relation publisher: group
+ relation subscriber: group
relation domain: domain
permission admin = administrator + group->admin + domain->admin
permission delete = admin
permission edit = admin + group->edit + domain->edit
permission view = edit + group->view + domain->view
permission share = edit
permission publish = group
permission subscribe = group
+ permission connect = publish + subscribe
// These permission are made for only list purpose. It helps to list users have only particular permission excluding other higher and lower permission.
permission admin_only = admin
permission edit_only = edit - admin
permission viewer_only = view - edit
// These permission are made for only list purpose. It helps to list users from external, users who are not in group but have permission on the group through parent group
permission ext_admin = admin - administrator // For list of external admin , not having direct relation with group, but have indirect relation from parent group
}
Then we need add new optional json field with name relation
in thing channel connect request .
relation
field should be a string array and support only two options publish
and subscribe
So we need to modify exactly at connectChannelThingRequest
in things/api/http/requests.go
, and also it validation function
type connectChannelThingRequest struct {
token string
ThingID string `json:"thing_id,omitempty"`
ChannelID string `json:"channel_id,omitempty"`
+ Relation string `json:"relation,omitempty"`
}
func (req *connectChannelThingRequest) validate() error {
if req.ThingID == "" || req.ChannelID == "" {
return apiutil.ErrMissingID
}
+ if req.Relation != auth.Publisher || req.Relation != auth.Publisher {
+ return apiutil.ErrInvalidRelation
+ }
return nil
}
Then we need to modify connectChannelThingEndpoint
and connectEndpoint
in things/api/http/endpoints.go
func connectChannelThingEndpoint(svc groups.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(connectChannelThingRequest)
if err := req.validate(); err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
- if err := svc.Assign(ctx, req.token, req.ChannelID, auth.GroupRelation, auth.ThingsKind, req.ThingID); err != nil {
+ if err := svc.Assign(ctx, req.token, req.ChannelID, req,Relation, auth.ThingsKind, req.ThingID); err != nil {
return nil, err
}
return connectChannelThingRes{}, nil
}
}
func connectEndpoint(svc groups.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(connectChannelThingRequest)
if err := req.validate(); err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
- if err := svc.Assign(ctx, req.token, req.ChannelID, auth.GroupRelation, auth.ThingsKind, req.ThingID); err != nil {
+ if err := svc.Assign(ctx, req.token, req.ChannelID, req.Relation, auth.ThingsKind, req.ThingID); err != nil {
return nil, err
}
return connectChannelThingRes{}, nil
}
}
Then we need to change the Thing relation assign logic in internal/groups/service.go
func (svc service) Assign(ctx context.Context, token, groupID, relation, memberKind string, memberIDs ...string) error {
res, err := svc.identify(ctx, token)
if err != nil {
return err
}
if _, err := svc.authorizeKind(ctx, res.GetDomainId(), auth.UserType, auth.UsersKind, res.GetId(), auth.EditPermission, auth.GroupType, groupID); err != nil {
return err
}
policies := magistrala.AddPoliciesReq{}
switch memberKind {
case auth.ThingsKind:
+ var thingRelations []string = []string{auth.PublisherRelation, auth.SubscriberRelation}
+ if relation == "" {
+ thingRelations = []string{relation}
+ }
+ for _, relation := range thingRelations {
for _, memberID := range memberIDs {
policies.AddPoliciesReq = append(policies.AddPoliciesReq, &magistrala.AddPolicyReq{
Domain: res.GetDomainId(),
SubjectType: auth.GroupType,
SubjectKind: auth.ChannelsKind,
Subject: groupID,
Relation: relation,
ObjectType: auth.ThingType,
Object: memberID,
})
}
+ }
case auth.ChannelsKind:
for _, memberID := range memberIDs {
policies.AddPoliciesReq = append(policies.AddPoliciesReq, &magistrala.AddPolicyReq{
Domain: res.GetDomainId(),
SubjectType: auth.GroupType,
Subject: memberID,
Relation: relation,
ObjectType: auth.GroupType,
Object: groupID,
})
}
case auth.GroupsKind:
return svc.assignParentGroup(ctx, res.GetDomainId(), groupID, memberIDs)
case auth.UsersKind:
for _, memberID := range memberIDs {
policies.AddPoliciesReq = append(policies.AddPoliciesReq, &magistrala.AddPolicyReq{
Domain: res.GetDomainId(),
SubjectType: auth.UserType,
Subject: auth.EncodeDomainUserID(res.GetDomainId(), memberID),
Relation: relation,
ObjectType: auth.GroupType,
Object: groupID,
})
}
default:
return errMemberKind
}
if _, err := svc.auth.AddPolicies(ctx, &policies); err != nil {
return errors.Wrap(svcerr.ErrAddPolicies, err)
}
return nil
}
Is your feature request related to a problem? Please describe.
Things could not be related to groups as subscribe or publish relation , Instead group related to thing as publish or subscribe relation . In present case , thing is object and group becomes subject.
Subject is Group(channel) Object is Thing
Because of this we could not check
thing
(Subject) havepublish
permission ongroup
(Object)At present it will work like
group
(Subject) havepublish
permission onthing
(Object)Describe the feature you are requesting, as well as the possible use case(s) for it.
Actually, thing should be subject and group should be object.
So if we have like above we can do permission check like
thing
havepublish
permission ongroup
This changes will lead to change in service logic for
List thing channels
andList channel things
Indicate the importance of this feature to you.
Must-have
Anything else?
No response