Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / tests / projects.py @ baa9073a

History | View | Annotate | Download (10.1 kB)

1
# Copyright 2011 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from astakos.im.tests.common import *
35

    
36

    
37
class TestProjects(TestCase):
38
    """
39
    Test projects.
40
    """
41
    def setUp(self):
42
        # astakos resources
43
        self.astakos_service = Service.objects.create(name="astakos",
44
                                                      api_url="/astakos/api/")
45
        self.resource = Resource.objects.create(name="astakos.pending_app",
46
                                                uplimit=0,
47
                                                allow_in_projects=False,
48
                                                service=self.astakos_service)
49

    
50
        # custom service resources
51
        self.service = Service.objects.create(name="service1",
52
                                              api_url="http://service.api")
53
        self.resource = Resource.objects.create(name="service1.resource",
54
                                                uplimit=100,
55
                                                service=self.service)
56
        self.admin = get_local_user("projects-admin@synnefo.org")
57
        self.admin.uuid = 'uuid1'
58
        self.admin.save()
59

    
60
        self.user = get_local_user("user@synnefo.org")
61
        self.member = get_local_user("member@synnefo.org")
62
        self.member2 = get_local_user("member2@synnefo.org")
63

    
64
        self.admin_client = get_user_client("projects-admin@synnefo.org")
65
        self.user_client = get_user_client("user@synnefo.org")
66
        self.member_client = get_user_client("member@synnefo.org")
67
        self.member2_client = get_user_client("member2@synnefo.org")
68

    
69
        quotas.qh_sync_users(AstakosUser.objects.all())
70

    
71
    def tearDown(self):
72
        Service.objects.all().delete()
73
        ProjectApplication.objects.all().delete()
74

    
75
    @im_settings(PROJECT_ADMINS=['uuid1'])
76
    def test_application_limit(self):
77
        # user cannot create a project
78
        r = self.user_client.get(reverse('project_add'), follow=True)
79
        self.assertRedirects(r, reverse('project_list'))
80
        self.assertContains(r, "You are not allowed to create a new project")
81

    
82
        # but admin can
83
        r = self.admin_client.get(reverse('project_add'), follow=True)
84
        self.assertRedirects(r, reverse('project_add'))
85

    
86
    @im_settings(PROJECT_ADMINS=['uuid1'])
87
    def test_allow_in_project(self):
88
        dfrom = datetime.now()
89
        dto = datetime.now() + timedelta(days=30)
90

    
91
        # astakos.pending_uplimit allow_in_project flag is False
92
        # we shouldn't be able to create a project application using this
93
        # resource.
94
        application_data = {
95
            'name': 'project.synnefo.org',
96
            'homepage': 'https://www.synnefo.org',
97
            'start_date': dfrom.strftime("%Y-%m-%d"),
98
            'end_date': dto.strftime("%Y-%m-%d"),
99
            'member_join_policy': 2,
100
            'member_leave_policy': 1,
101
            'service1.resource_uplimit': 100,
102
            'is_selected_service1.resource': "1",
103
            'astakos.pending_app_uplimit': 100,
104
            'is_selected_accounts': "1",
105
            'user': self.user.pk
106
        }
107
        form = forms.ProjectApplicationForm(data=application_data)
108
        # form is invalid
109
        self.assertEqual(form.is_valid(), False)
110

    
111
        del application_data['astakos.pending_app_uplimit']
112
        del application_data['is_selected_accounts']
113
        form = forms.ProjectApplicationForm(data=application_data)
114
        self.assertEqual(form.is_valid(), True)
115

    
116
    @im_settings(PROJECT_ADMINS=['uuid1'])
117
    def test_applications(self):
118
        # let user have 2 pending applications
119
        quotas.add_base_quota(self.user, 'astakos.pending_app', 2)
120

    
121
        r = self.user_client.get(reverse('project_add'), follow=True)
122
        self.assertRedirects(r, reverse('project_add'))
123

    
124
        # user fills the project application form
125
        post_url = reverse('project_add') + '?verify=1'
126
        dfrom = datetime.now()
127
        dto = datetime.now() + timedelta(days=30)
128
        application_data = {
129
            'name': 'project.synnefo.org',
130
            'homepage': 'https://www.synnefo.org',
131
            'start_date': dfrom.strftime("%Y-%m-%d"),
132
            'end_date': dto.strftime("%Y-%m-%d"),
133
            'member_join_policy': 2,
134
            'member_leave_policy': 1,
135
            'service1.resource_uplimit': 100,
136
            'is_selected_service1.resource': "1",
137
            'user': self.user.pk
138
        }
139
        r = self.user_client.post(post_url, data=application_data, follow=True)
140
        self.assertEqual(r.status_code, 200)
141
        self.assertEqual(r.context['form'].is_valid(), True)
142

    
143
        # confirm request
144
        post_url = reverse('project_add') + '?verify=0&edit=0'
145
        r = self.user_client.post(post_url, data=application_data, follow=True)
146
        self.assertContains(r, "The project application has been received")
147
        self.assertRedirects(r, reverse('project_list'))
148
        self.assertEqual(ProjectApplication.objects.count(), 1)
149
        app1_id = ProjectApplication.objects.filter().order_by('pk')[0].pk
150

    
151
        # create another one
152
        application_data['name'] = 'project2.synnefo.org'
153
        r = self.user_client.post(post_url, data=application_data, follow=True)
154
        app2_id = ProjectApplication.objects.filter().order_by('pk')[1].pk
155

    
156
        # no more applications (LIMIT is 2)
157
        r = self.user_client.get(reverse('project_add'), follow=True)
158
        self.assertRedirects(r, reverse('project_list'))
159
        self.assertContains(r, "You are not allowed to create a new project")
160

    
161
        # login
162
        self.admin_client.get(reverse("edit_profile"))
163
        # admin approves
164
        r = self.admin_client.post(reverse('project_app_approve',
165
                                           kwargs={'application_id': app1_id}),
166
                                   follow=True)
167
        self.assertEqual(r.status_code, 200)
168

    
169
        # project created
170
        self.assertEqual(Project.objects.count(), 1)
171

    
172
        # login
173
        self.member_client.get(reverse("edit_profile"))
174
        # cannot join app2 (not approved yet)
175
        join_url = reverse("project_join", kwargs={'chain_id': app2_id})
176
        r = self.member_client.post(join_url, follow=True)
177
        self.assertEqual(r.status_code, 403)
178

    
179
        # can join app1
180
        self.member_client.get(reverse("edit_profile"))
181
        join_url = reverse("project_join", kwargs={'chain_id': app1_id})
182
        r = self.member_client.post(join_url, follow=True)
183
        self.assertEqual(r.status_code, 200)
184

    
185
        memberships = ProjectMembership.objects.all()
186
        self.assertEqual(len(memberships), 1)
187
        memb_id = memberships[0].id
188

    
189
        reject_member_url = reverse('project_reject_member',
190
                                    kwargs={'chain_id': app1_id, 'memb_id':
191
                                            memb_id})
192
        accept_member_url = reverse('project_accept_member',
193
                                    kwargs={'chain_id': app1_id, 'memb_id':
194
                                            memb_id})
195

    
196
        # only project owner is allowed to reject
197
        r = self.member_client.post(reject_member_url, follow=True)
198
        self.assertContains(r, "You do not have the permissions")
199
        self.assertEqual(r.status_code, 200)
200

    
201
        # user (owns project) rejects membership
202
        r = self.user_client.post(reject_member_url, follow=True)
203
        self.assertEqual(ProjectMembership.objects.count(), 0)
204

    
205
        # user rejoins
206
        self.member_client.get(reverse("edit_profile"))
207
        join_url = reverse("project_join", kwargs={'chain_id': app1_id})
208
        r = self.member_client.post(join_url, follow=True)
209
        self.assertEqual(r.status_code, 200)
210
        self.assertEqual(ProjectMembership.objects.count(), 1)
211

    
212
        # user (owns project) accepts membership
213
        r = self.user_client.post(accept_member_url, follow=True)
214
        self.assertEqual(ProjectMembership.objects.count(), 1)
215
        membership = ProjectMembership.objects.get()
216
        self.assertEqual(membership.state, ProjectMembership.ACCEPTED)
217

    
218
        user_quotas = quotas.get_users_quotas([self.member])
219
        resource = 'service1.resource'
220
        newlimit = user_quotas[self.member.uuid]['system'][resource]['limit']
221
        # 100 from initial uplimit + 100 from project
222
        self.assertEqual(newlimit, 200)
223

    
224
        remove_member_url = reverse('project_remove_member',
225
                                    kwargs={'chain_id': app1_id, 'memb_id':
226
                                            membership.id})
227
        r = self.user_client.post(remove_member_url, follow=True)
228
        self.assertEqual(r.status_code, 200)
229

    
230
        user_quotas = quotas.get_users_quotas([self.member])
231
        resource = 'service1.resource'
232
        newlimit = user_quotas[self.member.uuid]['system'][resource]['limit']
233
        # 200 - 100 from project
234
        self.assertEqual(newlimit, 100)