aboutsummaryrefslogtreecommitdiff
path: root/app/models/account.go
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/account.go')
-rw-r--r--app/models/account.go95
1 files changed, 64 insertions, 31 deletions
diff --git a/app/models/account.go b/app/models/account.go
index 0ae1821..61b144d 100644
--- a/app/models/account.go
+++ b/app/models/account.go
@@ -2,10 +2,11 @@ package models
2 2
3import ( 3import (
4 "context" 4 "context"
5 "fmt"
6 "time" 5 "time"
7 6
8 "code.crute.us/mcrute/golib/db/mongodb" 7 "code.crute.us/mcrute/golib/db/mongodb"
8 "go.mongodb.org/mongo-driver/bson"
9 "go.mongodb.org/mongo-driver/bson/primitive"
9) 10)
10 11
11const accountCol = "accounts" 12const accountCol = "accounts"
@@ -20,43 +21,48 @@ type AccountStore interface {
20} 21}
21 22
22type Account struct { 23type Account struct {
23 ShortName string `bson:"_id"` 24 ShortName string `bson:"_id" json:"short_name"`
24 AccountType string 25 AccountType string `json:"account_type"`
25 AccountNumber int 26 AccountNumber int `json:"account_number"`
26 Name string 27 Name string `json:"name"`
27 ConsoleSessionDuration time.Duration 28 ConsoleSessionDuration time.Duration `json:"console_session_duration, omitempty"`
28 VaultMaterial string 29 VaultMaterial string `json:"vault_material,omitempty"`
29 DefaultRegion string 30 DefaultRegion string `json:"default_region"`
30 Users []string 31 Users []string `json:"users,omitempty"`
32 Deleted *time.Time `json:"deleted,omitempty" bson:"deleted,omitempty"`
31} 33}
32 34
33func (a *Account) ConsoleSessionDurationSecs() int64 { 35func (a *Account) ConsoleSessionDurationSecs() int64 {
34 return int64(a.ConsoleSessionDuration.Seconds()) 36 return int64(a.ConsoleSessionDuration.Seconds())
35} 37}
36 38
37func (a *Account) CanAccess(u *User) bool { 39func (a *Account) CanBeModifiedBy(u *User) bool {
38 if u.IsAdmin { 40 return u.IsAdmin
39 return true
40 }
41 // Linear search should be fine for now, these lists are pretty small
42 for _, n := range a.Users {
43 if n == u.Username {
44 return true
45 }
46 }
47 return false
48} 41}
49 42
50type MongoDbAccountStore struct { 43type MongoDbAccountStore struct {
51 Db *mongodb.Mongo 44 Db *mongodb.Mongo
45
46 // ReturnDeleted will allow all methods to return deleted items. By default
47 // items where the Deleted field is set will not be returned. This should
48 // be the common cast for most code using this store but in some Admin
49 // use-cases it would be useful to show deleted accounts.
50 ReturnDeleted bool
52} 51}
53 52
54// List returns all accounts in the system. 53// List returns all accounts in the system.
55func (s *MongoDbAccountStore) List(ctx context.Context) ([]*Account, error) { 54func (s *MongoDbAccountStore) List(ctx context.Context) ([]*Account, error) {
56 var out []*Account 55 var out []*Account
57 if err := s.Db.FindAll(ctx, accountCol, &out); err != nil { 56
57 filter := bson.M{}
58 if !s.ReturnDeleted {
59 filter["deleted"] = primitive.Null{}
60 }
61
62 if err := s.Db.FindAllByFilter(ctx, accountCol, filter, &out); err != nil {
58 return nil, err 63 return nil, err
59 } 64 }
65
60 return out, nil 66 return out, nil
61} 67}
62 68
@@ -68,34 +74,56 @@ func (s *MongoDbAccountStore) List(ctx context.Context) ([]*Account, error) {
68// just use List directly. 74// just use List directly.
69func (s *MongoDbAccountStore) ListForUser(ctx context.Context, u *User) ([]*Account, error) { 75func (s *MongoDbAccountStore) ListForUser(ctx context.Context, u *User) ([]*Account, error) {
70 var out []*Account 76 var out []*Account
71 filter := mongodb.AnyInTopLevelArray("Users", u.Username) 77
78 filter := mongodb.AnyInTopLevelArray("users", u.Username)
79 if !s.ReturnDeleted {
80 filter["deleted"] = primitive.Null{}
81 }
82
72 if err := s.Db.FindAllByFilter(ctx, accountCol, filter, &out); err != nil { 83 if err := s.Db.FindAllByFilter(ctx, accountCol, filter, &out); err != nil {
73 return nil, err 84 return nil, err
74 } 85 }
86
75 return out, nil 87 return out, nil
76} 88}
77 89
78func (s *MongoDbAccountStore) Get(ctx context.Context, id string) (*Account, error) { 90func (s *MongoDbAccountStore) Get(ctx context.Context, id string) (*Account, error) {
79 var a Account 91 var a Account
80 if err := s.Db.FindOneById(ctx, accountCol, id, &a); err != nil { 92
93 filter := bson.M{"_id": id}
94 if !s.ReturnDeleted {
95 filter["deleted"] = primitive.Null{}
96 }
97
98 if err := s.Db.FindOneByFilter(ctx, accountCol, filter, &a); err != nil {
81 return nil, err 99 return nil, err
82 } 100 }
101
83 return &a, nil 102 return &a, nil
84} 103}
85 104
86// GetForUser returns an account if the user has access to this account, 105// GetForUser returns an account if the user has access to this account,
87// otherwise it returns an error. This is the authorized version of Get. 106// otherwise it returns an error. This is the authorized version of Get.
88func (s *MongoDbAccountStore) GetForUser(ctx context.Context, id string, u *User) (*Account, error) { 107func (s *MongoDbAccountStore) GetForUser(ctx context.Context, id string, u *User) (*Account, error) {
89 a, err := s.Get(ctx, id) 108 var a Account
90 if err != nil { 109 var filter bson.M
91 return nil, err 110
111 if u.IsAdmin {
112 filter = bson.M{"_id": id}
113 } else {
114 filter = mongodb.AnyInTopLevelArray("users", u.Username)
115 filter["_id"] = id
92 } 116 }
93 117
94 if !a.CanAccess(u) { 118 if !s.ReturnDeleted {
95 return nil, fmt.Errorf("User does not have access to account") 119 filter["deleted"] = primitive.Null{}
96 } 120 }
97 121
98 return a, nil 122 if err := s.Db.FindOneByFilter(ctx, accountCol, filter, &a); err != nil {
123 return nil, err
124 }
125
126 return &a, nil
99} 127}
100 128
101func (s *MongoDbAccountStore) Put(ctx context.Context, a *Account) error { 129func (s *MongoDbAccountStore) Put(ctx context.Context, a *Account) error {
@@ -106,10 +134,15 @@ func (s *MongoDbAccountStore) Put(ctx context.Context, a *Account) error {
106} 134}
107 135
108func (s *MongoDbAccountStore) Delete(ctx context.Context, a *Account) error { 136func (s *MongoDbAccountStore) Delete(ctx context.Context, a *Account) error {
109 if err := s.Db.DeleteOneById(ctx, accountCol, a.ShortName); err != nil { 137 a, err := s.Get(ctx, a.ShortName)
138 if err != nil {
110 return err 139 return err
111 } 140 }
112 return nil 141
142 now := time.Now()
143 a.Deleted = &now
144
145 return s.Put(ctx, a)
113} 146}
114 147
115var _ AccountStore = (*MongoDbAccountStore)(nil) 148var _ AccountStore = (*MongoDbAccountStore)(nil)