def patch(): """Update terms of service for the user.""" token = g.jwt_oidc_token_info request_json = request.get_json() valid_format, errors = schema_utils.validate(request_json, 'termsofuse') if not valid_format: return {'message': schema_utils.serialize(errors)}, http_status.HTTP_400_BAD_REQUEST version = request_json['termsversion'] is_terms_accepted = request_json['istermsaccepted'] try: response, status = UserService.update_terms_of_use(token, is_terms_accepted, version).as_dict(), \ http_status.HTTP_200_OK except BusinessException as exception: response, status = {'code': exception.code, 'message': exception.message}, exception.status_code return response, status
def get(): """Get a list of orgs that the current user is associated with.""" token = g.jwt_oidc_token_info try: user = UserService.find_by_jwt_token(token) if not user: response, status = {'message': 'User not found.'}, http_status.HTTP_404_NOT_FOUND else: all_orgs = OrgService.get_orgs(user.identifier) orgs = OrgSchema().dump( all_orgs, many=True) response, status = jsonify({'orgs': orgs}), http_status.HTTP_200_OK except BusinessException as exception: response, status = {'code': exception.code, 'message': exception.message}, exception.status_code return response, status
def put(): """Update an existing contact for the user associated with the JWT in the authorization header.""" request_json = request.get_json() valid_format, errors = schema_utils.validate(request_json, 'contact') if not valid_format: return { 'message': schema_utils.serialize(errors) }, http_status.HTTP_400_BAD_REQUEST try: response, status = UserService.update_contact( request_json).as_dict(), http_status.HTTP_200_OK except BusinessException as exception: response, status = { 'code': exception.code, 'message': exception.message }, exception.status_code return response, status
def get(): """Retrieve the set of contacts asociated with the current user identifier by the JWT in the header.""" token = g.jwt_oidc_token_info if not token: return { 'message': 'Authorization required.' }, http_status.HTTP_401_UNAUTHORIZED try: response, status = UserService.get_contacts( token), http_status.HTTP_200_OK except BusinessException as exception: response, status = { 'code': exception.code, 'message': exception.message }, exception.status_code return response, status
def post(): """Post a new user using the request body who has a proper invitation.""" try: request_json = request.get_json() invitation_token = request.headers.get('invitation_token', None) invitation = InvitationService.validate_token( invitation_token).as_dict() valid_format, errors = schema_utils.validate( request_json, 'anonymous_user') if not valid_format: return { 'message': schema_utils.serialize(errors) }, http_status.HTTP_400_BAD_REQUEST membership_details = { 'email': invitation['recipientEmail'], 'membershipType': invitation['membership'][0]['membershipType'], 'update_password_on_login': False } membership_details.update(request_json) user = UserService.create_user_and_add_membership( [membership_details], invitation['membership'][0]['org']['id'], single_mode=True) user_dict = user['users'][0] if user_dict['http_status'] != http_status.HTTP_201_CREATED: response, status = { 'code': user_dict['http_status'], 'message': user_dict['error'] }, user_dict['http_status'] else: InvitationService.accept_invitation(invitation['id'], None, None, False) response, status = user, http_status.HTTP_201_CREATED except BusinessException as exception: response, status = { 'code': exception.code, 'message': exception.message }, exception.status_code return response, status
def post(): """Create a new contact for the user associated with the JWT in the authorization header.""" token = g.jwt_oidc_token_info request_json = request.get_json() valid_format, errors = schema_utils.validate(request_json, 'contact') if not valid_format: return { 'message': schema_utils.serialize(errors) }, http_status.HTTP_400_BAD_REQUEST try: response, status = UserService.add_contact( token, request_json).as_dict(), http_status.HTTP_201_CREATED except BusinessException as exception: response, status = { 'code': exception.code, 'message': exception.message }, exception.status_code return response, status
def get(org_id): """Get the membership for the given org and user.""" try: user = UserService.find_by_jwt_token() if not user: response, status = { 'message': 'User not found.' }, http_status.HTTP_404_NOT_FOUND else: membership = MembershipService \ .get_membership_for_org_and_user_all_status(org_id=org_id, user_id=user.identifier) response, status = MembershipSchema( exclude=['org']).dump(membership), http_status.HTTP_200_OK except BusinessException as exception: response, status = { 'code': exception.code, 'message': exception.message }, exception.status_code return response, status
def post(): """Post a new user using the request body (which will contain a JWT). If the user already exists, update the name. """ token = g.jwt_oidc_token_info if not token: return { 'message': 'Authorization required.' }, http_status.HTTP_401_UNAUTHORIZED try: response, status = UserService.save_from_jwt_token( token).as_dict(), http_status.HTTP_201_CREATED except BusinessException as exception: response, status = { 'code': exception.code, 'message': exception.message }, exception.status_code return response, status
def post(): """Post a new user using the request body (which will contain a JWT). If the user already exists, update the name. """ token = g.jwt_oidc_token_info try: user = UserService.save_from_jwt_token(token) response, status = user.as_dict(), http_status.HTTP_201_CREATED # Add the user to public_users group if the user doesn't have public_user group KeycloakService.join_users_group(g.jwt_oidc_token_info) # If the user doesn't have account_holder role check if user is part of any orgs and add to the group if token.get('loginSource', '') in (BCSC, BCROS) \ and Role.ACCOUNT_HOLDER.value not in token.get('roles', []) \ and len(OrgService.get_orgs(user.identifier, [Status.ACTIVE.value])) > 0: KeycloakService.join_account_holders_group() except BusinessException as exception: response, status = {'code': exception.code, 'message': exception.message}, exception.status_code return response, status
def notify_admin(user, invitation_id, membership_id, invitation_origin): """Admins should be notified if user has responded to invitation.""" current_app.logger.debug('<notify_admin') admin_list = UserService.get_admins_for_membership(membership_id) invitation: InvitationModel = InvitationModel.find_invitation_by_id(invitation_id) context_path = CONFIG.AUTH_WEB_TOKEN_CONFIRM_PATH # Don't send email in case no admin exist in the org. (staff sent invitation) if len(admin_list) >= 1: admin_emails = ','.join([str(x.contacts[0].contact.email) for x in admin_list if x.contacts]) else: # No admin, find Sender email to notify sender (staff) admin_emails = invitation.sender.email if admin_emails != '': Invitation.send_admin_notification(user.as_dict(), '{}/{}'.format(invitation_origin, context_path), admin_emails, invitation.membership[0].org.name) current_app.logger.debug('>notify_admin') return Invitation(invitation)
def get(user_id): """Get info related to the user. Currently returns the org details associated with the user.But later can be extended to applications etc """ token = g.jwt_oidc_token_info # TODO make this check better.may be read from DB or something if token.get('sub', None) != user_id: return {'message': 'Unauthorized'}, http_status.HTTP_401_UNAUTHORIZED try: user = UserService.find_by_jwt_token(token) if not user: response, status = json.dumps([]), http_status.HTTP_200_OK else: all_settings = UserSettingsService.fetch_user_settings(user.identifier) response, status = jsonify(UserSettingsSchema(many=True).dump(all_settings)), http_status.HTTP_200_OK except BusinessException: response, status = json.dumps([]), http_status.HTTP_200_OK return response, status
def post(): """Post a new user using the request body (which will contain a JWT). If the user already exists, update the name. """ token = g.jwt_oidc_token_info try: request_json = request.get_json(silent=True) # For BCeID users validate schema. if token.get( 'loginSource', None ) == LoginSource.BCEID.value and request_json is not None: valid_format, errors = schema_utils.validate( request_json, 'user') if not valid_format: return { 'message': schema_utils.serialize(errors) }, http_status.HTTP_400_BAD_REQUEST user = UserService.save_from_jwt_token(token, request_json) response, status = user.as_dict(), http_status.HTTP_201_CREATED # Add the user to public_users group if the user doesn't have public_user group if token.get('loginSource', '') != LoginSource.STAFF.value: KeycloakService.join_users_group(token) # For anonymous users, there are no invitation process for members, # so whenever they login perform this check and add them to corresponding groups if token.get('loginSource', '') == LoginSource.BCROS.value: if len( OrgService.get_orgs(user.identifier, [Status.ACTIVE.value])) > 0: KeycloakService.join_account_holders_group() except BusinessException as exception: response, status = { 'code': exception.code, 'message': exception.message }, exception.status_code return response, status
def get(): """Get a list of orgs that the current user is associated with.""" token = g.jwt_oidc_token_info if not token: return { 'message': 'Authorization required.' }, http_status.HTTP_401_UNAUTHORIZED try: user = UserService.find_by_jwt_token(token) if not user: response, status = { 'message': 'User not found.' }, http_status.HTTP_404_NOT_FOUND else: response, status = jsonify( user.get_orgs()), http_status.HTTP_200_OK except BusinessException as exception: response, status = { 'code': exception.code, 'message': exception.message }, exception.status_code return response, status
def post(): """Admin users can post multiple users to his org.Use it for anonymous purpose only.""" try: request_json = request.get_json() valid_format, errors = schema_utils.validate( request_json, 'bulk_user') if not valid_format: return { 'message': schema_utils.serialize(errors) }, http_status.HTTP_400_BAD_REQUEST users = UserService.create_user_and_add_membership( request_json['users'], request_json['orgId']) is_any_error = any(user['http_status'] != 201 for user in users['users']) response, status = users, http_status.HTTP_207_MULTI_STATUS if is_any_error else http_status.HTTP_200_OK except BusinessException as exception: response, status = { 'code': exception.code, 'message': exception.message }, exception.status_code return response, status
def get(): """Get a list of orgs that the current user is associated with.""" token = g.jwt_oidc_token_info try: user = UserService.find_by_jwt_token(token) if not user: response, status = {'message': 'User not found.'}, http_status.HTTP_404_NOT_FOUND else: # response, status = jsonify(user.get_orgs()), http_status.HTTP_200_OK all_orgs = OrgService.get_orgs(user.identifier) exclude_fields = [] # only approved users should see entities.. # TODO when endpoints are separated into afilliations endpoint, this logic can be removed if all_orgs: if all_orgs[0].members and all_orgs[0].members[0].status != Status.ACTIVE.value: exclude_fields.append('affiliated_entities') orgs = OrgSchema(exclude=exclude_fields).dump( all_orgs, many=True) response, status = jsonify({'orgs': orgs}), http_status.HTTP_200_OK except BusinessException as exception: response, status = {'code': exception.code, 'message': exception.message}, exception.status_code return response, status
def accept_invitation(invitation_id, user: UserService, origin, add_membership: bool = True, token_info: Dict = None): """Add user, role and org from the invitation to membership.""" current_app.logger.debug('>accept_invitation') invitation: InvitationModel = InvitationModel.find_invitation_by_id( invitation_id) if invitation is None: raise BusinessException(Error.DATA_NOT_FOUND, None) if invitation.invitation_status_code == 'ACCEPTED': raise BusinessException(Error.ACTIONED_INVITATION, None) if invitation.invitation_status_code == 'EXPIRED': raise BusinessException(Error.EXPIRED_INVITATION, None) if getattr(token_info, 'loginSource', None) is not None: # bcros comes with out token login_source = token_info.get('loginSource', None) if invitation.login_source != login_source: raise BusinessException(Error.INVALID_USER_CREDENTIALS, None) if add_membership: for membership in invitation.membership: membership_model = MembershipModel() membership_model.org_id = membership.org_id membership_model.user_id = user.identifier membership_model.membership_type = membership.membership_type # check to ensure an invitation for this user/org has not already been processed existing_membership = MembershipService \ .get_membership_for_org_and_user(org_id=membership_model.org_id, user_id=membership_model.user_id) if existing_membership: raise BusinessException(Error.DATA_ALREADY_EXISTS, None) org_model: OrgModel = OrgModel.find_by_org_id( membership.org_id) # GOVM users gets direct approval since they are IDIR users. membership_model.status = Invitation._get_status_based_on_org( org_model) membership_model.save() try: # skip notifying admin if it auto approved # for now , auto approval happens for GOVM.If more auto approval comes , just check if its GOVM if membership_model.status != Status.ACTIVE.value: Invitation.notify_admin(user, invitation_id, membership_model.id, origin) except BusinessException as exception: current_app.logger.error( '<send_notification_to_admin failed', exception.message) invitation.accepted_date = datetime.now() invitation.invitation_status = InvitationStatusModel.get_status_by_code( 'ACCEPTED') invitation.save() # Call keycloak to add the user to the group. if user: group_name: str = KeycloakService.join_users_group(token_info) KeycloakService.join_account_holders_group(user.keycloak_guid) if group_name == GROUP_GOV_ACCOUNT_USERS: # Add contact to the user. user.add_contact(token_info, dict(email=token_info.get('email', None)), throw_error_for_duplicates=False) current_app.logger.debug('<accept_invitation') return Invitation(invitation)