blob: b57db4e0951fa9833d44a2b57baab3d7a55a9700 [file] [log] [blame]
# Copyright 2013 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Logic for profiles."""
from google.appengine.ext import db
from melange import types
from melange.utils import rich_bool
from melange.appengine import db as melange_db
ONLY_ORG_ADMIN = 'only_org_admin'
def canResignAsOrgAdminForOrg(profile, org_key, models=types.MELANGE_MODELS):
"""Tells whether the specified profile can resign from their organization
administrator role for the specified organization.
An organization administrator may be removed from the list of administrators
of an organization, if there is at least one other user with this role.
Args:
profile: the specified profile entity.
org_key: the specified organization entity.
models: instance of types.Models that represent appropriate models.
Returns:
RichBool whose value is set to True, if the organization administrator
is allowed to resign. Otherwise, RichBool whose value is set to False
and extra part is a string that represents the reason why the user
is not allowed to resign.
"""
if org_key not in profile.org_admin_for:
raise ValueError(
'The specified profile is not an organization administrator for %s' %
org_key.name())
# retrieve keys of other org admins
org_admin_keys = getOrgAdmins(org_key, keys_only=True, models=models)
org_admin_keys.remove(profile.key())
# try to retrieve the first org admin from the list
# therefore, it can be safely used within a XG transaction
if org_admin_keys and models.profile_model.get(org_admin_keys[0]):
return rich_bool.TRUE
else:
return rich_bool.RichBool(False, extra=ONLY_ORG_ADMIN)
def getOrgAdmins(org_key, keys_only=False, extra_attrs=None,
models=types.MELANGE_MODELS):
"""Returns organization administrators for the specified organization.
Additional constraints on administrators may be specified by passing a custom
extra_attrs dictionary. Each element of the dictionary maps a property
with a requested value. The value must be a sequence.
Please note that this function executes a non-ancestor query, so it cannot
be safely used within transactions.
Args:
org_key: organization key
keys_only: If true, return only keys instead of complete entities
extra_args: a dictionary containing additional constraints on
organization administrators to retrieve
models: instance of types.Models that represent appropriate models.
Returns:
list of profiles entities or keys of organization administrators
"""
query = models.profile_model.all(keys_only=keys_only)
query.filter('org_admin_for', org_key)
query.filter('status', 'active')
_handleExtraAttrs(query, extra_attrs)
return query.fetch(limit=1000)
def assignNoRoleForOrg(profile, org_key):
"""Removes any elevated role for the specified profile profile for the
specified organization.
Args:
profile: profile entity.
org_key: organization key.
"""
if org_key in profile.mentor_for:
profile.mentor_for.remove(org_key)
profile.is_mentor = True if len(profile.mentor_for) else False
if org_key in profile.org_admin_for:
profile.org_admin_for.remove(org_key)
profile.is_org_admin = True if len(profile.org_admin_for) else False
profile.put()
def assignMentorRoleForOrg(profile, org_key):
"""Assigns the specified profile to a mentor role for the specified
organization. If a user is currently an organization administrator,
they will be lowered to a mentor role.
Args:
profile: profile entity.
organization: organization key.
"""
if org_key in profile.org_admin_for:
profile.org_admin_for.remove(org_key)
profile.is_org_admin = bool(profile.org_admin_for)
profile.is_mentor = True
profile.mentor_for = list(set(profile.mentor_for + [org_key]))
profile.put()
def assignOrgAdminRoleForOrg(profile, org_key):
"""Assigns the specified profile to an organization administrator role
for the specified organization.
Args:
profile: profile entity.
org_key: organization key.
"""
if org_key not in profile.org_admin_for:
if org_key not in profile.mentor_for:
profile.is_mentor = True
profile.mentor_for.append(org_key)
profile.is_org_admin = True
profile.org_admin_for.append(org_key)
profile.put()
def getProfileForUsername(username, program_key, models=types.MELANGE_MODELS):
"""Returns profile entity for a user with the specified username and
for the specified program.
Args:
username: a string containing username of the user.
program_key: program key.
models: instance of types.Models that represent appropriate models.
Returns:
profile entity for the specified user and program or None if the user
does not have a profile for this program.
"""
profile_key = db.Key.from_path(
models.profile_model.kind(), '%s/%s' % (program_key.name(), username),
parent=db.Key.from_path('User', username))
return db.get(profile_key)
def _handleExtraAttrs(query, extra_attrs):
"""Extends the specified query by handling extra attributes.
The attributes are specified in the passed dictionary. Each element of
the dictionary maps a property with a requested value. The value must
be a sequence (list or tuple).
Args:
query: query to extend.
extra_attrs: a dictionary containing additional constraints on the query.
"""
if extra_attrs:
for prop, value in extra_attrs.iteritems():
melange_db.addFilterToQuery(query, prop, value)