Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / functions.py @ 733f013d

History | View | Annotate | Download (33.4 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 8998f09a Sofia Papagiannaki
from astakos.im.quotas import qh_sync_user, get_pending_app_quota, \
48 8998f09a Sofia Papagiannaki
    register_pending_apps, qh_sync_project, qh_sync_locked_users, \
49 8998f09a Sofia Papagiannaki
    get_users_for_update, members_to_sync
50 8998f09a Sofia Papagiannaki
from astakos.im.project_notif import membership_change_notify, \
51 8998f09a Sofia Papagiannaki
    membership_enroll_notify, membership_request_notify, \
52 8998f09a Sofia Papagiannaki
    membership_leave_request_notify, application_submit_notify, \
53 8998f09a Sofia Papagiannaki
    application_approve_notify, application_deny_notify, \
54 e872c133 Giorgos Korfiatis
    project_termination_notify, project_suspension_notify, \
55 e872c133 Giorgos Korfiatis
    project_unsuspension_notify, project_reinstatement_notify
56 0a7a4104 Kostas Papadimitriou
from astakos.im import settings
57 8998f09a Sofia Papagiannaki
58 ae497612 Olga Brani
import astakos.im.messages as astakos_messages
59 f36af44a Antony Chazapis
60 f36af44a Antony Chazapis
logger = logging.getLogger(__name__)
61 f36af44a Antony Chazapis
62 5ce3ce4f Sofia Papagiannaki
63 bf0c6de5 Sofia Papagiannaki
def login(request, user):
64 bf0c6de5 Sofia Papagiannaki
    auth_login(request, user)
65 c3c2212a Sofia Papagiannaki
    from astakos.im.models import SessionCatalog
66 c3c2212a Sofia Papagiannaki
    SessionCatalog(
67 c0b26605 Sofia Papagiannaki
        session_key=request.session.session_key,
68 c3c2212a Sofia Papagiannaki
        user=user
69 c3c2212a Sofia Papagiannaki
    ).save()
70 5df4c364 Kostas Papadimitriou
    logger.info('%s logged in.', user.log_display)
71 5df4c364 Kostas Papadimitriou
72 bf0c6de5 Sofia Papagiannaki
73 5df4c364 Kostas Papadimitriou
def logout(request, *args, **kwargs):
74 5df4c364 Kostas Papadimitriou
    user = request.user
75 5df4c364 Kostas Papadimitriou
    auth_logout(request, *args, **kwargs)
76 5df4c364 Kostas Papadimitriou
    logger.info('%s logged out.', user.log_display)
77 111f3da6 Sofia Papagiannaki
78 5ce3ce4f Sofia Papagiannaki
79 683cf244 Sofia Papagiannaki
def send_verification(user, template_name='im/activation_email.txt'):
80 f36af44a Antony Chazapis
    """
81 683cf244 Sofia Papagiannaki
    Send email to user to verify his/her email and activate his/her account.
82 f36af44a Antony Chazapis
    """
83 e3ff6830 Georgios D. Tsoukalas
    url = join_urls(settings.BASE_HOST,
84 e3ff6830 Georgios D. Tsoukalas
                    user.get_activation_url(nxt=reverse('index')))
85 683cf244 Sofia Papagiannaki
    message = render_to_string(template_name, {
86 5ce3ce4f Sofia Papagiannaki
                               'user': user,
87 5ce3ce4f Sofia Papagiannaki
                               'url': url,
88 6c7af65c Georgios D. Tsoukalas
                               'baseurl': settings.BASE_URL,
89 8998f09a Sofia Papagiannaki
                               'site_name': settings.SITENAME,
90 8998f09a Sofia Papagiannaki
                               'support': settings.CONTACT_EMAIL})
91 1cbce16f Sofia Papagiannaki
    sender = settings.SERVER_EMAIL
92 cfb7dd4f Giorgos Korfiatis
    send_mail(_(astakos_messages.VERIFICATION_EMAIL_SUBJECT), message, sender,
93 cfb7dd4f Giorgos Korfiatis
              [user.email],
94 e7cb4085 Kostas Papadimitriou
              connection=get_connection())
95 e7cb4085 Kostas Papadimitriou
    logger.info("Sent user verirfication email: %s", user.log_display)
96 683cf244 Sofia Papagiannaki
97 5ce3ce4f Sofia Papagiannaki
98 9a06d96f Olga Brani
def _send_admin_notification(template_name,
99 e7cb4085 Kostas Papadimitriou
                             context=None,
100 e7cb4085 Kostas Papadimitriou
                             user=None,
101 e7cb4085 Kostas Papadimitriou
                             msg="",
102 9a06d96f Olga Brani
                             subject='alpha2 testing notification',):
103 683cf244 Sofia Papagiannaki
    """
104 e7cb4085 Kostas Papadimitriou
    Send notification email to settings.HELPDESK + settings.MANAGERS +
105 e7cb4085 Kostas Papadimitriou
    settings.ADMINS.
106 683cf244 Sofia Papagiannaki
    """
107 e7cb4085 Kostas Papadimitriou
    if context is None:
108 e7cb4085 Kostas Papadimitriou
        context = {}
109 e7cb4085 Kostas Papadimitriou
    if not 'user' in context:
110 e7cb4085 Kostas Papadimitriou
        context['user'] = user
111 e7cb4085 Kostas Papadimitriou
112 e7cb4085 Kostas Papadimitriou
    message = render_to_string(template_name, context)
113 1cbce16f Sofia Papagiannaki
    sender = settings.SERVER_EMAIL
114 e7cb4085 Kostas Papadimitriou
    recipient_list = [e[1] for e in settings.HELPDESK +
115 e7cb4085 Kostas Papadimitriou
                      settings.MANAGERS + settings.ADMINS]
116 e7cb4085 Kostas Papadimitriou
    send_mail(subject, message, sender, recipient_list,
117 e7cb4085 Kostas Papadimitriou
              connection=get_connection())
118 e7cb4085 Kostas Papadimitriou
    if user:
119 e7cb4085 Kostas Papadimitriou
        msg = 'Sent admin notification (%s) for user %s' % (msg,
120 e7cb4085 Kostas Papadimitriou
                                                            user.log_display)
121 8f5a3a06 Sofia Papagiannaki
    else:
122 e7cb4085 Kostas Papadimitriou
        msg = 'Sent admin notification (%s)' % msg
123 683cf244 Sofia Papagiannaki
124 8998f09a Sofia Papagiannaki
    logger.log(settings.LOGGING_LEVEL, msg)
125 5ce3ce4f Sofia Papagiannaki
126 e7cb4085 Kostas Papadimitriou
127 e7cb4085 Kostas Papadimitriou
def send_account_pending_moderation_notification(
128 e7cb4085 Kostas Papadimitriou
        user,
129 e7cb4085 Kostas Papadimitriou
        template_name='im/account_pending_moderation_notification.txt'):
130 e7cb4085 Kostas Papadimitriou
    """
131 e7cb4085 Kostas Papadimitriou
    Notify admins that a new user has verified his email address and moderation
132 e7cb4085 Kostas Papadimitriou
    step is required to activate his account.
133 e7cb4085 Kostas Papadimitriou
    """
134 cfb7dd4f Giorgos Korfiatis
    subject = (_(astakos_messages.ACCOUNT_CREATION_SUBJECT) %
135 cfb7dd4f Giorgos Korfiatis
               {'user': user.email})
136 e7cb4085 Kostas Papadimitriou
    return _send_admin_notification(template_name, {}, subject=subject,
137 e7cb4085 Kostas Papadimitriou
                                    user=user, msg="account creation")
138 9a06d96f Olga Brani
139 9a06d96f Olga Brani
140 e7cb4085 Kostas Papadimitriou
def send_account_activated_notification(
141 e7cb4085 Kostas Papadimitriou
        user,
142 e7cb4085 Kostas Papadimitriou
        template_name='im/account_activated_notification.txt'):
143 a0be6a0c Sofia Papagiannaki
    """
144 e7cb4085 Kostas Papadimitriou
    Send email to settings.HELPDESK + settings.MANAGERES + settings.ADMINS
145 e7cb4085 Kostas Papadimitriou
    lists to notify that a new account has been accepted and activated.
146 a0be6a0c Sofia Papagiannaki
    """
147 3abf6c78 Sofia Papagiannaki
    message = render_to_string(
148 3abf6c78 Sofia Papagiannaki
        template_name,
149 3abf6c78 Sofia Papagiannaki
        {'user': user}
150 3abf6c78 Sofia Papagiannaki
    )
151 1cbce16f Sofia Papagiannaki
    sender = settings.SERVER_EMAIL
152 e7cb4085 Kostas Papadimitriou
    recipient_list = [e[1] for e in settings.HELPDESK +
153 e7cb4085 Kostas Papadimitriou
                      settings.MANAGERS + settings.ADMINS]
154 cfb7dd4f Giorgos Korfiatis
    send_mail(_(astakos_messages.HELPDESK_NOTIFICATION_EMAIL_SUBJECT) %
155 cfb7dd4f Giorgos Korfiatis
              {'user': user.email},
156 e7cb4085 Kostas Papadimitriou
              message, sender, recipient_list, connection=get_connection())
157 d59f5608 Sofia Papagiannaki
    msg = 'Sent helpdesk admin notification for %s'
158 d59f5608 Sofia Papagiannaki
    logger.log(settings.LOGGING_LEVEL, msg, user.email)
159 a0be6a0c Sofia Papagiannaki
160 5ce3ce4f Sofia Papagiannaki
161 683cf244 Sofia Papagiannaki
def send_invitation(invitation, template_name='im/invitation.txt'):
162 683cf244 Sofia Papagiannaki
    """
163 683cf244 Sofia Papagiannaki
    Send invitation email.
164 683cf244 Sofia Papagiannaki
    """
165 cfb7dd4f Giorgos Korfiatis
    subject = _(astakos_messages.INVITATION_EMAIL_SUBJECT)
166 8c8e318d Kostas Papadimitriou
    url = '%s?code=%d' % (join_urls(settings.BASE_HOST,
167 8c8e318d Kostas Papadimitriou
                                    reverse('index')), invitation.code)
168 aab4d540 Sofia Papagiannaki
    message = render_to_string(template_name, {
169 5ce3ce4f Sofia Papagiannaki
                               'invitation': invitation,
170 5ce3ce4f Sofia Papagiannaki
                               'url': url,
171 6c7af65c Georgios D. Tsoukalas
                               'baseurl': settings.BASE_URL,
172 8998f09a Sofia Papagiannaki
                               'site_name': settings.SITENAME,
173 8998f09a Sofia Papagiannaki
                               'support': settings.CONTACT_EMAIL})
174 1cbce16f Sofia Papagiannaki
    sender = settings.SERVER_EMAIL
175 e7cb4085 Kostas Papadimitriou
    send_mail(subject, message, sender, [invitation.username],
176 e7cb4085 Kostas Papadimitriou
              connection=get_connection())
177 d59f5608 Sofia Papagiannaki
    msg = 'Sent invitation %s'
178 d59f5608 Sofia Papagiannaki
    logger.log(settings.LOGGING_LEVEL, msg, invitation)
179 e7cb4085 Kostas Papadimitriou
    inviter_invitations = invitation.inviter.invitations
180 e7cb4085 Kostas Papadimitriou
    invitation.inviter.invitations = max(0, inviter_invitations - 1)
181 e7cb4085 Kostas Papadimitriou
    invitation.inviter.save()
182 683cf244 Sofia Papagiannaki
183 5ce3ce4f Sofia Papagiannaki
184 683cf244 Sofia Papagiannaki
def send_greeting(user, email_template_name='im/welcome_email.txt'):
185 683cf244 Sofia Papagiannaki
    """
186 e7cb4085 Kostas Papadimitriou
    Send welcome email to an accepted/activated user.
187 5ce3ce4f Sofia Papagiannaki

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