1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-04-24 13:48:49 +08:00

NOISSUE: Fix Response , SDK, Listing of users with Relation (#1935)

* fix: response of requests

Signed-off-by: Arvindh <arvindh91@gmail.com>

* fix: sdk url

Signed-off-by: Arvindh <arvindh91@gmail.com>

* fix: listing of users with relation

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: Arvindh <arvindh91@gmail.com>
This commit is contained in:
Arvindh 2023-10-18 19:28:14 +05:30 committed by GitHub
parent 89fcf1207d
commit 75b37e078f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 149 additions and 63 deletions

View File

@ -8,6 +8,35 @@ import (
"encoding/json"
)
const (
TokenKind = "token"
GroupsKind = "groups"
ChannelsKind = "channels"
ThingsKind = "things"
UsersKind = "users"
GroupType = "group"
ChannelType = "channel"
ThingType = "thing"
UserType = "user"
OwnerRelation = "owner"
AdminRelation = "admin"
EditorRelation = "editor"
ViewerRelation = "viewer"
ParentGroupRelation = "parent_group"
RoleGroupRelation = "role_group"
GroupRelation = "group"
AdministratorPermission = "administrator"
DeletePermission = "delete"
EditPermission = "edit"
ViewPermission = "view"
SharePermission = "share"
PublishPermission = "publish"
SubscribePermission = "subscribe"
)
// PolicyReq represents an argument struct for making a policy related
// function calls.
type PolicyReq struct {

View File

@ -404,3 +404,19 @@ func (svc service) authenticate(token string) (string, string, error) {
return key.Issuer, key.Subject, nil
}
// Switch the relative permission for the relation
func SwitchToPermission(relation string) string {
switch relation {
case OwnerRelation:
return AdministratorPermission
case AdminRelation:
return AdministratorPermission
case EditorRelation:
return EditPermission
case ViewerRelation:
return ViewPermission
default:
return relation
}
}

View File

@ -16,12 +16,12 @@ func CreateGroupEndpoint(svc groups.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(createGroupReq)
if err := req.validate(); err != nil {
return createGroupRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
group, err := svc.CreateGroup(ctx, req.token, req.Group)
if err != nil {
return createGroupRes{}, err
return nil, err
}
return createGroupRes{created: true, Group: group}, nil
@ -32,12 +32,12 @@ func ViewGroupEndpoint(svc groups.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(groupReq)
if err := req.validate(); err != nil {
return viewGroupRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
group, err := svc.ViewGroup(ctx, req.token, req.id)
if err != nil {
return viewGroupRes{}, err
return nil, err
}
return viewGroupRes{Group: group}, nil
@ -48,7 +48,7 @@ func UpdateGroupEndpoint(svc groups.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(updateGroupReq)
if err := req.validate(); err != nil {
return updateGroupRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
group := groups.Group{
@ -60,7 +60,7 @@ func UpdateGroupEndpoint(svc groups.Service) endpoint.Endpoint {
group, err := svc.UpdateGroup(ctx, req.token, group)
if err != nil {
return updateGroupRes{}, err
return nil, err
}
return updateGroupRes{Group: group}, nil
@ -102,11 +102,11 @@ func ListGroupsEndpoint(svc groups.Service, memberKind string) endpoint.Endpoint
req.memberKind = memberKind
}
if err := req.validate(); err != nil {
return groupPageRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
page, err := svc.ListGroups(ctx, req.token, req.memberKind, req.memberID, req.Page)
if err != nil {
return groupPageRes{}, err
return nil, err
}
if req.tree {
@ -124,12 +124,12 @@ func ListMembersEndpoint(svc groups.Service, memberKind string) endpoint.Endpoin
req.memberKind = memberKind
}
if err := req.validate(); err != nil {
return membershipPageRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
page, err := svc.ListMembers(ctx, req.token, req.groupID, req.permission, req.memberKind)
if err != nil {
return membershipPageRes{}, err
return nil, err
}
return listMembersRes{
@ -172,7 +172,7 @@ func UnassignMembersEndpoint(svc groups.Service, relation string, memberKind str
req.MemberKind = memberKind
}
if err := req.validate(); err != nil {
return membershipPageRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
if err := svc.Unassign(ctx, req.token, req.groupID, req.Relation, req.MemberKind, req.Members...); err != nil {

View File

@ -158,7 +158,7 @@ func (res changeStatusRes) Empty() bool {
type assignRes struct{}
func (res assignRes) Code() int {
return http.StatusOK
return http.StatusCreated
}
func (res assignRes) Headers() map[string]string {

View File

@ -152,7 +152,7 @@ func (sdk mfSDK) AddUserToChannel(channelID string, req UsersRelationRequest, to
return errors.NewSDKError(err)
}
url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, usersEndpoint)
url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, usersEndpoint, assignEndpoint)
_, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusOK)
return sdkerr
@ -164,9 +164,9 @@ func (sdk mfSDK) RemoveUserFromChannel(channelID string, req UsersRelationReques
return errors.NewSDKError(err)
}
url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, usersEndpoint)
url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, usersEndpoint, unassignEndpoint)
_, _, sdkerr := sdk.processRequest(http.MethodDelete, url, token, data, nil, http.StatusOK)
_, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusOK)
return sdkerr
}
@ -193,7 +193,7 @@ func (sdk mfSDK) AddUserGroupToChannel(channelID string, req UserGroupsRequest,
return errors.NewSDKError(err)
}
url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, groupsEndpoint)
url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, groupsEndpoint, assignEndpoint)
_, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusOK)
return sdkerr
@ -205,9 +205,9 @@ func (sdk mfSDK) RemoveUserGroupFromChannel(channelID string, req UserGroupsRequ
return errors.NewSDKError(err)
}
url := fmt.Sprintf("%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, groupsEndpoint)
url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, groupsEndpoint, unassignEndpoint)
_, _, sdkerr := sdk.processRequest(http.MethodDelete, url, token, data, nil, http.StatusOK)
_, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusOK)
return sdkerr
}
@ -255,7 +255,7 @@ func (sdk mfSDK) Disconnect(connIDs Connection, token string) errors.SDKError {
}
func (sdk mfSDK) ConnectThing(thingID, channelID, token string) errors.SDKError {
url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, thingsEndpoint, thingID)
url := fmt.Sprintf("%s/%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, thingsEndpoint, thingID, connectEndpoint)
_, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, nil, nil, http.StatusNoContent)
@ -263,9 +263,9 @@ func (sdk mfSDK) ConnectThing(thingID, channelID, token string) errors.SDKError
}
func (sdk mfSDK) DisconnectThing(thingID, channelID, token string) errors.SDKError {
url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, thingsEndpoint, thingID)
url := fmt.Sprintf("%s/%s/%s/%s/%s/%s", sdk.thingsURL, channelsEndpoint, channelID, thingsEndpoint, thingID, disconnectEndpoint)
_, _, sdkerr := sdk.processRequest(http.MethodDelete, url, token, nil, nil, http.StatusNoContent)
_, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, nil, nil, http.StatusNoContent)
return sdkerr
}

View File

@ -151,7 +151,7 @@ func (sdk mfSDK) AddUserToGroup(groupID string, req UsersRelationRequest, token
return errors.NewSDKError(err)
}
url := fmt.Sprintf("%s/%s/%s/%s", sdk.usersURL, groupsEndpoint, groupID, usersEndpoint)
url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.usersURL, groupsEndpoint, groupID, usersEndpoint, assignEndpoint)
_, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusOK)
return sdkerr
@ -163,9 +163,9 @@ func (sdk mfSDK) RemoveUserFromGroup(groupID string, req UsersRelationRequest, t
return errors.NewSDKError(err)
}
url := fmt.Sprintf("%s/%s/%s/%s", sdk.usersURL, groupsEndpoint, groupID, usersEndpoint)
url := fmt.Sprintf("%s/%s/%s/%s/%s", sdk.usersURL, groupsEndpoint, groupID, usersEndpoint, unassignEndpoint)
_, _, sdkerr := sdk.processRequest(http.MethodDelete, url, token, data, nil, http.StatusOK)
_, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusOK)
return sdkerr
}

View File

@ -14,6 +14,8 @@ import (
const (
usersEndpoint = "users"
assignEndpoint = "assign"
unassignEndpoint = "unassign"
enableEndpoint = "enable"
disableEndpoint = "disable"
issueTokenEndpoint = "tokens/issue"

View File

@ -18,12 +18,12 @@ func createClientEndpoint(svc things.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(createClientReq)
if err := req.validate(); err != nil {
return createClientRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
client, err := svc.CreateThings(ctx, req.token, req.client)
if err != nil {
return createClientRes{}, err
return nil, err
}
return createClientRes{
@ -37,12 +37,12 @@ func createClientsEndpoint(svc things.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(createClientsReq)
if err := req.validate(); err != nil {
return clientsPageRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
page, err := svc.CreateThings(ctx, req.token, req.Clients...)
if err != nil {
return clientsPageRes{}, err
return nil, err
}
res := clientsPageRes{
@ -79,7 +79,7 @@ func listClientsEndpoint(svc things.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(listClientsReq)
if err := req.validate(); err != nil {
return mfclients.ClientsPage{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
pm := mfclients.Page{
@ -94,7 +94,7 @@ func listClientsEndpoint(svc things.Service) endpoint.Endpoint {
}
page, err := svc.ListClients(ctx, req.token, req.userID, pm)
if err != nil {
return mfclients.ClientsPage{}, err
return nil, err
}
res := clientsPageRes{
@ -117,12 +117,12 @@ func listMembersEndpoint(svc things.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(listMembersReq)
if err := req.validate(); err != nil {
return memberPageRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
page, err := svc.ListClientsByGroup(ctx, req.token, req.groupID, req.Page)
if err != nil {
return memberPageRes{}, err
return nil, err
}
return buildMembersResponse(page), nil
@ -348,11 +348,11 @@ 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 connectChannelThingRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
if err := svc.Assign(ctx, req.token, req.ChannelID, "group", "things", req.ThingID); err != nil {
return connectChannelThingRes{}, err
return nil, err
}
return connectChannelThingRes{}, nil
@ -363,11 +363,11 @@ func disconnectEndpoint(svc groups.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(disconnectChannelThingRequest)
if err := req.validate(); err != nil {
return disconnectChannelThingRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
if err := svc.Unassign(ctx, req.token, req.ChannelID, "group", "things", req.ThingID); err != nil {
return disconnectChannelThingRes{}, err
return nil, err
}
return disconnectChannelThingRes{}, nil
@ -378,11 +378,11 @@ func thingShareEndpoint(svc things.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(thingShareRequest)
if err := req.validate(); err != nil {
return thingShareRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
if err := svc.Share(ctx, req.token, req.thingID, req.Relation, req.UserIDs...); err != nil {
return thingShareRes{}, err
return nil, err
}
return thingShareRes{}, nil
@ -393,11 +393,11 @@ func thingUnshareEndpoint(svc things.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(thingUnshareRequest)
if err := req.validate(); err != nil {
return thingUnshareRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
if err := svc.Unshare(ctx, req.token, req.thingID, req.Relation, req.UserIDs...); err != nil {
return thingShareRes{}, err
return nil, err
}
return thingUnshareRes{}, nil

View File

@ -158,7 +158,7 @@ func (res deleteClientRes) Empty() bool {
type assignUsersGroupsRes struct{}
func (res assignUsersGroupsRes) Code() int {
return http.StatusOK
return http.StatusCreated
}
func (res assignUsersGroupsRes) Headers() map[string]string {
@ -186,7 +186,7 @@ func (res unassignUsersGroupsRes) Empty() bool {
type assignUsersRes struct{}
func (res assignUsersRes) Code() int {
return http.StatusOK
return http.StatusCreated
}
func (res assignUsersRes) Headers() map[string]string {
@ -214,7 +214,7 @@ func (res unassignUsersRes) Empty() bool {
type assignUserGroupsRes struct{}
func (res assignUserGroupsRes) Code() int {
return http.StatusOK
return http.StatusCreated
}
func (res assignUserGroupsRes) Headers() map[string]string {
@ -242,7 +242,7 @@ func (res unassignUserGroupsRes) Empty() bool {
type connectChannelThingRes struct{}
func (res connectChannelThingRes) Code() int {
return http.StatusOK
return http.StatusCreated
}
func (res connectChannelThingRes) Headers() map[string]string {
@ -270,7 +270,7 @@ func (res disconnectChannelThingRes) Empty() bool {
type thingShareRes struct{}
func (res thingShareRes) Code() int {
return http.StatusOK
return http.StatusCreated
}
func (res thingShareRes) Headers() map[string]string {

View File

@ -17,12 +17,12 @@ func registrationEndpoint(svc users.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(createClientReq)
if err := req.validate(); err != nil {
return createClientRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
client, err := svc.RegisterClient(ctx, req.token, req.client)
if err != nil {
return createClientRes{}, err
return nil, err
}
return createClientRes{
@ -68,7 +68,7 @@ func listClientsEndpoint(svc users.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(listClientsReq)
if err := req.validate(); err != nil {
return mfclients.ClientsPage{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
pm := mfclients.Page{
@ -83,7 +83,7 @@ func listClientsEndpoint(svc users.Service) endpoint.Endpoint {
}
page, err := svc.ListClients(ctx, req.token, pm)
if err != nil {
return mfclients.ClientsPage{}, err
return nil, err
}
res := clientsPageRes{
@ -107,12 +107,12 @@ func listMembersByGroupEndpoint(svc users.Service) endpoint.Endpoint {
req := request.(listMembersByObjectReq)
req.objectKind = "groups"
if err := req.validate(); err != nil {
return memberPageRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
page, err := svc.ListMembers(ctx, req.token, req.objectKind, req.objectID, req.Page)
if err != nil {
return memberPageRes{}, err
return nil, err
}
return buildMembersResponse(page), nil
@ -125,12 +125,12 @@ func listMembersByChannelEndpoint(svc users.Service) endpoint.Endpoint {
// In spiceDB schema, using the same 'group' type for both channels and groups, rather than having a separate type for channels.
req.objectKind = "groups"
if err := req.validate(); err != nil {
return memberPageRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
page, err := svc.ListMembers(ctx, req.token, req.objectKind, req.objectID, req.Page)
if err != nil {
return memberPageRes{}, err
return nil, err
}
return buildMembersResponse(page), nil
@ -142,12 +142,12 @@ func listMembersByThingEndpoint(svc users.Service) endpoint.Endpoint {
req := request.(listMembersByObjectReq)
req.objectKind = "things"
if err := req.validate(); err != nil {
return memberPageRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
page, err := svc.ListMembers(ctx, req.token, req.objectKind, req.objectID, req.Page)
if err != nil {
return memberPageRes{}, err
return nil, err
}
return buildMembersResponse(page), nil

View File

@ -143,10 +143,10 @@ func assignUsersEndpoint(svc groups.Service) endpoint.Endpoint {
req := request.(assignUsersReq)
if err := req.validate(); err != nil {
return assignUsersRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
if err := svc.Assign(ctx, req.token, req.groupID, req.Relation, "users", req.UserIDs...); err != nil {
return assignUsersRes{}, err
return nil, err
}
return assignUsersRes{}, nil
}
@ -157,7 +157,7 @@ func unassignUsersEndpoint(svc groups.Service) endpoint.Endpoint {
req := request.(unassignUsersReq)
if err := req.validate(); err != nil {
return unassignUsersRes{}, errors.Wrap(apiutil.ErrValidation, err)
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
if err := svc.Unassign(ctx, req.token, req.groupID, req.Relation, "users", req.UserIDs...); err != nil {

View File

@ -206,7 +206,7 @@ func (res passwChangeRes) Empty() bool {
type assignUsersRes struct{}
func (res assignUsersRes) Code() int {
return http.StatusOK
return http.StatusCreated
}
func (res assignUsersRes) Headers() map[string]string {
@ -214,7 +214,7 @@ func (res assignUsersRes) Headers() map[string]string {
}
func (res assignUsersRes) Empty() bool {
return false
return true
}
type unassignUsersRes struct{}
@ -228,5 +228,5 @@ func (res unassignUsersRes) Headers() map[string]string {
}
func (res unassignUsersRes) Empty() bool {
return false
return true
}

View File

@ -17,6 +17,8 @@ import (
)
const (
ownerRelation = "owner"
userKind = "users"
tokenKind = "token"
thingsKind = "things"
@ -88,6 +90,10 @@ func (svc service) RegisterClient(ctx context.Context, token string, cli mfclien
return mfclients.Client{}, err
}
if err := svc.addOwnerPolicy(ctx, ownerID, client.ID); err != nil {
return mfclients.Client{}, err
}
return client, nil
}
@ -322,6 +328,9 @@ func (svc service) UpdateClientOwner(ctx context.Context, token string, cli mfcl
UpdatedBy: tokenUserID,
}
if err := svc.updateOwnerPolicy(ctx, tokenUserID, cli.Owner, cli.ID); err != nil {
return mfclients.Client{}, err
}
return svc.clients.UpdateOwner(ctx, client)
}
@ -383,7 +392,7 @@ func (svc service) ListMembers(ctx context.Context, token, objectKind string, ob
objectType = groupType
}
if _, err := svc.authorize(ctx, userType, tokenKind, token, pm.Permission, objectType, objectID); err != nil {
if _, err := svc.authorize(ctx, userType, tokenKind, token, auth.SwitchToPermission(pm.Permission), objectType, objectID); err != nil {
return mfclients.MembersPage{}, err
}
uids, err := svc.auth.ListAllSubjects(ctx, &mainflux.ListSubjectsReq{
@ -415,7 +424,8 @@ func (svc service) ListMembers(ctx context.Context, token, objectKind string, ob
}
func (svc *service) isOwner(ctx context.Context, clientID, ownerID string) error {
return svc.clients.IsOwner(ctx, clientID, ownerID)
_, err := svc.authorize(ctx, userType, userKind, ownerID, ownerRelation, userType, clientID)
return err
}
func (svc *service) authorize(ctx context.Context, subjType, subjKind, subj, perm, objType, obj string) (string, error) {
@ -445,3 +455,32 @@ func (svc service) Identify(ctx context.Context, token string) (string, error) {
}
return user.GetId(), nil
}
func (svc service) updateOwnerPolicy(ctx context.Context, previousOwnerID, ownerID, userID string) error {
if previousOwnerID != "" {
if _, err := svc.auth.DeletePolicy(ctx, &mainflux.DeletePolicyReq{
SubjectType: userType,
Subject: previousOwnerID,
Relation: ownerRelation,
ObjectType: userType,
Object: userID,
}); err != nil {
return err
}
}
return svc.addOwnerPolicy(ctx, ownerID, userID)
}
func (svc service) addOwnerPolicy(ctx context.Context, ownerID, userID string) error {
if ownerID != "" {
if _, err := svc.auth.AddPolicy(ctx, &mainflux.AddPolicyReq{
SubjectType: userType,
Subject: ownerID,
Relation: ownerRelation,
ObjectType: userType,
Object: userID,
}); err != nil {
return err
}
}
return nil
}