Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (10 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
    @im_settings(PROJECT_ADMINS=['uuid1'])
72
    def test_application_limit(self):
73
        # user cannot create a project
74
        r = self.user_client.get(reverse('project_add'), follow=True)
75
        self.assertRedirects(r, reverse('project_list'))
76
        self.assertContains(r, "You are not allowed to create a new project")
77

    
78
        # but admin can
79
        r = self.admin_client.get(reverse('project_add'), follow=True)
80
        self.assertRedirects(r, reverse('project_add'))
81

    
82
    @im_settings(PROJECT_ADMINS=['uuid1'])
83
    def test_allow_in_project(self):
84
        dfrom = datetime.now()
85
        dto = datetime.now() + timedelta(days=30)
86

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

    
107
        del application_data['astakos.pending_app_uplimit']
108
        del application_data['is_selected_accounts']
109
        form = forms.ProjectApplicationForm(data=application_data)
110
        self.assertEqual(form.is_valid(), True)
111

    
112
    @im_settings(PROJECT_ADMINS=['uuid1'])
113
    def test_applications(self):
114
        # let user have 2 pending applications
115
        quotas.add_base_quota(self.user, 'astakos.pending_app', 2)
116

    
117
        r = self.user_client.get(reverse('project_add'), follow=True)
118
        self.assertRedirects(r, reverse('project_add'))
119

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

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

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

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

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

    
165
        # project created
166
        self.assertEqual(Project.objects.count(), 1)
167

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

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

    
181
        memberships = ProjectMembership.objects.all()
182
        self.assertEqual(len(memberships), 1)
183
        memb_id = memberships[0].id
184

    
185
        reject_member_url = reverse('project_reject_member',
186
                                    kwargs={'chain_id': app1_id, 'memb_id':
187
                                            memb_id})
188
        accept_member_url = reverse('project_accept_member',
189
                                    kwargs={'chain_id': app1_id, 'memb_id':
190
                                            memb_id})
191

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

    
197
        # user (owns project) rejects membership
198
        r = self.user_client.post(reject_member_url, follow=True)
199
        self.assertEqual(ProjectMembership.objects.count(), 0)
200

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

    
208
        # user (owns project) accepts membership
209
        r = self.user_client.post(accept_member_url, follow=True)
210
        self.assertEqual(ProjectMembership.objects.count(), 1)
211
        membership = ProjectMembership.objects.get()
212
        self.assertEqual(membership.state, ProjectMembership.ACCEPTED)
213

    
214
        user_quotas = quotas.get_users_quotas([self.member])
215
        resource = 'service1.resource'
216
        newlimit = user_quotas[self.member.uuid]['system'][resource]['limit']
217
        # 100 from initial uplimit + 100 from project
218
        self.assertEqual(newlimit, 200)
219

    
220
        remove_member_url = reverse('project_remove_member',
221
                                    kwargs={'chain_id': app1_id, 'memb_id':
222
                                            membership.id})
223
        r = self.user_client.post(remove_member_url, follow=True)
224
        self.assertEqual(r.status_code, 200)
225

    
226
        user_quotas = quotas.get_users_quotas([self.member])
227
        resource = 'service1.resource'
228
        newlimit = user_quotas[self.member.uuid]['system'][resource]['limit']
229
        # 200 - 100 from project
230
        self.assertEqual(newlimit, 100)