root / snf-astakos-app / astakos / im / tests / projects.py @ 1ac3349d
History | View | Annotate | Download (10 kB)
1 | 1ac3349d | Kostas Papadimitriou | # Copyright 2011 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | 1ac3349d | Kostas Papadimitriou | #
|
3 | 1ac3349d | Kostas Papadimitriou | # Redistribution and use in source and binary forms, with or
|
4 | 1ac3349d | Kostas Papadimitriou | # without modification, are permitted provided that the following
|
5 | 1ac3349d | Kostas Papadimitriou | # conditions are met:
|
6 | 1ac3349d | Kostas Papadimitriou | #
|
7 | 1ac3349d | Kostas Papadimitriou | # 1. Redistributions of source code must retain the above
|
8 | 1ac3349d | Kostas Papadimitriou | # copyright notice, this list of conditions and the following
|
9 | 1ac3349d | Kostas Papadimitriou | # disclaimer.
|
10 | 1ac3349d | Kostas Papadimitriou | #
|
11 | 1ac3349d | Kostas Papadimitriou | # 2. Redistributions in binary form must reproduce the above
|
12 | 1ac3349d | Kostas Papadimitriou | # copyright notice, this list of conditions and the following
|
13 | 1ac3349d | Kostas Papadimitriou | # disclaimer in the documentation and/or other materials
|
14 | 1ac3349d | Kostas Papadimitriou | # provided with the distribution.
|
15 | 1ac3349d | Kostas Papadimitriou | #
|
16 | 1ac3349d | Kostas Papadimitriou | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | 1ac3349d | Kostas Papadimitriou | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | 1ac3349d | Kostas Papadimitriou | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | 1ac3349d | Kostas Papadimitriou | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | 1ac3349d | Kostas Papadimitriou | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | 1ac3349d | Kostas Papadimitriou | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | 1ac3349d | Kostas Papadimitriou | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | 1ac3349d | Kostas Papadimitriou | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | 1ac3349d | Kostas Papadimitriou | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | 1ac3349d | Kostas Papadimitriou | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | 1ac3349d | Kostas Papadimitriou | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | 1ac3349d | Kostas Papadimitriou | # POSSIBILITY OF SUCH DAMAGE.
|
28 | 1ac3349d | Kostas Papadimitriou | #
|
29 | 1ac3349d | Kostas Papadimitriou | # The views and conclusions contained in the software and
|
30 | 1ac3349d | Kostas Papadimitriou | # documentation are those of the authors and should not be
|
31 | 1ac3349d | Kostas Papadimitriou | # interpreted as representing official policies, either expressed
|
32 | 1ac3349d | Kostas Papadimitriou | # or implied, of GRNET S.A.
|
33 | 1ac3349d | Kostas Papadimitriou | |
34 | 1ac3349d | Kostas Papadimitriou | from astakos.im.tests.common import * |
35 | 1ac3349d | Kostas Papadimitriou | |
36 | 1ac3349d | Kostas Papadimitriou | |
37 | 1ac3349d | Kostas Papadimitriou | class TestProjects(TestCase): |
38 | 1ac3349d | Kostas Papadimitriou | """
|
39 | 1ac3349d | Kostas Papadimitriou | Test projects.
|
40 | 1ac3349d | Kostas Papadimitriou | """
|
41 | 1ac3349d | Kostas Papadimitriou | def setUp(self): |
42 | 1ac3349d | Kostas Papadimitriou | # astakos resources
|
43 | 1ac3349d | Kostas Papadimitriou | self.astakos_service = Service.objects.create(name="astakos", |
44 | 1ac3349d | Kostas Papadimitriou | api_url="/astakos/api/")
|
45 | 1ac3349d | Kostas Papadimitriou | self.resource = Resource.objects.create(name="astakos.pending_app", |
46 | 1ac3349d | Kostas Papadimitriou | uplimit=0,
|
47 | 1ac3349d | Kostas Papadimitriou | allow_in_projects=False,
|
48 | 1ac3349d | Kostas Papadimitriou | service=self.astakos_service)
|
49 | 1ac3349d | Kostas Papadimitriou | |
50 | 1ac3349d | Kostas Papadimitriou | # custom service resources
|
51 | 1ac3349d | Kostas Papadimitriou | self.service = Service.objects.create(name="service1", |
52 | 1ac3349d | Kostas Papadimitriou | api_url="http://service.api")
|
53 | 1ac3349d | Kostas Papadimitriou | self.resource = Resource.objects.create(name="service1.resource", |
54 | 1ac3349d | Kostas Papadimitriou | uplimit=100,
|
55 | 1ac3349d | Kostas Papadimitriou | service=self.service)
|
56 | 1ac3349d | Kostas Papadimitriou | self.admin = get_local_user("projects-admin@synnefo.org") |
57 | 1ac3349d | Kostas Papadimitriou | self.admin.uuid = 'uuid1' |
58 | 1ac3349d | Kostas Papadimitriou | self.admin.save()
|
59 | 1ac3349d | Kostas Papadimitriou | |
60 | 1ac3349d | Kostas Papadimitriou | self.user = get_local_user("user@synnefo.org") |
61 | 1ac3349d | Kostas Papadimitriou | self.member = get_local_user("member@synnefo.org") |
62 | 1ac3349d | Kostas Papadimitriou | self.member2 = get_local_user("member2@synnefo.org") |
63 | 1ac3349d | Kostas Papadimitriou | |
64 | 1ac3349d | Kostas Papadimitriou | self.admin_client = get_user_client("projects-admin@synnefo.org") |
65 | 1ac3349d | Kostas Papadimitriou | self.user_client = get_user_client("user@synnefo.org") |
66 | 1ac3349d | Kostas Papadimitriou | self.member_client = get_user_client("member@synnefo.org") |
67 | 1ac3349d | Kostas Papadimitriou | self.member2_client = get_user_client("member2@synnefo.org") |
68 | 1ac3349d | Kostas Papadimitriou | |
69 | 1ac3349d | Kostas Papadimitriou | quotas.qh_sync_users(AstakosUser.objects.all()) |
70 | 1ac3349d | Kostas Papadimitriou | |
71 | 1ac3349d | Kostas Papadimitriou | @im_settings(PROJECT_ADMINS=['uuid1']) |
72 | 1ac3349d | Kostas Papadimitriou | def test_application_limit(self): |
73 | 1ac3349d | Kostas Papadimitriou | # user cannot create a project
|
74 | 1ac3349d | Kostas Papadimitriou | r = self.user_client.get(reverse('project_add'), follow=True) |
75 | 1ac3349d | Kostas Papadimitriou | self.assertRedirects(r, reverse('project_list')) |
76 | 1ac3349d | Kostas Papadimitriou | self.assertContains(r, "You are not allowed to create a new project") |
77 | 1ac3349d | Kostas Papadimitriou | |
78 | 1ac3349d | Kostas Papadimitriou | # but admin can
|
79 | 1ac3349d | Kostas Papadimitriou | r = self.admin_client.get(reverse('project_add'), follow=True) |
80 | 1ac3349d | Kostas Papadimitriou | self.assertRedirects(r, reverse('project_add')) |
81 | 1ac3349d | Kostas Papadimitriou | |
82 | 1ac3349d | Kostas Papadimitriou | @im_settings(PROJECT_ADMINS=['uuid1']) |
83 | 1ac3349d | Kostas Papadimitriou | def test_allow_in_project(self): |
84 | 1ac3349d | Kostas Papadimitriou | dfrom = datetime.now() |
85 | 1ac3349d | Kostas Papadimitriou | dto = datetime.now() + timedelta(days=30)
|
86 | 1ac3349d | Kostas Papadimitriou | |
87 | 1ac3349d | Kostas Papadimitriou | # astakos.pending_uplimit allow_in_project flag is False
|
88 | 1ac3349d | Kostas Papadimitriou | # we shouldn't be able to create a project application using this
|
89 | 1ac3349d | Kostas Papadimitriou | # resource.
|
90 | 1ac3349d | Kostas Papadimitriou | application_data = { |
91 | 1ac3349d | Kostas Papadimitriou | 'name': 'project.synnefo.org', |
92 | 1ac3349d | Kostas Papadimitriou | 'homepage': 'https://www.synnefo.org', |
93 | 1ac3349d | Kostas Papadimitriou | 'start_date': dfrom.strftime("%Y-%m-%d"), |
94 | 1ac3349d | Kostas Papadimitriou | 'end_date': dto.strftime("%Y-%m-%d"), |
95 | 1ac3349d | Kostas Papadimitriou | 'member_join_policy': 2, |
96 | 1ac3349d | Kostas Papadimitriou | 'member_leave_policy': 1, |
97 | 1ac3349d | Kostas Papadimitriou | 'service1.resource_uplimit': 100, |
98 | 1ac3349d | Kostas Papadimitriou | 'is_selected_service1.resource': "1", |
99 | 1ac3349d | Kostas Papadimitriou | 'astakos.pending_app_uplimit': 100, |
100 | 1ac3349d | Kostas Papadimitriou | 'is_selected_accounts': "1", |
101 | 1ac3349d | Kostas Papadimitriou | 'user': self.user.pk |
102 | 1ac3349d | Kostas Papadimitriou | } |
103 | 1ac3349d | Kostas Papadimitriou | form = forms.ProjectApplicationForm(data=application_data) |
104 | 1ac3349d | Kostas Papadimitriou | # form is invalid
|
105 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(form.is_valid(), False) |
106 | 1ac3349d | Kostas Papadimitriou | |
107 | 1ac3349d | Kostas Papadimitriou | del application_data['astakos.pending_app_uplimit'] |
108 | 1ac3349d | Kostas Papadimitriou | del application_data['is_selected_accounts'] |
109 | 1ac3349d | Kostas Papadimitriou | form = forms.ProjectApplicationForm(data=application_data) |
110 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(form.is_valid(), True) |
111 | 1ac3349d | Kostas Papadimitriou | |
112 | 1ac3349d | Kostas Papadimitriou | @im_settings(PROJECT_ADMINS=['uuid1']) |
113 | 1ac3349d | Kostas Papadimitriou | def test_applications(self): |
114 | 1ac3349d | Kostas Papadimitriou | # let user have 2 pending applications
|
115 | 1ac3349d | Kostas Papadimitriou | quotas.add_base_quota(self.user, 'astakos.pending_app', 2) |
116 | 1ac3349d | Kostas Papadimitriou | |
117 | 1ac3349d | Kostas Papadimitriou | r = self.user_client.get(reverse('project_add'), follow=True) |
118 | 1ac3349d | Kostas Papadimitriou | self.assertRedirects(r, reverse('project_add')) |
119 | 1ac3349d | Kostas Papadimitriou | |
120 | 1ac3349d | Kostas Papadimitriou | # user fills the project application form
|
121 | 1ac3349d | Kostas Papadimitriou | post_url = reverse('project_add') + '?verify=1' |
122 | 1ac3349d | Kostas Papadimitriou | dfrom = datetime.now() |
123 | 1ac3349d | Kostas Papadimitriou | dto = datetime.now() + timedelta(days=30)
|
124 | 1ac3349d | Kostas Papadimitriou | application_data = { |
125 | 1ac3349d | Kostas Papadimitriou | 'name': 'project.synnefo.org', |
126 | 1ac3349d | Kostas Papadimitriou | 'homepage': 'https://www.synnefo.org', |
127 | 1ac3349d | Kostas Papadimitriou | 'start_date': dfrom.strftime("%Y-%m-%d"), |
128 | 1ac3349d | Kostas Papadimitriou | 'end_date': dto.strftime("%Y-%m-%d"), |
129 | 1ac3349d | Kostas Papadimitriou | 'member_join_policy': 2, |
130 | 1ac3349d | Kostas Papadimitriou | 'member_leave_policy': 1, |
131 | 1ac3349d | Kostas Papadimitriou | 'service1.resource_uplimit': 100, |
132 | 1ac3349d | Kostas Papadimitriou | 'is_selected_service1.resource': "1", |
133 | 1ac3349d | Kostas Papadimitriou | 'user': self.user.pk |
134 | 1ac3349d | Kostas Papadimitriou | } |
135 | 1ac3349d | Kostas Papadimitriou | r = self.user_client.post(post_url, data=application_data, follow=True) |
136 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(r.status_code, 200) |
137 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(r.context['form'].is_valid(), True) |
138 | 1ac3349d | Kostas Papadimitriou | |
139 | 1ac3349d | Kostas Papadimitriou | # confirm request
|
140 | 1ac3349d | Kostas Papadimitriou | post_url = reverse('project_add') + '?verify=0&edit=0' |
141 | 1ac3349d | Kostas Papadimitriou | r = self.user_client.post(post_url, data=application_data, follow=True) |
142 | 1ac3349d | Kostas Papadimitriou | self.assertContains(r, "The project application has been received") |
143 | 1ac3349d | Kostas Papadimitriou | self.assertRedirects(r, reverse('project_list')) |
144 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(ProjectApplication.objects.count(), 1) |
145 | 1ac3349d | Kostas Papadimitriou | app1_id = ProjectApplication.objects.filter().order_by('pk')[0].pk |
146 | 1ac3349d | Kostas Papadimitriou | |
147 | 1ac3349d | Kostas Papadimitriou | # create another one
|
148 | 1ac3349d | Kostas Papadimitriou | application_data['name'] = 'project2.synnefo.org' |
149 | 1ac3349d | Kostas Papadimitriou | r = self.user_client.post(post_url, data=application_data, follow=True) |
150 | 1ac3349d | Kostas Papadimitriou | app2_id = ProjectApplication.objects.filter().order_by('pk')[1].pk |
151 | 1ac3349d | Kostas Papadimitriou | |
152 | 1ac3349d | Kostas Papadimitriou | # no more applications (LIMIT is 2)
|
153 | 1ac3349d | Kostas Papadimitriou | r = self.user_client.get(reverse('project_add'), follow=True) |
154 | 1ac3349d | Kostas Papadimitriou | self.assertRedirects(r, reverse('project_list')) |
155 | 1ac3349d | Kostas Papadimitriou | self.assertContains(r, "You are not allowed to create a new project") |
156 | 1ac3349d | Kostas Papadimitriou | |
157 | 1ac3349d | Kostas Papadimitriou | # login
|
158 | 1ac3349d | Kostas Papadimitriou | self.admin_client.get(reverse("edit_profile")) |
159 | 1ac3349d | Kostas Papadimitriou | # admin approves
|
160 | 1ac3349d | Kostas Papadimitriou | r = self.admin_client.post(reverse('project_app_approve', |
161 | 1ac3349d | Kostas Papadimitriou | kwargs={'application_id': app1_id}),
|
162 | 1ac3349d | Kostas Papadimitriou | follow=True)
|
163 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(r.status_code, 200) |
164 | 1ac3349d | Kostas Papadimitriou | |
165 | 1ac3349d | Kostas Papadimitriou | # project created
|
166 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(Project.objects.count(), 1) |
167 | 1ac3349d | Kostas Papadimitriou | |
168 | 1ac3349d | Kostas Papadimitriou | # login
|
169 | 1ac3349d | Kostas Papadimitriou | self.member_client.get(reverse("edit_profile")) |
170 | 1ac3349d | Kostas Papadimitriou | # cannot join app2 (not approved yet)
|
171 | 1ac3349d | Kostas Papadimitriou | join_url = reverse("project_join", kwargs={'chain_id': app2_id}) |
172 | 1ac3349d | Kostas Papadimitriou | r = self.member_client.post(join_url, follow=True) |
173 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(r.status_code, 403) |
174 | 1ac3349d | Kostas Papadimitriou | |
175 | 1ac3349d | Kostas Papadimitriou | # can join app1
|
176 | 1ac3349d | Kostas Papadimitriou | self.member_client.get(reverse("edit_profile")) |
177 | 1ac3349d | Kostas Papadimitriou | join_url = reverse("project_join", kwargs={'chain_id': app1_id}) |
178 | 1ac3349d | Kostas Papadimitriou | r = self.member_client.post(join_url, follow=True) |
179 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(r.status_code, 200) |
180 | 1ac3349d | Kostas Papadimitriou | |
181 | 1ac3349d | Kostas Papadimitriou | memberships = ProjectMembership.objects.all() |
182 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(len(memberships), 1) |
183 | 1ac3349d | Kostas Papadimitriou | memb_id = memberships[0].id
|
184 | 1ac3349d | Kostas Papadimitriou | |
185 | 1ac3349d | Kostas Papadimitriou | reject_member_url = reverse('project_reject_member',
|
186 | 1ac3349d | Kostas Papadimitriou | kwargs={'chain_id': app1_id, 'memb_id': |
187 | 1ac3349d | Kostas Papadimitriou | memb_id}) |
188 | 1ac3349d | Kostas Papadimitriou | accept_member_url = reverse('project_accept_member',
|
189 | 1ac3349d | Kostas Papadimitriou | kwargs={'chain_id': app1_id, 'memb_id': |
190 | 1ac3349d | Kostas Papadimitriou | memb_id}) |
191 | 1ac3349d | Kostas Papadimitriou | |
192 | 1ac3349d | Kostas Papadimitriou | # only project owner is allowed to reject
|
193 | 1ac3349d | Kostas Papadimitriou | r = self.member_client.post(reject_member_url, follow=True) |
194 | 1ac3349d | Kostas Papadimitriou | self.assertContains(r, "You do not have the permissions") |
195 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(r.status_code, 200) |
196 | 1ac3349d | Kostas Papadimitriou | |
197 | 1ac3349d | Kostas Papadimitriou | # user (owns project) rejects membership
|
198 | 1ac3349d | Kostas Papadimitriou | r = self.user_client.post(reject_member_url, follow=True) |
199 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(ProjectMembership.objects.count(), 0) |
200 | 1ac3349d | Kostas Papadimitriou | |
201 | 1ac3349d | Kostas Papadimitriou | # user rejoins
|
202 | 1ac3349d | Kostas Papadimitriou | self.member_client.get(reverse("edit_profile")) |
203 | 1ac3349d | Kostas Papadimitriou | join_url = reverse("project_join", kwargs={'chain_id': app1_id}) |
204 | 1ac3349d | Kostas Papadimitriou | r = self.member_client.post(join_url, follow=True) |
205 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(r.status_code, 200) |
206 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(ProjectMembership.objects.count(), 1) |
207 | 1ac3349d | Kostas Papadimitriou | |
208 | 1ac3349d | Kostas Papadimitriou | # user (owns project) accepts membership
|
209 | 1ac3349d | Kostas Papadimitriou | r = self.user_client.post(accept_member_url, follow=True) |
210 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(ProjectMembership.objects.count(), 1) |
211 | 1ac3349d | Kostas Papadimitriou | membership = ProjectMembership.objects.get() |
212 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(membership.state, ProjectMembership.ACCEPTED)
|
213 | 1ac3349d | Kostas Papadimitriou | |
214 | 1ac3349d | Kostas Papadimitriou | user_quotas = quotas.get_users_quotas([self.member])
|
215 | 1ac3349d | Kostas Papadimitriou | resource = 'service1.resource'
|
216 | 1ac3349d | Kostas Papadimitriou | newlimit = user_quotas[self.member.uuid]['system'][resource]['limit'] |
217 | 1ac3349d | Kostas Papadimitriou | # 100 from initial uplimit + 100 from project
|
218 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(newlimit, 200) |
219 | 1ac3349d | Kostas Papadimitriou | |
220 | 1ac3349d | Kostas Papadimitriou | remove_member_url = reverse('project_remove_member',
|
221 | 1ac3349d | Kostas Papadimitriou | kwargs={'chain_id': app1_id, 'memb_id': |
222 | 1ac3349d | Kostas Papadimitriou | membership.id}) |
223 | 1ac3349d | Kostas Papadimitriou | r = self.user_client.post(remove_member_url, follow=True) |
224 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(r.status_code, 200) |
225 | 1ac3349d | Kostas Papadimitriou | |
226 | 1ac3349d | Kostas Papadimitriou | user_quotas = quotas.get_users_quotas([self.member])
|
227 | 1ac3349d | Kostas Papadimitriou | resource = 'service1.resource'
|
228 | 1ac3349d | Kostas Papadimitriou | newlimit = user_quotas[self.member.uuid]['system'][resource]['limit'] |
229 | 1ac3349d | Kostas Papadimitriou | # 200 - 100 from project
|
230 | 1ac3349d | Kostas Papadimitriou | self.assertEqual(newlimit, 100) |