1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
package models
import (
"context"
"fmt"
"time"
"code.crute.us/mcrute/golib/db/mongodb"
)
const accountCol = "accounts"
type AccountStore interface {
List(context.Context) ([]*Account, error)
ListForUser(context.Context, *User) ([]*Account, error)
Get(context.Context, string) (*Account, error) // Error on not found
GetForUser(context.Context, string, *User) (*Account, error) // Error on not found
Put(context.Context, *Account) error
Delete(context.Context, *Account) error
}
type Account struct {
ShortName string `bson:"_id"`
AccountType string
AccountNumber int
Name string
ConsoleSessionDuration time.Duration
VaultMaterial string
DefaultRegion string
Users []string
}
func (a *Account) ConsoleSessionDurationSecs() int64 {
return int64(a.ConsoleSessionDuration.Seconds())
}
func (a *Account) CanAccess(u *User) bool {
if u.IsAdmin {
return true
}
// Linear search should be fine for now, these lists are pretty small
for _, n := range a.Users {
if n == u.Username {
return true
}
}
return false
}
type MongoDbAccountStore struct {
Db *mongodb.Mongo
}
// List returns all accounts in the system.
func (s *MongoDbAccountStore) List(ctx context.Context) ([]*Account, error) {
var out []*Account
if err := s.Db.FindAll(ctx, accountCol, &out); err != nil {
return nil, err
}
return out, nil
}
// ListForUser returns all accounts for which the user has access. This is the
// authorized version of List.
//
// Note this does not handle the case where a user is an admin but not
// explicitly listed in the allowed users list for an account. For that case
// just use List directly.
func (s *MongoDbAccountStore) ListForUser(ctx context.Context, u *User) ([]*Account, error) {
var out []*Account
filter := mongodb.AnyInTopLevelArray("Users", u.Username)
if err := s.Db.FindAllByFilter(ctx, accountCol, filter, &out); err != nil {
return nil, err
}
return out, nil
}
func (s *MongoDbAccountStore) Get(ctx context.Context, id string) (*Account, error) {
var a Account
if err := s.Db.FindOneById(ctx, accountCol, id, &a); err != nil {
return nil, err
}
return &a, nil
}
// GetForUser returns an account if the user has access to this account,
// otherwise it returns an error. This is the authorized version of Get.
func (s *MongoDbAccountStore) GetForUser(ctx context.Context, id string, u *User) (*Account, error) {
a, err := s.Get(ctx, id)
if err != nil {
return nil, err
}
if !a.CanAccess(u) {
return nil, fmt.Errorf("User does not have access to account")
}
return a, nil
}
func (s *MongoDbAccountStore) Put(ctx context.Context, a *Account) error {
if err := s.Db.ReplaceOneById(ctx, accountCol, a.ShortName, a); err != nil {
return err
}
return nil
}
func (s *MongoDbAccountStore) Delete(ctx context.Context, a *Account) error {
if err := s.Db.DeleteOneById(ctx, accountCol, a.ShortName); err != nil {
return err
}
return nil
}
var _ AccountStore = (*MongoDbAccountStore)(nil)
|