Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / functions.py @ 62d30634

History | View | Annotate | Download (33.3 kB)

1 abd8467c Giorgos Korfiatis
# Copyright 2011, 2012, 2013 GRNET S.A. All rights reserved.
2 5ce3ce4f Sofia Papagiannaki
#
3 f36af44a Antony Chazapis
# Redistribution and use in source and binary forms, with or
4 f36af44a Antony Chazapis
# without modification, are permitted provided that the following
5 f36af44a Antony Chazapis
# conditions are met:
6 5ce3ce4f Sofia Papagiannaki
#
7 f36af44a Antony Chazapis
#   1. Redistributions of source code must retain the above
8 f36af44a Antony Chazapis
#      copyright notice, this list of conditions and the following
9 f36af44a Antony Chazapis
#      disclaimer.
10 5ce3ce4f Sofia Papagiannaki
#
11 f36af44a Antony Chazapis
#   2. Redistributions in binary form must reproduce the above
12 f36af44a Antony Chazapis
#      copyright notice, this list of conditions and the following
13 f36af44a Antony Chazapis
#      disclaimer in the documentation and/or other materials
14 f36af44a Antony Chazapis
#      provided with the distribution.
15 5ce3ce4f Sofia Papagiannaki
#
16 f36af44a Antony Chazapis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 f36af44a Antony Chazapis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 f36af44a Antony Chazapis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 f36af44a Antony Chazapis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 f36af44a Antony Chazapis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 f36af44a Antony Chazapis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 f36af44a Antony Chazapis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 f36af44a Antony Chazapis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 f36af44a Antony Chazapis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 f36af44a Antony Chazapis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 f36af44a Antony Chazapis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 f36af44a Antony Chazapis
# POSSIBILITY OF SUCH DAMAGE.
28 5ce3ce4f Sofia Papagiannaki
#
29 f36af44a Antony Chazapis
# The views and conclusions contained in the software and
30 f36af44a Antony Chazapis
# documentation are those of the authors and should not be
31 f36af44a Antony Chazapis
# interpreted as representing official policies, either expressed
32 f36af44a Antony Chazapis
# or implied, of GRNET S.A.
33 f36af44a Antony Chazapis
34 f36af44a Antony Chazapis
import logging
35 f36af44a Antony Chazapis
36 f36af44a Antony Chazapis
from django.utils.translation import ugettext as _
37 f9224cc0 Sofia Papagiannaki
from django.core.mail import send_mail, get_connection
38 f36af44a Antony Chazapis
from django.core.urlresolvers import reverse
39 8998f09a Sofia Papagiannaki
from django.contrib.auth import login as auth_login, logout as auth_logout
40 3c22bad0 Giorgos Korfiatis
from django.db.models import Q
41 27e26a41 Sofia Papagiannaki
42 734107ef Kostas Papadimitriou
from synnefo_branding.utils import render_to_string
43 734107ef Kostas Papadimitriou
44 d2c9adac Christos Stavrakakis
from synnefo.lib import join_urls
45 8998f09a Sofia Papagiannaki
from astakos.im.models import AstakosUser, Invitation, ProjectMembership, \
46 1b52192e Giorgos Korfiatis
    ProjectApplication, Project, new_chain, Resource, ProjectLock
47 7f3bbafa Giorgos Korfiatis
from astakos.im import quotas
48 7f3bbafa Giorgos Korfiatis
from astakos.im import project_notif
49 0a7a4104 Kostas Papadimitriou
from astakos.im import settings
50 8998f09a Sofia Papagiannaki
51 ae497612 Olga Brani
import astakos.im.messages as astakos_messages
52 f36af44a Antony Chazapis
53 f36af44a Antony Chazapis
logger = logging.getLogger(__name__)
54 f36af44a Antony Chazapis
55 5ce3ce4f Sofia Papagiannaki
56 bf0c6de5 Sofia Papagiannaki
def login(request, user):
57 bf0c6de5 Sofia Papagiannaki
    auth_login(request, user)
58 c3c2212a Sofia Papagiannaki
    from astakos.im.models import SessionCatalog
59 c3c2212a Sofia Papagiannaki
    SessionCatalog(
60 c0b26605 Sofia Papagiannaki
        session_key=request.session.session_key,
61 c3c2212a Sofia Papagiannaki
        user=user
62 c3c2212a Sofia Papagiannaki
    ).save()
63 5df4c364 Kostas Papadimitriou
    logger.info('%s logged in.', user.log_display)
64 5df4c364 Kostas Papadimitriou
65 bf0c6de5 Sofia Papagiannaki
66 5df4c364 Kostas Papadimitriou
def logout(request, *args, **kwargs):
67 5df4c364 Kostas Papadimitriou
    user = request.user
68 5df4c364 Kostas Papadimitriou
    auth_logout(request, *args, **kwargs)
69 5764728a Sofia Papagiannaki
    user.delete_online_access_tokens()
70 5df4c364 Kostas Papadimitriou
    logger.info('%s logged out.', user.log_display)
71 111f3da6 Sofia Papagiannaki
72 5ce3ce4f Sofia Papagiannaki
73 683cf244 Sofia Papagiannaki
def send_verification(user, template_name='im/activation_email.txt'):
74 f36af44a Antony Chazapis
    """
75 683cf244 Sofia Papagiannaki
    Send email to user to verify his/her email and activate his/her account.
76 f36af44a Antony Chazapis
    """
77 e3ff6830 Georgios D. Tsoukalas
    url = join_urls(settings.BASE_HOST,
78 e3ff6830 Georgios D. Tsoukalas
                    user.get_activation_url(nxt=reverse('index')))
79 683cf244 Sofia Papagiannaki
    message = render_to_string(template_name, {
80 5ce3ce4f Sofia Papagiannaki
                               'user': user,
81 5ce3ce4f Sofia Papagiannaki
                               'url': url,
82 6c7af65c Georgios D. Tsoukalas
                               'baseurl': settings.BASE_URL,
83 8998f09a Sofia Papagiannaki
                               'site_name': settings.SITENAME,
84 8998f09a Sofia Papagiannaki
                               'support': settings.CONTACT_EMAIL})
85 1cbce16f Sofia Papagiannaki
    sender = settings.SERVER_EMAIL
86 cfb7dd4f Giorgos Korfiatis
    send_mail(_(astakos_messages.VERIFICATION_EMAIL_SUBJECT), message, sender,
87 cfb7dd4f Giorgos Korfiatis
              [user.email],
88 e7cb4085 Kostas Papadimitriou
              connection=get_connection())
89 e7cb4085 Kostas Papadimitriou
    logger.info("Sent user verirfication email: %s", user.log_display)
90 683cf244 Sofia Papagiannaki
91 5ce3ce4f Sofia Papagiannaki
92 9a06d96f Olga Brani
def _send_admin_notification(template_name,
93 e7cb4085 Kostas Papadimitriou
                             context=None,
94 e7cb4085 Kostas Papadimitriou
                             user=None,
95 e7cb4085 Kostas Papadimitriou
                             msg="",
96 9a06d96f Olga Brani
                             subject='alpha2 testing notification',):
97 683cf244 Sofia Papagiannaki
    """
98 e7cb4085 Kostas Papadimitriou
    Send notification email to settings.HELPDESK + settings.MANAGERS +
99 e7cb4085 Kostas Papadimitriou
    settings.ADMINS.
100 683cf244 Sofia Papagiannaki
    """
101 e7cb4085 Kostas Papadimitriou
    if context is None:
102 e7cb4085 Kostas Papadimitriou
        context = {}
103 e7cb4085 Kostas Papadimitriou
    if not 'user' in context:
104 e7cb4085 Kostas Papadimitriou
        context['user'] = user
105 e7cb4085 Kostas Papadimitriou
106 e7cb4085 Kostas Papadimitriou
    message = render_to_string(template_name, context)
107 1cbce16f Sofia Papagiannaki
    sender = settings.SERVER_EMAIL
108 e7cb4085 Kostas Papadimitriou
    recipient_list = [e[1] for e in settings.HELPDESK +
109 e7cb4085 Kostas Papadimitriou
                      settings.MANAGERS + settings.ADMINS]
110 e7cb4085 Kostas Papadimitriou
    send_mail(subject, message, sender, recipient_list,
111 e7cb4085 Kostas Papadimitriou
              connection=get_connection())
112 e7cb4085 Kostas Papadimitriou
    if user:
113 e7cb4085 Kostas Papadimitriou
        msg = 'Sent admin notification (%s) for user %s' % (msg,
114 e7cb4085 Kostas Papadimitriou
                                                            user.log_display)
115 8f5a3a06 Sofia Papagiannaki
    else:
116 e7cb4085 Kostas Papadimitriou
        msg = 'Sent admin notification (%s)' % msg
117 683cf244 Sofia Papagiannaki
118 8998f09a Sofia Papagiannaki
    logger.log(settings.LOGGING_LEVEL, msg)
119 5ce3ce4f Sofia Papagiannaki
120 e7cb4085 Kostas Papadimitriou
121 e7cb4085 Kostas Papadimitriou
def send_account_pending_moderation_notification(
122 e7cb4085 Kostas Papadimitriou
        user,
123 e7cb4085 Kostas Papadimitriou
        template_name='im/account_pending_moderation_notification.txt'):
124 e7cb4085 Kostas Papadimitriou
    """
125 e7cb4085 Kostas Papadimitriou
    Notify admins that a new user has verified his email address and moderation
126 e7cb4085 Kostas Papadimitriou
    step is required to activate his account.
127 e7cb4085 Kostas Papadimitriou
    """
128 cfb7dd4f Giorgos Korfiatis
    subject = (_(astakos_messages.ACCOUNT_CREATION_SUBJECT) %
129 cfb7dd4f Giorgos Korfiatis
               {'user': user.email})
130 e7cb4085 Kostas Papadimitriou
    return _send_admin_notification(template_name, {}, subject=subject,
131 e7cb4085 Kostas Papadimitriou
                                    user=user, msg="account creation")
132 9a06d96f Olga Brani
133 9a06d96f Olga Brani
134 e7cb4085 Kostas Papadimitriou
def send_account_activated_notification(
135 e7cb4085 Kostas Papadimitriou
        user,
136 e7cb4085 Kostas Papadimitriou
        template_name='im/account_activated_notification.txt'):
137 a0be6a0c Sofia Papagiannaki
    """
138 e7cb4085 Kostas Papadimitriou
    Send email to settings.HELPDESK + settings.MANAGERES + settings.ADMINS
139 e7cb4085 Kostas Papadimitriou
    lists to notify that a new account has been accepted and activated.
140 a0be6a0c Sofia Papagiannaki
    """
141 3abf6c78 Sofia Papagiannaki
    message = render_to_string(
142 3abf6c78 Sofia Papagiannaki
        template_name,
143 3abf6c78 Sofia Papagiannaki
        {'user': user}
144 3abf6c78 Sofia Papagiannaki
    )
145 1cbce16f Sofia Papagiannaki
    sender = settings.SERVER_EMAIL
146 e7cb4085 Kostas Papadimitriou
    recipient_list = [e[1] for e in settings.HELPDESK +
147 e7cb4085 Kostas Papadimitriou
                      settings.MANAGERS + settings.ADMINS]
148 cfb7dd4f Giorgos Korfiatis
    send_mail(_(astakos_messages.HELPDESK_NOTIFICATION_EMAIL_SUBJECT) %
149 cfb7dd4f Giorgos Korfiatis
              {'user': user.email},
150 e7cb4085 Kostas Papadimitriou
              message, sender, recipient_list, connection=get_connection())
151 d59f5608 Sofia Papagiannaki
    msg = 'Sent helpdesk admin notification for %s'
152 d59f5608 Sofia Papagiannaki
    logger.log(settings.LOGGING_LEVEL, msg, user.email)
153 a0be6a0c Sofia Papagiannaki
154 5ce3ce4f Sofia Papagiannaki
155 683cf244 Sofia Papagiannaki
def send_invitation(invitation, template_name='im/invitation.txt'):
156 683cf244 Sofia Papagiannaki
    """
157 683cf244 Sofia Papagiannaki
    Send invitation email.
158 683cf244 Sofia Papagiannaki
    """
159 cfb7dd4f Giorgos Korfiatis
    subject = _(astakos_messages.INVITATION_EMAIL_SUBJECT)
160 8c8e318d Kostas Papadimitriou
    url = '%s?code=%d' % (join_urls(settings.BASE_HOST,
161 8c8e318d Kostas Papadimitriou
                                    reverse('index')), invitation.code)
162 aab4d540 Sofia Papagiannaki
    message = render_to_string(template_name, {
163 5ce3ce4f Sofia Papagiannaki
                               'invitation': invitation,
164 5ce3ce4f Sofia Papagiannaki
                               'url': url,
165 6c7af65c Georgios D. Tsoukalas
                               'baseurl': settings.BASE_URL,
166 8998f09a Sofia Papagiannaki
                               'site_name': settings.SITENAME,
167 8998f09a Sofia Papagiannaki
                               'support': settings.CONTACT_EMAIL})
168 1cbce16f Sofia Papagiannaki
    sender = settings.SERVER_EMAIL
169 e7cb4085 Kostas Papadimitriou
    send_mail(subject, message, sender, [invitation.username],
170 e7cb4085 Kostas Papadimitriou
              connection=get_connection())
171 d59f5608 Sofia Papagiannaki
    msg = 'Sent invitation %s'
172 d59f5608 Sofia Papagiannaki
    logger.log(settings.LOGGING_LEVEL, msg, invitation)
173 e7cb4085 Kostas Papadimitriou
    inviter_invitations = invitation.inviter.invitations
174 e7cb4085 Kostas Papadimitriou
    invitation.inviter.invitations = max(0, inviter_invitations - 1)
175 e7cb4085 Kostas Papadimitriou
    invitation.inviter.save()
176 683cf244 Sofia Papagiannaki
177 5ce3ce4f Sofia Papagiannaki
178 683cf244 Sofia Papagiannaki
def send_greeting(user, email_template_name='im/welcome_email.txt'):
179 683cf244 Sofia Papagiannaki
    """
180 e7cb4085 Kostas Papadimitriou
    Send welcome email to an accepted/activated user.
181 5ce3ce4f Sofia Papagiannaki

182 f36af44a Antony Chazapis
    Raises SMTPException, socket.error
183 f36af44a Antony Chazapis
    """
184 cfb7dd4f Giorgos Korfiatis
    subject = _(astakos_messages.GREETING_EMAIL_SUBJECT)
185 f36af44a Antony Chazapis
    message = render_to_string(email_template_name, {
186 5ce3ce4f Sofia Papagiannaki
                               'user': user,
187 8c8e318d Kostas Papadimitriou
                               'url': join_urls(settings.BASE_HOST,
188 8c8e318d Kostas Papadimitriou
                                                reverse('index')),
189 6c7af65c Georgios D. Tsoukalas
                               'baseurl': settings.BASE_URL,
190 8998f09a Sofia Papagiannaki
                               'site_name': settings.SITENAME,
191 8998f09a Sofia Papagiannaki
                               'support': settings.CONTACT_EMAIL})
192 1cbce16f Sofia Papagiannaki
    sender = settings.SERVER_EMAIL
193 e7cb4085 Kostas Papadimitriou
    send_mail(subject, message, sender, [user.email],
194 e7cb4085 Kostas Papadimitriou
              connection=get_connection())
195 d59f5608 Sofia Papagiannaki
    msg = 'Sent greeting %s'
196 d59f5608 Sofia Papagiannaki
    logger.log(settings.LOGGING_LEVEL, msg, user.log_display)
197 8f5a3a06 Sofia Papagiannaki
198 5ce3ce4f Sofia Papagiannaki
199 8f5a3a06 Sofia Papagiannaki
def send_feedback(msg, data, user, email_template_name='im/feedback_mail.txt'):
200 cfb7dd4f Giorgos Korfiatis
    subject = _(astakos_messages.FEEDBACK_EMAIL_SUBJECT)
201 7d145e78 Sofia Papagiannaki
    from_email = settings.SERVER_EMAIL
202 0a7a4104 Kostas Papadimitriou
    recipient_list = [e[1] for e in settings.HELPDESK]
203 8f5a3a06 Sofia Papagiannaki
    content = render_to_string(email_template_name, {
204 8f5a3a06 Sofia Papagiannaki
        'message': msg,
205 8f5a3a06 Sofia Papagiannaki
        'data': data,
206 8f5a3a06 Sofia Papagiannaki
        'user': user})
207 e182fc26 Sofia Papagiannaki
    send_mail(subject, content, from_email, recipient_list,
208 e182fc26 Sofia Papagiannaki
              connection=get_connection())
209 d59f5608 Sofia Papagiannaki
    msg = 'Sent feedback from %s'
210 d59f5608 Sofia Papagiannaki
    logger.log(settings.LOGGING_LEVEL, msg, user.log_display)
211 f36af44a Antony Chazapis
212 5ce3ce4f Sofia Papagiannaki
213 d59f5608 Sofia Papagiannaki
def send_change_email(ec, request,
214 d59f5608 Sofia Papagiannaki
                      email_template_name=
215 d59f5608 Sofia Papagiannaki
                      'registration/email_change_email.txt'):
216 e182fc26 Sofia Papagiannaki
    url = ec.get_url()
217 e182fc26 Sofia Papagiannaki
    url = request.build_absolute_uri(url)
218 80a548e3 Christos Stavrakakis
    c = {'url': url,
219 80a548e3 Christos Stavrakakis
         'site_name': settings.SITENAME,
220 8fb8d0cf Giorgos Korfiatis
         'support': settings.CONTACT_EMAIL,
221 734107ef Kostas Papadimitriou
         'ec': ec}
222 734107ef Kostas Papadimitriou
    message = render_to_string(email_template_name, c)
223 e182fc26 Sofia Papagiannaki
    from_email = settings.SERVER_EMAIL
224 cfb7dd4f Giorgos Korfiatis
    send_mail(_(astakos_messages.EMAIL_CHANGE_EMAIL_SUBJECT), message,
225 cfb7dd4f Giorgos Korfiatis
              from_email,
226 734107ef Kostas Papadimitriou
              [ec.new_email_address], connection=get_connection())
227 d59f5608 Sofia Papagiannaki
    msg = 'Sent change email for %s'
228 d59f5608 Sofia Papagiannaki
    logger.log(settings.LOGGING_LEVEL, msg, ec.user.log_display)
229 f36af44a Antony Chazapis
230 5ce3ce4f Sofia Papagiannaki
231 73fbaec4 Sofia Papagiannaki
def invite(inviter, email, realname):
232 73fbaec4 Sofia Papagiannaki
    inv = Invitation(inviter=inviter, username=email, realname=realname)
233 73fbaec4 Sofia Papagiannaki
    inv.save()
234 73fbaec4 Sofia Papagiannaki
    send_invitation(inv)
235 e30537f1 Sofia Papagiannaki
    inviter.invitations = max(0, inviter.invitations - 1)
236 73fbaec4 Sofia Papagiannaki
    inviter.save()
237 5ce3ce4f Sofia Papagiannaki
238 73fbaec4 Sofia Papagiannaki
239 7a08e179 Giorgos Korfiatis
### PROJECT FUNCTIONS ###
240 fcc1e93f Sofia Papagiannaki
241 f12bcb3d Giorgos Korfiatis
242 f12bcb3d Giorgos Korfiatis
class ProjectError(Exception):
243 f12bcb3d Giorgos Korfiatis
    pass
244 f12bcb3d Giorgos Korfiatis
245 f12bcb3d Giorgos Korfiatis
246 f12bcb3d Giorgos Korfiatis
class ProjectNotFound(ProjectError):
247 f12bcb3d Giorgos Korfiatis
    pass
248 f12bcb3d Giorgos Korfiatis
249 f12bcb3d Giorgos Korfiatis
250 f12bcb3d Giorgos Korfiatis
class ProjectForbidden(ProjectError):
251 f12bcb3d Giorgos Korfiatis
    pass
252 f12bcb3d Giorgos Korfiatis
253 f12bcb3d Giorgos Korfiatis
254 f12bcb3d Giorgos Korfiatis
class ProjectBadRequest(ProjectError):
255 f12bcb3d Giorgos Korfiatis
    pass
256 f12bcb3d Giorgos Korfiatis
257 f12bcb3d Giorgos Korfiatis
258 f12bcb3d Giorgos Korfiatis
class ProjectConflict(ProjectError):
259 f12bcb3d Giorgos Korfiatis
    pass
260 f12bcb3d Giorgos Korfiatis
261 b0686c16 Giorgos Korfiatis
AUTO_ACCEPT_POLICY = 1
262 7a08e179 Giorgos Korfiatis
MODERATED_POLICY = 2
263 7a08e179 Giorgos Korfiatis
CLOSED_POLICY = 3
264 7a08e179 Giorgos Korfiatis
265 7a08e179 Giorgos Korfiatis
POLICIES = [AUTO_ACCEPT_POLICY, MODERATED_POLICY, CLOSED_POLICY]
266 b0686c16 Giorgos Korfiatis
267 73fbaec4 Sofia Papagiannaki
268 a75dbd7b Giorgos Korfiatis
def get_related_project_id(application_id):
269 a75dbd7b Giorgos Korfiatis
    try:
270 a75dbd7b Giorgos Korfiatis
        app = ProjectApplication.objects.get(id=application_id)
271 6d583e07 Giorgos Korfiatis
        return app.chain_id
272 7a08e179 Giorgos Korfiatis
    except ProjectApplication.DoesNotExist:
273 0932ac43 Giorgos Korfiatis
        return None
274 0932ac43 Giorgos Korfiatis
275 7a08e179 Giorgos Korfiatis
276 eb9ff37a Sofia Papagiannaki
def get_project_by_id(project_id):
277 eb9ff37a Sofia Papagiannaki
    try:
278 2556cf45 Giorgos Korfiatis
        return Project.objects.select_related(
279 2556cf45 Giorgos Korfiatis
            "application", "application__owner",
280 2556cf45 Giorgos Korfiatis
            "application__applicant").get(id=project_id)
281 eb9ff37a Sofia Papagiannaki
    except Project.DoesNotExist:
282 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.UNKNOWN_PROJECT_ID) % project_id
283 f12bcb3d Giorgos Korfiatis
        raise ProjectNotFound(m)
284 7a08e179 Giorgos Korfiatis
285 eb9ff37a Sofia Papagiannaki
286 6335ad6f Giorgos Korfiatis
def get_project_for_update(project_id):
287 8dcaa6ac Giorgos Korfiatis
    try:
288 c7e03d20 Giorgos Korfiatis
        return Project.objects.select_for_update().get(id=project_id)
289 6335ad6f Giorgos Korfiatis
    except Project.DoesNotExist:
290 6335ad6f Giorgos Korfiatis
        m = _(astakos_messages.UNKNOWN_PROJECT_ID) % project_id
291 f12bcb3d Giorgos Korfiatis
        raise ProjectNotFound(m)
292 7a08e179 Giorgos Korfiatis
293 8dcaa6ac Giorgos Korfiatis
294 6335ad6f Giorgos Korfiatis
def get_project_of_application_for_update(app_id):
295 3c22bad0 Giorgos Korfiatis
    app = get_application(app_id)
296 6335ad6f Giorgos Korfiatis
    return get_project_for_update(app.chain_id)
297 3c22bad0 Giorgos Korfiatis
298 3c22bad0 Giorgos Korfiatis
299 1b52192e Giorgos Korfiatis
def get_project_lock():
300 c7e03d20 Giorgos Korfiatis
    ProjectLock.objects.select_for_update().get(pk=1)
301 1b52192e Giorgos Korfiatis
302 1b52192e Giorgos Korfiatis
303 3c22bad0 Giorgos Korfiatis
def get_application(application_id):
304 19eb3ee6 Giorgos Korfiatis
    try:
305 3c22bad0 Giorgos Korfiatis
        return ProjectApplication.objects.get(id=application_id)
306 19eb3ee6 Giorgos Korfiatis
    except ProjectApplication.DoesNotExist:
307 19eb3ee6 Giorgos Korfiatis
        m = _(astakos_messages.UNKNOWN_PROJECT_APPLICATION_ID) % application_id
308 f12bcb3d Giorgos Korfiatis
        raise ProjectNotFound(m)
309 19eb3ee6 Giorgos Korfiatis
310 7a08e179 Giorgos Korfiatis
311 6335ad6f Giorgos Korfiatis
def get_project_of_membership_for_update(memb_id):
312 dc946891 Giorgos Korfiatis
    m = get_membership_by_id(memb_id)
313 6335ad6f Giorgos Korfiatis
    return get_project_for_update(m.project_id)
314 dc946891 Giorgos Korfiatis
315 dc946891 Giorgos Korfiatis
316 3c049f6d Giorgos Korfiatis
def get_user_by_uuid(uuid):
317 3c049f6d Giorgos Korfiatis
    try:
318 3c049f6d Giorgos Korfiatis
        return AstakosUser.objects.get(uuid=uuid)
319 3c049f6d Giorgos Korfiatis
    except AstakosUser.DoesNotExist:
320 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.UNKNOWN_USER_ID) % uuid
321 f12bcb3d Giorgos Korfiatis
        raise ProjectNotFound(m)
322 3c049f6d Giorgos Korfiatis
323 97e93991 Kostas Papadimitriou
324 3c22bad0 Giorgos Korfiatis
def get_membership(project_id, user_id):
325 73fbaec4 Sofia Papagiannaki
    try:
326 3c22bad0 Giorgos Korfiatis
        objs = ProjectMembership.objects.select_related('project', 'person')
327 3c22bad0 Giorgos Korfiatis
        return objs.get(project__id=project_id, person__id=user_id)
328 73fbaec4 Sofia Papagiannaki
    except ProjectMembership.DoesNotExist:
329 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
330 f12bcb3d Giorgos Korfiatis
        raise ProjectNotFound(m)
331 7a08e179 Giorgos Korfiatis
332 73fbaec4 Sofia Papagiannaki
333 866e5768 Giorgos Korfiatis
def get_membership_by_id(memb_id):
334 7f3c4920 Giorgos Korfiatis
    try:
335 3c22bad0 Giorgos Korfiatis
        objs = ProjectMembership.objects.select_related('project', 'person')
336 866e5768 Giorgos Korfiatis
        return objs.get(id=memb_id)
337 7f3c4920 Giorgos Korfiatis
    except ProjectMembership.DoesNotExist:
338 7f3c4920 Giorgos Korfiatis
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
339 f12bcb3d Giorgos Korfiatis
        raise ProjectNotFound(m)
340 7f3c4920 Giorgos Korfiatis
341 7f3c4920 Giorgos Korfiatis
342 c5b0bbb7 Giorgos Korfiatis
ALLOWED_CHECKS = [
343 c5b0bbb7 Giorgos Korfiatis
    (lambda u, a: not u or u.is_project_admin()),
344 c5b0bbb7 Giorgos Korfiatis
    (lambda u, a: a.owner == u),
345 c5b0bbb7 Giorgos Korfiatis
    (lambda u, a: a.applicant == u),
346 62d30634 Giorgos Korfiatis
    (lambda u, a: a.chain.overall_state() == Project.O_ACTIVE and not a.private
347 c5b0bbb7 Giorgos Korfiatis
     or bool(a.chain.projectmembership_set.any_accepted().filter(person=u))),
348 c5b0bbb7 Giorgos Korfiatis
]
349 c5b0bbb7 Giorgos Korfiatis
350 c5b0bbb7 Giorgos Korfiatis
ADMIN_LEVEL = 0
351 c5b0bbb7 Giorgos Korfiatis
OWNER_LEVEL = 1
352 c5b0bbb7 Giorgos Korfiatis
APPLICANT_LEVEL = 2
353 c5b0bbb7 Giorgos Korfiatis
ANY_LEVEL = 3
354 c5b0bbb7 Giorgos Korfiatis
355 c5b0bbb7 Giorgos Korfiatis
356 c5b0bbb7 Giorgos Korfiatis
def _check_yield(b, silent=False):
357 c5b0bbb7 Giorgos Korfiatis
    if b:
358 c5b0bbb7 Giorgos Korfiatis
        return True
359 d07ce657 Giorgos Korfiatis
360 c5b0bbb7 Giorgos Korfiatis
    if silent:
361 c5b0bbb7 Giorgos Korfiatis
        return False
362 d07ce657 Giorgos Korfiatis
363 d07ce657 Giorgos Korfiatis
    m = _(astakos_messages.NOT_ALLOWED)
364 f12bcb3d Giorgos Korfiatis
    raise ProjectForbidden(m)
365 d07ce657 Giorgos Korfiatis
366 907f15db Giorgos Korfiatis
367 c5b0bbb7 Giorgos Korfiatis
def membership_check_allowed(membership, request_user,
368 c5b0bbb7 Giorgos Korfiatis
                             level=OWNER_LEVEL, silent=False):
369 c5b0bbb7 Giorgos Korfiatis
    r = project_check_allowed(
370 c5b0bbb7 Giorgos Korfiatis
        membership.project, request_user, level, silent=True)
371 c5b0bbb7 Giorgos Korfiatis
372 c5b0bbb7 Giorgos Korfiatis
    return _check_yield(r or membership.person == request_user, silent)
373 c5b0bbb7 Giorgos Korfiatis
374 c5b0bbb7 Giorgos Korfiatis
375 c5b0bbb7 Giorgos Korfiatis
def project_check_allowed(project, request_user,
376 c5b0bbb7 Giorgos Korfiatis
                          level=OWNER_LEVEL, silent=False):
377 c5b0bbb7 Giorgos Korfiatis
    return app_check_allowed(project.application, request_user, level, silent)
378 c5b0bbb7 Giorgos Korfiatis
379 c5b0bbb7 Giorgos Korfiatis
380 c5b0bbb7 Giorgos Korfiatis
def app_check_allowed(application, request_user,
381 c5b0bbb7 Giorgos Korfiatis
                      level=OWNER_LEVEL, silent=False):
382 c5b0bbb7 Giorgos Korfiatis
    checks = (f(request_user, application) for f in ALLOWED_CHECKS[:level+1])
383 c5b0bbb7 Giorgos Korfiatis
    return _check_yield(any(checks), silent)
384 c5b0bbb7 Giorgos Korfiatis
385 c5b0bbb7 Giorgos Korfiatis
386 907f15db Giorgos Korfiatis
def checkAlive(project):
387 907f15db Giorgos Korfiatis
    if not project.is_alive:
388 3805be31 Giorgos Korfiatis
        m = _(astakos_messages.NOT_ALIVE_PROJECT) % project.id
389 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
390 7a08e179 Giorgos Korfiatis
391 907f15db Giorgos Korfiatis
392 866e5768 Giorgos Korfiatis
def accept_membership_project_checks(project, request_user):
393 c5b0bbb7 Giorgos Korfiatis
    project_check_allowed(project, request_user)
394 907f15db Giorgos Korfiatis
    checkAlive(project)
395 b0686c16 Giorgos Korfiatis
396 b0686c16 Giorgos Korfiatis
    join_policy = project.application.member_join_policy
397 b0686c16 Giorgos Korfiatis
    if join_policy == CLOSED_POLICY:
398 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.MEMBER_JOIN_POLICY_CLOSED)
399 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
400 b0686c16 Giorgos Korfiatis
401 8dcaa6ac Giorgos Korfiatis
    if project.violates_members_limit(adding=1):
402 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.MEMBER_NUMBER_LIMIT_REACHED)
403 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
404 73fbaec4 Sofia Papagiannaki
405 d07ce657 Giorgos Korfiatis
406 866e5768 Giorgos Korfiatis
def accept_membership_checks(membership, request_user):
407 71c741dc Giorgos Korfiatis
    if not membership.check_action("accept"):
408 14f7f6a5 Giorgos Korfiatis
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
409 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
410 d4fc6292 Giorgos Korfiatis
411 866e5768 Giorgos Korfiatis
    project = membership.project
412 866e5768 Giorgos Korfiatis
    accept_membership_project_checks(project, request_user)
413 866e5768 Giorgos Korfiatis
414 866e5768 Giorgos Korfiatis
415 da4ac460 Giorgos Korfiatis
def accept_membership(memb_id, request_user=None, reason=None):
416 866e5768 Giorgos Korfiatis
    project = get_project_of_membership_for_update(memb_id)
417 866e5768 Giorgos Korfiatis
    membership = get_membership_by_id(memb_id)
418 866e5768 Giorgos Korfiatis
    accept_membership_checks(membership, request_user)
419 7f3c4920 Giorgos Korfiatis
    user = membership.person
420 da4ac460 Giorgos Korfiatis
    membership.perform_action("accept", actor=request_user, reason=reason)
421 7f3bbafa Giorgos Korfiatis
    quotas.qh_sync_user(user)
422 f30f0170 Giorgos Korfiatis
    logger.info("User %s has been accepted in %s." %
423 7f3c4920 Giorgos Korfiatis
                (user.log_display, project))
424 73fbaec4 Sofia Papagiannaki
425 7f3bbafa Giorgos Korfiatis
    project_notif.membership_change_notify(project, user, 'accepted')
426 73fbaec4 Sofia Papagiannaki
    return membership
427 73fbaec4 Sofia Papagiannaki
428 7a08e179 Giorgos Korfiatis
429 866e5768 Giorgos Korfiatis
def reject_membership_checks(membership, request_user):
430 71c741dc Giorgos Korfiatis
    if not membership.check_action("reject"):
431 866e5768 Giorgos Korfiatis
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
432 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
433 866e5768 Giorgos Korfiatis
434 866e5768 Giorgos Korfiatis
    project = membership.project
435 c5b0bbb7 Giorgos Korfiatis
    project_check_allowed(project, request_user)
436 907f15db Giorgos Korfiatis
    checkAlive(project)
437 e47fb17a Sofia Papagiannaki
438 d07ce657 Giorgos Korfiatis
439 da4ac460 Giorgos Korfiatis
def reject_membership(memb_id, request_user=None, reason=None):
440 6335ad6f Giorgos Korfiatis
    project = get_project_of_membership_for_update(memb_id)
441 dc946891 Giorgos Korfiatis
    membership = get_membership_by_id(memb_id)
442 866e5768 Giorgos Korfiatis
    reject_membership_checks(membership, request_user)
443 7f3c4920 Giorgos Korfiatis
    user = membership.person
444 da4ac460 Giorgos Korfiatis
    membership.perform_action("reject", actor=request_user, reason=reason)
445 f30f0170 Giorgos Korfiatis
    logger.info("Request of user %s for %s has been rejected." %
446 7f3c4920 Giorgos Korfiatis
                (user.log_display, project))
447 73fbaec4 Sofia Papagiannaki
448 7f3bbafa Giorgos Korfiatis
    project_notif.membership_change_notify(project, user, 'rejected')
449 73fbaec4 Sofia Papagiannaki
    return membership
450 73fbaec4 Sofia Papagiannaki
451 7a08e179 Giorgos Korfiatis
452 866e5768 Giorgos Korfiatis
def cancel_membership_checks(membership, request_user):
453 71c741dc Giorgos Korfiatis
    if not membership.check_action("cancel"):
454 aad0e329 Giorgos Korfiatis
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
455 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
456 aad0e329 Giorgos Korfiatis
457 c5b0bbb7 Giorgos Korfiatis
    membership_check_allowed(membership, request_user, level=ADMIN_LEVEL)
458 3c22bad0 Giorgos Korfiatis
    project = membership.project
459 866e5768 Giorgos Korfiatis
    checkAlive(project)
460 866e5768 Giorgos Korfiatis
461 866e5768 Giorgos Korfiatis
462 da4ac460 Giorgos Korfiatis
def cancel_membership(memb_id, request_user, reason=None):
463 866e5768 Giorgos Korfiatis
    project = get_project_of_membership_for_update(memb_id)
464 866e5768 Giorgos Korfiatis
    membership = get_membership_by_id(memb_id)
465 866e5768 Giorgos Korfiatis
    cancel_membership_checks(membership, request_user)
466 da4ac460 Giorgos Korfiatis
    membership.perform_action("cancel", actor=request_user, reason=reason)
467 f30f0170 Giorgos Korfiatis
    logger.info("Request of user %s for %s has been cancelled." %
468 f30f0170 Giorgos Korfiatis
                (membership.person.log_display, project))
469 aad0e329 Giorgos Korfiatis
470 7a08e179 Giorgos Korfiatis
471 866e5768 Giorgos Korfiatis
def remove_membership_checks(membership, request_user=None):
472 71c741dc Giorgos Korfiatis
    if not membership.check_action("remove"):
473 866e5768 Giorgos Korfiatis
        m = _(astakos_messages.NOT_ACCEPTED_MEMBERSHIP)
474 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
475 866e5768 Giorgos Korfiatis
476 866e5768 Giorgos Korfiatis
    project = membership.project
477 c5b0bbb7 Giorgos Korfiatis
    project_check_allowed(project, request_user)
478 907f15db Giorgos Korfiatis
    checkAlive(project)
479 73fbaec4 Sofia Papagiannaki
480 b0686c16 Giorgos Korfiatis
    leave_policy = project.application.member_leave_policy
481 b0686c16 Giorgos Korfiatis
    if leave_policy == CLOSED_POLICY:
482 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.MEMBER_LEAVE_POLICY_CLOSED)
483 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
484 7a08e179 Giorgos Korfiatis
485 b0686c16 Giorgos Korfiatis
486 da4ac460 Giorgos Korfiatis
def remove_membership(memb_id, request_user=None, reason=None):
487 6335ad6f Giorgos Korfiatis
    project = get_project_of_membership_for_update(memb_id)
488 dc946891 Giorgos Korfiatis
    membership = get_membership_by_id(memb_id)
489 866e5768 Giorgos Korfiatis
    remove_membership_checks(membership, request_user)
490 7f3c4920 Giorgos Korfiatis
    user = membership.person
491 da4ac460 Giorgos Korfiatis
    membership.perform_action("remove", actor=request_user, reason=reason)
492 7f3bbafa Giorgos Korfiatis
    quotas.qh_sync_user(user)
493 f30f0170 Giorgos Korfiatis
    logger.info("User %s has been removed from %s." %
494 7f3c4920 Giorgos Korfiatis
                (user.log_display, project))
495 73fbaec4 Sofia Papagiannaki
496 7f3bbafa Giorgos Korfiatis
    project_notif.membership_change_notify(project, user, 'removed')
497 73fbaec4 Sofia Papagiannaki
    return membership
498 73fbaec4 Sofia Papagiannaki
499 7a08e179 Giorgos Korfiatis
500 2556cf45 Giorgos Korfiatis
def enroll_member_by_email(project_id, email, request_user=None, reason=None):
501 2556cf45 Giorgos Korfiatis
    try:
502 733f013d Giorgos Korfiatis
        user = AstakosUser.objects.accepted().get(email=email)
503 2556cf45 Giorgos Korfiatis
        return enroll_member(project_id, user, request_user, reason=reason)
504 2556cf45 Giorgos Korfiatis
    except AstakosUser.DoesNotExist:
505 733f013d Giorgos Korfiatis
        raise ProjectConflict(astakos_messages.UNKNOWN_USERS % email)
506 2556cf45 Giorgos Korfiatis
507 2556cf45 Giorgos Korfiatis
508 da4ac460 Giorgos Korfiatis
def enroll_member(project_id, user, request_user=None, reason=None):
509 f12bcb3d Giorgos Korfiatis
    try:
510 f12bcb3d Giorgos Korfiatis
        project = get_project_for_update(project_id)
511 f12bcb3d Giorgos Korfiatis
    except ProjectNotFound as e:
512 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(e.message)
513 866e5768 Giorgos Korfiatis
    accept_membership_project_checks(project, request_user)
514 e05c541e Giorgos Korfiatis
515 1a14083b Giorgos Korfiatis
    try:
516 1a14083b Giorgos Korfiatis
        membership = get_membership(project_id, user.id)
517 71c741dc Giorgos Korfiatis
        if not membership.check_action("enroll"):
518 1a14083b Giorgos Korfiatis
            m = _(astakos_messages.MEMBERSHIP_ACCEPTED)
519 f12bcb3d Giorgos Korfiatis
            raise ProjectConflict(m)
520 a5aa11ee Giorgos Korfiatis
        membership.perform_action("enroll", actor=request_user, reason=reason)
521 f12bcb3d Giorgos Korfiatis
    except ProjectNotFound:
522 a5aa11ee Giorgos Korfiatis
        membership = new_membership(project, user, actor=request_user,
523 a5aa11ee Giorgos Korfiatis
                                    enroll=True)
524 d4fc6292 Giorgos Korfiatis
525 7f3bbafa Giorgos Korfiatis
    quotas.qh_sync_user(user)
526 f30f0170 Giorgos Korfiatis
    logger.info("User %s has been enrolled in %s." %
527 f30f0170 Giorgos Korfiatis
                (membership.person.log_display, project))
528 570015d2 Giorgos Korfiatis
529 7f3bbafa Giorgos Korfiatis
    project_notif.membership_enroll_notify(project, membership.person)
530 907f15db Giorgos Korfiatis
    return membership
531 8dcaa6ac Giorgos Korfiatis
532 7a08e179 Giorgos Korfiatis
533 866e5768 Giorgos Korfiatis
def leave_project_checks(membership, request_user):
534 71c741dc Giorgos Korfiatis
    if not membership.check_action("leave"):
535 866e5768 Giorgos Korfiatis
        m = _(astakos_messages.NOT_ACCEPTED_MEMBERSHIP)
536 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
537 866e5768 Giorgos Korfiatis
538 c5b0bbb7 Giorgos Korfiatis
    membership_check_allowed(membership, request_user, level=ADMIN_LEVEL)
539 866e5768 Giorgos Korfiatis
    project = membership.project
540 907f15db Giorgos Korfiatis
    checkAlive(project)
541 8dcaa6ac Giorgos Korfiatis
542 03869281 Sofia Papagiannaki
    leave_policy = project.application.member_leave_policy
543 b0686c16 Giorgos Korfiatis
    if leave_policy == CLOSED_POLICY:
544 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.MEMBER_LEAVE_POLICY_CLOSED)
545 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
546 7a08e179 Giorgos Korfiatis
547 73fbaec4 Sofia Papagiannaki
548 d4660e00 Giorgos Korfiatis
def can_leave_request(project, user):
549 d4660e00 Giorgos Korfiatis
    m = user.get_membership(project)
550 d4660e00 Giorgos Korfiatis
    if m is None:
551 d4660e00 Giorgos Korfiatis
        return False
552 866e5768 Giorgos Korfiatis
    try:
553 866e5768 Giorgos Korfiatis
        leave_project_checks(m, user)
554 f12bcb3d Giorgos Korfiatis
    except ProjectError:
555 866e5768 Giorgos Korfiatis
        return False
556 866e5768 Giorgos Korfiatis
    return True
557 d4660e00 Giorgos Korfiatis
558 d07ce657 Giorgos Korfiatis
559 da4ac460 Giorgos Korfiatis
def leave_project(memb_id, request_user, reason=None):
560 6335ad6f Giorgos Korfiatis
    project = get_project_of_membership_for_update(memb_id)
561 dc946891 Giorgos Korfiatis
    membership = get_membership_by_id(memb_id)
562 866e5768 Giorgos Korfiatis
    leave_project_checks(membership, request_user)
563 3c22bad0 Giorgos Korfiatis
564 bb6a4465 Giorgos Korfiatis
    auto_accepted = False
565 4e057833 Sofia Papagiannaki
    leave_policy = project.application.member_leave_policy
566 b0686c16 Giorgos Korfiatis
    if leave_policy == AUTO_ACCEPT_POLICY:
567 da4ac460 Giorgos Korfiatis
        membership.perform_action("remove", actor=request_user, reason=reason)
568 7f3bbafa Giorgos Korfiatis
        quotas.qh_sync_user(request_user)
569 f30f0170 Giorgos Korfiatis
        logger.info("User %s has left %s." %
570 3c22bad0 Giorgos Korfiatis
                    (request_user.log_display, project))
571 bb6a4465 Giorgos Korfiatis
        auto_accepted = True
572 73fbaec4 Sofia Papagiannaki
    else:
573 da4ac460 Giorgos Korfiatis
        membership.perform_action("leave_request", actor=request_user,
574 da4ac460 Giorgos Korfiatis
                                  reason=reason)
575 f30f0170 Giorgos Korfiatis
        logger.info("User %s requested to leave %s." %
576 3c22bad0 Giorgos Korfiatis
                    (request_user.log_display, project))
577 84498bca Giorgos Korfiatis
        project_notif.membership_request_notify(
578 84498bca Giorgos Korfiatis
            project, membership.person, "leave")
579 bb6a4465 Giorgos Korfiatis
    return auto_accepted
580 73fbaec4 Sofia Papagiannaki
581 7a08e179 Giorgos Korfiatis
582 ff67242a Giorgos Korfiatis
def join_project_checks(project):
583 907f15db Giorgos Korfiatis
    checkAlive(project)
584 8dcaa6ac Giorgos Korfiatis
585 974ee6a6 Sofia Papagiannaki
    join_policy = project.application.member_join_policy
586 b0686c16 Giorgos Korfiatis
    if join_policy == CLOSED_POLICY:
587 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.MEMBER_JOIN_POLICY_CLOSED)
588 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
589 7a08e179 Giorgos Korfiatis
590 73fbaec4 Sofia Papagiannaki
591 b10ceccd Giorgos Korfiatis
Nothing = type('Nothing', (), {})
592 b10ceccd Giorgos Korfiatis
593 b10ceccd Giorgos Korfiatis
594 b10ceccd Giorgos Korfiatis
def can_join_request(project, user, membership=Nothing):
595 34244dfa Giorgos Korfiatis
    try:
596 34244dfa Giorgos Korfiatis
        join_project_checks(project)
597 f12bcb3d Giorgos Korfiatis
    except ProjectError:
598 d4660e00 Giorgos Korfiatis
        return False
599 34244dfa Giorgos Korfiatis
600 b10ceccd Giorgos Korfiatis
    m = (membership if membership is not Nothing
601 b10ceccd Giorgos Korfiatis
         else user.get_membership(project))
602 1a14083b Giorgos Korfiatis
    if not m:
603 1a14083b Giorgos Korfiatis
        return True
604 71c741dc Giorgos Korfiatis
    return m.check_action("join")
605 1a14083b Giorgos Korfiatis
606 1a14083b Giorgos Korfiatis
607 a5aa11ee Giorgos Korfiatis
def new_membership(project, user, actor=None, reason=None, enroll=False):
608 a5aa11ee Giorgos Korfiatis
    state = (ProjectMembership.ACCEPTED if enroll
609 a5aa11ee Giorgos Korfiatis
             else ProjectMembership.REQUESTED)
610 a5aa11ee Giorgos Korfiatis
    m = ProjectMembership.objects.create(
611 a5aa11ee Giorgos Korfiatis
        project=project, person=user, state=state)
612 a5aa11ee Giorgos Korfiatis
    m._log_create(None, state, actor=actor, reason=reason)
613 1a14083b Giorgos Korfiatis
    return m
614 d4660e00 Giorgos Korfiatis
615 d07ce657 Giorgos Korfiatis
616 da4ac460 Giorgos Korfiatis
def join_project(project_id, request_user, reason=None):
617 6335ad6f Giorgos Korfiatis
    project = get_project_for_update(project_id)
618 ff67242a Giorgos Korfiatis
    join_project_checks(project)
619 d07ce657 Giorgos Korfiatis
620 1a14083b Giorgos Korfiatis
    try:
621 1a14083b Giorgos Korfiatis
        membership = get_membership(project.id, request_user.id)
622 71c741dc Giorgos Korfiatis
        if not membership.check_action("join"):
623 866e5768 Giorgos Korfiatis
            msg = _(astakos_messages.MEMBERSHIP_ASSOCIATED)
624 f12bcb3d Giorgos Korfiatis
            raise ProjectConflict(msg)
625 da4ac460 Giorgos Korfiatis
        membership.perform_action("join", actor=request_user, reason=reason)
626 f12bcb3d Giorgos Korfiatis
    except ProjectNotFound:
627 da4ac460 Giorgos Korfiatis
        membership = new_membership(project, request_user, actor=request_user,
628 da4ac460 Giorgos Korfiatis
                                    reason=reason)
629 73fbaec4 Sofia Papagiannaki
630 4e057833 Sofia Papagiannaki
    join_policy = project.application.member_join_policy
631 7a08e179 Giorgos Korfiatis
    if (join_policy == AUTO_ACCEPT_POLICY and (
632 7a08e179 Giorgos Korfiatis
            not project.violates_members_limit(adding=1))):
633 da4ac460 Giorgos Korfiatis
        membership.perform_action("accept", actor=request_user, reason=reason)
634 7f3bbafa Giorgos Korfiatis
        quotas.qh_sync_user(request_user)
635 f30f0170 Giorgos Korfiatis
        logger.info("User %s joined %s." %
636 3c22bad0 Giorgos Korfiatis
                    (request_user.log_display, project))
637 bb6a4465 Giorgos Korfiatis
    else:
638 84498bca Giorgos Korfiatis
        project_notif.membership_request_notify(
639 84498bca Giorgos Korfiatis
            project, membership.person, "join")
640 f30f0170 Giorgos Korfiatis
        logger.info("User %s requested to join %s." %
641 3c22bad0 Giorgos Korfiatis
                    (request_user.log_display, project))
642 e1723ca1 Giorgos Korfiatis
    return membership
643 8dcaa6ac Giorgos Korfiatis
644 7a08e179 Giorgos Korfiatis
645 866e5768 Giorgos Korfiatis
MEMBERSHIP_ACTION_CHECKS = {
646 866e5768 Giorgos Korfiatis
    "leave":  leave_project_checks,
647 866e5768 Giorgos Korfiatis
    "cancel": cancel_membership_checks,
648 866e5768 Giorgos Korfiatis
    "accept": accept_membership_checks,
649 866e5768 Giorgos Korfiatis
    "reject": reject_membership_checks,
650 866e5768 Giorgos Korfiatis
    "remove": remove_membership_checks,
651 866e5768 Giorgos Korfiatis
}
652 866e5768 Giorgos Korfiatis
653 866e5768 Giorgos Korfiatis
654 866e5768 Giorgos Korfiatis
def membership_allowed_actions(membership, request_user):
655 866e5768 Giorgos Korfiatis
    allowed = []
656 866e5768 Giorgos Korfiatis
    for action, check in MEMBERSHIP_ACTION_CHECKS.iteritems():
657 866e5768 Giorgos Korfiatis
        try:
658 866e5768 Giorgos Korfiatis
            check(membership, request_user)
659 866e5768 Giorgos Korfiatis
            allowed.append(action)
660 f12bcb3d Giorgos Korfiatis
        except ProjectError:
661 866e5768 Giorgos Korfiatis
            pass
662 866e5768 Giorgos Korfiatis
    return allowed
663 866e5768 Giorgos Korfiatis
664 866e5768 Giorgos Korfiatis
665 6da04174 Giorgos Korfiatis
def submit_application(owner=None,
666 6da04174 Giorgos Korfiatis
                       name=None,
667 c4028837 Giorgos Korfiatis
                       project_id=None,
668 6da04174 Giorgos Korfiatis
                       homepage=None,
669 6da04174 Giorgos Korfiatis
                       description=None,
670 6da04174 Giorgos Korfiatis
                       start_date=None,
671 6da04174 Giorgos Korfiatis
                       end_date=None,
672 6da04174 Giorgos Korfiatis
                       member_join_policy=None,
673 6da04174 Giorgos Korfiatis
                       member_leave_policy=None,
674 6da04174 Giorgos Korfiatis
                       limit_on_members_number=None,
675 62d30634 Giorgos Korfiatis
                       private=False,
676 6da04174 Giorgos Korfiatis
                       comments=None,
677 b2369828 Giorgos Korfiatis
                       resources=None,
678 6da04174 Giorgos Korfiatis
                       request_user=None):
679 69c822cc Giorgos Korfiatis
680 c4028837 Giorgos Korfiatis
    project = None
681 c4028837 Giorgos Korfiatis
    if project_id is not None:
682 6335ad6f Giorgos Korfiatis
        project = get_project_for_update(project_id)
683 c5b0bbb7 Giorgos Korfiatis
        project_check_allowed(project, request_user, level=APPLICANT_LEVEL)
684 ee4aa6eb Giorgos Korfiatis
685 b2369828 Giorgos Korfiatis
    policies = validate_resource_policies(resources)
686 b2369828 Giorgos Korfiatis
687 9770ba6c Giorgos Korfiatis
    force = request_user.is_project_admin()
688 c4028837 Giorgos Korfiatis
    ok, limit = qh_add_pending_app(owner, project, force)
689 9770ba6c Giorgos Korfiatis
    if not ok:
690 c7c0ec58 Giorgos Korfiatis
        m = _(astakos_messages.REACHED_PENDING_APPLICATION_LIMIT) % limit
691 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
692 c7c0ec58 Giorgos Korfiatis
693 6da04174 Giorgos Korfiatis
    application = ProjectApplication(
694 6da04174 Giorgos Korfiatis
        applicant=request_user,
695 6da04174 Giorgos Korfiatis
        owner=owner,
696 6da04174 Giorgos Korfiatis
        name=name,
697 6da04174 Giorgos Korfiatis
        homepage=homepage,
698 6da04174 Giorgos Korfiatis
        description=description,
699 6da04174 Giorgos Korfiatis
        start_date=start_date,
700 6da04174 Giorgos Korfiatis
        end_date=end_date,
701 6da04174 Giorgos Korfiatis
        member_join_policy=member_join_policy,
702 6da04174 Giorgos Korfiatis
        member_leave_policy=member_leave_policy,
703 6da04174 Giorgos Korfiatis
        limit_on_members_number=limit_on_members_number,
704 62d30634 Giorgos Korfiatis
        private=private,
705 6da04174 Giorgos Korfiatis
        comments=comments)
706 1352dabb Kostas Papadimitriou
707 c4028837 Giorgos Korfiatis
    if project is None:
708 6d583e07 Giorgos Korfiatis
        chain = new_chain()
709 6d583e07 Giorgos Korfiatis
        application.chain_id = chain.chain
710 6d583e07 Giorgos Korfiatis
        application.save()
711 6d583e07 Giorgos Korfiatis
        Project.objects.create(id=chain.chain, application=application)
712 3e3743f2 Giorgos Korfiatis
    else:
713 c4028837 Giorgos Korfiatis
        application.chain = project
714 6d583e07 Giorgos Korfiatis
        application.save()
715 c4028837 Giorgos Korfiatis
        if project.application.state != ProjectApplication.APPROVED:
716 c4028837 Giorgos Korfiatis
            project.application = application
717 c4028837 Giorgos Korfiatis
            project.save()
718 6d583e07 Giorgos Korfiatis
719 6d583e07 Giorgos Korfiatis
        pending = ProjectApplication.objects.filter(
720 c4028837 Giorgos Korfiatis
            chain=project,
721 6d583e07 Giorgos Korfiatis
            state=ProjectApplication.PENDING).exclude(id=application.id)
722 3e3743f2 Giorgos Korfiatis
        for app in pending:
723 3e3743f2 Giorgos Korfiatis
            app.state = ProjectApplication.REPLACED
724 3e3743f2 Giorgos Korfiatis
            app.save()
725 3e3743f2 Giorgos Korfiatis
726 b2369828 Giorgos Korfiatis
    if policies is not None:
727 b2369828 Giorgos Korfiatis
        set_resource_policies(application, policies)
728 f30f0170 Giorgos Korfiatis
    logger.info("User %s submitted %s." %
729 f30f0170 Giorgos Korfiatis
                (request_user.log_display, application.log_display))
730 84498bca Giorgos Korfiatis
    project_notif.application_notify(application, "submit")
731 a3eb3a95 Giorgos Korfiatis
    return application
732 73fbaec4 Sofia Papagiannaki
733 7a08e179 Giorgos Korfiatis
734 b2369828 Giorgos Korfiatis
def validate_resource_policies(policies):
735 b2369828 Giorgos Korfiatis
    if not isinstance(policies, dict):
736 b2369828 Giorgos Korfiatis
        raise ProjectBadRequest("Malformed resource policies")
737 b2369828 Giorgos Korfiatis
738 b2369828 Giorgos Korfiatis
    resource_names = policies.keys()
739 85ae5a4c Giorgos Korfiatis
    resources = Resource.objects.filter(name__in=resource_names,
740 85ae5a4c Giorgos Korfiatis
                                        api_visible=True)
741 b2369828 Giorgos Korfiatis
    resource_d = {}
742 b2369828 Giorgos Korfiatis
    for resource in resources:
743 b2369828 Giorgos Korfiatis
        resource_d[resource.name] = resource
744 b2369828 Giorgos Korfiatis
745 b2369828 Giorgos Korfiatis
    found = resource_d.keys()
746 b2369828 Giorgos Korfiatis
    nonex = [name for name in resource_names if name not in found]
747 b2369828 Giorgos Korfiatis
    if nonex:
748 f12bcb3d Giorgos Korfiatis
        raise ProjectBadRequest("Malformed resource policies")
749 b2369828 Giorgos Korfiatis
750 b2369828 Giorgos Korfiatis
    pols = []
751 b2369828 Giorgos Korfiatis
    for resource_name, specs in policies.iteritems():
752 b2369828 Giorgos Korfiatis
        p_capacity = specs.get("project_capacity")
753 b2369828 Giorgos Korfiatis
        m_capacity = specs.get("member_capacity")
754 b2369828 Giorgos Korfiatis
755 b2369828 Giorgos Korfiatis
        if p_capacity is not None and not isinstance(p_capacity, (int, long)):
756 f12bcb3d Giorgos Korfiatis
            raise ProjectBadRequest("Malformed resource policies")
757 b2369828 Giorgos Korfiatis
        if not isinstance(m_capacity, (int, long)):
758 f12bcb3d Giorgos Korfiatis
            raise ProjectBadRequest("Malformed resource policies")
759 b2369828 Giorgos Korfiatis
        pols.append((resource_d[resource_name], m_capacity, p_capacity))
760 b2369828 Giorgos Korfiatis
    return pols
761 b2369828 Giorgos Korfiatis
762 b2369828 Giorgos Korfiatis
763 b2369828 Giorgos Korfiatis
def set_resource_policies(application, policies):
764 b2369828 Giorgos Korfiatis
    for resource, m_capacity, p_capacity in policies:
765 b2369828 Giorgos Korfiatis
        g = application.projectresourcegrant_set
766 b2369828 Giorgos Korfiatis
        g.create(resource=resource,
767 b2369828 Giorgos Korfiatis
                 member_capacity=m_capacity,
768 b2369828 Giorgos Korfiatis
                 project_capacity=p_capacity)
769 b2369828 Giorgos Korfiatis
770 b2369828 Giorgos Korfiatis
771 64d0c13e Giorgos Korfiatis
def cancel_application(application_id, request_user=None, reason=""):
772 6335ad6f Giorgos Korfiatis
    get_project_of_application_for_update(application_id)
773 3c22bad0 Giorgos Korfiatis
    application = get_application(application_id)
774 c5b0bbb7 Giorgos Korfiatis
    app_check_allowed(application, request_user, level=APPLICANT_LEVEL)
775 3c638f72 Giorgos Korfiatis
776 01bdbd17 Giorgos Korfiatis
    if not application.can_cancel():
777 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.APPLICATION_CANNOT_CANCEL %
778 7a08e179 Giorgos Korfiatis
              (application.id, application.state_display()))
779 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
780 3c638f72 Giorgos Korfiatis
781 9770ba6c Giorgos Korfiatis
    qh_release_pending_app(application.owner)
782 9770ba6c Giorgos Korfiatis
783 88beea39 Giorgos Korfiatis
    application.cancel(actor=request_user, reason=reason)
784 f30f0170 Giorgos Korfiatis
    logger.info("%s has been cancelled." % (application.log_display))
785 3c638f72 Giorgos Korfiatis
786 7a08e179 Giorgos Korfiatis
787 64d0c13e Giorgos Korfiatis
def dismiss_application(application_id, request_user=None, reason=""):
788 6335ad6f Giorgos Korfiatis
    get_project_of_application_for_update(application_id)
789 3c22bad0 Giorgos Korfiatis
    application = get_application(application_id)
790 c5b0bbb7 Giorgos Korfiatis
    app_check_allowed(application, request_user, level=APPLICANT_LEVEL)
791 3c638f72 Giorgos Korfiatis
792 01bdbd17 Giorgos Korfiatis
    if not application.can_dismiss():
793 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.APPLICATION_CANNOT_DISMISS %
794 7a08e179 Giorgos Korfiatis
              (application.id, application.state_display()))
795 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
796 3c638f72 Giorgos Korfiatis
797 88beea39 Giorgos Korfiatis
    application.dismiss(actor=request_user, reason=reason)
798 f30f0170 Giorgos Korfiatis
    logger.info("%s has been dismissed." % (application.log_display))
799 3c638f72 Giorgos Korfiatis
800 7a08e179 Giorgos Korfiatis
801 64d0c13e Giorgos Korfiatis
def deny_application(application_id, request_user=None, reason=""):
802 6335ad6f Giorgos Korfiatis
    get_project_of_application_for_update(application_id)
803 3c22bad0 Giorgos Korfiatis
    application = get_application(application_id)
804 01bdbd17 Giorgos Korfiatis
805 c5b0bbb7 Giorgos Korfiatis
    app_check_allowed(application, request_user, level=ADMIN_LEVEL)
806 d07ce657 Giorgos Korfiatis
807 01bdbd17 Giorgos Korfiatis
    if not application.can_deny():
808 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.APPLICATION_CANNOT_DENY %
809 7a08e179 Giorgos Korfiatis
              (application.id, application.state_display()))
810 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
811 19eb3ee6 Giorgos Korfiatis
812 9770ba6c Giorgos Korfiatis
    qh_release_pending_app(application.owner)
813 9770ba6c Giorgos Korfiatis
814 88beea39 Giorgos Korfiatis
    application.deny(actor=request_user, reason=reason)
815 f30f0170 Giorgos Korfiatis
    logger.info("%s has been denied with reason \"%s\"." %
816 f30f0170 Giorgos Korfiatis
                (application.log_display, reason))
817 84498bca Giorgos Korfiatis
    project_notif.application_notify(application, "deny")
818 19eb3ee6 Giorgos Korfiatis
819 7a08e179 Giorgos Korfiatis
820 3c22bad0 Giorgos Korfiatis
def check_conflicting_projects(application):
821 6d583e07 Giorgos Korfiatis
    project = application.chain
822 3c22bad0 Giorgos Korfiatis
    new_project_name = application.name
823 8dcaa6ac Giorgos Korfiatis
    try:
824 3c22bad0 Giorgos Korfiatis
        q = Q(name=new_project_name) & ~Q(state=Project.TERMINATED)
825 3c22bad0 Giorgos Korfiatis
        conflicting_project = Project.objects.get(q)
826 3c22bad0 Giorgos Korfiatis
        if (conflicting_project != project):
827 3c22bad0 Giorgos Korfiatis
            m = (_("cannot approve: project with name '%s' "
828 8fb8d0cf Giorgos Korfiatis
                   "already exists (id: %s)") %
829 8fb8d0cf Giorgos Korfiatis
                 (new_project_name, conflicting_project.id))
830 f12bcb3d Giorgos Korfiatis
            raise ProjectConflict(m)  # invalid argument
831 3c22bad0 Giorgos Korfiatis
    except Project.DoesNotExist:
832 3c22bad0 Giorgos Korfiatis
        pass
833 3c22bad0 Giorgos Korfiatis
834 3c22bad0 Giorgos Korfiatis
835 3c22bad0 Giorgos Korfiatis
def approve_application(app_id, request_user=None, reason=""):
836 1b52192e Giorgos Korfiatis
    get_project_lock()
837 6335ad6f Giorgos Korfiatis
    project = get_project_of_application_for_update(app_id)
838 3c22bad0 Giorgos Korfiatis
    application = get_application(app_id)
839 8dcaa6ac Giorgos Korfiatis
840 c5b0bbb7 Giorgos Korfiatis
    app_check_allowed(application, request_user, level=ADMIN_LEVEL)
841 d07ce657 Giorgos Korfiatis
842 01bdbd17 Giorgos Korfiatis
    if not application.can_approve():
843 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.APPLICATION_CANNOT_APPROVE %
844 7a08e179 Giorgos Korfiatis
              (application.id, application.state_display()))
845 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
846 01bdbd17 Giorgos Korfiatis
847 6d583e07 Giorgos Korfiatis
    check_conflicting_projects(application)
848 3c22bad0 Giorgos Korfiatis
849 3c22bad0 Giorgos Korfiatis
    # Pre-lock members and owner together in order to impose an ordering
850 3c22bad0 Giorgos Korfiatis
    # on locking users
851 7f3bbafa Giorgos Korfiatis
    members = quotas.members_to_sync(project)
852 3c22bad0 Giorgos Korfiatis
    uids_to_sync = [member.id for member in members]
853 3c22bad0 Giorgos Korfiatis
    owner = application.owner
854 3c22bad0 Giorgos Korfiatis
    uids_to_sync.append(owner.id)
855 7f3bbafa Giorgos Korfiatis
    quotas.get_users_for_update(uids_to_sync)
856 3c22bad0 Giorgos Korfiatis
857 3c22bad0 Giorgos Korfiatis
    qh_release_pending_app(owner, locked=True)
858 88beea39 Giorgos Korfiatis
    application.approve(actor=request_user, reason=reason)
859 6d583e07 Giorgos Korfiatis
    project.application = application
860 6d583e07 Giorgos Korfiatis
    project.name = application.name
861 6d583e07 Giorgos Korfiatis
    project.save()
862 6d583e07 Giorgos Korfiatis
    if project.is_deactivated():
863 1b52192e Giorgos Korfiatis
        project.resume(actor=request_user, reason="APPROVE")
864 7f3bbafa Giorgos Korfiatis
    quotas.qh_sync_locked_users(members)
865 f30f0170 Giorgos Korfiatis
    logger.info("%s has been approved." % (application.log_display))
866 84498bca Giorgos Korfiatis
    project_notif.application_notify(application, "approve")
867 eb9ff37a Sofia Papagiannaki
868 7a08e179 Giorgos Korfiatis
869 7eadc230 Giorgos Korfiatis
def check_expiration(execute=False):
870 7eadc230 Giorgos Korfiatis
    objects = Project.objects
871 7eadc230 Giorgos Korfiatis
    expired = objects.expired_projects()
872 7eadc230 Giorgos Korfiatis
    if execute:
873 7eadc230 Giorgos Korfiatis
        for project in expired:
874 9f715f94 Giorgos Korfiatis
            terminate(project.pk)
875 7eadc230 Giorgos Korfiatis
876 7eadc230 Giorgos Korfiatis
    return [project.expiration_info() for project in expired]
877 7eadc230 Giorgos Korfiatis
878 7a08e179 Giorgos Korfiatis
879 88beea39 Giorgos Korfiatis
def terminate(project_id, request_user=None, reason=None):
880 6335ad6f Giorgos Korfiatis
    project = get_project_for_update(project_id)
881 c5b0bbb7 Giorgos Korfiatis
    project_check_allowed(project, request_user, level=ADMIN_LEVEL)
882 907f15db Giorgos Korfiatis
    checkAlive(project)
883 5b9e9530 Giorgos Korfiatis
884 88beea39 Giorgos Korfiatis
    project.terminate(actor=request_user, reason=reason)
885 7f3bbafa Giorgos Korfiatis
    quotas.qh_sync_project(project)
886 f30f0170 Giorgos Korfiatis
    logger.info("%s has been terminated." % (project))
887 570015d2 Giorgos Korfiatis
888 84498bca Giorgos Korfiatis
    project_notif.project_notify(project, "terminate")
889 eb9ff37a Sofia Papagiannaki
890 7a08e179 Giorgos Korfiatis
891 88beea39 Giorgos Korfiatis
def suspend(project_id, request_user=None, reason=None):
892 6335ad6f Giorgos Korfiatis
    project = get_project_for_update(project_id)
893 c5b0bbb7 Giorgos Korfiatis
    project_check_allowed(project, request_user, level=ADMIN_LEVEL)
894 db99f198 Giorgos Korfiatis
    checkAlive(project)
895 db99f198 Giorgos Korfiatis
896 88beea39 Giorgos Korfiatis
    project.suspend(actor=request_user, reason=reason)
897 7f3bbafa Giorgos Korfiatis
    quotas.qh_sync_project(project)
898 f30f0170 Giorgos Korfiatis
    logger.info("%s has been suspended." % (project))
899 570015d2 Giorgos Korfiatis
900 84498bca Giorgos Korfiatis
    project_notif.project_notify(project, "suspend")
901 db99f198 Giorgos Korfiatis
902 7a08e179 Giorgos Korfiatis
903 e872c133 Giorgos Korfiatis
def unsuspend(project_id, request_user=None, reason=None):
904 6335ad6f Giorgos Korfiatis
    project = get_project_for_update(project_id)
905 c5b0bbb7 Giorgos Korfiatis
    project_check_allowed(project, request_user, level=ADMIN_LEVEL)
906 db99f198 Giorgos Korfiatis
907 db99f198 Giorgos Korfiatis
    if not project.is_suspended:
908 3805be31 Giorgos Korfiatis
        m = _(astakos_messages.NOT_SUSPENDED_PROJECT) % project.id
909 f12bcb3d Giorgos Korfiatis
        raise ProjectConflict(m)
910 db99f198 Giorgos Korfiatis
911 88beea39 Giorgos Korfiatis
    project.resume(actor=request_user, reason=reason)
912 7f3bbafa Giorgos Korfiatis
    quotas.qh_sync_project(project)
913 f30f0170 Giorgos Korfiatis
    logger.info("%s has been unsuspended." % (project))
914 84498bca Giorgos Korfiatis
    project_notif.project_notify(project, "unsuspend")
915 e872c133 Giorgos Korfiatis
916 e872c133 Giorgos Korfiatis
917 e872c133 Giorgos Korfiatis
def reinstate(project_id, request_user=None, reason=None):
918 e872c133 Giorgos Korfiatis
    get_project_lock()
919 e872c133 Giorgos Korfiatis
    project = get_project_for_update(project_id)
920 e872c133 Giorgos Korfiatis
    project_check_allowed(project, request_user, level=ADMIN_LEVEL)
921 e872c133 Giorgos Korfiatis
922 e872c133 Giorgos Korfiatis
    if not project.is_terminated:
923 e872c133 Giorgos Korfiatis
        m = _(astakos_messages.NOT_TERMINATED_PROJECT) % project.id
924 e872c133 Giorgos Korfiatis
        raise ProjectConflict(m)
925 e872c133 Giorgos Korfiatis
926 e872c133 Giorgos Korfiatis
    check_conflicting_projects(project.application)
927 e872c133 Giorgos Korfiatis
    project.resume(actor=request_user, reason=reason)
928 7f3bbafa Giorgos Korfiatis
    quotas.qh_sync_project(project)
929 e872c133 Giorgos Korfiatis
    logger.info("%s has been reinstated" % (project))
930 84498bca Giorgos Korfiatis
    project_notif.project_notify(project, "reinstate")
931 ff67242a Giorgos Korfiatis
932 7a08e179 Giorgos Korfiatis
933 3f5851eb Giorgos Korfiatis
def _partition_by(f, l):
934 3f5851eb Giorgos Korfiatis
    d = {}
935 3f5851eb Giorgos Korfiatis
    for x in l:
936 3f5851eb Giorgos Korfiatis
        group = f(x)
937 3f5851eb Giorgos Korfiatis
        group_l = d.get(group, [])
938 3f5851eb Giorgos Korfiatis
        group_l.append(x)
939 3f5851eb Giorgos Korfiatis
        d[group] = group_l
940 3f5851eb Giorgos Korfiatis
    return d
941 3f5851eb Giorgos Korfiatis
942 3f5851eb Giorgos Korfiatis
943 3f5851eb Giorgos Korfiatis
def count_pending_app(users):
944 103086a4 Giorgos Korfiatis
    users = list(users)
945 3f5851eb Giorgos Korfiatis
    apps = ProjectApplication.objects.filter(state=ProjectApplication.PENDING,
946 3f5851eb Giorgos Korfiatis
                                             owner__in=users)
947 3f5851eb Giorgos Korfiatis
    apps_d = _partition_by(lambda a: a.owner.uuid, apps)
948 3f5851eb Giorgos Korfiatis
949 3f5851eb Giorgos Korfiatis
    usage = {}
950 3f5851eb Giorgos Korfiatis
    for user in users:
951 3f5851eb Giorgos Korfiatis
        uuid = user.uuid
952 3f5851eb Giorgos Korfiatis
        usage[uuid] = len(apps_d.get(uuid, []))
953 3f5851eb Giorgos Korfiatis
    return usage
954 3f5851eb Giorgos Korfiatis
955 3f5851eb Giorgos Korfiatis
956 74c9dfca Giorgos Korfiatis
def get_pending_app_diff(project):
957 c4028837 Giorgos Korfiatis
    if project is None:
958 9770ba6c Giorgos Korfiatis
        diff = 1
959 9770ba6c Giorgos Korfiatis
    else:
960 9770ba6c Giorgos Korfiatis
        objs = ProjectApplication.objects
961 c4028837 Giorgos Korfiatis
        q = objs.filter(chain=project, state=ProjectApplication.PENDING)
962 9770ba6c Giorgos Korfiatis
        count = q.count()
963 9770ba6c Giorgos Korfiatis
        diff = 1 - count
964 3c22bad0 Giorgos Korfiatis
    return diff
965 3c22bad0 Giorgos Korfiatis
966 3c22bad0 Giorgos Korfiatis
967 c4028837 Giorgos Korfiatis
def qh_add_pending_app(user, project=None, force=False):
968 c7e03d20 Giorgos Korfiatis
    user = AstakosUser.objects.select_for_update().get(id=user.id)
969 74c9dfca Giorgos Korfiatis
    diff = get_pending_app_diff(project)
970 7f3bbafa Giorgos Korfiatis
    return quotas.register_pending_apps(user, diff, force)
971 3c22bad0 Giorgos Korfiatis
972 c7c0ec58 Giorgos Korfiatis
973 c4028837 Giorgos Korfiatis
def check_pending_app_quota(user, project=None):
974 74c9dfca Giorgos Korfiatis
    diff = get_pending_app_diff(project)
975 7f3bbafa Giorgos Korfiatis
    quota = quotas.get_pending_app_quota(user)
976 3c22bad0 Giorgos Korfiatis
    limit = quota['limit']
977 3c22bad0 Giorgos Korfiatis
    usage = quota['usage']
978 3c22bad0 Giorgos Korfiatis
    if usage + diff > limit:
979 3c22bad0 Giorgos Korfiatis
        return False, limit
980 3c22bad0 Giorgos Korfiatis
    return True, None
981 c7c0ec58 Giorgos Korfiatis
982 c7c0ec58 Giorgos Korfiatis
983 3c22bad0 Giorgos Korfiatis
def qh_release_pending_app(user, locked=False):
984 3c22bad0 Giorgos Korfiatis
    if not locked:
985 c7e03d20 Giorgos Korfiatis
        user = AstakosUser.objects.select_for_update().get(id=user.id)
986 7f3bbafa Giorgos Korfiatis
    quotas.register_pending_apps(user, -1)