21700: Install Bundler system-wide in Rails postinst
[arvados.git] / lib / controller / localdb / group_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package localdb
6
7 import (
8         "git.arvados.org/arvados.git/lib/ctrlctx"
9         "git.arvados.org/arvados.git/sdk/go/arvados"
10         "git.arvados.org/arvados.git/sdk/go/arvadostest"
11         check "gopkg.in/check.v1"
12 )
13
14 var _ = check.Suite(&GroupSuite{})
15
16 type GroupSuite struct {
17         localdbSuite
18 }
19
20 func (s *GroupSuite) TestGroupCreateWithProperties(c *check.C) {
21         s.setUpVocabulary(c, "")
22
23         tests := []struct {
24                 name    string
25                 props   map[string]interface{}
26                 success bool
27         }{
28                 {"Invalid prop key", map[string]interface{}{"Priority": "IDVALIMPORTANCES1"}, false},
29                 {"Invalid prop value", map[string]interface{}{"IDTAGIMPORTANCES": "high"}, false},
30                 {"Valid prop key & value", map[string]interface{}{"IDTAGIMPORTANCES": "IDVALIMPORTANCES1"}, true},
31                 {"Empty properties", map[string]interface{}{}, true},
32         }
33         for _, tt := range tests {
34                 c.Log(c.TestName()+" ", tt.name)
35
36                 grp, err := s.localdb.GroupCreate(s.userctx, arvados.CreateOptions{
37                         Select: []string{"uuid", "properties"},
38                         Attrs: map[string]interface{}{
39                                 "group_class": "project",
40                                 "properties":  tt.props,
41                         }})
42                 if tt.success {
43                         c.Assert(err, check.IsNil)
44                         c.Assert(grp.Properties, check.DeepEquals, tt.props)
45                 } else {
46                         c.Assert(err, check.NotNil)
47                 }
48         }
49 }
50
51 func (s *GroupSuite) TestGroupUpdateWithProperties(c *check.C) {
52         s.setUpVocabulary(c, "")
53
54         tests := []struct {
55                 name    string
56                 props   map[string]interface{}
57                 success bool
58         }{
59                 {"Invalid prop key", map[string]interface{}{"Priority": "IDVALIMPORTANCES1"}, false},
60                 {"Invalid prop value", map[string]interface{}{"IDTAGIMPORTANCES": "high"}, false},
61                 {"Valid prop key & value", map[string]interface{}{"IDTAGIMPORTANCES": "IDVALIMPORTANCES1"}, true},
62                 {"Empty properties", map[string]interface{}{}, true},
63         }
64         for _, tt := range tests {
65                 c.Log(c.TestName()+" ", tt.name)
66                 grp, err := s.localdb.GroupCreate(s.userctx, arvados.CreateOptions{
67                         Attrs: map[string]interface{}{
68                                 "group_class": "project",
69                         },
70                 })
71                 c.Assert(err, check.IsNil)
72                 grp, err = s.localdb.GroupUpdate(s.userctx, arvados.UpdateOptions{
73                         UUID:   grp.UUID,
74                         Select: []string{"uuid", "properties"},
75                         Attrs: map[string]interface{}{
76                                 "properties": tt.props,
77                         }})
78                 if tt.success {
79                         c.Assert(err, check.IsNil)
80                         c.Assert(grp.Properties, check.DeepEquals, tt.props)
81                 } else {
82                         c.Assert(err, check.NotNil)
83                 }
84         }
85 }
86
87 func (s *GroupSuite) TestCanWriteCanManageResponses(c *check.C) {
88         ctxUser1 := ctrlctx.NewWithToken(s.ctx, s.cluster, arvadostest.ActiveTokenV2)
89         ctxUser2 := ctrlctx.NewWithToken(s.ctx, s.cluster, arvadostest.SpectatorToken)
90         ctxAdmin := ctrlctx.NewWithToken(s.ctx, s.cluster, arvadostest.AdminToken)
91         project, err := s.localdb.GroupCreate(ctxUser1, arvados.CreateOptions{
92                 Attrs: map[string]interface{}{
93                         "group_class": "project",
94                 },
95         })
96         c.Assert(err, check.IsNil)
97         c.Check(project.CanWrite, check.Equals, true)
98         c.Check(project.CanManage, check.Equals, true)
99
100         subproject, err := s.localdb.GroupCreate(ctxUser1, arvados.CreateOptions{
101                 Attrs: map[string]interface{}{
102                         "owner_uuid":  project.UUID,
103                         "group_class": "project",
104                 },
105         })
106         c.Assert(err, check.IsNil)
107         c.Check(subproject.CanWrite, check.Equals, true)
108         c.Check(subproject.CanManage, check.Equals, true)
109
110         projlist, err := s.localdb.GroupList(ctxUser1, arvados.ListOptions{
111                 Limit:   -1,
112                 Filters: []arvados.Filter{{"uuid", "in", []string{project.UUID, subproject.UUID}}},
113         })
114         c.Assert(err, check.IsNil)
115         c.Assert(projlist.Items, check.HasLen, 2)
116         for _, p := range projlist.Items {
117                 c.Check(p.CanWrite, check.Equals, true)
118                 c.Check(p.CanManage, check.Equals, true)
119         }
120
121         // Give 2nd user permission to read
122         permlink, err := s.localdb.LinkCreate(ctxAdmin, arvados.CreateOptions{
123                 Attrs: map[string]interface{}{
124                         "link_class": "permission",
125                         "name":       "can_read",
126                         "tail_uuid":  arvadostest.SpectatorUserUUID,
127                         "head_uuid":  project.UUID,
128                 },
129         })
130         c.Assert(err, check.IsNil)
131
132         // As 2nd user: can read, cannot manage, cannot write
133         project2, err := s.localdb.GroupGet(ctxUser2, arvados.GetOptions{UUID: project.UUID})
134         c.Assert(err, check.IsNil)
135         c.Check(project2.CanWrite, check.Equals, false)
136         c.Check(project2.CanManage, check.Equals, false)
137
138         _, err = s.localdb.LinkUpdate(ctxAdmin, arvados.UpdateOptions{
139                 UUID: permlink.UUID,
140                 Attrs: map[string]interface{}{
141                         "name": "can_write",
142                 },
143         })
144         c.Assert(err, check.IsNil)
145
146         // As 2nd user: cannot manage, can write
147         project2, err = s.localdb.GroupGet(ctxUser2, arvados.GetOptions{UUID: project.UUID})
148         c.Assert(err, check.IsNil)
149         c.Check(project2.CanWrite, check.Equals, true)
150         c.Check(project2.CanManage, check.Equals, false)
151
152         // As owner: after freezing, can manage (owner), cannot write (frozen)
153         project, err = s.localdb.GroupUpdate(ctxUser1, arvados.UpdateOptions{
154                 UUID: project.UUID,
155                 Attrs: map[string]interface{}{
156                         "frozen_by_uuid": arvadostest.ActiveUserUUID,
157                 }})
158         c.Assert(err, check.IsNil)
159         c.Check(project.CanWrite, check.Equals, false)
160         c.Check(project.CanManage, check.Equals, true)
161
162         // As admin: can manage (admin), cannot write (frozen)
163         project, err = s.localdb.GroupGet(ctxAdmin, arvados.GetOptions{UUID: project.UUID})
164         c.Assert(err, check.IsNil)
165         c.Check(project.CanWrite, check.Equals, false)
166         c.Check(project.CanManage, check.Equals, true)
167
168         // As 2nd user: cannot manage (perm), cannot write (frozen)
169         project2, err = s.localdb.GroupGet(ctxUser2, arvados.GetOptions{UUID: project.UUID})
170         c.Assert(err, check.IsNil)
171         c.Check(project2.CanWrite, check.Equals, false)
172         c.Check(project2.CanManage, check.Equals, false)
173
174         // After upgrading perm to "manage", as 2nd user: can manage (perm), cannot write (frozen)
175         _, err = s.localdb.LinkUpdate(ctxAdmin, arvados.UpdateOptions{
176                 UUID: permlink.UUID,
177                 Attrs: map[string]interface{}{
178                         "name": "can_manage",
179                 },
180         })
181         c.Assert(err, check.IsNil)
182         project2, err = s.localdb.GroupGet(ctxUser2, arvados.GetOptions{UUID: project.UUID})
183         c.Assert(err, check.IsNil)
184         c.Check(project2.CanWrite, check.Equals, false)
185         c.Check(project2.CanManage, check.Equals, true)
186
187         // 2nd user can also manage (but not write) the subject inside the frozen project
188         subproject2, err := s.localdb.GroupGet(ctxUser2, arvados.GetOptions{UUID: subproject.UUID})
189         c.Assert(err, check.IsNil)
190         c.Check(subproject2.CanWrite, check.Equals, false)
191         c.Check(subproject2.CanManage, check.Equals, true)
192
193         u, err := s.localdb.UserGet(ctxUser1, arvados.GetOptions{
194                 UUID: arvadostest.ActiveUserUUID,
195         })
196         c.Assert(err, check.IsNil)
197         c.Check(u.CanWrite, check.Equals, true)
198         c.Check(u.CanManage, check.Equals, true)
199
200         for _, selectParam := range [][]string{
201                 nil,
202                 {"can_write", "can_manage"},
203         } {
204                 c.Logf("selectParam: %+v", selectParam)
205                 ulist, err := s.localdb.UserList(ctxUser1, arvados.ListOptions{
206                         Limit:   -1,
207                         Filters: []arvados.Filter{{"uuid", "=", arvadostest.ActiveUserUUID}},
208                         Select:  selectParam,
209                 })
210                 c.Assert(err, check.IsNil)
211                 c.Assert(ulist.Items, check.HasLen, 1)
212                 c.Logf("%+v", ulist.Items)
213                 for _, u := range ulist.Items {
214                         c.Check(u.CanWrite, check.Equals, true)
215                         c.Check(u.CanManage, check.Equals, true)
216                 }
217         }
218 }