Skip to content

Commit 448bdcb

Browse files
committed
feat(api,cli): namespace store
1 parent c763c62 commit 448bdcb

28 files changed

+517
-245
lines changed

api/routes/nsadm.go

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"strconv"
66

77
"github.com/shellhub-io/shellhub/api/pkg/gateway"
8+
"github.com/shellhub-io/shellhub/pkg/api/query"
89
"github.com/shellhub-io/shellhub/pkg/api/requests"
910
)
1011

@@ -35,6 +36,14 @@ func (h *Handler) GetNamespaceList(c gateway.Context) error {
3536
}
3637

3738
req.Paginator.Normalize()
39+
40+
if req.Sorter.By == "" {
41+
req.Sorter.By = "created_at"
42+
}
43+
if req.Sorter.Order == "" {
44+
req.Sorter.Order = query.OrderAsc
45+
}
46+
3847
if err := req.Filters.Unmarshal(); err != nil {
3948
return err
4049
}

api/services/api-key.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/hex"
77
"errors"
88

9+
"github.com/shellhub-io/shellhub/api/store"
910
"github.com/shellhub-io/shellhub/pkg/api/requests"
1011
"github.com/shellhub-io/shellhub/pkg/api/responses"
1112
"github.com/shellhub-io/shellhub/pkg/clock"
@@ -31,7 +32,7 @@ type APIKeyService interface {
3132
}
3233

3334
func (s *service) CreateAPIKey(ctx context.Context, req *requests.CreateAPIKey) (*responses.CreateAPIKey, error) {
34-
if _, err := s.store.NamespaceGet(ctx, req.TenantID); err != nil {
35+
if _, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, req.TenantID); err != nil {
3536
return nil, NewErrNamespaceNotFound(req.TenantID, err)
3637
}
3738

@@ -97,7 +98,7 @@ func (s *service) ListAPIKeys(ctx context.Context, req *requests.ListAPIKey) ([]
9798
}
9899

99100
func (s *service) UpdateAPIKey(ctx context.Context, req *requests.UpdateAPIKey) error {
100-
ns, err := s.store.NamespaceGet(ctx, req.TenantID)
101+
ns, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, req.TenantID)
101102
if err != nil {
102103
return NewErrNamespaceNotFound(req.TenantID, err)
103104
}

api/services/auth.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ func (s *service) AuthDevice(ctx context.Context, req requests.DeviceAuth, remot
150150
}
151151

152152
// The order here is critical as we don't want to register devices if the tenant id is invalid
153-
namespace, err := s.store.NamespaceGet(ctx, device.TenantID)
153+
namespace, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, device.TenantID)
154154
if err != nil {
155155
return nil, NewErrNamespaceNotFound(device.TenantID, err)
156156
}
@@ -264,7 +264,7 @@ func (s *service) AuthLocalUser(ctx context.Context, req *requests.AuthLocalUser
264264
role := ""
265265
// Populate the tenant and role when the user is associated with a namespace. If the member status is pending, we
266266
// ignore the namespace.
267-
if ns, _ := s.store.NamespaceGetPreferred(ctx, user.ID); ns != nil && ns.TenantID != "" {
267+
if ns, _ := s.store.UserPreferredNamespace(ctx, store.UserIdentID, user.ID); ns != nil && ns.TenantID != "" {
268268
if m, _ := ns.FindMember(user.ID); m.Status != models.MemberStatusPending {
269269
tenantID = ns.TenantID
270270
role = m.Role.String()
@@ -333,7 +333,8 @@ func (s *service) CreateUserToken(ctx context.Context, req *requests.CreateUserT
333333
switch req.TenantID {
334334
case "":
335335
// A user may not have a preferred namespace. In such cases, we create a token without it.
336-
namespace, err := s.store.NamespaceGetPreferred(ctx, user.ID)
336+
337+
namespace, err := s.store.UserPreferredNamespace(ctx, store.UserIdentID, user.ID)
337338
if err != nil {
338339
break
339340
}
@@ -348,7 +349,7 @@ func (s *service) CreateUserToken(ctx context.Context, req *requests.CreateUserT
348349
role = member.Role.String()
349350
}
350351
default:
351-
namespace, err := s.store.NamespaceGet(ctx, req.TenantID)
352+
namespace, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, req.TenantID)
352353
if err != nil {
353354
return nil, NewErrNamespaceNotFound(req.TenantID, err)
354355
}
@@ -459,7 +460,7 @@ func (s *service) AuthPublicKey(ctx context.Context, req requests.PublicKeyAuth)
459460
}
460461

461462
func (s *service) GetUserRole(ctx context.Context, tenantID, userID string) (string, error) {
462-
ns, err := s.store.NamespaceGet(ctx, tenantID)
463+
ns, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, tenantID)
463464
if err != nil {
464465
return "", err
465466
}

api/services/device.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func (s *service) ListDevices(ctx context.Context, req *requests.DeviceList) ([]
4444
}
4545

4646
if req.TenantID != "" {
47-
ns, err := s.store.NamespaceGet(ctx, req.TenantID)
47+
ns, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, req.TenantID)
4848
if err != nil {
4949
return nil, 0, NewErrNamespaceNotFound(req.TenantID, err)
5050
}
@@ -96,7 +96,7 @@ func (s *service) DeleteDevice(ctx context.Context, uid models.UID, tenant strin
9696
return NewErrDeviceNotFound(uid, err)
9797
}
9898

99-
ns, err := s.store.NamespaceGet(ctx, tenant)
99+
ns, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, tenant)
100100
if err != nil {
101101
return NewErrNamespaceNotFound(tenant, err)
102102
}
@@ -184,7 +184,7 @@ func (s *service) OfflineDevice(ctx context.Context, uid models.UID) error {
184184

185185
// UpdateDeviceStatus updates the device status.
186186
func (s *service) UpdateDeviceStatus(ctx context.Context, tenant string, uid models.UID, status models.DeviceStatus) error {
187-
namespace, err := s.store.NamespaceGet(ctx, tenant)
187+
namespace, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, tenant)
188188
if err != nil {
189189
return NewErrNamespaceNotFound(tenant, err)
190190
}

api/services/member.go

+22-37
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package services
22

33
import (
44
"context"
5-
"errors"
65
"strings"
76
"time"
87

@@ -48,7 +47,7 @@ type MemberService interface {
4847
}
4948

5049
func (s *service) AddNamespaceMember(ctx context.Context, req *requests.NamespaceAddMember) (*models.Namespace, error) {
51-
namespace, err := s.store.NamespaceGet(ctx, req.TenantID)
50+
namespace, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, req.TenantID)
5251
if err != nil || namespace == nil {
5352
return nil, NewErrNamespaceNotFound(req.TenantID, err)
5453
}
@@ -101,12 +100,12 @@ func (s *service) AddNamespaceMember(ctx context.Context, req *requests.Namespac
101100
return nil, err
102101
}
103102
} else {
104-
if err := s.store.WithTransaction(ctx, s.addMember(passiveUser.ID, req)); err != nil {
103+
if err := s.addMember(passiveUser.ID, req)(ctx); err != nil {
105104
return nil, err
106105
}
107106
}
108107

109-
return s.store.NamespaceGet(ctx, req.TenantID)
108+
return s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, req.TenantID)
110109
}
111110

112111
// addMember returns a transaction callback that adds a member and sends an invite if the instance is cloud.
@@ -127,7 +126,7 @@ func (s *service) addMember(memberID string, req *requests.NamespaceAddMember) s
127126
member.ExpiresAt = time.Time{}
128127
}
129128

130-
if err := s.store.NamespaceAddMember(ctx, req.TenantID, member); err != nil {
129+
if err := s.store.NamespaceCreateMemberships(ctx, req.TenantID, *member); err != nil {
131130
return err
132131
}
133132

@@ -145,19 +144,19 @@ func (s *service) addMember(memberID string, req *requests.NamespaceAddMember) s
145144
// specified ID.
146145
func (s *service) resendMemberInvite(memberID string, req *requests.NamespaceAddMember) store.TransactionCb {
147146
return func(ctx context.Context) error {
148-
expiresAt := clock.Now().Add(7 * (24 * time.Hour))
149-
changes := &models.MemberChanges{ExpiresAt: &expiresAt, Role: req.MemberRole}
147+
// expiresAt := clock.Now().Add(7 * (24 * time.Hour))
148+
// changes := &models.MemberChanges{ExpiresAt: &expiresAt, Role: req.MemberRole}
150149

151-
if err := s.store.NamespaceUpdateMember(ctx, req.TenantID, memberID, changes); err != nil {
152-
return err
153-
}
150+
// if err := s.store.NamespaceUpdateMember(ctx, req.TenantID, memberID, changes); err != nil {
151+
// return err
152+
// }
154153

155154
return s.client.InviteMember(ctx, req.TenantID, memberID, req.FowardedHost)
156155
}
157156
}
158157

159158
func (s *service) UpdateNamespaceMember(ctx context.Context, req *requests.NamespaceUpdateMember) error {
160-
namespace, err := s.store.NamespaceGet(ctx, req.TenantID)
159+
namespace, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, req.TenantID)
161160
if err != nil {
162161
return NewErrNamespaceNotFound(req.TenantID, err)
163162
}
@@ -172,19 +171,20 @@ func (s *service) UpdateNamespaceMember(ctx context.Context, req *requests.Names
172171
return NewErrNamespaceMemberNotFound(user.ID, err)
173172
}
174173

175-
if _, ok := namespace.FindMember(req.MemberID); !ok {
174+
member, ok := namespace.FindMember(req.MemberID)
175+
if !ok {
176176
return NewErrNamespaceMemberNotFound(req.MemberID, err)
177177
}
178178

179-
changes := &models.MemberChanges{Role: req.MemberRole}
180-
181-
if changes.Role != authorizer.RoleInvalid {
179+
if req.MemberRole != authorizer.RoleInvalid {
182180
if !active.Role.HasAuthority(req.MemberRole) {
183181
return NewErrRoleInvalid()
184182
}
183+
184+
member.Role = req.MemberRole
185185
}
186186

187-
if err := s.store.NamespaceUpdateMember(ctx, req.TenantID, req.MemberID, changes); err != nil {
187+
if err := s.store.NamespaceSaveMembership(ctx, req.TenantID, member); err != nil {
188188
return err
189189
}
190190

@@ -194,7 +194,7 @@ func (s *service) UpdateNamespaceMember(ctx context.Context, req *requests.Names
194194
}
195195

196196
func (s *service) RemoveNamespaceMember(ctx context.Context, req *requests.NamespaceRemoveMember) (*models.Namespace, error) {
197-
namespace, err := s.store.NamespaceGet(ctx, req.TenantID)
197+
namespace, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, req.TenantID)
198198
if err != nil {
199199
return nil, NewErrNamespaceNotFound(req.TenantID, err)
200200
}
@@ -218,7 +218,7 @@ func (s *service) RemoveNamespaceMember(ctx context.Context, req *requests.Names
218218
return nil, NewErrRoleInvalid()
219219
}
220220

221-
if err := s.removeMember(ctx, namespace, req.MemberID); err != nil { //nolint:revive
221+
if err := s.store.NamespaceDeleteMembership(ctx, req.TenantID, passive); err != nil {
222222
return nil, err
223223
}
224224

@@ -229,11 +229,11 @@ func (s *service) RemoveNamespaceMember(ctx context.Context, req *requests.Names
229229
Error("failed to uncache the token")
230230
}
231231

232-
return s.store.NamespaceGet(ctx, req.TenantID)
232+
return s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, req.TenantID)
233233
}
234234

235235
func (s *service) LeaveNamespace(ctx context.Context, req *requests.LeaveNamespace) (*models.UserAuthResponse, error) {
236-
ns, err := s.store.NamespaceGet(ctx, req.TenantID)
236+
ns, err := s.store.NamespaceGet(ctx, store.NamespaceIdentTenantID, req.TenantID)
237237
if err != nil {
238238
return nil, NewErrNamespaceNotFound(req.TenantID, err)
239239
}
@@ -248,7 +248,7 @@ func (s *service) LeaveNamespace(ctx context.Context, req *requests.LeaveNamespa
248248
return nil, NewErrAuthForbidden()
249249
}
250250

251-
if err := s.removeMember(ctx, ns, user.ID); err != nil { //nolint:revive
251+
if err := s.store.NamespaceDeleteMembership(ctx, req.TenantID, member); err != nil {
252252
return nil, err
253253
}
254254

@@ -259,7 +259,7 @@ func (s *service) LeaveNamespace(ctx context.Context, req *requests.LeaveNamespa
259259
}
260260

261261
user.Preferences.PreferredNamespace = ""
262-
if err := s.store.Save(ctx, user); err != nil {
262+
if err := s.store.UserSave(ctx, user); err != nil {
263263
log.WithError(err).
264264
WithField("tenant_id", req.TenantID).
265265
WithField("user_id", req.UserID).
@@ -276,18 +276,3 @@ func (s *service) LeaveNamespace(ctx context.Context, req *requests.LeaveNamespa
276276
// TODO: make this method a util function
277277
return s.CreateUserToken(ctx, &requests.CreateUserToken{UserID: req.UserID})
278278
}
279-
280-
func (s *service) removeMember(ctx context.Context, ns *models.Namespace, userID string) error {
281-
if err := s.store.NamespaceRemoveMember(ctx, ns.TenantID, userID); err != nil {
282-
switch {
283-
case errors.Is(err, store.ErrNoDocuments):
284-
return NewErrNamespaceNotFound(ns.TenantID, err)
285-
// case errors.Is(err, mongo.ErrUserNotFound): // TODO: generic error
286-
// return NewErrNamespaceMemberNotFound(userID, err)
287-
default:
288-
return err
289-
}
290-
}
291-
292-
return nil
293-
}

0 commit comments

Comments
 (0)