Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (30.7 kB)

1 bd1f667b Giorgos Korfiatis
# Copyright 2011, 2012, 2013 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 2556cf45 Giorgos Korfiatis
from snf_django.utils.testing import assertGreater, assertIn, assertRaises
36 2556cf45 Giorgos Korfiatis
37 2556cf45 Giorgos Korfiatis
38 2556cf45 Giorgos Korfiatis
class ProjectAPITest(TestCase):
39 2556cf45 Giorgos Korfiatis
40 2556cf45 Giorgos Korfiatis
    def setUp(self):
41 2556cf45 Giorgos Korfiatis
        self.client = Client()
42 2556cf45 Giorgos Korfiatis
        component1 = Component.objects.create(name="comp1")
43 2556cf45 Giorgos Korfiatis
        register.add_service(component1, "service1", "type1", [])
44 2556cf45 Giorgos Korfiatis
        # custom service resources
45 2556cf45 Giorgos Korfiatis
        resource11 = {"name": "service1.resource11",
46 2556cf45 Giorgos Korfiatis
                      "desc": "resource11 desc",
47 2556cf45 Giorgos Korfiatis
                      "service_type": "type1",
48 2556cf45 Giorgos Korfiatis
                      "service_origin": "service1",
49 2556cf45 Giorgos Korfiatis
                      "allow_in_projects": True}
50 2556cf45 Giorgos Korfiatis
        r, _ = register.add_resource(resource11)
51 2556cf45 Giorgos Korfiatis
        register.update_resource(r, 100)
52 2556cf45 Giorgos Korfiatis
        resource12 = {"name": "service1.resource12",
53 2556cf45 Giorgos Korfiatis
                      "desc": "resource11 desc",
54 2556cf45 Giorgos Korfiatis
                      "service_type": "type1",
55 2556cf45 Giorgos Korfiatis
                      "service_origin": "service1",
56 2556cf45 Giorgos Korfiatis
                      "unit": "bytes"}
57 2556cf45 Giorgos Korfiatis
        r, _ = register.add_resource(resource12)
58 2556cf45 Giorgos Korfiatis
        register.update_resource(r, 1024)
59 2556cf45 Giorgos Korfiatis
60 2556cf45 Giorgos Korfiatis
        # create user
61 2556cf45 Giorgos Korfiatis
        self.user1 = get_local_user("test@grnet.gr")
62 2556cf45 Giorgos Korfiatis
        quotas.qh_sync_user(self.user1)
63 2556cf45 Giorgos Korfiatis
        self.user2 = get_local_user("test2@grnet.gr")
64 2556cf45 Giorgos Korfiatis
        self.user2.uuid = "uuid2"
65 2556cf45 Giorgos Korfiatis
        self.user2.save()
66 2556cf45 Giorgos Korfiatis
        quotas.qh_sync_user(self.user2)
67 2556cf45 Giorgos Korfiatis
        self.user3 = get_local_user("test3@grnet.gr")
68 2556cf45 Giorgos Korfiatis
        quotas.qh_sync_user(self.user3)
69 2556cf45 Giorgos Korfiatis
70 2556cf45 Giorgos Korfiatis
        astakos = Component.objects.create(name="astakos")
71 2556cf45 Giorgos Korfiatis
        register.add_service(astakos, "astakos_account", "account", [])
72 2556cf45 Giorgos Korfiatis
        # create another service
73 2556cf45 Giorgos Korfiatis
        pending_app = {"name": "astakos.pending_app",
74 2556cf45 Giorgos Korfiatis
                       "desc": "pend app desc",
75 2556cf45 Giorgos Korfiatis
                       "service_type": "account",
76 2556cf45 Giorgos Korfiatis
                       "service_origin": "astakos_account",
77 2556cf45 Giorgos Korfiatis
                       "allow_in_projects": False}
78 2556cf45 Giorgos Korfiatis
        r, _ = register.add_resource(pending_app)
79 2556cf45 Giorgos Korfiatis
        register.update_resource(r, 3)
80 2556cf45 Giorgos Korfiatis
81 2556cf45 Giorgos Korfiatis
    def create(self, app, headers):
82 2556cf45 Giorgos Korfiatis
        dump = json.dumps(app)
83 2556cf45 Giorgos Korfiatis
        r = self.client.post(reverse("api_projects"), dump,
84 2556cf45 Giorgos Korfiatis
                             content_type="application/json", **headers)
85 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
86 2556cf45 Giorgos Korfiatis
        return r.status_code, body
87 2556cf45 Giorgos Korfiatis
88 2556cf45 Giorgos Korfiatis
    def modify(self, app, project_id, headers):
89 2556cf45 Giorgos Korfiatis
        dump = json.dumps(app)
90 2556cf45 Giorgos Korfiatis
        kwargs = {"project_id": project_id}
91 2556cf45 Giorgos Korfiatis
        r = self.client.post(reverse("api_project", kwargs=kwargs), dump,
92 2556cf45 Giorgos Korfiatis
                             content_type="application/json", **headers)
93 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
94 2556cf45 Giorgos Korfiatis
        return r.status_code, body
95 2556cf45 Giorgos Korfiatis
96 2556cf45 Giorgos Korfiatis
    def project_action(self, project_id, action, headers):
97 2556cf45 Giorgos Korfiatis
        action = json.dumps({action: "reason"})
98 2556cf45 Giorgos Korfiatis
        r = self.client.post(reverse("api_project_action",
99 2556cf45 Giorgos Korfiatis
                                     kwargs={"project_id": project_id}),
100 2556cf45 Giorgos Korfiatis
                             action, content_type="application/json",
101 2556cf45 Giorgos Korfiatis
                             **headers)
102 2556cf45 Giorgos Korfiatis
        return r.status_code
103 2556cf45 Giorgos Korfiatis
104 2556cf45 Giorgos Korfiatis
    def app_action(self, app_id, action, headers):
105 2556cf45 Giorgos Korfiatis
        action = json.dumps({action: "reason"})
106 2556cf45 Giorgos Korfiatis
        r = self.client.post(reverse("api_application_action",
107 2556cf45 Giorgos Korfiatis
                                     kwargs={"app_id": app_id}),
108 2556cf45 Giorgos Korfiatis
                             action, content_type="application/json",
109 2556cf45 Giorgos Korfiatis
                             **headers)
110 2556cf45 Giorgos Korfiatis
        return r.status_code
111 2556cf45 Giorgos Korfiatis
112 2556cf45 Giorgos Korfiatis
    def memb_action(self, memb_id, action, headers):
113 2556cf45 Giorgos Korfiatis
        action = json.dumps({action: "reason"})
114 2556cf45 Giorgos Korfiatis
        r = self.client.post(reverse("api_membership_action",
115 2556cf45 Giorgos Korfiatis
                                     kwargs={"memb_id": memb_id}), action,
116 2556cf45 Giorgos Korfiatis
                             content_type="application/json", **headers)
117 2556cf45 Giorgos Korfiatis
        return r.status_code
118 2556cf45 Giorgos Korfiatis
119 2556cf45 Giorgos Korfiatis
    def join(self, project_id, headers):
120 2556cf45 Giorgos Korfiatis
        action = {"join": {"project": project_id}}
121 2556cf45 Giorgos Korfiatis
        req = json.dumps(action)
122 2556cf45 Giorgos Korfiatis
        r = self.client.post(reverse("api_memberships"), req,
123 2556cf45 Giorgos Korfiatis
                             content_type="application/json", **headers)
124 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
125 2556cf45 Giorgos Korfiatis
        return r.status_code, body
126 2556cf45 Giorgos Korfiatis
127 2556cf45 Giorgos Korfiatis
    def enroll(self, project_id, user, headers):
128 2556cf45 Giorgos Korfiatis
        action = {
129 2556cf45 Giorgos Korfiatis
            "enroll": {
130 2556cf45 Giorgos Korfiatis
                "project": project_id,
131 2556cf45 Giorgos Korfiatis
                "user": user.email,
132 2556cf45 Giorgos Korfiatis
            }
133 2556cf45 Giorgos Korfiatis
        }
134 2556cf45 Giorgos Korfiatis
        req = json.dumps(action)
135 2556cf45 Giorgos Korfiatis
        r = self.client.post(reverse("api_memberships"), req,
136 2556cf45 Giorgos Korfiatis
                             content_type="application/json", **headers)
137 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
138 2556cf45 Giorgos Korfiatis
        return r.status_code, body
139 2556cf45 Giorgos Korfiatis
140 2556cf45 Giorgos Korfiatis
    @im_settings(PROJECT_ADMINS=["uuid2"])
141 2556cf45 Giorgos Korfiatis
    def test_projects(self):
142 2556cf45 Giorgos Korfiatis
        client = self.client
143 2556cf45 Giorgos Korfiatis
        h_owner = {"HTTP_X_AUTH_TOKEN": self.user1.auth_token}
144 2556cf45 Giorgos Korfiatis
        h_admin = {"HTTP_X_AUTH_TOKEN": self.user2.auth_token}
145 2556cf45 Giorgos Korfiatis
        h_plain = {"HTTP_X_AUTH_TOKEN": self.user3.auth_token}
146 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_project", kwargs={"project_id": 1}))
147 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 401)
148 2556cf45 Giorgos Korfiatis
149 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_project", kwargs={"project_id": 1}),
150 2556cf45 Giorgos Korfiatis
                       **h_owner)
151 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 404)
152 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_application", kwargs={"app_id": 1}),
153 2556cf45 Giorgos Korfiatis
                       **h_owner)
154 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 404)
155 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_membership", kwargs={"memb_id": 1}),
156 2556cf45 Giorgos Korfiatis
                       **h_owner)
157 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 404)
158 2556cf45 Giorgos Korfiatis
159 2556cf45 Giorgos Korfiatis
        status = self.memb_action(1, "accept", h_admin)
160 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 404)
161 2556cf45 Giorgos Korfiatis
162 2556cf45 Giorgos Korfiatis
        app1 = {"name": "test.pr",
163 2556cf45 Giorgos Korfiatis
                "end_date": "2013-5-5T20:20:20Z",
164 2556cf45 Giorgos Korfiatis
                "join_policy": "auto",
165 e98239db Giorgos Korfiatis
                "max_members": 5,
166 2556cf45 Giorgos Korfiatis
                "resources": {"service1.resource11": {
167 2556cf45 Giorgos Korfiatis
                    "member_capacity": 512}}
168 2556cf45 Giorgos Korfiatis
                }
169 2556cf45 Giorgos Korfiatis
170 2556cf45 Giorgos Korfiatis
        status, body = self.modify(app1, 1, h_owner)
171 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 404)
172 2556cf45 Giorgos Korfiatis
173 2556cf45 Giorgos Korfiatis
        # Create
174 2556cf45 Giorgos Korfiatis
        status, body = self.create(app1, h_owner)
175 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 201)
176 2556cf45 Giorgos Korfiatis
        project_id = body["id"]
177 2556cf45 Giorgos Korfiatis
        app_id = body["application"]
178 2556cf45 Giorgos Korfiatis
179 2556cf45 Giorgos Korfiatis
        # Get project
180 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_project",
181 2556cf45 Giorgos Korfiatis
                               kwargs={"project_id": project_id}),
182 2556cf45 Giorgos Korfiatis
                       **h_owner)
183 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 200)
184 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
185 2556cf45 Giorgos Korfiatis
        self.assertEqual(body["id"], project_id)
186 2556cf45 Giorgos Korfiatis
        self.assertEqual(body["application"], app_id)
187 2556cf45 Giorgos Korfiatis
        self.assertEqual(body["state"], "pending")
188 2556cf45 Giorgos Korfiatis
        self.assertEqual(body["owner"], self.user1.uuid)
189 2556cf45 Giorgos Korfiatis
190 2556cf45 Giorgos Korfiatis
        # Approve forbidden
191 2556cf45 Giorgos Korfiatis
        status = self.app_action(app_id, "approve", h_owner)
192 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 403)
193 2556cf45 Giorgos Korfiatis
194 2556cf45 Giorgos Korfiatis
        # Create another with the same name
195 2556cf45 Giorgos Korfiatis
        status, body = self.create(app1, h_owner)
196 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 201)
197 2556cf45 Giorgos Korfiatis
        project2_id = body["id"]
198 2556cf45 Giorgos Korfiatis
        project2_app_id = body["application"]
199 2556cf45 Giorgos Korfiatis
200 2556cf45 Giorgos Korfiatis
        # Create yet another, with different name
201 2556cf45 Giorgos Korfiatis
        app_p3 = copy.deepcopy(app1)
202 2556cf45 Giorgos Korfiatis
        app_p3["name"] = "new.pr"
203 2556cf45 Giorgos Korfiatis
        status, body = self.create(app_p3, h_owner)
204 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 201)
205 2556cf45 Giorgos Korfiatis
        project3_app_id = body["application"]
206 2556cf45 Giorgos Korfiatis
207 2556cf45 Giorgos Korfiatis
        # No more pending allowed
208 2556cf45 Giorgos Korfiatis
        status, body = self.create(app_p3, h_owner)
209 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 409)
210 2556cf45 Giorgos Korfiatis
211 2556cf45 Giorgos Korfiatis
        # Cancel
212 2556cf45 Giorgos Korfiatis
        status = self.app_action(project3_app_id, "cancel", h_owner)
213 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
214 2556cf45 Giorgos Korfiatis
215 2556cf45 Giorgos Korfiatis
        # Modify
216 2556cf45 Giorgos Korfiatis
        app2 = {"name": "test.pr",
217 2556cf45 Giorgos Korfiatis
                "start_date": "2013-5-5T20:20:20Z",
218 2556cf45 Giorgos Korfiatis
                "end_date": "2013-7-5T20:20:20Z",
219 2556cf45 Giorgos Korfiatis
                "join_policy": "moderated",
220 2556cf45 Giorgos Korfiatis
                "leave_policy": "auto",
221 2556cf45 Giorgos Korfiatis
                "max_members": 3,
222 2556cf45 Giorgos Korfiatis
                "resources": {"service1.resource11": {
223 2556cf45 Giorgos Korfiatis
                    "member_capacity": 1024}}
224 2556cf45 Giorgos Korfiatis
                }
225 2556cf45 Giorgos Korfiatis
226 2556cf45 Giorgos Korfiatis
        status, body = self.modify(app2, project_id, h_owner)
227 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 201)
228 2556cf45 Giorgos Korfiatis
        self.assertEqual(project_id, body["id"])
229 2556cf45 Giorgos Korfiatis
        app2_id = body["application"]
230 2556cf45 Giorgos Korfiatis
        assertGreater(app2_id, app_id)
231 2556cf45 Giorgos Korfiatis
232 2556cf45 Giorgos Korfiatis
        # Dismiss failed
233 2556cf45 Giorgos Korfiatis
        status = self.app_action(app2_id, "dismiss", h_owner)
234 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 409)
235 2556cf45 Giorgos Korfiatis
236 2556cf45 Giorgos Korfiatis
        # Deny
237 2556cf45 Giorgos Korfiatis
        status = self.app_action(app2_id, "deny", h_admin)
238 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
239 2556cf45 Giorgos Korfiatis
240 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_application", kwargs={"app_id": app2_id}),
241 2556cf45 Giorgos Korfiatis
                       **h_owner)
242 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
243 2556cf45 Giorgos Korfiatis
        self.assertEqual(body["state"], "denied")
244 2556cf45 Giorgos Korfiatis
245 2556cf45 Giorgos Korfiatis
        # Dismiss
246 2556cf45 Giorgos Korfiatis
        status = self.app_action(app2_id, "dismiss", h_owner)
247 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
248 2556cf45 Giorgos Korfiatis
249 2556cf45 Giorgos Korfiatis
        # Resubmit
250 2556cf45 Giorgos Korfiatis
        status, body = self.modify(app2, project_id, h_owner)
251 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 201)
252 2556cf45 Giorgos Korfiatis
        app3_id = body["application"]
253 2556cf45 Giorgos Korfiatis
254 2556cf45 Giorgos Korfiatis
        # Approve
255 2556cf45 Giorgos Korfiatis
        status = self.app_action(app3_id, "approve", h_admin)
256 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
257 2556cf45 Giorgos Korfiatis
258 2556cf45 Giorgos Korfiatis
        # Get related apps
259 2556cf45 Giorgos Korfiatis
        req = {"body": json.dumps({"project": project_id})}
260 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_applications"), req, **h_owner)
261 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 200)
262 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
263 2556cf45 Giorgos Korfiatis
        self.assertEqual(len(body), 3)
264 2556cf45 Giorgos Korfiatis
265 2556cf45 Giorgos Korfiatis
        # Get apps
266 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_applications"), **h_owner)
267 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 200)
268 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
269 2556cf45 Giorgos Korfiatis
        self.assertEqual(len(body), 5)
270 2556cf45 Giorgos Korfiatis
271 2556cf45 Giorgos Korfiatis
        # Enroll
272 2556cf45 Giorgos Korfiatis
        status, body = self.enroll(project_id, self.user3, h_owner)
273 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
274 2556cf45 Giorgos Korfiatis
        m_plain_id = body["id"]
275 2556cf45 Giorgos Korfiatis
276 2556cf45 Giorgos Korfiatis
        # Join
277 2556cf45 Giorgos Korfiatis
        status, body = self.join(project_id, h_owner)
278 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
279 2556cf45 Giorgos Korfiatis
        memb_id = body["id"]
280 2556cf45 Giorgos Korfiatis
281 2556cf45 Giorgos Korfiatis
        # Check memberships
282 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_memberships"), **h_plain)
283 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
284 2556cf45 Giorgos Korfiatis
        self.assertEqual(len(body), 1)
285 2556cf45 Giorgos Korfiatis
        m = body[0]
286 2556cf45 Giorgos Korfiatis
        self.assertEqual(m["user"], self.user3.uuid)
287 2556cf45 Giorgos Korfiatis
        self.assertEqual(m["state"], "accepted")
288 2556cf45 Giorgos Korfiatis
289 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_memberships"), **h_owner)
290 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
291 2556cf45 Giorgos Korfiatis
        self.assertEqual(len(body), 2)
292 2556cf45 Giorgos Korfiatis
293 2556cf45 Giorgos Korfiatis
        # Check membership
294 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_membership", kwargs={"memb_id": memb_id}),
295 2556cf45 Giorgos Korfiatis
                       **h_admin)
296 2556cf45 Giorgos Korfiatis
        m = json.loads(r.content)
297 2556cf45 Giorgos Korfiatis
        self.assertEqual(m["user"], self.user1.uuid)
298 2556cf45 Giorgos Korfiatis
        self.assertEqual(m["state"], "requested")
299 2556cf45 Giorgos Korfiatis
        self.assertEqual(sorted(m["allowed_actions"]),
300 2556cf45 Giorgos Korfiatis
                         ["accept", "cancel", "reject"])
301 2556cf45 Giorgos Korfiatis
302 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_membership", kwargs={"memb_id": memb_id}),
303 2556cf45 Giorgos Korfiatis
                       **h_plain)
304 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 403)
305 2556cf45 Giorgos Korfiatis
306 2556cf45 Giorgos Korfiatis
        status = self.memb_action(memb_id, "leave", h_admin)
307 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 409)
308 2556cf45 Giorgos Korfiatis
309 2556cf45 Giorgos Korfiatis
        status = self.memb_action(memb_id, "cancel", h_owner)
310 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
311 2556cf45 Giorgos Korfiatis
312 2556cf45 Giorgos Korfiatis
        status, body = self.join(project_id, h_owner)
313 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
314 2556cf45 Giorgos Korfiatis
        self.assertEqual(memb_id, body["id"])
315 2556cf45 Giorgos Korfiatis
316 2556cf45 Giorgos Korfiatis
        status = self.memb_action(memb_id, "reject", h_owner)
317 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
318 2556cf45 Giorgos Korfiatis
319 2556cf45 Giorgos Korfiatis
        status, body = self.join(project_id, h_owner)
320 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
321 2556cf45 Giorgos Korfiatis
        self.assertEqual(memb_id, body["id"])
322 2556cf45 Giorgos Korfiatis
323 2556cf45 Giorgos Korfiatis
        status = self.memb_action(memb_id, "accept", h_owner)
324 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
325 2556cf45 Giorgos Korfiatis
326 2556cf45 Giorgos Korfiatis
        # Enroll fails, already in
327 2556cf45 Giorgos Korfiatis
        status, body = self.enroll(project_id, self.user1, h_owner)
328 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 409)
329 2556cf45 Giorgos Korfiatis
330 2556cf45 Giorgos Korfiatis
        # Remove member
331 2556cf45 Giorgos Korfiatis
        status = self.memb_action(memb_id, "remove", h_owner)
332 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
333 2556cf45 Giorgos Korfiatis
334 2556cf45 Giorgos Korfiatis
        # Enroll a removed member
335 2556cf45 Giorgos Korfiatis
        status, body = self.enroll(project_id, self.user1, h_owner)
336 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
337 2556cf45 Giorgos Korfiatis
338 2556cf45 Giorgos Korfiatis
        # Remove member
339 2556cf45 Giorgos Korfiatis
        status = self.memb_action(memb_id, "remove", h_owner)
340 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
341 2556cf45 Giorgos Korfiatis
342 2556cf45 Giorgos Korfiatis
        # Re-join
343 2556cf45 Giorgos Korfiatis
        status, body = self.join(project_id, h_owner)
344 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
345 2556cf45 Giorgos Korfiatis
        self.assertEqual(memb_id, body["id"])
346 2556cf45 Giorgos Korfiatis
347 2556cf45 Giorgos Korfiatis
        # Enroll a requested member
348 2556cf45 Giorgos Korfiatis
        status, body = self.enroll(project_id, self.user1, h_owner)
349 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
350 2556cf45 Giorgos Korfiatis
351 2556cf45 Giorgos Korfiatis
        # Enroll fails, already in
352 2556cf45 Giorgos Korfiatis
        status, body = self.enroll(project_id, self.user1, h_owner)
353 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 409)
354 2556cf45 Giorgos Korfiatis
355 d915cf3c Giorgos Korfiatis
        # Enroll fails, project does not exist
356 d915cf3c Giorgos Korfiatis
        status, body = self.enroll(-1, self.user1, h_owner)
357 d915cf3c Giorgos Korfiatis
        self.assertEqual(status, 409)
358 d915cf3c Giorgos Korfiatis
359 2556cf45 Giorgos Korfiatis
        # Get projects
360 2556cf45 Giorgos Korfiatis
        ## Simple user mode
361 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_projects"), **h_plain)
362 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
363 2556cf45 Giorgos Korfiatis
        self.assertEqual(len(body), 1)
364 2556cf45 Giorgos Korfiatis
        p = body[0]
365 2556cf45 Giorgos Korfiatis
        with assertRaises(KeyError):
366 2556cf45 Giorgos Korfiatis
            p["pending_application"]
367 2556cf45 Giorgos Korfiatis
368 2556cf45 Giorgos Korfiatis
        ## Owner mode
369 2556cf45 Giorgos Korfiatis
        filters = {"filter": {"state": ["active", "cancelled"]}}
370 2556cf45 Giorgos Korfiatis
        req = {"body": json.dumps(filters)}
371 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_projects"), req, **h_owner)
372 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
373 2556cf45 Giorgos Korfiatis
        self.assertEqual(len(body), 2)
374 2556cf45 Giorgos Korfiatis
        assertIn("pending_application", body[0])
375 2556cf45 Giorgos Korfiatis
376 2556cf45 Giorgos Korfiatis
        filters = {"filter": {"state": "pending"}}
377 2556cf45 Giorgos Korfiatis
        req = {"body": json.dumps(filters)}
378 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_projects"), req, **h_owner)
379 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
380 2556cf45 Giorgos Korfiatis
        self.assertEqual(len(body), 1)
381 2556cf45 Giorgos Korfiatis
        self.assertEqual(body[0]["id"], project2_id)
382 2556cf45 Giorgos Korfiatis
383 2556cf45 Giorgos Korfiatis
        filters = {"filter": {"name": "test.pr"}}
384 2556cf45 Giorgos Korfiatis
        req = {"body": json.dumps(filters)}
385 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_projects"), req, **h_owner)
386 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
387 2556cf45 Giorgos Korfiatis
        self.assertEqual(len(body), 2)
388 2556cf45 Giorgos Korfiatis
389 2556cf45 Giorgos Korfiatis
        # Leave failed
390 2556cf45 Giorgos Korfiatis
        status = self.memb_action(m_plain_id, "leave", h_owner)
391 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 403)
392 2556cf45 Giorgos Korfiatis
393 2556cf45 Giorgos Korfiatis
        # Leave
394 2556cf45 Giorgos Korfiatis
        status = self.memb_action(m_plain_id, "leave", h_plain)
395 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
396 2556cf45 Giorgos Korfiatis
397 2556cf45 Giorgos Korfiatis
        # Suspend failed
398 2556cf45 Giorgos Korfiatis
        status = self.project_action(project_id, "suspend", h_owner)
399 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 403)
400 2556cf45 Giorgos Korfiatis
401 2556cf45 Giorgos Korfiatis
        # Unsuspend failed
402 2556cf45 Giorgos Korfiatis
        status = self.project_action(project_id, "unsuspend", h_admin)
403 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 409)
404 2556cf45 Giorgos Korfiatis
405 2556cf45 Giorgos Korfiatis
        # Suspend
406 2556cf45 Giorgos Korfiatis
        status = self.project_action(project_id, "suspend", h_admin)
407 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
408 2556cf45 Giorgos Korfiatis
409 2556cf45 Giorgos Korfiatis
        # Cannot view project
410 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_project",
411 2556cf45 Giorgos Korfiatis
                               kwargs={"project_id": project_id}), **h_plain)
412 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 403)
413 2556cf45 Giorgos Korfiatis
414 2556cf45 Giorgos Korfiatis
        # Unsuspend
415 2556cf45 Giorgos Korfiatis
        status = self.project_action(project_id, "unsuspend", h_admin)
416 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
417 2556cf45 Giorgos Korfiatis
418 2556cf45 Giorgos Korfiatis
        # Cannot approve, project with same name exists
419 2556cf45 Giorgos Korfiatis
        status = self.app_action(project2_app_id, "approve", h_admin)
420 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 409)
421 2556cf45 Giorgos Korfiatis
422 2556cf45 Giorgos Korfiatis
        # Terminate
423 2556cf45 Giorgos Korfiatis
        status = self.project_action(project_id, "terminate", h_admin)
424 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
425 2556cf45 Giorgos Korfiatis
426 2556cf45 Giorgos Korfiatis
        # Join failed
427 2556cf45 Giorgos Korfiatis
        status, _ = self.join(project_id, h_admin)
428 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 409)
429 2556cf45 Giorgos Korfiatis
430 2556cf45 Giorgos Korfiatis
        # Can approve now
431 2556cf45 Giorgos Korfiatis
        status = self.app_action(project2_app_id, "approve", h_admin)
432 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
433 2556cf45 Giorgos Korfiatis
434 2556cf45 Giorgos Korfiatis
        # Join new project
435 2556cf45 Giorgos Korfiatis
        status, body = self.join(project2_id, h_plain)
436 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
437 2556cf45 Giorgos Korfiatis
        m_project2 = body["id"]
438 2556cf45 Giorgos Korfiatis
439 2556cf45 Giorgos Korfiatis
        # Get memberships of project
440 2556cf45 Giorgos Korfiatis
        body = {"body": json.dumps({"project": project2_id})}
441 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_memberships"), body, **h_owner)
442 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
443 2556cf45 Giorgos Korfiatis
        self.assertEqual(len(body), 1)
444 2556cf45 Giorgos Korfiatis
        self.assertEqual(body[0]["id"], m_project2)
445 2556cf45 Giorgos Korfiatis
446 2556cf45 Giorgos Korfiatis
        # Remove member
447 2556cf45 Giorgos Korfiatis
        status = self.memb_action(m_project2, "remove", h_owner)
448 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 200)
449 2556cf45 Giorgos Korfiatis
450 2556cf45 Giorgos Korfiatis
        # Reinstate failed
451 2556cf45 Giorgos Korfiatis
        status = self.project_action(project_id, "reinstate", h_admin)
452 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 409)
453 2556cf45 Giorgos Korfiatis
454 2556cf45 Giorgos Korfiatis
        # Rename
455 2556cf45 Giorgos Korfiatis
        app2_renamed = copy.deepcopy(app2)
456 2556cf45 Giorgos Korfiatis
        app2_renamed["name"] = "new.name"
457 2556cf45 Giorgos Korfiatis
        status, body = self.modify(app2_renamed, project_id, h_owner)
458 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 201)
459 2556cf45 Giorgos Korfiatis
        app2_renamed_id = body["application"]
460 2556cf45 Giorgos Korfiatis
461 2556cf45 Giorgos Korfiatis
        # Get project
462 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_project",
463 2556cf45 Giorgos Korfiatis
                               kwargs={"project_id": project_id}), **h_owner)
464 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
465 2556cf45 Giorgos Korfiatis
        self.assertEqual(body["application"], app3_id)
466 2556cf45 Giorgos Korfiatis
        self.assertEqual(body["pending_application"], app2_renamed_id)
467 2556cf45 Giorgos Korfiatis
        self.assertEqual(body["state"], "terminated")
468 2556cf45 Giorgos Korfiatis
        assertIn("deactivation_date", body)
469 2556cf45 Giorgos Korfiatis
470 2556cf45 Giorgos Korfiatis
        # Get application
471 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_application",
472 2556cf45 Giorgos Korfiatis
                               kwargs={"app_id": app2_renamed_id}), **h_plain)
473 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 403)
474 2556cf45 Giorgos Korfiatis
475 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_application",
476 2556cf45 Giorgos Korfiatis
                               kwargs={"app_id": app2_renamed_id}), **h_owner)
477 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 200)
478 2556cf45 Giorgos Korfiatis
        body = json.loads(r.content)
479 2556cf45 Giorgos Korfiatis
        self.assertEqual(body["state"], "pending")
480 2556cf45 Giorgos Korfiatis
        self.assertEqual(body["name"], "new.name")
481 2556cf45 Giorgos Korfiatis
482 2556cf45 Giorgos Korfiatis
        # Approve (automatically reinstates)
483 2556cf45 Giorgos Korfiatis
        action = json.dumps({"approve": ""})
484 2556cf45 Giorgos Korfiatis
        r = client.post(reverse("api_application_action",
485 2556cf45 Giorgos Korfiatis
                                kwargs={"app_id": app2_renamed_id}),
486 2556cf45 Giorgos Korfiatis
                        action, content_type="application/json", **h_admin)
487 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 200)
488 2556cf45 Giorgos Korfiatis
489 2556cf45 Giorgos Korfiatis
        # Bad requests
490 2556cf45 Giorgos Korfiatis
        r = client.head(reverse("api_projects"), **h_admin)
491 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 400)
492 2556cf45 Giorgos Korfiatis
493 2556cf45 Giorgos Korfiatis
        r = client.head(reverse("api_project",
494 2556cf45 Giorgos Korfiatis
                                kwargs={"project_id": 1}), **h_admin)
495 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 400)
496 2556cf45 Giorgos Korfiatis
497 2556cf45 Giorgos Korfiatis
        r = client.head(reverse("api_applications"), **h_admin)
498 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 400)
499 2556cf45 Giorgos Korfiatis
500 2556cf45 Giorgos Korfiatis
        r = client.head(reverse("api_memberships"), **h_admin)
501 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 400)
502 2556cf45 Giorgos Korfiatis
503 2556cf45 Giorgos Korfiatis
        status = self.project_action(1, "nonex", h_owner)
504 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 400)
505 2556cf45 Giorgos Korfiatis
506 2556cf45 Giorgos Korfiatis
        action = json.dumps({"suspend": "", "unsuspend": ""})
507 2556cf45 Giorgos Korfiatis
        r = client.post(reverse("api_project_action",
508 2556cf45 Giorgos Korfiatis
                                kwargs={"project_id": 1}),
509 2556cf45 Giorgos Korfiatis
                        action, content_type="application/json", **h_owner)
510 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 400)
511 2556cf45 Giorgos Korfiatis
512 2556cf45 Giorgos Korfiatis
        ap = {"owner": "nonex",
513 2556cf45 Giorgos Korfiatis
              "join_policy": "nonex",
514 2556cf45 Giorgos Korfiatis
              "leave_policy": "nonex",
515 2556cf45 Giorgos Korfiatis
              "start_date": "nonex",
516 2556cf45 Giorgos Korfiatis
              "homepage": {},
517 2556cf45 Giorgos Korfiatis
              "max_members": -3,
518 2556cf45 Giorgos Korfiatis
              "resources": [],
519 2556cf45 Giorgos Korfiatis
              }
520 2556cf45 Giorgos Korfiatis
521 2556cf45 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
522 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 400)
523 2556cf45 Giorgos Korfiatis
        self.assertEqual(body["badRequest"]["message"], "User does not exist.")
524 2556cf45 Giorgos Korfiatis
525 2556cf45 Giorgos Korfiatis
        ap["owner"] = self.user1.uuid
526 2556cf45 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
527 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 400)
528 2556cf45 Giorgos Korfiatis
529 2556cf45 Giorgos Korfiatis
        ap["name"] = "some.name"
530 2556cf45 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
531 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 400)
532 2556cf45 Giorgos Korfiatis
533 2556cf45 Giorgos Korfiatis
        ap["join_policy"] = "auto"
534 2556cf45 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
535 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 400)
536 2556cf45 Giorgos Korfiatis
537 2556cf45 Giorgos Korfiatis
        ap["leave_policy"] = "closed"
538 2556cf45 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
539 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 400)
540 2556cf45 Giorgos Korfiatis
541 2556cf45 Giorgos Korfiatis
        ap["start_date"] = "2013-01-01T0:0Z"
542 2556cf45 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
543 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 400)
544 2556cf45 Giorgos Korfiatis
545 2556cf45 Giorgos Korfiatis
        ap["end_date"] = "2014-01-01T0:0Z"
546 2556cf45 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
547 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 400)
548 2556cf45 Giorgos Korfiatis
549 2556cf45 Giorgos Korfiatis
        ap["max_members"] = 0
550 2556cf45 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
551 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 400)
552 2556cf45 Giorgos Korfiatis
553 2556cf45 Giorgos Korfiatis
        ap["homepage"] = "a.stri.ng"
554 2556cf45 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
555 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 400)
556 2556cf45 Giorgos Korfiatis
557 2556cf45 Giorgos Korfiatis
        ap["resources"] = {42: 42}
558 2556cf45 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
559 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 400)
560 2556cf45 Giorgos Korfiatis
561 2556cf45 Giorgos Korfiatis
        ap["resources"] = {"service1.resource11": {"member_capacity": 512}}
562 2556cf45 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
563 2556cf45 Giorgos Korfiatis
        self.assertEqual(status, 201)
564 2556cf45 Giorgos Korfiatis
565 a23ac2f7 Giorgos Korfiatis
        ap["name"] = "non_domain_name"
566 a23ac2f7 Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
567 a23ac2f7 Giorgos Korfiatis
        self.assertEqual(status, 400)
568 a23ac2f7 Giorgos Korfiatis
569 e98239db Giorgos Korfiatis
        ap["name"] = "domain.name"
570 e98239db Giorgos Korfiatis
        ap.pop("max_members")
571 e98239db Giorgos Korfiatis
        status, body = self.create(ap, h_owner)
572 e98239db Giorgos Korfiatis
        self.assertEqual(status, 400)
573 e98239db Giorgos Korfiatis
574 2556cf45 Giorgos Korfiatis
        filters = {"filter": {"state": "nonex"}}
575 2556cf45 Giorgos Korfiatis
        req = {"body": json.dumps(filters)}
576 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_projects"), req, **h_owner)
577 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 400)
578 2556cf45 Giorgos Korfiatis
579 2556cf45 Giorgos Korfiatis
        filters = {"filter": {"nonex": "nonex"}}
580 2556cf45 Giorgos Korfiatis
        req = {"body": json.dumps(filters)}
581 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_projects"), req, **h_owner)
582 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 400)
583 2556cf45 Giorgos Korfiatis
584 2556cf45 Giorgos Korfiatis
        req = {"body": json.dumps({"project": "nonex"})}
585 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_applications"), req, **h_owner)
586 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 400)
587 2556cf45 Giorgos Korfiatis
588 2556cf45 Giorgos Korfiatis
        req = {"body": json.dumps({"project": "nonex"})}
589 2556cf45 Giorgos Korfiatis
        r = client.get(reverse("api_memberships"), req, **h_owner)
590 2556cf45 Giorgos Korfiatis
        self.assertEqual(r.status_code, 400)
591 1ac3349d Kostas Papadimitriou
592 1ac3349d Kostas Papadimitriou
593 1ac3349d Kostas Papadimitriou
class TestProjects(TestCase):
594 1ac3349d Kostas Papadimitriou
    """
595 1ac3349d Kostas Papadimitriou
    Test projects.
596 1ac3349d Kostas Papadimitriou
    """
597 1ac3349d Kostas Papadimitriou
    def setUp(self):
598 1ac3349d Kostas Papadimitriou
        # astakos resources
599 1ac3349d Kostas Papadimitriou
        self.resource = Resource.objects.create(name="astakos.pending_app",
600 1ac3349d Kostas Papadimitriou
                                                uplimit=0,
601 1ac3349d Kostas Papadimitriou
                                                allow_in_projects=False,
602 bd1f667b Giorgos Korfiatis
                                                service_type="astakos")
603 1ac3349d Kostas Papadimitriou
604 1ac3349d Kostas Papadimitriou
        # custom service resources
605 1ac3349d Kostas Papadimitriou
        self.resource = Resource.objects.create(name="service1.resource",
606 1ac3349d Kostas Papadimitriou
                                                uplimit=100,
607 bd1f667b Giorgos Korfiatis
                                                service_type="service1")
608 1ac3349d Kostas Papadimitriou
        self.admin = get_local_user("projects-admin@synnefo.org")
609 1ac3349d Kostas Papadimitriou
        self.admin.uuid = 'uuid1'
610 1ac3349d Kostas Papadimitriou
        self.admin.save()
611 1ac3349d Kostas Papadimitriou
612 1ac3349d Kostas Papadimitriou
        self.user = get_local_user("user@synnefo.org")
613 1ac3349d Kostas Papadimitriou
        self.member = get_local_user("member@synnefo.org")
614 1ac3349d Kostas Papadimitriou
        self.member2 = get_local_user("member2@synnefo.org")
615 1ac3349d Kostas Papadimitriou
616 1ac3349d Kostas Papadimitriou
        self.admin_client = get_user_client("projects-admin@synnefo.org")
617 1ac3349d Kostas Papadimitriou
        self.user_client = get_user_client("user@synnefo.org")
618 1ac3349d Kostas Papadimitriou
        self.member_client = get_user_client("member@synnefo.org")
619 1ac3349d Kostas Papadimitriou
        self.member2_client = get_user_client("member2@synnefo.org")
620 1ac3349d Kostas Papadimitriou
621 1ac3349d Kostas Papadimitriou
        quotas.qh_sync_users(AstakosUser.objects.all())
622 1ac3349d Kostas Papadimitriou
623 baa9073a Kostas Papadimitriou
    def tearDown(self):
624 baa9073a Kostas Papadimitriou
        Service.objects.all().delete()
625 baa9073a Kostas Papadimitriou
        ProjectApplication.objects.all().delete()
626 fce2ebcb Kostas Papadimitriou
        Project.objects.all().delete()
627 fce2ebcb Kostas Papadimitriou
        AstakosUser.objects.all().delete()
628 baa9073a Kostas Papadimitriou
629 1ac3349d Kostas Papadimitriou
    @im_settings(PROJECT_ADMINS=['uuid1'])
630 1ac3349d Kostas Papadimitriou
    def test_application_limit(self):
631 1ac3349d Kostas Papadimitriou
        # user cannot create a project
632 1ac3349d Kostas Papadimitriou
        r = self.user_client.get(reverse('project_add'), follow=True)
633 1ac3349d Kostas Papadimitriou
        self.assertRedirects(r, reverse('project_list'))
634 1ac3349d Kostas Papadimitriou
        self.assertContains(r, "You are not allowed to create a new project")
635 1ac3349d Kostas Papadimitriou
636 1ac3349d Kostas Papadimitriou
        # but admin can
637 1ac3349d Kostas Papadimitriou
        r = self.admin_client.get(reverse('project_add'), follow=True)
638 1ac3349d Kostas Papadimitriou
        self.assertRedirects(r, reverse('project_add'))
639 1ac3349d Kostas Papadimitriou
640 1ac3349d Kostas Papadimitriou
    @im_settings(PROJECT_ADMINS=['uuid1'])
641 1ac3349d Kostas Papadimitriou
    def test_allow_in_project(self):
642 1ac3349d Kostas Papadimitriou
        dfrom = datetime.now()
643 1ac3349d Kostas Papadimitriou
        dto = datetime.now() + timedelta(days=30)
644 1ac3349d Kostas Papadimitriou
645 1ac3349d Kostas Papadimitriou
        # astakos.pending_uplimit allow_in_project flag is False
646 1ac3349d Kostas Papadimitriou
        # we shouldn't be able to create a project application using this
647 1ac3349d Kostas Papadimitriou
        # resource.
648 1ac3349d Kostas Papadimitriou
        application_data = {
649 1ac3349d Kostas Papadimitriou
            'name': 'project.synnefo.org',
650 1ac3349d Kostas Papadimitriou
            'homepage': 'https://www.synnefo.org',
651 1ac3349d Kostas Papadimitriou
            'start_date': dfrom.strftime("%Y-%m-%d"),
652 1ac3349d Kostas Papadimitriou
            'end_date': dto.strftime("%Y-%m-%d"),
653 1ac3349d Kostas Papadimitriou
            'member_join_policy': 2,
654 1ac3349d Kostas Papadimitriou
            'member_leave_policy': 1,
655 e98239db Giorgos Korfiatis
            'limit_on_members_number': 5,
656 1ac3349d Kostas Papadimitriou
            'service1.resource_uplimit': 100,
657 1ac3349d Kostas Papadimitriou
            'is_selected_service1.resource': "1",
658 1ac3349d Kostas Papadimitriou
            'astakos.pending_app_uplimit': 100,
659 1ac3349d Kostas Papadimitriou
            'is_selected_accounts': "1",
660 1ac3349d Kostas Papadimitriou
            'user': self.user.pk
661 1ac3349d Kostas Papadimitriou
        }
662 1ac3349d Kostas Papadimitriou
        form = forms.ProjectApplicationForm(data=application_data)
663 1ac3349d Kostas Papadimitriou
        # form is invalid
664 1ac3349d Kostas Papadimitriou
        self.assertEqual(form.is_valid(), False)
665 1ac3349d Kostas Papadimitriou
666 1ac3349d Kostas Papadimitriou
        del application_data['astakos.pending_app_uplimit']
667 1ac3349d Kostas Papadimitriou
        del application_data['is_selected_accounts']
668 1ac3349d Kostas Papadimitriou
        form = forms.ProjectApplicationForm(data=application_data)
669 1ac3349d Kostas Papadimitriou
        self.assertEqual(form.is_valid(), True)
670 1ac3349d Kostas Papadimitriou
671 1ac3349d Kostas Papadimitriou
    @im_settings(PROJECT_ADMINS=['uuid1'])
672 1ac3349d Kostas Papadimitriou
    def test_applications(self):
673 1ac3349d Kostas Papadimitriou
        # let user have 2 pending applications
674 1ac3349d Kostas Papadimitriou
        quotas.add_base_quota(self.user, 'astakos.pending_app', 2)
675 1ac3349d Kostas Papadimitriou
676 1ac3349d Kostas Papadimitriou
        r = self.user_client.get(reverse('project_add'), follow=True)
677 1ac3349d Kostas Papadimitriou
        self.assertRedirects(r, reverse('project_add'))
678 1ac3349d Kostas Papadimitriou
679 1ac3349d Kostas Papadimitriou
        # user fills the project application form
680 1ac3349d Kostas Papadimitriou
        post_url = reverse('project_add') + '?verify=1'
681 1ac3349d Kostas Papadimitriou
        dfrom = datetime.now()
682 1ac3349d Kostas Papadimitriou
        dto = datetime.now() + timedelta(days=30)
683 1ac3349d Kostas Papadimitriou
        application_data = {
684 1ac3349d Kostas Papadimitriou
            'name': 'project.synnefo.org',
685 1ac3349d Kostas Papadimitriou
            'homepage': 'https://www.synnefo.org',
686 1ac3349d Kostas Papadimitriou
            'start_date': dfrom.strftime("%Y-%m-%d"),
687 1ac3349d Kostas Papadimitriou
            'end_date': dto.strftime("%Y-%m-%d"),
688 1ac3349d Kostas Papadimitriou
            'member_join_policy': 2,
689 1ac3349d Kostas Papadimitriou
            'member_leave_policy': 1,
690 1ac3349d Kostas Papadimitriou
            'service1.resource_uplimit': 100,
691 1ac3349d Kostas Papadimitriou
            'is_selected_service1.resource': "1",
692 1ac3349d Kostas Papadimitriou
            'user': self.user.pk
693 1ac3349d Kostas Papadimitriou
        }
694 1ac3349d Kostas Papadimitriou
        r = self.user_client.post(post_url, data=application_data, follow=True)
695 1ac3349d Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
696 e98239db Giorgos Korfiatis
        self.assertEqual(r.context['form'].is_valid(), False)
697 e98239db Giorgos Korfiatis
698 e98239db Giorgos Korfiatis
        application_data['limit_on_members_number'] = 5
699 e98239db Giorgos Korfiatis
        r = self.user_client.post(post_url, data=application_data, follow=True)
700 e98239db Giorgos Korfiatis
        self.assertEqual(r.status_code, 200)
701 1ac3349d Kostas Papadimitriou
        self.assertEqual(r.context['form'].is_valid(), True)
702 1ac3349d Kostas Papadimitriou
703 1ac3349d Kostas Papadimitriou
        # confirm request
704 1ac3349d Kostas Papadimitriou
        post_url = reverse('project_add') + '?verify=0&edit=0'
705 1ac3349d Kostas Papadimitriou
        r = self.user_client.post(post_url, data=application_data, follow=True)
706 1ac3349d Kostas Papadimitriou
        self.assertContains(r, "The project application has been received")
707 1ac3349d Kostas Papadimitriou
        self.assertRedirects(r, reverse('project_list'))
708 1ac3349d Kostas Papadimitriou
        self.assertEqual(ProjectApplication.objects.count(), 1)
709 50f74340 Giorgos Korfiatis
        app1 = ProjectApplication.objects.filter().order_by('pk')[0]
710 50f74340 Giorgos Korfiatis
        app1_id = app1.pk
711 50f74340 Giorgos Korfiatis
        project1_id = app1.chain_id
712 1ac3349d Kostas Papadimitriou
713 1ac3349d Kostas Papadimitriou
        # create another one
714 1ac3349d Kostas Papadimitriou
        application_data['name'] = 'project2.synnefo.org'
715 1ac3349d Kostas Papadimitriou
        r = self.user_client.post(post_url, data=application_data, follow=True)
716 50f74340 Giorgos Korfiatis
        app2 = ProjectApplication.objects.filter().order_by('pk')[1]
717 50f74340 Giorgos Korfiatis
        project2_id = app2.chain_id
718 1ac3349d Kostas Papadimitriou
719 1ac3349d Kostas Papadimitriou
        # no more applications (LIMIT is 2)
720 1ac3349d Kostas Papadimitriou
        r = self.user_client.get(reverse('project_add'), follow=True)
721 1ac3349d Kostas Papadimitriou
        self.assertRedirects(r, reverse('project_list'))
722 1ac3349d Kostas Papadimitriou
        self.assertContains(r, "You are not allowed to create a new project")
723 1ac3349d Kostas Papadimitriou
724 50f74340 Giorgos Korfiatis
        # one project per application
725 50f74340 Giorgos Korfiatis
        self.assertEqual(Project.objects.count(), 2)
726 50f74340 Giorgos Korfiatis
727 1ac3349d Kostas Papadimitriou
        # login
728 1ac3349d Kostas Papadimitriou
        self.admin_client.get(reverse("edit_profile"))
729 1ac3349d Kostas Papadimitriou
        # admin approves
730 1ac3349d Kostas Papadimitriou
        r = self.admin_client.post(reverse('project_app_approve',
731 1ac3349d Kostas Papadimitriou
                                           kwargs={'application_id': app1_id}),
732 1ac3349d Kostas Papadimitriou
                                   follow=True)
733 1ac3349d Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
734 1ac3349d Kostas Papadimitriou
735 50f74340 Giorgos Korfiatis
        Q_ACTIVE = Project.o_state_q(Project.O_ACTIVE)
736 50f74340 Giorgos Korfiatis
        self.assertEqual(Project.objects.filter(Q_ACTIVE).count(), 1)
737 1ac3349d Kostas Papadimitriou
738 1ac3349d Kostas Papadimitriou
        # login
739 1ac3349d Kostas Papadimitriou
        self.member_client.get(reverse("edit_profile"))
740 50f74340 Giorgos Korfiatis
        # cannot join project2 (not approved yet)
741 50f74340 Giorgos Korfiatis
        join_url = reverse("project_join", kwargs={'chain_id': project2_id})
742 1ac3349d Kostas Papadimitriou
        r = self.member_client.post(join_url, follow=True)
743 1ac3349d Kostas Papadimitriou
744 50f74340 Giorgos Korfiatis
        # can join project1
745 1ac3349d Kostas Papadimitriou
        self.member_client.get(reverse("edit_profile"))
746 50f74340 Giorgos Korfiatis
        join_url = reverse("project_join", kwargs={'chain_id': project1_id})
747 1ac3349d Kostas Papadimitriou
        r = self.member_client.post(join_url, follow=True)
748 1ac3349d Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
749 1ac3349d Kostas Papadimitriou
750 1ac3349d Kostas Papadimitriou
        memberships = ProjectMembership.objects.all()
751 1ac3349d Kostas Papadimitriou
        self.assertEqual(len(memberships), 1)
752 1ac3349d Kostas Papadimitriou
        memb_id = memberships[0].id
753 1ac3349d Kostas Papadimitriou
754 1ac3349d Kostas Papadimitriou
        reject_member_url = reverse('project_reject_member',
755 50f74340 Giorgos Korfiatis
                                    kwargs={'memb_id': memb_id})
756 1ac3349d Kostas Papadimitriou
        accept_member_url = reverse('project_accept_member',
757 50f74340 Giorgos Korfiatis
                                    kwargs={'memb_id': memb_id})
758 1ac3349d Kostas Papadimitriou
759 1ac3349d Kostas Papadimitriou
        # only project owner is allowed to reject
760 1ac3349d Kostas Papadimitriou
        r = self.member_client.post(reject_member_url, follow=True)
761 1ac3349d Kostas Papadimitriou
        self.assertContains(r, "You do not have the permissions")
762 1ac3349d Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
763 1ac3349d Kostas Papadimitriou
764 1ac3349d Kostas Papadimitriou
        # user (owns project) rejects membership
765 1ac3349d Kostas Papadimitriou
        r = self.user_client.post(reject_member_url, follow=True)
766 50f74340 Giorgos Korfiatis
        self.assertEqual(ProjectMembership.objects.any_accepted().count(), 0)
767 1ac3349d Kostas Papadimitriou
768 1ac3349d Kostas Papadimitriou
        # user rejoins
769 1ac3349d Kostas Papadimitriou
        self.member_client.get(reverse("edit_profile"))
770 1ac3349d Kostas Papadimitriou
        join_url = reverse("project_join", kwargs={'chain_id': app1_id})
771 1ac3349d Kostas Papadimitriou
        r = self.member_client.post(join_url, follow=True)
772 1ac3349d Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
773 50f74340 Giorgos Korfiatis
        self.assertEqual(ProjectMembership.objects.requested().count(), 1)
774 1ac3349d Kostas Papadimitriou
775 1ac3349d Kostas Papadimitriou
        # user (owns project) accepts membership
776 1ac3349d Kostas Papadimitriou
        r = self.user_client.post(accept_member_url, follow=True)
777 50f74340 Giorgos Korfiatis
        self.assertEqual(ProjectMembership.objects.any_accepted().count(), 1)
778 1ac3349d Kostas Papadimitriou
        membership = ProjectMembership.objects.get()
779 1ac3349d Kostas Papadimitriou
        self.assertEqual(membership.state, ProjectMembership.ACCEPTED)
780 1ac3349d Kostas Papadimitriou
781 1ac3349d Kostas Papadimitriou
        user_quotas = quotas.get_users_quotas([self.member])
782 1ac3349d Kostas Papadimitriou
        resource = 'service1.resource'
783 1ac3349d Kostas Papadimitriou
        newlimit = user_quotas[self.member.uuid]['system'][resource]['limit']
784 1ac3349d Kostas Papadimitriou
        # 100 from initial uplimit + 100 from project
785 1ac3349d Kostas Papadimitriou
        self.assertEqual(newlimit, 200)
786 1ac3349d Kostas Papadimitriou
787 1ac3349d Kostas Papadimitriou
        remove_member_url = reverse('project_remove_member',
788 50f74340 Giorgos Korfiatis
                                    kwargs={'memb_id': membership.id})
789 1ac3349d Kostas Papadimitriou
        r = self.user_client.post(remove_member_url, follow=True)
790 1ac3349d Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
791 1ac3349d Kostas Papadimitriou
792 1ac3349d Kostas Papadimitriou
        user_quotas = quotas.get_users_quotas([self.member])
793 1ac3349d Kostas Papadimitriou
        resource = 'service1.resource'
794 1ac3349d Kostas Papadimitriou
        newlimit = user_quotas[self.member.uuid]['system'][resource]['limit']
795 1ac3349d Kostas Papadimitriou
        # 200 - 100 from project
796 1ac3349d Kostas Papadimitriou
        self.assertEqual(newlimit, 100)
797 b130ec7c Kostas Papadimitriou
798 b130ec7c Kostas Papadimitriou
        # support email gets rendered in emails content
799 b130ec7c Kostas Papadimitriou
        for mail in get_mailbox('user@synnefo.org'):
800 d4e4e501 Christos Stavrakakis
            self.assertTrue(settings.CONTACT_EMAIL in
801 b130ec7c Kostas Papadimitriou
                            mail.message().as_string())