Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / functions.py @ 362dadaa

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

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