Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / functions.py @ 67cf14bf

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

195 f36af44a Antony Chazapis
    Raises SMTPException, socket.error
196 f36af44a Antony Chazapis
    """
197 4f78c22c Sofia Papagiannaki
    subject = _(GREETING_EMAIL_SUBJECT)
198 f36af44a Antony Chazapis
    message = render_to_string(email_template_name, {
199 5ce3ce4f Sofia Papagiannaki
                               'user': user,
200 d2c9adac Christos Stavrakakis
                               'url': join_urls(BASEURL, reverse('index')),
201 5ce3ce4f Sofia Papagiannaki
                               'baseurl': BASEURL,
202 5ce3ce4f Sofia Papagiannaki
                               'site_name': SITENAME,
203 31bc3a62 Kostas Papadimitriou
                               'support': CONTACT_EMAIL})
204 1cbce16f Sofia Papagiannaki
    sender = settings.SERVER_EMAIL
205 e7cb4085 Kostas Papadimitriou
    send_mail(subject, message, sender, [user.email],
206 e7cb4085 Kostas Papadimitriou
              connection=get_connection())
207 e7cb4085 Kostas Papadimitriou
    msg = 'Sent greeting %s' % user.log_display
208 e7cb4085 Kostas Papadimitriou
    logger.log(LOGGING_LEVEL, msg)
209 8f5a3a06 Sofia Papagiannaki
210 5ce3ce4f Sofia Papagiannaki
211 8f5a3a06 Sofia Papagiannaki
def send_feedback(msg, data, user, email_template_name='im/feedback_mail.txt'):
212 4f78c22c Sofia Papagiannaki
    subject = _(FEEDBACK_EMAIL_SUBJECT)
213 7d145e78 Sofia Papagiannaki
    from_email = settings.SERVER_EMAIL
214 0a7a4104 Kostas Papadimitriou
    recipient_list = [e[1] for e in settings.HELPDESK]
215 8f5a3a06 Sofia Papagiannaki
    content = render_to_string(email_template_name, {
216 8f5a3a06 Sofia Papagiannaki
        'message': msg,
217 8f5a3a06 Sofia Papagiannaki
        'data': data,
218 8f5a3a06 Sofia Papagiannaki
        'user': user})
219 e182fc26 Sofia Papagiannaki
    send_mail(subject, content, from_email, recipient_list,
220 e182fc26 Sofia Papagiannaki
              connection=get_connection())
221 e182fc26 Sofia Papagiannaki
    msg = 'Sent feedback from %s' % user.log_display
222 e182fc26 Sofia Papagiannaki
    logger.log(LOGGING_LEVEL, msg)
223 f36af44a Antony Chazapis
224 5ce3ce4f Sofia Papagiannaki
225 73fbaec4 Sofia Papagiannaki
def send_change_email(
226 73fbaec4 Sofia Papagiannaki
    ec, request, email_template_name='registration/email_change_email.txt'):
227 e182fc26 Sofia Papagiannaki
    url = ec.get_url()
228 e182fc26 Sofia Papagiannaki
    url = request.build_absolute_uri(url)
229 734107ef Kostas Papadimitriou
    c = {'url': url, 'site_name': SITENAME, 'support': CONTACT_EMAIL,
230 734107ef Kostas Papadimitriou
         'ec': ec}
231 734107ef Kostas Papadimitriou
    message = render_to_string(email_template_name, c)
232 e182fc26 Sofia Papagiannaki
    from_email = settings.SERVER_EMAIL
233 734107ef Kostas Papadimitriou
    send_mail(_(EMAIL_CHANGE_EMAIL_SUBJECT), message, from_email,
234 734107ef Kostas Papadimitriou
              [ec.new_email_address], connection=get_connection())
235 e182fc26 Sofia Papagiannaki
    msg = 'Sent change email for %s' % ec.user.log_display
236 e182fc26 Sofia Papagiannaki
    logger.log(LOGGING_LEVEL, msg)
237 f36af44a Antony Chazapis
238 5ce3ce4f Sofia Papagiannaki
239 73fbaec4 Sofia Papagiannaki
def invite(inviter, email, realname):
240 73fbaec4 Sofia Papagiannaki
    inv = Invitation(inviter=inviter, username=email, realname=realname)
241 73fbaec4 Sofia Papagiannaki
    inv.save()
242 73fbaec4 Sofia Papagiannaki
    send_invitation(inv)
243 e30537f1 Sofia Papagiannaki
    inviter.invitations = max(0, inviter.invitations - 1)
244 73fbaec4 Sofia Papagiannaki
    inviter.save()
245 5ce3ce4f Sofia Papagiannaki
246 73fbaec4 Sofia Papagiannaki
247 7a08e179 Giorgos Korfiatis
### PROJECT FUNCTIONS ###
248 fcc1e93f Sofia Papagiannaki
249 b0686c16 Giorgos Korfiatis
AUTO_ACCEPT_POLICY = 1
250 7a08e179 Giorgos Korfiatis
MODERATED_POLICY = 2
251 7a08e179 Giorgos Korfiatis
CLOSED_POLICY = 3
252 7a08e179 Giorgos Korfiatis
253 7a08e179 Giorgos Korfiatis
POLICIES = [AUTO_ACCEPT_POLICY, MODERATED_POLICY, CLOSED_POLICY]
254 b0686c16 Giorgos Korfiatis
255 73fbaec4 Sofia Papagiannaki
256 73fbaec4 Sofia Papagiannaki
def get_project_by_application_id(project_application_id):
257 73fbaec4 Sofia Papagiannaki
    try:
258 73fbaec4 Sofia Papagiannaki
        return Project.objects.get(application__id=project_application_id)
259 73fbaec4 Sofia Papagiannaki
    except Project.DoesNotExist:
260 7a08e179 Giorgos Korfiatis
        m = (_(astakos_messages.UNKNOWN_PROJECT_APPLICATION_ID) %
261 7a08e179 Giorgos Korfiatis
             project_application_id)
262 7a08e179 Giorgos Korfiatis
        raise IOError(m)
263 7a08e179 Giorgos Korfiatis
264 73fbaec4 Sofia Papagiannaki
265 a75dbd7b Giorgos Korfiatis
def get_related_project_id(application_id):
266 a75dbd7b Giorgos Korfiatis
    try:
267 a75dbd7b Giorgos Korfiatis
        app = ProjectApplication.objects.get(id=application_id)
268 a75dbd7b Giorgos Korfiatis
        chain = app.chain
269 7a08e179 Giorgos Korfiatis
        Project.objects.get(id=chain)
270 a75dbd7b Giorgos Korfiatis
        return chain
271 3966d268 Giorgos Korfiatis
    except (ProjectApplication.DoesNotExist, Project.DoesNotExist):
272 a75dbd7b Giorgos Korfiatis
        return None
273 a75dbd7b Giorgos Korfiatis
274 7a08e179 Giorgos Korfiatis
275 0932ac43 Giorgos Korfiatis
def get_chain_of_application_id(application_id):
276 0932ac43 Giorgos Korfiatis
    try:
277 0932ac43 Giorgos Korfiatis
        app = ProjectApplication.objects.get(id=application_id)
278 0932ac43 Giorgos Korfiatis
        chain = app.chain
279 0932ac43 Giorgos Korfiatis
        return chain.chain
280 7a08e179 Giorgos Korfiatis
    except ProjectApplication.DoesNotExist:
281 0932ac43 Giorgos Korfiatis
        return None
282 0932ac43 Giorgos Korfiatis
283 7a08e179 Giorgos Korfiatis
284 eb9ff37a Sofia Papagiannaki
def get_project_by_id(project_id):
285 eb9ff37a Sofia Papagiannaki
    try:
286 eb9ff37a Sofia Papagiannaki
        return Project.objects.get(id=project_id)
287 eb9ff37a Sofia Papagiannaki
    except Project.DoesNotExist:
288 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.UNKNOWN_PROJECT_ID) % project_id
289 7a08e179 Giorgos Korfiatis
        raise IOError(m)
290 7a08e179 Giorgos Korfiatis
291 eb9ff37a Sofia Papagiannaki
292 c10f1cf5 Giorgos Korfiatis
def get_project_by_name(name):
293 c10f1cf5 Giorgos Korfiatis
    try:
294 c10f1cf5 Giorgos Korfiatis
        return Project.objects.get(name=name)
295 c10f1cf5 Giorgos Korfiatis
    except Project.DoesNotExist:
296 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.UNKNOWN_PROJECT_ID) % name
297 7a08e179 Giorgos Korfiatis
        raise IOError(m)
298 c10f1cf5 Giorgos Korfiatis
299 c10f1cf5 Giorgos Korfiatis
300 3c22bad0 Giorgos Korfiatis
def get_chain_for_update(chain_id):
301 8dcaa6ac Giorgos Korfiatis
    try:
302 3c22bad0 Giorgos Korfiatis
        return Chain.objects.get_for_update(chain=chain_id)
303 3c22bad0 Giorgos Korfiatis
    except Chain.DoesNotExist:
304 3c22bad0 Giorgos Korfiatis
        m = _(astakos_messages.UNKNOWN_PROJECT_ID) % chain_id
305 7a08e179 Giorgos Korfiatis
        raise IOError(m)
306 7a08e179 Giorgos Korfiatis
307 8dcaa6ac Giorgos Korfiatis
308 3c22bad0 Giorgos Korfiatis
def get_chain_of_application_for_update(app_id):
309 3c22bad0 Giorgos Korfiatis
    app = get_application(app_id)
310 3c22bad0 Giorgos Korfiatis
    return Chain.objects.get_for_update(chain=app.chain_id)
311 3c22bad0 Giorgos Korfiatis
312 3c22bad0 Giorgos Korfiatis
313 3c22bad0 Giorgos Korfiatis
def get_application(application_id):
314 19eb3ee6 Giorgos Korfiatis
    try:
315 3c22bad0 Giorgos Korfiatis
        return ProjectApplication.objects.get(id=application_id)
316 19eb3ee6 Giorgos Korfiatis
    except ProjectApplication.DoesNotExist:
317 19eb3ee6 Giorgos Korfiatis
        m = _(astakos_messages.UNKNOWN_PROJECT_APPLICATION_ID) % application_id
318 19eb3ee6 Giorgos Korfiatis
        raise IOError(m)
319 19eb3ee6 Giorgos Korfiatis
320 7a08e179 Giorgos Korfiatis
321 73fbaec4 Sofia Papagiannaki
def get_user_by_id(user_id):
322 73fbaec4 Sofia Papagiannaki
    try:
323 974ee6a6 Sofia Papagiannaki
        return AstakosUser.objects.get(id=user_id)
324 73fbaec4 Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
325 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.UNKNOWN_USER_ID) % user_id
326 7a08e179 Giorgos Korfiatis
        raise IOError(m)
327 7a08e179 Giorgos Korfiatis
328 73fbaec4 Sofia Papagiannaki
329 3c049f6d Giorgos Korfiatis
def get_user_by_uuid(uuid):
330 3c049f6d Giorgos Korfiatis
    try:
331 3c049f6d Giorgos Korfiatis
        return AstakosUser.objects.get(uuid=uuid)
332 3c049f6d Giorgos Korfiatis
    except AstakosUser.DoesNotExist:
333 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.UNKNOWN_USER_ID) % uuid
334 7a08e179 Giorgos Korfiatis
        raise IOError(m)
335 3c049f6d Giorgos Korfiatis
336 97e93991 Kostas Papadimitriou
337 3c22bad0 Giorgos Korfiatis
def get_membership(project_id, user_id):
338 73fbaec4 Sofia Papagiannaki
    try:
339 3c22bad0 Giorgos Korfiatis
        objs = ProjectMembership.objects.select_related('project', 'person')
340 3c22bad0 Giorgos Korfiatis
        return objs.get(project__id=project_id, person__id=user_id)
341 73fbaec4 Sofia Papagiannaki
    except ProjectMembership.DoesNotExist:
342 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
343 7a08e179 Giorgos Korfiatis
        raise IOError(m)
344 7a08e179 Giorgos Korfiatis
345 73fbaec4 Sofia Papagiannaki
346 3c22bad0 Giorgos Korfiatis
def get_membership_by_id(project_id, memb_id):
347 7f3c4920 Giorgos Korfiatis
    try:
348 3c22bad0 Giorgos Korfiatis
        objs = ProjectMembership.objects.select_related('project', 'person')
349 3c22bad0 Giorgos Korfiatis
        return objs.get(project__id=project_id, id=memb_id)
350 7f3c4920 Giorgos Korfiatis
    except ProjectMembership.DoesNotExist:
351 7f3c4920 Giorgos Korfiatis
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
352 7f3c4920 Giorgos Korfiatis
        raise IOError(m)
353 7f3c4920 Giorgos Korfiatis
354 7f3c4920 Giorgos Korfiatis
355 d07ce657 Giorgos Korfiatis
def checkAllowed(entity, request_user, admin_only=False):
356 3c638f72 Giorgos Korfiatis
    if isinstance(entity, Project):
357 3c638f72 Giorgos Korfiatis
        application = entity.application
358 3c638f72 Giorgos Korfiatis
    elif isinstance(entity, ProjectApplication):
359 3c638f72 Giorgos Korfiatis
        application = entity
360 3c638f72 Giorgos Korfiatis
    else:
361 3c638f72 Giorgos Korfiatis
        m = "%s not a Project nor a ProjectApplication" % (entity,)
362 3c638f72 Giorgos Korfiatis
        raise ValueError(m)
363 3c638f72 Giorgos Korfiatis
364 d07ce657 Giorgos Korfiatis
    if not request_user or request_user.is_project_admin():
365 d07ce657 Giorgos Korfiatis
        return
366 d07ce657 Giorgos Korfiatis
367 d07ce657 Giorgos Korfiatis
    if not admin_only and application.owner == request_user:
368 d07ce657 Giorgos Korfiatis
        return
369 d07ce657 Giorgos Korfiatis
370 d07ce657 Giorgos Korfiatis
    m = _(astakos_messages.NOT_ALLOWED)
371 d07ce657 Giorgos Korfiatis
    raise PermissionDenied(m)
372 d07ce657 Giorgos Korfiatis
373 907f15db Giorgos Korfiatis
374 907f15db Giorgos Korfiatis
def checkAlive(project):
375 907f15db Giorgos Korfiatis
    if not project.is_alive:
376 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.NOT_ALIVE_PROJECT) % project.__dict__
377 7a08e179 Giorgos Korfiatis
        raise PermissionDenied(m)
378 7a08e179 Giorgos Korfiatis
379 907f15db Giorgos Korfiatis
380 ff67242a Giorgos Korfiatis
def accept_membership_checks(project, request_user):
381 907f15db Giorgos Korfiatis
    checkAllowed(project, request_user)
382 907f15db Giorgos Korfiatis
    checkAlive(project)
383 b0686c16 Giorgos Korfiatis
384 b0686c16 Giorgos Korfiatis
    join_policy = project.application.member_join_policy
385 b0686c16 Giorgos Korfiatis
    if join_policy == CLOSED_POLICY:
386 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.MEMBER_JOIN_POLICY_CLOSED)
387 7a08e179 Giorgos Korfiatis
        raise PermissionDenied(m)
388 b0686c16 Giorgos Korfiatis
389 8dcaa6ac Giorgos Korfiatis
    if project.violates_members_limit(adding=1):
390 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.MEMBER_NUMBER_LIMIT_REACHED)
391 7a08e179 Giorgos Korfiatis
        raise PermissionDenied(m)
392 73fbaec4 Sofia Papagiannaki
393 d07ce657 Giorgos Korfiatis
394 7f3c4920 Giorgos Korfiatis
def accept_membership(project_id, memb_id, request_user=None):
395 3c22bad0 Giorgos Korfiatis
    get_chain_for_update(project_id)
396 14f7f6a5 Giorgos Korfiatis
397 3c22bad0 Giorgos Korfiatis
    membership = get_membership_by_id(project_id, memb_id)
398 14f7f6a5 Giorgos Korfiatis
    if not membership.can_accept():
399 14f7f6a5 Giorgos Korfiatis
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
400 14f7f6a5 Giorgos Korfiatis
        raise PermissionDenied(m)
401 d4fc6292 Giorgos Korfiatis
402 3c22bad0 Giorgos Korfiatis
    project = membership.project
403 3c22bad0 Giorgos Korfiatis
    accept_membership_checks(project, request_user)
404 7f3c4920 Giorgos Korfiatis
    user = membership.person
405 73fbaec4 Sofia Papagiannaki
    membership.accept()
406 e336910f Giorgos Korfiatis
    qh_sync_user(user)
407 f30f0170 Giorgos Korfiatis
    logger.info("User %s has been accepted in %s." %
408 7f3c4920 Giorgos Korfiatis
                (user.log_display, project))
409 73fbaec4 Sofia Papagiannaki
410 7f3c4920 Giorgos Korfiatis
    membership_change_notify(project, user, 'accepted')
411 73fbaec4 Sofia Papagiannaki
    return membership
412 73fbaec4 Sofia Papagiannaki
413 7a08e179 Giorgos Korfiatis
414 ff67242a Giorgos Korfiatis
def reject_membership_checks(project, request_user):
415 907f15db Giorgos Korfiatis
    checkAllowed(project, request_user)
416 907f15db Giorgos Korfiatis
    checkAlive(project)
417 e47fb17a Sofia Papagiannaki
418 d07ce657 Giorgos Korfiatis
419 7f3c4920 Giorgos Korfiatis
def reject_membership(project_id, memb_id, request_user=None):
420 3c22bad0 Giorgos Korfiatis
    get_chain_for_update(project_id)
421 3c22bad0 Giorgos Korfiatis
422 3c22bad0 Giorgos Korfiatis
    membership = get_membership_by_id(project_id, memb_id)
423 14f7f6a5 Giorgos Korfiatis
    if not membership.can_reject():
424 14f7f6a5 Giorgos Korfiatis
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
425 14f7f6a5 Giorgos Korfiatis
        raise PermissionDenied(m)
426 d4fc6292 Giorgos Korfiatis
427 3c22bad0 Giorgos Korfiatis
    project = membership.project
428 3c22bad0 Giorgos Korfiatis
    reject_membership_checks(project, request_user)
429 7f3c4920 Giorgos Korfiatis
    user = membership.person
430 73fbaec4 Sofia Papagiannaki
    membership.reject()
431 f30f0170 Giorgos Korfiatis
    logger.info("Request of user %s for %s has been rejected." %
432 7f3c4920 Giorgos Korfiatis
                (user.log_display, project))
433 73fbaec4 Sofia Papagiannaki
434 7f3c4920 Giorgos Korfiatis
    membership_change_notify(project, user, 'rejected')
435 73fbaec4 Sofia Papagiannaki
    return membership
436 73fbaec4 Sofia Papagiannaki
437 7a08e179 Giorgos Korfiatis
438 aad0e329 Giorgos Korfiatis
def cancel_membership_checks(project):
439 aad0e329 Giorgos Korfiatis
    checkAlive(project)
440 aad0e329 Giorgos Korfiatis
441 d07ce657 Giorgos Korfiatis
442 d07ce657 Giorgos Korfiatis
def cancel_membership(project_id, request_user):
443 3c22bad0 Giorgos Korfiatis
    get_chain_for_update(project_id)
444 3c22bad0 Giorgos Korfiatis
445 3c22bad0 Giorgos Korfiatis
    membership = get_membership(project_id, request_user.id)
446 aad0e329 Giorgos Korfiatis
    if not membership.can_cancel():
447 aad0e329 Giorgos Korfiatis
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
448 aad0e329 Giorgos Korfiatis
        raise PermissionDenied(m)
449 aad0e329 Giorgos Korfiatis
450 3c22bad0 Giorgos Korfiatis
    project = membership.project
451 3c22bad0 Giorgos Korfiatis
    cancel_membership_checks(project)
452 aad0e329 Giorgos Korfiatis
    membership.cancel()
453 f30f0170 Giorgos Korfiatis
    logger.info("Request of user %s for %s has been cancelled." %
454 f30f0170 Giorgos Korfiatis
                (membership.person.log_display, project))
455 aad0e329 Giorgos Korfiatis
456 7a08e179 Giorgos Korfiatis
457 ff67242a Giorgos Korfiatis
def remove_membership_checks(project, request_user=None):
458 907f15db Giorgos Korfiatis
    checkAllowed(project, request_user)
459 907f15db Giorgos Korfiatis
    checkAlive(project)
460 73fbaec4 Sofia Papagiannaki
461 b0686c16 Giorgos Korfiatis
    leave_policy = project.application.member_leave_policy
462 b0686c16 Giorgos Korfiatis
    if leave_policy == CLOSED_POLICY:
463 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.MEMBER_LEAVE_POLICY_CLOSED)
464 7a08e179 Giorgos Korfiatis
        raise PermissionDenied(m)
465 7a08e179 Giorgos Korfiatis
466 b0686c16 Giorgos Korfiatis
467 7f3c4920 Giorgos Korfiatis
def remove_membership(project_id, memb_id, request_user=None):
468 3c22bad0 Giorgos Korfiatis
    get_chain_for_update(project_id)
469 3c22bad0 Giorgos Korfiatis
470 3c22bad0 Giorgos Korfiatis
    membership = get_membership_by_id(project_id, memb_id)
471 14f7f6a5 Giorgos Korfiatis
    if not membership.can_remove():
472 14f7f6a5 Giorgos Korfiatis
        m = _(astakos_messages.NOT_ACCEPTED_MEMBERSHIP)
473 14f7f6a5 Giorgos Korfiatis
        raise PermissionDenied(m)
474 d4fc6292 Giorgos Korfiatis
475 3c22bad0 Giorgos Korfiatis
    project = membership.project
476 3c22bad0 Giorgos Korfiatis
    remove_membership_checks(project, request_user)
477 7f3c4920 Giorgos Korfiatis
    user = membership.person
478 73fbaec4 Sofia Papagiannaki
    membership.remove()
479 e336910f Giorgos Korfiatis
    qh_sync_user(user)
480 f30f0170 Giorgos Korfiatis
    logger.info("User %s has been removed from %s." %
481 7f3c4920 Giorgos Korfiatis
                (user.log_display, project))
482 73fbaec4 Sofia Papagiannaki
483 7f3c4920 Giorgos Korfiatis
    membership_change_notify(project, user, 'removed')
484 73fbaec4 Sofia Papagiannaki
    return membership
485 73fbaec4 Sofia Papagiannaki
486 7a08e179 Giorgos Korfiatis
487 ff67242a Giorgos Korfiatis
def enroll_member(project_id, user, request_user=None):
488 3c22bad0 Giorgos Korfiatis
    get_chain_for_update(project_id)
489 3c22bad0 Giorgos Korfiatis
    project = get_project_by_id(project_id)
490 ff67242a Giorgos Korfiatis
    accept_membership_checks(project, request_user)
491 e05c541e Giorgos Korfiatis
492 e05c541e Giorgos Korfiatis
    membership, created = ProjectMembership.objects.get_or_create(
493 e05c541e Giorgos Korfiatis
        project=project,
494 e05c541e Giorgos Korfiatis
        person=user)
495 14f7f6a5 Giorgos Korfiatis
496 14f7f6a5 Giorgos Korfiatis
    if not membership.can_accept():
497 14f7f6a5 Giorgos Korfiatis
        m = _(astakos_messages.NOT_MEMBERSHIP_REQUEST)
498 14f7f6a5 Giorgos Korfiatis
        raise PermissionDenied(m)
499 d4fc6292 Giorgos Korfiatis
500 907f15db Giorgos Korfiatis
    membership.accept()
501 e336910f Giorgos Korfiatis
    qh_sync_user(user)
502 f30f0170 Giorgos Korfiatis
    logger.info("User %s has been enrolled in %s." %
503 f30f0170 Giorgos Korfiatis
                (membership.person.log_display, project))
504 570015d2 Giorgos Korfiatis
505 466cc12c Giorgos Korfiatis
    membership_enroll_notify(project, membership.person)
506 907f15db Giorgos Korfiatis
    return membership
507 8dcaa6ac Giorgos Korfiatis
508 7a08e179 Giorgos Korfiatis
509 ff67242a Giorgos Korfiatis
def leave_project_checks(project):
510 907f15db Giorgos Korfiatis
    checkAlive(project)
511 8dcaa6ac Giorgos Korfiatis
512 03869281 Sofia Papagiannaki
    leave_policy = project.application.member_leave_policy
513 b0686c16 Giorgos Korfiatis
    if leave_policy == CLOSED_POLICY:
514 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.MEMBER_LEAVE_POLICY_CLOSED)
515 7a08e179 Giorgos Korfiatis
        raise PermissionDenied(m)
516 7a08e179 Giorgos Korfiatis
517 73fbaec4 Sofia Papagiannaki
518 d4660e00 Giorgos Korfiatis
def can_leave_request(project, user):
519 d4660e00 Giorgos Korfiatis
    leave_policy = project.application.member_leave_policy
520 d4660e00 Giorgos Korfiatis
    if leave_policy == CLOSED_POLICY:
521 d4660e00 Giorgos Korfiatis
        return False
522 d4660e00 Giorgos Korfiatis
    m = user.get_membership(project)
523 d4660e00 Giorgos Korfiatis
    if m is None:
524 d4660e00 Giorgos Korfiatis
        return False
525 d4660e00 Giorgos Korfiatis
    if m.state != ProjectMembership.ACCEPTED:
526 d4660e00 Giorgos Korfiatis
        return False
527 d4660e00 Giorgos Korfiatis
    return True
528 d4660e00 Giorgos Korfiatis
529 d07ce657 Giorgos Korfiatis
530 d07ce657 Giorgos Korfiatis
def leave_project(project_id, request_user):
531 3c22bad0 Giorgos Korfiatis
    get_chain_for_update(project_id)
532 3c22bad0 Giorgos Korfiatis
533 3c22bad0 Giorgos Korfiatis
    membership = get_membership(project_id, request_user.id)
534 14f7f6a5 Giorgos Korfiatis
    if not membership.can_leave():
535 14f7f6a5 Giorgos Korfiatis
        m = _(astakos_messages.NOT_ACCEPTED_MEMBERSHIP)
536 14f7f6a5 Giorgos Korfiatis
        raise PermissionDenied(m)
537 4e057833 Sofia Papagiannaki
538 3c22bad0 Giorgos Korfiatis
    project = membership.project
539 3c22bad0 Giorgos Korfiatis
    leave_project_checks(project)
540 3c22bad0 Giorgos Korfiatis
541 bb6a4465 Giorgos Korfiatis
    auto_accepted = False
542 4e057833 Sofia Papagiannaki
    leave_policy = project.application.member_leave_policy
543 b0686c16 Giorgos Korfiatis
    if leave_policy == AUTO_ACCEPT_POLICY:
544 73fbaec4 Sofia Papagiannaki
        membership.remove()
545 e336910f Giorgos Korfiatis
        qh_sync_user(request_user)
546 f30f0170 Giorgos Korfiatis
        logger.info("User %s has left %s." %
547 3c22bad0 Giorgos Korfiatis
                    (request_user.log_display, project))
548 bb6a4465 Giorgos Korfiatis
        auto_accepted = True
549 73fbaec4 Sofia Papagiannaki
    else:
550 c1007621 Giorgos Korfiatis
        membership.leave_request()
551 f30f0170 Giorgos Korfiatis
        logger.info("User %s requested to leave %s." %
552 3c22bad0 Giorgos Korfiatis
                    (request_user.log_display, project))
553 bb6a4465 Giorgos Korfiatis
        membership_leave_request_notify(project, membership.person)
554 bb6a4465 Giorgos Korfiatis
    return auto_accepted
555 73fbaec4 Sofia Papagiannaki
556 7a08e179 Giorgos Korfiatis
557 ff67242a Giorgos Korfiatis
def join_project_checks(project):
558 907f15db Giorgos Korfiatis
    checkAlive(project)
559 8dcaa6ac Giorgos Korfiatis
560 974ee6a6 Sofia Papagiannaki
    join_policy = project.application.member_join_policy
561 b0686c16 Giorgos Korfiatis
    if join_policy == CLOSED_POLICY:
562 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.MEMBER_JOIN_POLICY_CLOSED)
563 7a08e179 Giorgos Korfiatis
        raise PermissionDenied(m)
564 7a08e179 Giorgos Korfiatis
565 73fbaec4 Sofia Papagiannaki
566 d4660e00 Giorgos Korfiatis
def can_join_request(project, user):
567 d4660e00 Giorgos Korfiatis
    join_policy = project.application.member_join_policy
568 d4660e00 Giorgos Korfiatis
    if join_policy == CLOSED_POLICY:
569 d4660e00 Giorgos Korfiatis
        return False
570 d4660e00 Giorgos Korfiatis
    m = user.get_membership(project)
571 d4660e00 Giorgos Korfiatis
    if m:
572 d4660e00 Giorgos Korfiatis
        return False
573 d4660e00 Giorgos Korfiatis
    return True
574 d4660e00 Giorgos Korfiatis
575 d07ce657 Giorgos Korfiatis
576 d07ce657 Giorgos Korfiatis
def join_project(project_id, request_user):
577 3c22bad0 Giorgos Korfiatis
    get_chain_for_update(project_id)
578 3c22bad0 Giorgos Korfiatis
    project = get_project_by_id(project_id)
579 ff67242a Giorgos Korfiatis
    join_project_checks(project)
580 d07ce657 Giorgos Korfiatis
581 d07ce657 Giorgos Korfiatis
    membership, created = ProjectMembership.objects.get_or_create(
582 d07ce657 Giorgos Korfiatis
        project=project,
583 d07ce657 Giorgos Korfiatis
        person=request_user)
584 d07ce657 Giorgos Korfiatis
585 d07ce657 Giorgos Korfiatis
    if not created:
586 d07ce657 Giorgos Korfiatis
        msg = _(astakos_messages.MEMBERSHIP_REQUEST_EXISTS)
587 d07ce657 Giorgos Korfiatis
        raise PermissionDenied(msg)
588 73fbaec4 Sofia Papagiannaki
589 bb6a4465 Giorgos Korfiatis
    auto_accepted = False
590 4e057833 Sofia Papagiannaki
    join_policy = project.application.member_join_policy
591 7a08e179 Giorgos Korfiatis
    if (join_policy == AUTO_ACCEPT_POLICY and (
592 7a08e179 Giorgos Korfiatis
            not project.violates_members_limit(adding=1))):
593 73fbaec4 Sofia Papagiannaki
        membership.accept()
594 e336910f Giorgos Korfiatis
        qh_sync_user(request_user)
595 f30f0170 Giorgos Korfiatis
        logger.info("User %s joined %s." %
596 3c22bad0 Giorgos Korfiatis
                    (request_user.log_display, project))
597 bb6a4465 Giorgos Korfiatis
        auto_accepted = True
598 bb6a4465 Giorgos Korfiatis
    else:
599 bb6a4465 Giorgos Korfiatis
        membership_request_notify(project, membership.person)
600 f30f0170 Giorgos Korfiatis
        logger.info("User %s requested to join %s." %
601 3c22bad0 Giorgos Korfiatis
                    (request_user.log_display, project))
602 bb6a4465 Giorgos Korfiatis
    return auto_accepted
603 8dcaa6ac Giorgos Korfiatis
604 7a08e179 Giorgos Korfiatis
605 6da04174 Giorgos Korfiatis
def submit_application(owner=None,
606 6da04174 Giorgos Korfiatis
                       name=None,
607 6da04174 Giorgos Korfiatis
                       precursor_id=None,
608 6da04174 Giorgos Korfiatis
                       homepage=None,
609 6da04174 Giorgos Korfiatis
                       description=None,
610 6da04174 Giorgos Korfiatis
                       start_date=None,
611 6da04174 Giorgos Korfiatis
                       end_date=None,
612 6da04174 Giorgos Korfiatis
                       member_join_policy=None,
613 6da04174 Giorgos Korfiatis
                       member_leave_policy=None,
614 6da04174 Giorgos Korfiatis
                       limit_on_members_number=None,
615 6da04174 Giorgos Korfiatis
                       comments=None,
616 6da04174 Giorgos Korfiatis
                       resource_policies=None,
617 6da04174 Giorgos Korfiatis
                       request_user=None):
618 69c822cc Giorgos Korfiatis
619 3e3743f2 Giorgos Korfiatis
    precursor = None
620 15ca2bea Giorgos Korfiatis
    if precursor_id is not None:
621 3c22bad0 Giorgos Korfiatis
        get_chain_of_application_for_update(precursor_id)
622 3c22bad0 Giorgos Korfiatis
        precursor = ProjectApplication.objects.get(id=precursor_id)
623 73fbaec4 Sofia Papagiannaki
624 3e3743f2 Giorgos Korfiatis
        if (request_user and
625 3e3743f2 Giorgos Korfiatis
            (not precursor.owner == request_user and
626 beda5f0f Georgios D. Tsoukalas
             not request_user.is_superuser
627 beda5f0f Georgios D. Tsoukalas
             and not request_user.is_project_admin())):
628 3e3743f2 Giorgos Korfiatis
            m = _(astakos_messages.NOT_ALLOWED)
629 3e3743f2 Giorgos Korfiatis
            raise PermissionDenied(m)
630 ee4aa6eb Giorgos Korfiatis
631 9770ba6c Giorgos Korfiatis
    force = request_user.is_project_admin()
632 9770ba6c Giorgos Korfiatis
    ok, limit = qh_add_pending_app(owner, precursor, force)
633 9770ba6c Giorgos Korfiatis
    if not ok:
634 c7c0ec58 Giorgos Korfiatis
        m = _(astakos_messages.REACHED_PENDING_APPLICATION_LIMIT) % limit
635 c7c0ec58 Giorgos Korfiatis
        raise PermissionDenied(m)
636 c7c0ec58 Giorgos Korfiatis
637 6da04174 Giorgos Korfiatis
    application = ProjectApplication(
638 6da04174 Giorgos Korfiatis
        applicant=request_user,
639 6da04174 Giorgos Korfiatis
        owner=owner,
640 6da04174 Giorgos Korfiatis
        name=name,
641 6da04174 Giorgos Korfiatis
        precursor_application_id=precursor_id,
642 6da04174 Giorgos Korfiatis
        homepage=homepage,
643 6da04174 Giorgos Korfiatis
        description=description,
644 6da04174 Giorgos Korfiatis
        start_date=start_date,
645 6da04174 Giorgos Korfiatis
        end_date=end_date,
646 6da04174 Giorgos Korfiatis
        member_join_policy=member_join_policy,
647 6da04174 Giorgos Korfiatis
        member_leave_policy=member_leave_policy,
648 6da04174 Giorgos Korfiatis
        limit_on_members_number=limit_on_members_number,
649 6da04174 Giorgos Korfiatis
        comments=comments)
650 1352dabb Kostas Papadimitriou
651 3e3743f2 Giorgos Korfiatis
    if precursor is None:
652 3e3743f2 Giorgos Korfiatis
        application.chain = new_chain()
653 3e3743f2 Giorgos Korfiatis
    else:
654 3e3743f2 Giorgos Korfiatis
        chain = precursor.chain
655 3e3743f2 Giorgos Korfiatis
        application.chain = chain
656 ea1e5d9f Giorgos Korfiatis
        objs = ProjectApplication.objects
657 3c22bad0 Giorgos Korfiatis
        pending = objs.filter(chain=chain, state=ProjectApplication.PENDING)
658 3e3743f2 Giorgos Korfiatis
        for app in pending:
659 3e3743f2 Giorgos Korfiatis
            app.state = ProjectApplication.REPLACED
660 3e3743f2 Giorgos Korfiatis
            app.save()
661 3e3743f2 Giorgos Korfiatis
662 3e3743f2 Giorgos Korfiatis
    application.save()
663 fa186923 Giorgos Korfiatis
    if resource_policies is not None:
664 fa186923 Giorgos Korfiatis
        application.set_resource_policies(resource_policies)
665 f30f0170 Giorgos Korfiatis
    logger.info("User %s submitted %s." %
666 f30f0170 Giorgos Korfiatis
                (request_user.log_display, application.log_display))
667 a3eb3a95 Giorgos Korfiatis
    application_submit_notify(application)
668 a3eb3a95 Giorgos Korfiatis
    return application
669 73fbaec4 Sofia Papagiannaki
670 7a08e179 Giorgos Korfiatis
671 64d0c13e Giorgos Korfiatis
def cancel_application(application_id, request_user=None, reason=""):
672 3c22bad0 Giorgos Korfiatis
    get_chain_of_application_for_update(application_id)
673 3c22bad0 Giorgos Korfiatis
    application = get_application(application_id)
674 3c638f72 Giorgos Korfiatis
    checkAllowed(application, request_user)
675 3c638f72 Giorgos Korfiatis
676 01bdbd17 Giorgos Korfiatis
    if not application.can_cancel():
677 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.APPLICATION_CANNOT_CANCEL %
678 7a08e179 Giorgos Korfiatis
              (application.id, application.state_display()))
679 01bdbd17 Giorgos Korfiatis
        raise PermissionDenied(m)
680 3c638f72 Giorgos Korfiatis
681 9770ba6c Giorgos Korfiatis
    qh_release_pending_app(application.owner)
682 9770ba6c Giorgos Korfiatis
683 3c638f72 Giorgos Korfiatis
    application.cancel()
684 f30f0170 Giorgos Korfiatis
    logger.info("%s has been cancelled." % (application.log_display))
685 3c638f72 Giorgos Korfiatis
686 7a08e179 Giorgos Korfiatis
687 64d0c13e Giorgos Korfiatis
def dismiss_application(application_id, request_user=None, reason=""):
688 3c22bad0 Giorgos Korfiatis
    get_chain_of_application_for_update(application_id)
689 3c22bad0 Giorgos Korfiatis
    application = get_application(application_id)
690 3c638f72 Giorgos Korfiatis
    checkAllowed(application, request_user)
691 3c638f72 Giorgos Korfiatis
692 01bdbd17 Giorgos Korfiatis
    if not application.can_dismiss():
693 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.APPLICATION_CANNOT_DISMISS %
694 7a08e179 Giorgos Korfiatis
              (application.id, application.state_display()))
695 01bdbd17 Giorgos Korfiatis
        raise PermissionDenied(m)
696 3c638f72 Giorgos Korfiatis
697 3c638f72 Giorgos Korfiatis
    application.dismiss()
698 f30f0170 Giorgos Korfiatis
    logger.info("%s has been dismissed." % (application.log_display))
699 3c638f72 Giorgos Korfiatis
700 7a08e179 Giorgos Korfiatis
701 64d0c13e Giorgos Korfiatis
def deny_application(application_id, request_user=None, reason=""):
702 3c22bad0 Giorgos Korfiatis
    get_chain_of_application_for_update(application_id)
703 3c22bad0 Giorgos Korfiatis
    application = get_application(application_id)
704 01bdbd17 Giorgos Korfiatis
705 d07ce657 Giorgos Korfiatis
    checkAllowed(application, request_user, admin_only=True)
706 d07ce657 Giorgos Korfiatis
707 01bdbd17 Giorgos Korfiatis
    if not application.can_deny():
708 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.APPLICATION_CANNOT_DENY %
709 7a08e179 Giorgos Korfiatis
              (application.id, application.state_display()))
710 01bdbd17 Giorgos Korfiatis
        raise PermissionDenied(m)
711 19eb3ee6 Giorgos Korfiatis
712 9770ba6c Giorgos Korfiatis
    qh_release_pending_app(application.owner)
713 9770ba6c Giorgos Korfiatis
714 2b745492 Giorgos Korfiatis
    application.deny(reason)
715 f30f0170 Giorgos Korfiatis
    logger.info("%s has been denied with reason \"%s\"." %
716 f30f0170 Giorgos Korfiatis
                (application.log_display, reason))
717 19eb3ee6 Giorgos Korfiatis
    application_deny_notify(application)
718 19eb3ee6 Giorgos Korfiatis
719 7a08e179 Giorgos Korfiatis
720 3c22bad0 Giorgos Korfiatis
def check_conflicting_projects(application):
721 3c22bad0 Giorgos Korfiatis
    try:
722 3c22bad0 Giorgos Korfiatis
        project = get_project_by_id(application.chain)
723 3c22bad0 Giorgos Korfiatis
    except IOError:
724 3c22bad0 Giorgos Korfiatis
        project = None
725 8dcaa6ac Giorgos Korfiatis
726 3c22bad0 Giorgos Korfiatis
    new_project_name = application.name
727 8dcaa6ac Giorgos Korfiatis
    try:
728 3c22bad0 Giorgos Korfiatis
        q = Q(name=new_project_name) & ~Q(state=Project.TERMINATED)
729 3c22bad0 Giorgos Korfiatis
        conflicting_project = Project.objects.get(q)
730 3c22bad0 Giorgos Korfiatis
        if (conflicting_project != project):
731 3c22bad0 Giorgos Korfiatis
            m = (_("cannot approve: project with name '%s' "
732 3c22bad0 Giorgos Korfiatis
                   "already exists (id: %s)") % (
733 3c22bad0 Giorgos Korfiatis
                    new_project_name, conflicting_project.id))
734 3c22bad0 Giorgos Korfiatis
            raise PermissionDenied(m) # invalid argument
735 3c22bad0 Giorgos Korfiatis
    except Project.DoesNotExist:
736 3c22bad0 Giorgos Korfiatis
        pass
737 3c22bad0 Giorgos Korfiatis
738 3c22bad0 Giorgos Korfiatis
    return project
739 3c22bad0 Giorgos Korfiatis
740 3c22bad0 Giorgos Korfiatis
741 3c22bad0 Giorgos Korfiatis
def approve_application(app_id, request_user=None, reason=""):
742 3c22bad0 Giorgos Korfiatis
    get_chain_of_application_for_update(app_id)
743 3c22bad0 Giorgos Korfiatis
    application = get_application(app_id)
744 8dcaa6ac Giorgos Korfiatis
745 d07ce657 Giorgos Korfiatis
    checkAllowed(application, request_user, admin_only=True)
746 d07ce657 Giorgos Korfiatis
747 01bdbd17 Giorgos Korfiatis
    if not application.can_approve():
748 7a08e179 Giorgos Korfiatis
        m = _(astakos_messages.APPLICATION_CANNOT_APPROVE %
749 7a08e179 Giorgos Korfiatis
              (application.id, application.state_display()))
750 01bdbd17 Giorgos Korfiatis
        raise PermissionDenied(m)
751 01bdbd17 Giorgos Korfiatis
752 3c22bad0 Giorgos Korfiatis
    project = check_conflicting_projects(application)
753 3c22bad0 Giorgos Korfiatis
754 3c22bad0 Giorgos Korfiatis
    # Pre-lock members and owner together in order to impose an ordering
755 3c22bad0 Giorgos Korfiatis
    # on locking users
756 3c22bad0 Giorgos Korfiatis
    members = members_to_sync(project) if project is not None else []
757 3c22bad0 Giorgos Korfiatis
    uids_to_sync = [member.id for member in members]
758 3c22bad0 Giorgos Korfiatis
    owner = application.owner
759 3c22bad0 Giorgos Korfiatis
    uids_to_sync.append(owner.id)
760 3c22bad0 Giorgos Korfiatis
    get_users_for_update(uids_to_sync)
761 3c22bad0 Giorgos Korfiatis
762 3c22bad0 Giorgos Korfiatis
    qh_release_pending_app(owner, locked=True)
763 3c22bad0 Giorgos Korfiatis
    application.approve(reason)
764 3c22bad0 Giorgos Korfiatis
    qh_sync_locked_users(members)
765 f30f0170 Giorgos Korfiatis
    logger.info("%s has been approved." % (application.log_display))
766 a3eb3a95 Giorgos Korfiatis
    application_approve_notify(application)
767 eb9ff37a Sofia Papagiannaki
768 7a08e179 Giorgos Korfiatis
769 7eadc230 Giorgos Korfiatis
def check_expiration(execute=False):
770 7eadc230 Giorgos Korfiatis
    objects = Project.objects
771 7eadc230 Giorgos Korfiatis
    expired = objects.expired_projects()
772 7eadc230 Giorgos Korfiatis
    if execute:
773 7eadc230 Giorgos Korfiatis
        for project in expired:
774 7eadc230 Giorgos Korfiatis
            terminate(project.id)
775 7eadc230 Giorgos Korfiatis
776 7eadc230 Giorgos Korfiatis
    return [project.expiration_info() for project in expired]
777 7eadc230 Giorgos Korfiatis
778 7a08e179 Giorgos Korfiatis
779 d07ce657 Giorgos Korfiatis
def terminate(project_id, request_user=None):
780 3c22bad0 Giorgos Korfiatis
    get_chain_for_update(project_id)
781 3c22bad0 Giorgos Korfiatis
    project = get_project_by_id(project_id)
782 d07ce657 Giorgos Korfiatis
    checkAllowed(project, request_user, admin_only=True)
783 907f15db Giorgos Korfiatis
    checkAlive(project)
784 5b9e9530 Giorgos Korfiatis
785 5b9e9530 Giorgos Korfiatis
    project.terminate()
786 e336910f Giorgos Korfiatis
    qh_sync_project(project)
787 f30f0170 Giorgos Korfiatis
    logger.info("%s has been terminated." % (project))
788 570015d2 Giorgos Korfiatis
789 a3eb3a95 Giorgos Korfiatis
    project_termination_notify(project)
790 eb9ff37a Sofia Papagiannaki
791 7a08e179 Giorgos Korfiatis
792 d07ce657 Giorgos Korfiatis
def suspend(project_id, request_user=None):
793 3c22bad0 Giorgos Korfiatis
    get_chain_for_update(project_id)
794 3c22bad0 Giorgos Korfiatis
    project = get_project_by_id(project_id)
795 d07ce657 Giorgos Korfiatis
    checkAllowed(project, request_user, admin_only=True)
796 db99f198 Giorgos Korfiatis
    checkAlive(project)
797 db99f198 Giorgos Korfiatis
798 db99f198 Giorgos Korfiatis
    project.suspend()
799 e336910f Giorgos Korfiatis
    qh_sync_project(project)
800 f30f0170 Giorgos Korfiatis
    logger.info("%s has been suspended." % (project))
801 570015d2 Giorgos Korfiatis
802 a3eb3a95 Giorgos Korfiatis
    project_suspension_notify(project)
803 db99f198 Giorgos Korfiatis
804 7a08e179 Giorgos Korfiatis
805 d07ce657 Giorgos Korfiatis
def resume(project_id, request_user=None):
806 3c22bad0 Giorgos Korfiatis
    get_chain_for_update(project_id)
807 3c22bad0 Giorgos Korfiatis
    project = get_project_by_id(project_id)
808 d07ce657 Giorgos Korfiatis
    checkAllowed(project, request_user, admin_only=True)
809 db99f198 Giorgos Korfiatis
810 db99f198 Giorgos Korfiatis
    if not project.is_suspended:
811 db99f198 Giorgos Korfiatis
        m = _(astakos_messages.NOT_SUSPENDED_PROJECT) % project.__dict__
812 db99f198 Giorgos Korfiatis
        raise PermissionDenied(m)
813 db99f198 Giorgos Korfiatis
814 db99f198 Giorgos Korfiatis
    project.resume()
815 e336910f Giorgos Korfiatis
    qh_sync_project(project)
816 f30f0170 Giorgos Korfiatis
    logger.info("%s has been unsuspended." % (project))
817 ff67242a Giorgos Korfiatis
818 7a08e179 Giorgos Korfiatis
819 ff67242a Giorgos Korfiatis
def get_by_chain_or_404(chain_id):
820 ff67242a Giorgos Korfiatis
    try:
821 ff67242a Giorgos Korfiatis
        project = Project.objects.get(id=chain_id)
822 ff67242a Giorgos Korfiatis
        application = project.application
823 ff67242a Giorgos Korfiatis
        return project, application
824 ff67242a Giorgos Korfiatis
    except:
825 ff67242a Giorgos Korfiatis
        application = ProjectApplication.objects.latest_of_chain(chain_id)
826 ff67242a Giorgos Korfiatis
        if application is None:
827 ff67242a Giorgos Korfiatis
            raise Http404
828 ff67242a Giorgos Korfiatis
        else:
829 ff67242a Giorgos Korfiatis
            return None, application
830 c7c0ec58 Giorgos Korfiatis
831 c7c0ec58 Giorgos Korfiatis
832 3f5851eb Giorgos Korfiatis
def _partition_by(f, l):
833 3f5851eb Giorgos Korfiatis
    d = {}
834 3f5851eb Giorgos Korfiatis
    for x in l:
835 3f5851eb Giorgos Korfiatis
        group = f(x)
836 3f5851eb Giorgos Korfiatis
        group_l = d.get(group, [])
837 3f5851eb Giorgos Korfiatis
        group_l.append(x)
838 3f5851eb Giorgos Korfiatis
        d[group] = group_l
839 3f5851eb Giorgos Korfiatis
    return d
840 3f5851eb Giorgos Korfiatis
841 3f5851eb Giorgos Korfiatis
842 3f5851eb Giorgos Korfiatis
def count_pending_app(users):
843 103086a4 Giorgos Korfiatis
    users = list(users)
844 3f5851eb Giorgos Korfiatis
    apps = ProjectApplication.objects.filter(state=ProjectApplication.PENDING,
845 3f5851eb Giorgos Korfiatis
                                             owner__in=users)
846 3f5851eb Giorgos Korfiatis
    apps_d = _partition_by(lambda a: a.owner.uuid, apps)
847 3f5851eb Giorgos Korfiatis
848 3f5851eb Giorgos Korfiatis
    usage = {}
849 3f5851eb Giorgos Korfiatis
    for user in users:
850 3f5851eb Giorgos Korfiatis
        uuid = user.uuid
851 3f5851eb Giorgos Korfiatis
        usage[uuid] = len(apps_d.get(uuid, []))
852 3f5851eb Giorgos Korfiatis
    return usage
853 3f5851eb Giorgos Korfiatis
854 3f5851eb Giorgos Korfiatis
855 3c22bad0 Giorgos Korfiatis
def get_pending_app_diff(user, precursor):
856 c7c0ec58 Giorgos Korfiatis
    if precursor is None:
857 9770ba6c Giorgos Korfiatis
        diff = 1
858 9770ba6c Giorgos Korfiatis
    else:
859 9770ba6c Giorgos Korfiatis
        chain = precursor.chain
860 9770ba6c Giorgos Korfiatis
        objs = ProjectApplication.objects
861 9770ba6c Giorgos Korfiatis
        q = objs.filter(chain=chain, state=ProjectApplication.PENDING)
862 9770ba6c Giorgos Korfiatis
        count = q.count()
863 9770ba6c Giorgos Korfiatis
        diff = 1 - count
864 3c22bad0 Giorgos Korfiatis
    return diff
865 3c22bad0 Giorgos Korfiatis
866 3c22bad0 Giorgos Korfiatis
867 3c22bad0 Giorgos Korfiatis
def qh_add_pending_app(user, precursor=None, force=False):
868 3c22bad0 Giorgos Korfiatis
    user = AstakosUser.forupdate.get_for_update(id=user.id)
869 3c22bad0 Giorgos Korfiatis
    diff = get_pending_app_diff(user, precursor)
870 3c22bad0 Giorgos Korfiatis
    return register_pending_apps(user, diff, force)
871 3c22bad0 Giorgos Korfiatis
872 c7c0ec58 Giorgos Korfiatis
873 3c22bad0 Giorgos Korfiatis
def check_pending_app_quota(user, precursor=None):
874 3c22bad0 Giorgos Korfiatis
    diff = get_pending_app_diff(user, precursor)
875 3c22bad0 Giorgos Korfiatis
    quota = get_pending_app_quota(user)
876 3c22bad0 Giorgos Korfiatis
    limit = quota['limit']
877 3c22bad0 Giorgos Korfiatis
    usage = quota['usage']
878 3c22bad0 Giorgos Korfiatis
    if usage + diff > limit:
879 3c22bad0 Giorgos Korfiatis
        return False, limit
880 3c22bad0 Giorgos Korfiatis
    return True, None
881 c7c0ec58 Giorgos Korfiatis
882 c7c0ec58 Giorgos Korfiatis
883 3c22bad0 Giorgos Korfiatis
def qh_release_pending_app(user, locked=False):
884 3c22bad0 Giorgos Korfiatis
    if not locked:
885 3c22bad0 Giorgos Korfiatis
        user = AstakosUser.forupdate.get_for_update(id=user.id)
886 9e3af524 Giorgos Korfiatis
    register_pending_apps(user, -1)