63 lines
2.2 KiB
Python
63 lines
2.2 KiB
Python
from flask import Blueprint, request
|
|
from zope import component
|
|
|
|
from .utils import authz_restrict_to_syscom, create_streaming_response
|
|
from ceo_common.errors import BadRequest
|
|
from ceo_common.interfaces import ILDAPService, IConfig
|
|
from ceod.transactions.members import UpdateMemberPositionsTransaction
|
|
|
|
bp = Blueprint('positions', __name__)
|
|
|
|
|
|
@bp.route('/', methods=['GET'], strict_slashes=False)
|
|
def get_positions():
|
|
ldap_srv = component.getUtility(ILDAPService)
|
|
|
|
positions = {}
|
|
for user in ldap_srv.get_users_with_positions():
|
|
for position in user.positions:
|
|
if position not in positions:
|
|
positions[position] = []
|
|
positions[position].append(user.uid)
|
|
|
|
return positions
|
|
|
|
|
|
@bp.route('/', methods=['POST'], strict_slashes=False)
|
|
@authz_restrict_to_syscom
|
|
def update_positions():
|
|
cfg = component.getUtility(IConfig)
|
|
body = request.get_json(force=True)
|
|
|
|
required = cfg.get('positions_required')
|
|
available = cfg.get('positions_available')
|
|
|
|
# remove falsy values and parse multiple users in each position
|
|
# Example: "user1,user2, user3" -> ["user1","user2","user3"]
|
|
position_to_usernames = {}
|
|
for position, usernames in body.items():
|
|
if not usernames:
|
|
continue
|
|
if type(usernames) is list:
|
|
position_to_usernames[position] = usernames
|
|
elif type(usernames) is str:
|
|
position_to_usernames[position] = usernames.replace(' ', '').split(',')
|
|
else:
|
|
raise BadRequest('usernames must be a list or comma-separated string')
|
|
|
|
# check for duplicates (i.e. one username specified twice in the same list)
|
|
for usernames in position_to_usernames.values():
|
|
if len(usernames) != len(set(usernames)):
|
|
raise BadRequest('username may only be specified at most once for a position')
|
|
|
|
for position in position_to_usernames.keys():
|
|
if position not in available:
|
|
raise BadRequest(f'unknown position: {position}')
|
|
|
|
for position in required:
|
|
if position not in position_to_usernames:
|
|
raise BadRequest(f'missing required position: {position}')
|
|
|
|
txn = UpdateMemberPositionsTransaction(position_to_usernames)
|
|
return create_streaming_response(txn)
|