diff options
Diffstat (limited to 'app/models/account.go')
-rw-r--r-- | app/models/account.go | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/app/models/account.go b/app/models/account.go new file mode 100644 index 0000000..0ae1821 --- /dev/null +++ b/app/models/account.go | |||
@@ -0,0 +1,115 @@ | |||
1 | package models | ||
2 | |||
3 | import ( | ||
4 | "context" | ||
5 | "fmt" | ||
6 | "time" | ||
7 | |||
8 | "code.crute.us/mcrute/golib/db/mongodb" | ||
9 | ) | ||
10 | |||
11 | const accountCol = "accounts" | ||
12 | |||
13 | type AccountStore interface { | ||
14 | List(context.Context) ([]*Account, error) | ||
15 | ListForUser(context.Context, *User) ([]*Account, error) | ||
16 | Get(context.Context, string) (*Account, error) // Error on not found | ||
17 | GetForUser(context.Context, string, *User) (*Account, error) // Error on not found | ||
18 | Put(context.Context, *Account) error | ||
19 | Delete(context.Context, *Account) error | ||
20 | } | ||
21 | |||
22 | type Account struct { | ||
23 | ShortName string `bson:"_id"` | ||
24 | AccountType string | ||
25 | AccountNumber int | ||
26 | Name string | ||
27 | ConsoleSessionDuration time.Duration | ||
28 | VaultMaterial string | ||
29 | DefaultRegion string | ||
30 | Users []string | ||
31 | } | ||
32 | |||
33 | func (a *Account) ConsoleSessionDurationSecs() int64 { | ||
34 | return int64(a.ConsoleSessionDuration.Seconds()) | ||
35 | } | ||
36 | |||
37 | func (a *Account) CanAccess(u *User) bool { | ||
38 | if 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 | } | ||
49 | |||
50 | type MongoDbAccountStore struct { | ||
51 | Db *mongodb.Mongo | ||
52 | } | ||
53 | |||
54 | // List returns all accounts in the system. | ||
55 | func (s *MongoDbAccountStore) List(ctx context.Context) ([]*Account, error) { | ||
56 | var out []*Account | ||
57 | if err := s.Db.FindAll(ctx, accountCol, &out); err != nil { | ||
58 | return nil, err | ||
59 | } | ||
60 | return out, nil | ||
61 | } | ||
62 | |||
63 | // ListForUser returns all accounts for which the user has access. This is the | ||
64 | // authorized version of List. | ||
65 | // | ||
66 | // Note this does not handle the case where a user is an admin but not | ||
67 | // explicitly listed in the allowed users list for an account. For that case | ||
68 | // just use List directly. | ||
69 | func (s *MongoDbAccountStore) ListForUser(ctx context.Context, u *User) ([]*Account, error) { | ||
70 | var out []*Account | ||
71 | filter := mongodb.AnyInTopLevelArray("Users", u.Username) | ||
72 | if err := s.Db.FindAllByFilter(ctx, accountCol, filter, &out); err != nil { | ||
73 | return nil, err | ||
74 | } | ||
75 | return out, nil | ||
76 | } | ||
77 | |||
78 | func (s *MongoDbAccountStore) Get(ctx context.Context, id string) (*Account, error) { | ||
79 | var a Account | ||
80 | if err := s.Db.FindOneById(ctx, accountCol, id, &a); err != nil { | ||
81 | return nil, err | ||
82 | } | ||
83 | return &a, nil | ||
84 | } | ||
85 | |||
86 | // 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. | ||
88 | func (s *MongoDbAccountStore) GetForUser(ctx context.Context, id string, u *User) (*Account, error) { | ||
89 | a, err := s.Get(ctx, id) | ||
90 | if err != nil { | ||
91 | return nil, err | ||
92 | } | ||
93 | |||
94 | if !a.CanAccess(u) { | ||
95 | return nil, fmt.Errorf("User does not have access to account") | ||
96 | } | ||
97 | |||
98 | return a, nil | ||
99 | } | ||
100 | |||
101 | func (s *MongoDbAccountStore) Put(ctx context.Context, a *Account) error { | ||
102 | if err := s.Db.ReplaceOneById(ctx, accountCol, a.ShortName, a); err != nil { | ||
103 | return err | ||
104 | } | ||
105 | return nil | ||
106 | } | ||
107 | |||
108 | func (s *MongoDbAccountStore) Delete(ctx context.Context, a *Account) error { | ||
109 | if err := s.Db.DeleteOneById(ctx, accountCol, a.ShortName); err != nil { | ||
110 | return err | ||
111 | } | ||
112 | return nil | ||
113 | } | ||
114 | |||
115 | var _ AccountStore = (*MongoDbAccountStore)(nil) | ||