Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (9.9 kB)

1
# Copyright 2011, 2012, 2013 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.resource = Resource.objects.create(name="astakos.pending_app",
44
                                                uplimit=0,
45
                                                allow_in_projects=False,
46
                                                service_type="astakos")
47

    
48
        # custom service resources
49
        self.resource = Resource.objects.create(name="service1.resource",
50
                                                uplimit=100,
51
                                                service_type="service1")
52
        self.admin = get_local_user("projects-admin@synnefo.org")
53
        self.admin.uuid = 'uuid1'
54
        self.admin.save()
55

    
56
        self.user = get_local_user("user@synnefo.org")
57
        self.member = get_local_user("member@synnefo.org")
58
        self.member2 = get_local_user("member2@synnefo.org")
59

    
60
        self.admin_client = get_user_client("projects-admin@synnefo.org")
61
        self.user_client = get_user_client("user@synnefo.org")
62
        self.member_client = get_user_client("member@synnefo.org")
63
        self.member2_client = get_user_client("member2@synnefo.org")
64

    
65
        quotas.qh_sync_users(AstakosUser.objects.all())
66

    
67
    def tearDown(self):
68
        Service.objects.all().delete()
69
        ProjectApplication.objects.all().delete()
70
        Project.objects.all().delete()
71
        AstakosUser.objects.all().delete()
72

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

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

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

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

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

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

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

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

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

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

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

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

    
167
        # project created
168
        self.assertEqual(Project.objects.count(), 1)
169

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

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

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

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

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

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

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

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

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

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

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