Skip to content

Commit

Permalink
add: groups event consumer & listing of things
Browse files Browse the repository at this point in the history
Signed-off-by: Arvindh <[email protected]>
  • Loading branch information
arvindh123 committed Jan 8, 2025
1 parent d89c199 commit ca260c1
Show file tree
Hide file tree
Showing 37 changed files with 1,690 additions and 294 deletions.
107 changes: 78 additions & 29 deletions clients/api/http/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
api "github.com/absmach/supermq/api/http"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/clients"
"github.com/absmach/supermq/groups"
"github.com/absmach/supermq/pkg/errors"
"github.com/go-chi/chi/v5"
)
Expand All @@ -27,58 +28,106 @@ func decodeViewClient(_ context.Context, r *http.Request) (interface{}, error) {
}

func decodeListClients(_ context.Context, r *http.Request) (interface{}, error) {
s, err := apiutil.ReadStringQuery(r, api.StatusKey, api.DefClientStatus)
name, err := apiutil.ReadStringQuery(r, api.NameKey, "")
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}
o, err := apiutil.ReadNumQuery[uint64](r, api.OffsetKey, api.DefOffset)

tag, err := apiutil.ReadStringQuery(r, api.TagKey, "")
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
l, err := apiutil.ReadNumQuery[uint64](r, api.LimitKey, api.DefLimit)

s, err := apiutil.ReadStringQuery(r, api.StatusKey, api.DefGroupStatus)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}
m, err := apiutil.ReadMetadataQuery(r, api.MetadataKey, nil)
status, err := clients.ToStatus(s)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}
n, err := apiutil.ReadStringQuery(r, api.NameKey, "")

meta, err := apiutil.ReadMetadataQuery(r, api.MetadataKey, nil)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}
t, err := apiutil.ReadStringQuery(r, api.TagKey, "")

offset, err := apiutil.ReadNumQuery[uint64](r, api.OffsetKey, api.DefOffset)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}
id, err := apiutil.ReadStringQuery(r, api.IDOrder, "")
limit, err := apiutil.ReadNumQuery[uint64](r, api.LimitKey, api.DefLimit)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}
p, err := apiutil.ReadStringQuery(r, api.PermissionKey, api.DefPermission)

dir, err := apiutil.ReadStringQuery(r, api.DirKey, api.DefDir)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}

lp, err := apiutil.ReadBoolQuery(r, api.ListPerms, api.DefListPerms)
order, err := apiutil.ReadStringQuery(r, api.OrderKey, api.DefOrder)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}
st, err := clients.ToStatus(s)

allActions, err := apiutil.ReadStringQuery(r, api.ActionsKey, "")
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}

actions := []string{}

allActions = strings.TrimSpace(allActions)
if allActions != "" {
actions = strings.Split(allActions, ",")
}
roleID, err := apiutil.ReadStringQuery(r, api.RoleIDKey, "")
if err != nil {
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}

roleName, err := apiutil.ReadStringQuery(r, api.RoleNameKey, "")
if err != nil {
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}

accessType, err := apiutil.ReadStringQuery(r, api.AccessTypeKey, "")
if err != nil {
return clients.Page{}, errors.Wrap(apiutil.ErrValidation, err)
}

userID, err := apiutil.ReadStringQuery(r, api.UserKey, "")
if err != nil {
return groups.PageMeta{}, errors.Wrap(apiutil.ErrValidation, err)
}

groupID, err := apiutil.ReadStringQuery(r, api.GroupKey, "")
if err != nil {
return groups.PageMeta{}, errors.Wrap(apiutil.ErrValidation, err)
}

channelID, err := apiutil.ReadStringQuery(r, api.ChannelKey, "")
if err != nil {
return groups.PageMeta{}, errors.Wrap(apiutil.ErrValidation, err)
}

req := listClientsReq{
status: st,
offset: o,
limit: l,
metadata: m,
name: n,
tag: t,
permission: p,
listPerms: lp,
userID: chi.URLParam(r, "userID"),
id: id,
name: name,
tag: tag,
status: status,
metadata: meta,
roleName: roleName,
roleID: roleID,
actions: actions,
accessType: accessType,
order: order,
dir: dir,
offset: offset,
limit: limit,
groupID: groupID,
channelID: channelID,
userID: userID,
}
return req, nil
}
Expand Down
30 changes: 18 additions & 12 deletions clients/api/http/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,25 @@ func listClientsEndpoint(svc clients.Service) endpoint.Endpoint {
}

pm := clients.Page{
Status: req.status,
Offset: req.offset,
Limit: req.limit,
Name: req.name,
Tag: req.tag,
Permission: req.permission,
Metadata: req.metadata,
ListPerms: req.listPerms,
Id: req.id,
}
page, err := svc.ListClients(ctx, session, req.userID, pm)
Status: req.status,
Offset: req.offset,
Limit: req.limit,
Name: req.name,
Tag: req.tag,
Metadata: req.metadata,
Group: req.groupID,
}

var page clients.ClientsPage
var err error
switch req.userID != "" {
case true:
page, err = svc.ListUserClients(ctx, session, req.userID, pm)
default:
page, err = svc.ListClients(ctx, session, pm)
}
if err != nil {
return nil, err
return clientsPageRes{}, err
}

res := clientsPageRes{
Expand Down
25 changes: 12 additions & 13 deletions clients/api/http/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,29 +71,28 @@ func (req viewClientPermsReq) validate() error {
}

type listClientsReq struct {
name string
tag string
status clients.Status
metadata clients.Metadata
roleName string
roleID string
actions []string
accessType string
order string
dir string
offset uint64
limit uint64
name string
tag string
permission string
visibility string
groupID string
channelID string
userID string
listPerms bool
metadata clients.Metadata
id string
}

func (req listClientsReq) validate() error {
if req.limit > api.MaxLimitSize || req.limit < 1 {
return apiutil.ErrLimitSize
}
if req.visibility != "" &&
req.visibility != api.AllVisibility &&
req.visibility != api.MyVisibility &&
req.visibility != api.SharedVisibility {
return apiutil.ErrInvalidVisibilityType
}

if len(req.name) > api.MaxNameSize {
return apiutil.ErrNameSize
}
Expand Down
3 changes: 1 addition & 2 deletions clients/api/http/requests_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,7 @@ func TestListClientsReqValidate(t *testing.T) {
{
desc: "invalid visibility",
req: listClientsReq{
limit: 10,
visibility: "invalid",
limit: 10,
},
err: apiutil.ErrInvalidVisibilityType,
},
Expand Down
59 changes: 41 additions & 18 deletions clients/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ type Repository interface {
// RetrieveAll retrieves all clients.
RetrieveAll(ctx context.Context, pm Page) (ClientsPage, error)

//RetrieveUserThings retrieve all clients of a given user id.
RetrieveUserThings(ctx context.Context, domainID, userID string, pm Page) (ClientsPage, error)

// SearchClients retrieves clients based on search criteria.
SearchClients(ctx context.Context, pm Page) (ClientsPage, error)

Expand Down Expand Up @@ -105,8 +108,11 @@ type Service interface {
// View retrieves client info for a given client ID and an authorized token.
View(ctx context.Context, session authn.Session, id string) (Client, error)

// ListClients retrieves clients list for a valid auth token.
ListClients(ctx context.Context, session authn.Session, reqUserID string, pm Page) (ClientsPage, error)
// ListClients retrieves clients list for given page query.
ListClients(ctx context.Context, session authn.Session, pm Page) (ClientsPage, error)

//ListUserClients retrieves clients list for a given user id and page query
ListUserClients(ctx context.Context, session authn.Session, userID string, pm Page) (ClientsPage, error)

// Update updates the client's name and metadata.
Update(ctx context.Context, session authn.Session, client Client) (Client, error)
Expand Down Expand Up @@ -161,8 +167,20 @@ type Client struct {
UpdatedAt time.Time `json:"updated_at,omitempty"`
UpdatedBy string `json:"updated_by,omitempty"`
Status Status `json:"status,omitempty"` // 1 for enabled, 0 for disabled
Permissions []string `json:"permissions,omitempty"`
Identity string `json:"identity,omitempty"`
// Extended
ParentGroupPath string `json:"parent_group_path"`
RoleID string `json:"role_id"`
RoleName string `json:"role_name"`
Actions []string `json:"actions"`
AccessType string `json:"access_type"`
AccessProviderId string `json:"access_provider_id"`
AccessProviderRoleId string `json:"access_provider_role_id"`
AccessProviderRoleName string `json:"access_provider_role_name"`
AccessProviderRoleActions []string `json:"access_provider_role_actions"`
}

type ClientsAdditional struct {
}

// ClientsPage contains page related metadata as well as list.
Expand All @@ -182,21 +200,26 @@ type MembersPage struct {
// Page contains the page metadata that helps navigation.

type Page struct {
Total uint64 `json:"total"`
Offset uint64 `json:"offset"`
Limit uint64 `json:"limit"`
Name string `json:"name,omitempty"`
Id string `json:"id,omitempty"`
Order string `json:"order,omitempty"`
Dir string `json:"dir,omitempty"`
Metadata Metadata `json:"metadata,omitempty"`
Domain string `json:"domain,omitempty"`
Tag string `json:"tag,omitempty"`
Permission string `json:"permission,omitempty"`
Status Status `json:"status,omitempty"`
IDs []string `json:"ids,omitempty"`
Identity string `json:"identity,omitempty"`
ListPerms bool `json:"-"`
Total uint64 `json:"total"`
Offset uint64 `json:"offset"`
Limit uint64 `json:"limit"`
Name string `json:"name,omitempty"`
Id string `json:"id,omitempty"`
Order string `json:"order,omitempty"`
Dir string `json:"dir,omitempty"`
Metadata Metadata `json:"metadata,omitempty"`
Domain string `json:"domain,omitempty"`
Tag string `json:"tag,omitempty"`
Status Status `json:"status,omitempty"`
IDs []string `json:"ids,omitempty"`
Identity string `json:"identity,omitempty"`
Group string `json:"group,omitempty"`
Channel string `json:"channel,omitempty"`
ConnectionType string `json:"connection_type,omitempty"`
RoleName string `json:"role_name,omitempty"`
RoleID string `json:"role_id,omitempty"`
Actions []string `json:"actions,omitempty"`
AccessType string `json:"access_type,omitempty"`
}

// Metadata represents arbitrary JSON.
Expand Down
51 changes: 44 additions & 7 deletions clients/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,12 @@ func (vcpe viewClientPermsEvent) Encode() (map[string]interface{}, error) {
}

type listClientEvent struct {
reqUserID string
clients.Page
}

func (lce listClientEvent) Encode() (map[string]interface{}, error) {
val := map[string]interface{}{
"operation": clientList,
"reqUserID": lce.reqUserID,
"total": lce.Total,
"offset": lce.Offset,
"limit": lce.Limit,
Expand All @@ -219,8 +217,50 @@ func (lce listClientEvent) Encode() (map[string]interface{}, error) {
if lce.Tag != "" {
val["tag"] = lce.Tag
}
if lce.Permission != "" {
val["permission"] = lce.Permission
if lce.Status.String() != "" {
val["status"] = lce.Status.String()
}
if len(lce.IDs) > 0 {
val["ids"] = lce.IDs
}
if lce.Identity != "" {
val["identity"] = lce.Identity
}

return val, nil
}

type listUserClientEvent struct {
userID string
clients.Page
}

func (lce listUserClientEvent) Encode() (map[string]interface{}, error) {
val := map[string]interface{}{
"operation": clientList,
"userID": lce.userID,
"total": lce.Total,
"offset": lce.Offset,
"limit": lce.Limit,
}

if lce.Name != "" {
val["name"] = lce.Name
}
if lce.Order != "" {
val["order"] = lce.Order
}
if lce.Dir != "" {
val["dir"] = lce.Dir
}
if lce.Metadata != nil {
val["metadata"] = lce.Metadata
}
if lce.Domain != "" {
val["domain"] = lce.Domain
}
if lce.Tag != "" {
val["tag"] = lce.Tag
}
if lce.Status.String() != "" {
val["status"] = lce.Status.String()
Expand Down Expand Up @@ -267,9 +307,6 @@ func (lcge listClientByGroupEvent) Encode() (map[string]interface{}, error) {
if lcge.Tag != "" {
val["tag"] = lcge.Tag
}
if lcge.Permission != "" {
val["permission"] = lcge.Permission
}
if lcge.Status.String() != "" {
val["status"] = lcge.Status.String()
}
Expand Down
Loading

0 comments on commit ca260c1

Please sign in to comment.