Beispiel #1
0
class DomainTagResource(Resource):
    decorators = [require_oauth()]

    @require_all_permissions(Permission.PermissionNames.CAN_EDIT_DOMAINS)
    @time_me(logger, 'DomainTags')
    def get(self, **kwargs):
        """
        Function will return all tags belonging to domain
        Note: "description" is a required field
        Endpoint:  POST /v1/users/tags
        Usage:
            >>> headers = {'Authorization': 'Bearer {access_token}'}
            >>> requests.get(url="host/v1/domains/4/tags", headers=headers)
        """
        # Retrieve tags belonging to domain
        # TODO: Should link Tag to domain
        domain_tags = Tag.query.join(CandidateTag, Candidate, User). \
            filter(Candidate.user_id == User.id, User.domain_id == request.user.domain_id). \
            filter(CandidateTag.candidate_id == Candidate.id).all()

        return {
            'domain_tags':
                [{
                     'id': tag.id,
                     'name': tag.name,
                     'added_datetime': DatetimeUtils.to_utc_str(tag.added_datetime),
                     'updated_datetime': DatetimeUtils.to_utc_str(tag.updated_datetime),
                 } for tag in domain_tags]
        }
Beispiel #2
0
class UserInviteApi(Resource):

    # Access token and role authentication decorators
    decorators = [require_oauth()]

    @require_all_permissions(Permission.PermissionNames.CAN_ADD_USERS)
    def post(self, **kwargs):
        """
        POST /users/<id>/invite This endpoint will send invitation email to an already existing user
        :param kwargs:
        :return: None
        """

        requested_user_id = kwargs.get('id')
        requested_user = User.get(requested_user_id)
        if not requested_user:
            raise NotFoundError("User with user id %s is not found" % requested_user_id)

        temp_password = gen_salt(8)
        requested_user.password = gettalent_generate_password_hash(temp_password)
        requested_user.password_reset_time = datetime.utcnow()
        requested_user.is_disabled = 0
        requested_user.registration_id = 'Invited'
        db.session.commit()

        send_new_account_email(requested_user.email, temp_password, requested_user.email)

        return '', 201
Beispiel #3
0
class UserGroupsApi(Resource):

    # Access token decorator
    decorators = [require_oauth()]

    @require_all_permissions(Permission.PermissionNames.CAN_GET_DOMAIN_GROUPS)
    def get(self, **kwargs):
        """
        GET /groups/<group_id>/users?include_stats=True     Fetch all users in a user_group and also include stats

        :return A dictionary containing id and lastName of all users of a user_group
        :rtype: dict
        """

        requested_group_id = kwargs.get('group_id')
        include_stats_flag = request.args.get('include_stats', False)

        requested_group = UserGroup.query.get(requested_group_id)

        if not requested_group:
            raise NotFoundError("Group with group_id %s doesn't exist" % requested_group_id)

        if request.user.role.name != 'TALENT_ADMIN' and requested_group.domain_id != request.user.domain_id:
            raise UnauthorizedError("User %s doesn't have appropriate permission to add users to a "
                                    "group %s" % (request.user.id, requested_group_id))

        users_data_dict = {user.id: user.to_dict() for user in UserGroup.all_users_of_group(requested_group_id)}
        return {"users": get_users_stats_from_mixpanel(users_data_dict, False, include_stats_flag).values()}

    @require_any_permission(Permission.PermissionNames.CAN_ADD_DOMAIN_GROUPS)
    def post(self, **kwargs):
        """
        POST /groups/<group_id>/users Add users in a given user_group

        :return A dictionary containing success message
        :rtype: dict
        """

        requested_group_id = kwargs.get('group_id')
        requested_group = UserGroup.query.get(requested_group_id)

        if not requested_group:
            raise NotFoundError("Group with group_id %s doesn't exist" % requested_group_id)

        posted_data = request.get_json(silent=True)
        if not posted_data or 'user_ids' not in posted_data:
            raise InvalidUsage("Request body is empty or not provided")

        if request.user.role.name != 'TALENT_ADMIN' and requested_group.domain_id != request.user.domain_id:
            raise UnauthorizedError("User %s doesn't have appropriate permission to add users to a "
                                    "group %s" % (request.user.id, requested_group_id))

        UserGroup.add_users_to_group(requested_group, posted_data.get('user_ids'))
        return '', 201
Beispiel #4
0
class DomainSourceResource(Resource):
    decorators = [require_oauth()]

    @require_all_permissions(Permission.PermissionNames.CAN_EDIT_DOMAINS)
    def post(self, **kwargs):
        """
        Function will create a source for domain
        Note: "description" is a required field
        Endpoint:  POST /v1/sources
        :return:  {'source': {'id': int}}
        Usage:
            >>> headers = {'Authorization': 'Bearer {access_token}', 'content-type': 'application/json'}
            >>> data = {"source": {"description": "job fair", "notes": "recruiter initials: ahb"}}
            >>> requests.post(url="host/v1/sources", headers=headers, data=json.dumps(data))
        """
        authed_user = request.user  # Authenticated user
        domain_id = authed_user.domain_id  # user's domain ID

        # Validate and obtain json data from request body
        body_dict = get_json_data_if_validated(request_body=request,
                                               json_schema=source_schema,
                                               format_checker=False)

        # Normalize description & notes
        source = body_dict['source']
        description = source['description'].encode('utf-8').strip().lower()
        notes = (source.get('notes') or '').strip().lower()

        # In case description is just a whitespace
        if not description:
            raise InvalidUsage("Source description is a required field")

        # Prevent duplicate sources for the same domain
        source = CandidateSource.get_by(domain_id=domain_id,
                                        description=description)
        if source:
            raise InvalidUsage(
                "Source (description: {}) already exists for domain: {}".
                format(description, domain_id),
                additional_error_info=dict(source_id=source.id))

        new_source = CandidateSource(description=description,
                                     notes=notes,
                                     domain_id=domain_id,
                                     added_datetime=datetime.datetime.utcnow())

        db.session.add(new_source)
        db.session.commit()

        return {'source': {'id': new_source.id}}, requests.codes.CREATED

    @require_all_permissions(Permission.PermissionNames.CAN_GET_DOMAINS)
    def get(self, **kwargs):
        """
        Function will return domain source(s)
        Endpoints:
             i. GET /v1/sources
            ii. GET /v1/sources/:id
        Example:
            >>> url = 'host/v1/sources'
            >>> headers = {'Authorization': 'Bearer {access_token}'}
            >>> requests.get(url=url, headers=headers)
        :returns:
            {'source': CandidateSource} if source_id is provided in url
            {'source': [CandidateSource, CandidateSource, ...]} if source_id is not provided in url
        """
        # Authenticated user & source ID
        authed_user, source_id = request.user, kwargs.get('id')
        domain_id = authed_user.domain_id  # User's domain ID

        # Return a single source If source ID is provided
        if source_id is not None:
            source = CandidateSource.get(source_id)
            # Source ID must be recognized
            if not source_id:
                raise InvalidUsage(
                    "Source ID ({}) not recognized.".format(source_id))

            # Source must belong to user's domain
            if source.domain_id != authed_user.domain_id:
                raise ForbiddenError(
                    "Source (ID: {}) does not belong to user's domain (ID: )".
                    format(source_id, domain_id))

            return {
                'source': {
                    'id':
                    source.id,
                    'description':
                    source.description,
                    'notes':
                    source.notes,
                    'domain_id':
                    source.domain_id,
                    'added_datetime':
                    DatetimeUtils.utc_isoformat(source.added_datetime)
                    if source.added_datetime else None
                }
            }

        # Get all of user's domain sources
        return {
            'sources':
            [{
                'id':
                source.id,
                'description':
                source.description,
                'notes':
                source.notes,
                'domain_id':
                source.domain_id,
                'added_datetime':
                DatetimeUtils.utc_isoformat(source.added_datetime)
                if source.added_datetime else None
            }
             for source in CandidateSource.domain_sources(domain_id=domain_id)]
        }
Beispiel #5
0
class DomainCustomFieldCategoriesResource(Resource):
    decorators = [require_oauth()]

    # TODO: update docstring
    @require_all_permissions(
        Permission.PermissionNames.CAN_ADD_DOMAIN_CUSTOM_FIELDS)
    def post(self):
        """
        Function will create custom field categories for user's domain
        resource url:  POST /v1/custom_field_categories
        :return: {"custom_field_categories": [{"id": int}, {"id": int}, ...]}
        :rtype: dict[list[dict]]
        Usage:
            >>> data = {
            >>> 	"custom_fields": [
            >>> 		{
            >>> 			"name": "color",
            >>> 			"categories": [
            >>> 				{
            >>> 					"name": "red",
            >>> 					"subcategories": [
            >>> 						{"name": "bright"}, {"name": "dark"}
            >>> 					]
            >>> 				},
            >>> 				{
            >>> 					"name": "green",
            >>> 					"subcategories": [
            >>> 						{"name": "bright"}, {"name": "dark"}
            >>> 					]
            >>> 				}
            >>> 			]
            >>> 		}
            >>> 	]
            >>> }
            >>> headers = {"Authorization": "Bearer {access_token}", "content-type": "application/json"}
            >>> requests.post(url="host/v1/custom_field_categories", data=json.dumps(data), headers=headers)
            <Response [201]>
        """
        # Validate and obtain json data from request body
        body_dict = get_json_data_if_validated(request, cf_schema_post, False)
        return {
            "custom_fields": [{
                "id": cf_id
            } for cf_id in add_or_update_custom_fields(
                custom_fields_data=body_dict['custom_fields'],
                domain_id=request.user.domain_id,
                is_creating=True)]
        }, requests.codes.CREATED

    # TODO: update docstring
    @require_all_permissions(Permission.PermissionNames.CAN_GET_DOMAINS)
    def get(self, **kwargs):
        """
        Function will return domain's custom field category(ies)
        resource url:
             i. GET /v1/custom_field_categories
            ii. GET /v1/custom_field_categories/:id
        :return: {"custom_field_categories": [{"id": int}, {"id": int}, ...]}
        :rtype: dict[list[dict]]
        Usage:
            >>> headers = {"Authorization": "Bearer {access_token}"}
            >>> requests.get(url="host/v1/custom_field_categories", headers=headers)
            <Response [200]>
        """
        return retrieve_domain_custom_fields(domain_id=request.user.domain_id,
                                             custom_field_id=kwargs.get('id'))

    # TODO: update docstring
    @require_all_permissions(
        Permission.PermissionNames.CAN_EDIT_DOMAIN_CUSTOM_FIELDS)
    def patch(self, **kwargs):
        """
        Function will update domain's custom field category(ies)
        resource url:
             i. PATCH /v1/custom_field_categories
        :return: {"custom_fields": [{"id": int}, {"id": int}, ...]}
        :rtype: dict[list[dict]]
        Usage:
            >>> data = {"custom_fields": [{"id": 5, "name": "Marketing"}, {"id": 6, "name": "Sales"}]}
            >>> headers = {"Authorization": "Bearer {access_token}"}
            >>> requests.get(url="host/v1/custom_field_categories", headers=headers)
            <Response [200]>
        """
        # Validate and obtain json data from request body
        body_dict = get_json_data_if_validated(request, cf_schema_patch, False)

        return {
            "custom_fields": [{
                "id": cf_id
            } for cf_id in add_or_update_custom_fields(
                body_dict['custom_fields'], request.user.domain_id)]
        }
Beispiel #6
0
class DomainAreaOfInterestResource(Resource):
    decorators = [require_oauth()]

    @require_all_permissions(Permission.PermissionNames.CAN_EDIT_DOMAINS)
    def post(self):
        """
        Function will create area(s) of interest for user's domain
        :return: {"areas_of_interest": [{"id": int}, {"id": int}, ...]}
        :rtype: dict[list[dict]]
        Usage:
            >>> data = {"areas_of_interest": [{"description": "finance"}]}
            >>> headers = {"Authorization": "Bearer {access_token}", "content-type": "application/json"}
            >>> requests.post(url="host/v1/areas_of_interest", data=json.dumps(data), headers=headers)
            <Response [201]>
        """
        # Authenticated user
        authed_user = request.user
        domain_id = authed_user.domain_id

        # Validate and get json data from request body
        body_dict = get_json_data_if_validated(request_body=request, json_schema=aoi_schema, format_checker=False)

        created_aoi_ids = create_or_update_domain_aois(domain_id, body_dict['areas_of_interest'], is_creating=True)
        return {"areas_of_interest": [{"id": cf_id} for cf_id in created_aoi_ids]}, 201

    @require_all_permissions(Permission.PermissionNames.CAN_GET_DOMAINS)
    def get(self, **kwargs):
        """
        Function will return domain's area(s) of interest
        resource url:  /v1/custom_fields
        :return: {"areas_of_interest": [{"id": int}, {"id": int}, ...]}
        :rtype: dict[list[dict]]
        Usage:
            >>> headers = {"Authorization": "Bearer {access_token}"}
            >>> requests.get(url="host/v1/custom_fields", headers=headers)
            <Response [200]>
        """
        aoi_id = kwargs.get('id')
        if aoi_id:
            return {"area_of_interest": retrieve_domain_aoi(request.user.domain_id, aoi_id)}

        return {"areas_of_interest": [
            {
                "id": aoi.id,
                "domain_id": aoi.domain_id,
                "description": aoi.name
            } for aoi in AreaOfInterest.get_domain_areas_of_interest(request.user.domain_id)]}

    @require_all_permissions(Permission.PermissionNames.CAN_EDIT_DOMAINS)
    def put(self, **kwargs):
        """
        Function will update area(s) of interest for user's domain
        :return: {"areas_of_interest": [{"id": int}, {"id": int}, ...]}
        :rtype: dict[list[dict]]
        Usage:
            >>> data = {"areas_of_interest": [{"id": 23, "description": "finance"}]}
            >>> headers = {"Authorization": "Bearer {access_token}", "content-type": "application/json"}
            >>> requests.put(url="host/v1/areas_of_interest", data=json.dumps(data), headers=headers)
            <Response [200]>
        """
        # Validate and get json data from request body
        body_dict = get_json_data_if_validated(request_body=request, json_schema=aoi_schema, format_checker=False)

        areas_of_interest = body_dict['areas_of_interest']  # required field, validated via json-schema
        domain_id = request.user.domain_id
        aoi_id_from_url = kwargs.get('id')

        # Only one record may be updated if aoi_id_from_url is provided
        if aoi_id_from_url and (len(areas_of_interest) > 1):
            raise InvalidUsage("Invalid usage")

        updated_aoi_ids = create_or_update_domain_aois(domain_id=domain_id, aois=body_dict['areas_of_interest'],
                                                       aoi_id_from_url=aoi_id_from_url, is_updating=True)
        return {"areas_of_interest": [{"id": aoi_id} for aoi_id in updated_aoi_ids]}

    @require_all_permissions(Permission.PermissionNames.CAN_EDIT_DOMAINS)
    def delete(self, **kwargs):
        """
        Function will delete domain area(s) of interest
        Endpoints:
             i. DELETE /v1/areas_of_interest        => will delete all of domain's aois
            ii. DELETE /v1/areas_of_interest/:id    => will delete a single aoi
        Usage:
            >>> headers = {"Authorization": "Bearer {access_token}", "content-type": "application/json"}
            >>> requests.delete(url="host/v1/areas_of_interest", headers=headers)
            <Response [200]>
        :return: {"areas_of_interest": [{"id": int}, {"id": int}, ...]}
        """
        aoi_id = kwargs.get('id')
        if aoi_id:  # delete specified area of interest
            delete_domain_aoi(request.user.domain_id, aoi_id)
            return {"area_of_interest": {"id": aoi_id}}
        else:  # delete all of domain's areas of interest
            deleted_aoi_ids = delete_domain_aois(request.user.domain_id)
            return {"areas_of_interest": [{"id": aoi_id} for aoi_id in deleted_aoi_ids]}
Beispiel #7
0
class UserApi(Resource):

    # Access token and role authentication decorators
    decorators = [require_oauth()]

    # 'SELF' is for readability. It means this endpoint will be accessible to any user
    @require_all_permissions(Permission.PermissionNames.CAN_GET_USERS)
    def get(self, **kwargs):
        """
        GET /users/<id>                             Fetch user object with user's basic info
        GET /users?domain_id=1                      Fetch all user ids of a given domain
        GET /users?domain_id=1&include_stats=True   Fetch all user ids of a given domain and also include stats

        :return A dictionary containing user basic info except safety critical info or a dictionary containing
                all user_ids of a domain
        :rtype: dict
        """

        requested_user_id = kwargs.get('id')
        include_stats_flag = request.args.get('include_stats', False)
        if requested_user_id:
            requested_user = User.query.get(requested_user_id)
            if not requested_user:
                raise NotFoundError("User with user id %s not found" % requested_user_id)

            if request.user.role.name != 'TALENT_ADMIN' and requested_user.domain_id != request.user.domain_id:
                raise UnauthorizedError("User %s doesn't have appropriate permission to get user %s" % (
                    request.user.id, requested_user_id))

            return {
                'user': get_users_stats_from_mixpanel(requested_user.to_dict(), True, include_stats_flag)
            }

        # User id is not provided so logged-in user wants to get all users of its domain
        else:
            domain_id = request.user.domain_id

            # Get all users of any domain if user is `TALENT_ADMIN`
            if request.user.role.name == 'TALENT_ADMIN' and request.args.get('domain_id'):
                domain_id = request.args.get('domain_id')
                if not is_number(domain_id) or not Domain.query.get(int(domain_id)):
                    raise InvalidUsage("Invalid Domain Id is provided")

            users_data_dict = {user.id: user.to_dict() for user in User.all_users_of_domain(int(domain_id))}
            return {'users': get_users_stats_from_mixpanel(users_data_dict, False, include_stats_flag).values()}

    @require_all_permissions(Permission.PermissionNames.CAN_ADD_USERS)
    def post(self):
        """
        POST /users  Create a new user
        input: {'users': [userDict1, userDict2, userDict3, ... ]}

        Take a JSON dictionary containing array of User dictionaries
        A single user dict must contain user's first name, last name, and email

        :return:  A dictionary containing array of user ids
        :rtype: dict
        """

        posted_data = request.get_json(silent=True)
        if not posted_data or 'users' not in posted_data:
            raise InvalidUsage("Request body is empty or not provided")

        # Save user object(s)
        users = posted_data['users']

        # User object(s) must be in a list
        if not isinstance(users, list):
            raise InvalidUsage("Request body is not properly formatted")

        for user_dict in users:

            first_name = user_dict.get('first_name', "").strip()
            last_name = user_dict.get('last_name', "").strip()
            email = user_dict.get('email', "").strip()

            if not first_name or not last_name or not email:
                raise InvalidUsage("first name, last name or email is missing in request body")

            if not is_valid_email(email=email):
                raise InvalidUsage("Email Address %s is not properly formatted" % email)

            # Check if user already exist
            already_existing_user = check_if_user_exists(email)
            if already_existing_user:
                if already_existing_user.is_disabled:
                    raise InvalidUsage("User with email=%s already exists in Database but is disabled" % email)
                else:
                    raise InvalidUsage("User with email=%s already exists in Database" % email)

            if request.user.role.name == 'TALENT_ADMIN':
                domain_id = user_dict.get('domain_id', request.user.domain_id)
            else:
                domain_id = request.user.domain_id
            user_dict['domain_id'] = domain_id

            role = user_dict.get('role', '')
            user_dict['role_id'] = validate_role(role, domain_id, request.user) if role else ''

        user_ids = []  # Newly created user object's id(s) are appended to this list
        for user_dict in users:
            first_name = user_dict.get('first_name', "").strip()
            last_name = user_dict.get('last_name', "").strip()
            email = user_dict.get('email', "").strip()
            phone = user_dict.get('phone', "").strip()
            dice_user_id = user_dict.get('dice_user_id')
            thumbnail_url = user_dict.get('thumbnail_url', '').strip()
            user_group_id = user_dict.get('user_group_id')
            locale = user_dict.get('locale', 'en-US')
            domain_id = user_dict.get('domain_id')
            role_id = user_dict.get('role_id', '')

            try:
                Locale.parse(locale, sep='-')
            except:
                raise InvalidUsage('A valid Locale value should be provided')

            user_id = create_user_for_company(first_name=first_name, last_name=last_name, email=email, phone=phone,
                                              domain_id=int(domain_id), dice_user_id=dice_user_id,
                                              thumbnail_url=thumbnail_url, user_group_id=user_group_id, locale=locale,
                                              role_id=role_id)
            user_ids.append(user_id)

        return {'users': user_ids}

    # 'SELF' is for readability. It means this endpoint will be accessible to any user
    @require_all_permissions(Permission.PermissionNames.CAN_EDIT_USERS)
    def put(self, **kwargs):
        """
        PUT /users/<id>

        Function will change credentials of one user per request.
        User will be allowed to modify itself

        :return: {'updated_user' {'id': user_id}}
        :rtype:  dict
        """

        requested_user_id = kwargs.get('id')
        requested_user = User.query.get(requested_user_id) if requested_user_id else None
        if not requested_user:
            raise NotFoundError("Either user_id is not provided or user doesn't exist")

        posted_data = request.get_json(silent=True)
        if not posted_data:
            raise InvalidUsage("Request body is empty or not provided")

        if request.user.role.name != 'TALENT_ADMIN' and requested_user.domain_id != request.user.domain_id:
            raise UnauthorizedError("Logged-in user doesn't have appropriate permissions to edit a user")

        if request.user.role.name == 'USER' and requested_user_id != request.user.id:
            raise UnauthorizedError("Logged-in user doesn't have appropriate permissions to edit a user")

        first_name = posted_data.get('first_name', '').strip()
        last_name = posted_data.get('last_name', '').strip()
        email = posted_data.get('email', '').strip()
        phone = posted_data.get('phone', '').strip()
        thumbnail_url = posted_data.get('thumbnail_url', '').strip()
        last_read_datetime = posted_data.get('last_read_datetime', '').strip()
        is_disabled = posted_data.get('is_disabled', 0)
        locale = posted_data.get('locale', '')

        try:
            last_read_datetime = parser.parse(last_read_datetime)
        except Exception as e:
            raise InvalidUsage("Last read datetime %s is invalid because: %s" % (last_read_datetime, e.message))

        if email and not is_valid_email(email=email):
            raise InvalidUsage("Email Address %s is not properly formatted" % email)

        if email and check_if_user_exists(email) and requested_user.email != email:
            raise InvalidUsage("Email Address %s already exists" % email)

        if not is_number(is_disabled) or (int(is_disabled) != 0 and int(is_disabled) != 1):
            raise InvalidUsage("Possible vaues of `is_disabled` are 0 and 1")

        is_disabled = int(is_disabled)

        if locale:
            try:
                Locale.parse(locale, sep='-')
            except:
                raise InvalidUsage('A valid Locale value should be provided')
        
        # Update user
        update_user_dict = {
            'first_name': first_name,
            'last_name': last_name,
            'email': email,
            'phone': phone,
            'thumbnail_url': thumbnail_url,
            'last_read_datetime': last_read_datetime,
            'is_disabled': is_disabled,
            'locale': locale
        }
        update_user_dict = dict((k, v) for k, v in update_user_dict.iteritems() if v)

        if is_disabled:
            update_user_dict['registration_id'] = ''

        User.query.filter(User.id == requested_user_id).update(update_user_dict)
        db.session.commit()

        if is_disabled:
            # Delete all tokens of deleted user
            request.user.password_reset_time = datetime.utcnow()
            tokens = Token.query.filter_by(user_id=requested_user_id).all()
            for token in tokens:
                token.delete()

        return {'updated_user': {'id': requested_user_id}}
Beispiel #8
0
class DomainCustomFieldsResource(Resource):
    decorators = [require_oauth()]

    @require_all_permissions(
        Permission.PermissionNames.CAN_ADD_DOMAIN_CUSTOM_FIELDS)
    def post(self):
        """
        Function will create custom field(s) for user's domain
        resource url:  POST /v1/custom_fields
        :return: {"custom_fields": [{"id": int}, {"id": int}, ...]}
        :rtype: dict[list[dict]]
        Usage:
            >>> data = {"custom_fields": [{"category_id": 1, "name": "job status"}]}
            >>> headers = {"Authorization": "Bearer {access_token}", "content-type": "application/json"}
            >>> requests.post(url="host/v1/custom_fields", data=json.dumps(data), headers=headers)
            <Response [201]>
        """
        # Validate and obtain json data from request body
        body_dict = get_json_data_if_validated(request, custom_fields_schema,
                                               False)

        return {
            "custom_fields":
            create_custom_fields(body_dict['custom_fields'],
                                 request.user.domain_id)
        }, requests.codes.CREATED

    @require_all_permissions(
        Permission.PermissionNames.CAN_GET_DOMAIN_CUSTOM_FIELDS)
    def get(self, **kwargs):
        """
        Function will return domain's custom field(s)
        resource url:
             i. GET /v1/custom_fields
            ii. GET /v1/custom_fields/:id
        :return: {"custom_fields": [{"id": int}, {"id": int}, ...]}
        :rtype: dict[list[dict]]
        Usage:
            >>> headers = {"Authorization": "Bearer {access_token}"}
            >>> requests.get(url="host/v1/custom_fields", headers=headers)
            <Response [200]>
        """
        custom_field_id = kwargs.get('id')

        # Return specified custom field data
        if custom_field_id:
            # Custom field ID must be recognized & belong to user's domain
            custom_field = get_custom_field_if_validated(
                custom_field_id, request.user)

            return {
                'custom_field': {
                    'id': custom_field.id,
                    'domain_id': custom_field.domain_id,
                    'name': custom_field.name,
                    'added_datetime': str(custom_field.added_time),
                    "type": custom_field.type,
                }
            }

        # Return all or filtered domain's custom fields
        # Authenticated user
        authed_user = request.user
        search_query = request.args.get('query', '')
        sort_type = request.args.get('sort_type', 'DESC')
        sort_by = request.args.get('sort_by', 'added_time')
        cf_type = request.args.get('type', 'all')

        query_object = CustomField.get_by_domain_id_and_filter_by_name_and_type(
            authed_user.domain.id, search_query, sort_by, sort_type, cf_type)
        items = [field.to_json() for field in query_object]
        response = {'custom_fields': items}
        return ApiResponse(response)

    @require_all_permissions(
        Permission.PermissionNames.CAN_EDIT_DOMAIN_CUSTOM_FIELDS)
    def put(self, **kwargs):
        """
        Function will update domain's custom field(s)
        resource url:
             i. PUT /v1/custom_fields
            ii. PUT /v1/custom_fields/:id
        :return: {"custom_fields": [{"id": int}, {"id": int}, ...]}
        :rtype: dict[list[dict]]
        Usage:
            >>> headers = {"Authorization": "Bearer {access_token}"}
            >>> data = {"custom_fields": [{"id": 4, "name": "job status"}]}
            >>> requests.put(url="host/v1/custom_fields", headers=headers, data=json.dumps(data))
            <Response [200]>
        """
        custom_field_id = kwargs.get('id')

        # Validate and obtain json data from request body
        schema = custom_field_schema if custom_field_id else custom_fields_schema
        body_dict = get_json_data_if_validated(request, schema, False)

        # Update specified custom field
        if custom_field_id:

            # Custom field ID must be recognized & belong to user's domain
            get_custom_field_if_validated(custom_field_id, request.user)

            # Remove whitespace(s) from custom field name
            custom_field_name = body_dict['custom_field']['name'].strip()
            if not custom_field_name:  # In case name is just a whitespace
                raise InvalidUsage(
                    "Name is required for creating custom field.")

            custom_field_query = CustomField.query.filter_by(
                id=custom_field_id)
            custom_field_query.update(dict(name=custom_field_name))
            db.session.commit()

            return {'custom_field': {'id': custom_field_id}}

        updated_custom_field_ids = []
        for custom_field in body_dict['custom_fields']:

            # Custom field ID must be provided
            custom_field_id = custom_field.get('id')
            if not custom_field_id:
                raise InvalidUsage("Custom field ID is required for updating.")

            # Remove whitespace(s) from custom field name
            custom_field_name = custom_field['name'].strip()
            if not custom_field_name:  # In case name is just a whitespace
                raise InvalidUsage(
                    "Name is required for creating custom field.")

            custom_field_query = CustomField.query.filter_by(
                id=custom_field_id)

            # Custom field ID must be recognized
            cf_object = custom_field_query.first()
            if not cf_object:
                raise NotFoundError(
                    'Custom field ID ({}) not recognized.'.format(
                        custom_field_id))

            # Custom field must belong to user's domain
            if cf_object.domain_id != request.user.domain_id:
                raise ForbiddenError('Not authorized')

            custom_field_query.update(dict(name=custom_field_name))
            updated_custom_field_ids.append(custom_field_id)

        db.session.commit()
        return {
            'custom_fields': [{
                'id': custom_field_id
            } for custom_field_id in updated_custom_field_ids]
        }

    @require_all_permissions(
        Permission.PermissionNames.CAN_DELETE_DOMAIN_CUSTOM_FIELDS)
    def delete(self, **kwargs):
        """
        Function will delete domain's custom field(s)
        resource url:
            i. DELETE /v1/custom_fields/:id
        :return: {"custom_field": {"id": int}}
        :rtype: dict[dict]
        Usage:
            >>> headers = {"Authorization": "Bearer {access_token}"}
            >>> requests.delete(url="host/v1/custom_fields/4", headers=headers)
            <Response [200]>
        """
        custom_field_id = kwargs.get('id')

        # Delete specified custom field
        if custom_field_id:

            # Custom field ID must be recognized
            custom_field = CustomField.get(custom_field_id)
            if not custom_field:
                raise NotFoundError(
                    "Custom field ID ({}) not recognized.".format(
                        custom_field_id))

            # Custom field must belong to user's domain
            if request.user.role.name != 'TALENT_ADMIN' and custom_field.domain_id != request.user.domain_id:
                raise ForbiddenError("Not authorized")

            custom_field_candidate_ids = CandidateCustomField.query.with_entities(
                CandidateCustomField.candidate_id).filter_by(
                    custom_field_id=custom_field_id).all()

            custom_field_candidate_ids = map(
                lambda custom_field_object: custom_field_object[0],
                custom_field_candidate_ids)

            update_candidates_on_cloudsearch(request.oauth_token,
                                             custom_field_candidate_ids)

            db.session.delete(custom_field)
            db.session.commit()

            return {'custom_field': {'id': custom_field_id}}
Beispiel #9
0
class DomainApi(Resource):

    # Access token and role authentication decorators
    decorators = [require_oauth()]

    @require_all_permissions(Permission.PermissionNames.CAN_GET_DOMAINS)
    def get(self, **kwargs):
        """
        GET /domains/<id> Fetch domain object with domain's basic info
        GET /domains Fetch all domain objects with domain's basic info
        :return A dictionary containing domain info except safety critical info
        :rtype: dict
        """

        requested_domain_id = kwargs.get('id')
        if requested_domain_id:
            requested_domain = Domain.query.get(requested_domain_id)
            if not requested_domain:
                raise NotFoundError("Domain with domain id %s not found" %
                                    requested_domain_id)

            if requested_domain_id == request.user.domain_id or request.user.role.name == 'TALENT_ADMIN':
                return {'domain': requested_domain.to_dict()}
        elif request.user.role.name == 'TALENT_ADMIN':

            is_disabled = request.args.get('is_disabled', 0)
            search_keyword = request.args.get('search', '').strip()
            if not is_number(is_disabled) or int(is_disabled) not in (0, 1):
                raise InvalidUsage('`is_disabled` can be either 0 or 1')

            domains = Domain.query.filter(
                Domain.is_disabled == is_disabled,
                Domain.name.ilike('%' + search_keyword + '%')).all()

            return {'domains': [domain.to_dict() for domain in domains]}

        raise UnauthorizedError(
            "Either logged-in user belongs to different domain as requested_domain or it doesn't "
            "have appropriate permissions")

    @require_all_permissions(Permission.PermissionNames.CAN_ADD_DOMAINS)
    def post(self):
        """
        POST /domains  Create a new Domain
        input: {'domains': [domain1, domain2, domain3, ... ]}

        Take a JSON dictionary containing array of Domain dictionaries
        A single domain dict must contain at least domain's name

        :return:  A dictionary containing array of user ids
        :rtype: dict
        """

        posted_data = request.get_json(silent=True)
        if not posted_data or 'domains' not in posted_data:
            raise InvalidUsage("Request body is empty or not provided")

        # Save domain object(s)
        domains = posted_data['domains']

        # Domain object(s) must be in a list
        if not isinstance(domains, list):
            raise InvalidUsage("Request body is not properly formatted")

        for index, domain_dict in enumerate(domains):

            name = domain_dict.get('name', '')
            default_culture_id = domain_dict.get('default_culture_id', '')
            expiration = domain_dict.get('expiration', '')

            if not name:
                raise InvalidUsage("Domain name should be provided")

            domain = Domain.query.filter_by(name=name).first()

            # If domain already exists then raise an exception
            if domain:
                if not domain.is_disabled:
                    raise InvalidUsage("Domain %s already exist" % name)
                else:
                    domain.is_disabled = 0
                    db.session.commit()
                    domains.pop(index)
                    continue

            # If Culture doesn't exist in database
            if default_culture_id and not Culture.query.get(
                    default_culture_id):
                raise InvalidUsage("Culture %s doesn't exist" %
                                   default_culture_id)

            if expiration:
                try:
                    parser.parse(expiration)
                except Exception as e:
                    raise InvalidUsage("Expiration Time is not valid as: %s" %
                                       e.message)

        domain_ids = [
        ]  # Newly created user object's id(s) are appended to this list
        for domain_dict in domains:

            name = domain_dict.get('name', '')
            expiration = domain_dict.get('expiration', '')
            default_culture_id = domain_dict.get('default_culture_id', 1)
            default_tracking_code = domain_dict.get('default_tracking_code',
                                                    None)
            dice_company_id = domain_dict.get('dice_company_id', None)
            expiration = parser.parse(expiration) if expiration else ""

            domain_id = get_or_create_domain(
                logged_in_user_id=request.user.id,
                name=name,
                expiration=expiration,
                default_culture_id=default_culture_id,
                default_tracking_code=default_tracking_code,
                dice_company_id=dice_company_id)

            domain_ids.append(domain_id)

        return {'domains': domain_ids}

    @require_all_permissions(Permission.PermissionNames.CAN_DELETE_DOMAINS)
    def delete(self, **kwargs):
        """
        DELETE /domains/<id>

        Function will disable domain-object in db

        :return: {'deleted_domain' {'id': domain_id}}
        :rtype:  dict
        """

        domain_id_to_delete = kwargs.get('id')
        if not domain_id_to_delete:
            raise InvalidUsage("Domain id is not provided")

        # Return 404 if requested user does not exist
        domain_to_delete = Domain.query.get(domain_id_to_delete)
        if not domain_to_delete:
            raise NotFoundError(
                "Requested domain with domain_id %s doesn't exist" %
                domain_id_to_delete)

        # Disable the domain by setting is_disabled field to 1
        Domain.query.filter(Domain.id == domain_id_to_delete).update(
            {'is_disabled': 1})

        # Disable all users of this domain as Domain has been disabled
        User.query.filter(User.domain_id == domain_id_to_delete).update(
            {'is_disabled': 1})
        db.session.commit()

        return {'deleted_domain': {'id': domain_id_to_delete}}

    @require_all_permissions(Permission.PermissionNames.CAN_EDIT_DOMAINS)
    def put(self, **kwargs):
        """
        PUT /domains/<id>

        Function will change credentials of one domain per request.

        :return: {'updated_domain' {'id': domain_id}}
        :rtype:  dict
        """

        requested_domain_id = kwargs.get('id')
        requested_domain = Domain.query.get(
            requested_domain_id) if requested_domain_id else None
        if not requested_domain:
            raise NotFoundError(
                "Either domain_id is not provided or domain doesn't exist")

        posted_data = request.get_json(silent=True)
        if not posted_data:
            raise InvalidUsage("Request body is empty or not provided")

        if request.user.role.name != 'TALENT_ADMIN' and requested_domain_id != request.user.domain_id:
            raise UnauthorizedError(
                "Logged-in user doesn't have appropriate permissions for this operation"
            )

        name = posted_data.get('name', '')
        expiration = posted_data.get('expiration', '')
        default_culture_id = posted_data.get('default_culture_id', '')
        default_tracking_code = posted_data.get('default_tracking_code', '')
        dice_company_id = posted_data.get('dice_company_Id', '')

        if expiration:
            try:
                expiration = parser.parse(expiration)
            except Exception as e:
                raise InvalidUsage("Expiration Time is not valid as: %s" %
                                   e.message)

        if name and Domain.query.filter_by(name=name).first():
            raise InvalidUsage('Domain %s already exists in database' % name)

        # If Culture doesn't exist in database
        if default_culture_id and not Culture.query.get(default_culture_id):
            raise InvalidUsage("Culture %s doesn't exist" % default_culture_id)

        is_disabled = request.args.get('is_disabled', 0)
        if not is_number(is_disabled) or int(is_disabled) not in (0, 1):
            raise InvalidUsage('`is_disabled` can be either 0 or 1')

        # Update user
        update_domain_dict = {
            'name': name,
            'expiration': expiration,
            'default_culture_id': default_culture_id,
            'default_tracking_code': default_tracking_code,
            'dice_company_id': dice_company_id,
            'is_disabled': is_disabled,
        }
        update_domain_dict = dict(
            (k, v) for k, v in update_domain_dict.iteritems() if v)
        Domain.query.filter(
            Domain.id == requested_domain_id).update(update_domain_dict)
        db.session.commit()

        return {'updated_domain': {'id': requested_domain_id}}

    @require_all_permissions(Permission.PermissionNames.CAN_EDIT_DOMAINS)
    def patch(self, **kwargs):
        """
        PATCH /domains/<id>

         This endpoint will update field `is_test_domain` of requested domain object.
        :rtype:  dict
        """
        requested_domain_id = kwargs.get('id')
        requested_domain = Domain.query.get(
            requested_domain_id) if requested_domain_id else None
        if not requested_domain:
            raise NotFoundError(
                "Either domain_id is not provided or domain doesn't exist")

        posted_data = request.get_json(silent=True)
        if not posted_data:
            raise InvalidUsage("Request body is empty or not provided")

        if request.user.role.name != 'TALENT_ADMIN' and requested_domain_id != request.user.domain_id:
            raise UnauthorizedError(
                "Logged-in user doesn't have appropriate permissions for this operation"
            )

        is_test_domain = posted_data.get('is_test_domain', 0)
        if is_test_domain not in (True, False, 1, 0):
            raise InvalidUsage(
                "is_test_domain field should be a boolean, given: %s" %
                is_test_domain)

        requested_domain.update(is_test_domain=is_test_domain)
        logger.info("Domain(id:%s) has been marked as test domain" %
                    requested_domain_id)
        return {'updated_domain': {'id': requested_domain_id}}
Beispiel #10
0
class DomainGroupsApi(Resource):

    # Access token decorator
    decorators = [require_oauth()]

    @require_all_permissions(Permission.PermissionNames.CAN_GET_DOMAIN_GROUPS)
    def get(self, **kwargs):
        """
        GET /domain/<domain_id>/groups Fetch all user_groups of a given domain

        :return A dictionary containing id and name of all user_groups of a given domain
        :rtype: dict
        """

        requested_domain_id = kwargs.get('domain_id')
        requested_domain = Domain.query.get(requested_domain_id)

        if not requested_domain:
            raise NotFoundError("Domain with domain_id %s doesn't exist" % requested_domain_id)

        if request.user.role.name != 'TALENT_ADMIN' and requested_domain_id != request.user.domain_id:
            raise UnauthorizedError("User %s doesn't have appropriate permission to get all user_groups "
                                    "of domain %s" % (request.user.id, requested_domain_id))

        all_user_groups_of_domain = UserGroup.all_groups_of_domain(requested_domain_id)
        return {"user_groups": [{'id': user_group.id, 'name': user_group.name} for user_group in
                                all_user_groups_of_domain]}

    @require_all_permissions(Permission.PermissionNames.CAN_ADD_DOMAIN_GROUPS)
    def post(self, **kwargs):
        """
        POST /domain/<domain_id>/groups Add user_groups to a given domain

        :return A dictionary containing ids of user_groups added to given domain
        :rtype: dict
        """

        requested_domain_id = kwargs.get('domain_id')
        requested_domain = Domain.query.get(requested_domain_id)

        if not requested_domain:
            raise NotFoundError("Domain with domain_id %s doesn't exist" % requested_domain_id)

        posted_data = request.get_json(silent=True)
        if not posted_data or 'groups' not in posted_data:
            raise InvalidUsage("Request body is empty or not provided")

        if request.user.role.name != 'TALENT_ADMIN' and requested_domain_id != request.user.domain_id:
            raise UnauthorizedError("User %s doesn't have appropriate permission to add user_groups "
                                    "to domain %s" % (request.user.id, requested_domain_id))

        user_groups = UserGroup.add_groups(posted_data.get('groups'), requested_domain_id)
        return {'user_groups': [user_group.id for user_group in user_groups]}

    @require_all_permissions(Permission.PermissionNames.CAN_EDIT_DOMAIN_GROUPS)
    def put(self, **kwargs):
        """
        PUT /domain/groups/<group_id> Edit a user group with given group_id

        :return A dictionary containing success message
        :rtype: dict
        """

        requested_group_id = kwargs.get('group_id')
        requested_group = UserGroup.query.get(requested_group_id)

        if not requested_group:
            raise NotFoundError("User Group with id %s doesn't exist" % requested_group_id)

        posted_data = request.get_json(silent=True)
        if not posted_data:
            raise InvalidUsage("Request body is empty or not provided")

        if request.user.role.name != 'TALENT_ADMIN' and requested_group.domain_id != request.user.domain_id:
            raise UnauthorizedError("User %s doesn't have appropriate permission to edit user_groups %s" % (
                request.user.id, requested_group.name))

        name = posted_data.get('name')
        description = posted_data.get('description')

        if not name and not description:
            raise InvalidUsage("Neither name nor description is provided")

        if name and not UserGroup.query.filter_by(name=name, domain_id=requested_group.domain_id).all():
            requested_group.name = name
        elif name:
            raise InvalidUsage("User group '%s' already exists in domain %s" % (name, requested_group.domain_id))

        if description:
            requested_group.description = description

        db.session.commit()
        return '', 201

    @require_all_permissions(Permission.PermissionNames.CAN_DELETE_DOMAIN_GROUPS)
    def delete(self, **kwargs):
        """
        DELETE /domain/<domain_id>/groups Remove user_groups from a given domain

        :return A dictionary containing success message
        :rtype: dict
        """

        requested_domain_id = kwargs.get('domain_id')
        requested_domain = Domain.query.get(requested_domain_id)

        if not requested_domain:
            raise NotFoundError("Domain with domain_id %s doesn't exist" % requested_domain_id)

        posted_data = request.get_json(silent=True)
        if not posted_data or 'groups' not in posted_data:
            raise InvalidUsage("Request body is empty or not provided")

        if request.user.role.name != 'TALENT_ADMIN' and requested_domain_id != request.user.domain_id:
            raise UnauthorizedError("User %s doesn't have appropriate permission to remove user_groups "
                                    "from domain %s" % (request.user.id, requested_domain_id))

        UserGroup.delete_groups(requested_domain_id, posted_data.get('groups'))
        return '', 200
Beispiel #11
0
class RolesApi(Resource):

    decorators = [require_oauth()]
    # Access token decorator

    @require_all_permissions(Permission.PermissionNames.CAN_GET_USER_ROLE)
    def get(self, **kwargs):
        """
        GET /users/roles Fetch all roles in the system which can be assigned to a user
        :param kwargs:
        :return:
        """
        static_roles = Role.query.filter(Role.name.in_(['TALENT_ADMIN', 'DOMAIN_ADMIN', 'ADMIN'])).all()
        static_roles = {static_role.name: static_role for static_role in static_roles}

        user_role_name = request.user.role.name
        if user_role_name == 'TALENT_ADMIN':
            roles_prefix = static_roles.values()
        elif user_role_name == 'DOMAIN_ADMIN':
            roles_prefix = [static_roles['DOMAIN_ADMIN'], static_roles['ADMIN']]
        elif user_role_name == 'ADMIN':
            roles_prefix = [static_roles['ADMIN']]
        else:
            roles_prefix = []

        roles_prefix += Role.query.filter(Role.name.notin_(['TALENT_ADMIN', 'DOMAIN_ADMIN', 'ADMIN']))
        return (
            {
                "roles": [{
                    'role_id': role_object.id,
                    'role_name': role_object.name,
                    'permissions': [{
                        'permission_id': permission.id,
                        'permission_name': permission.name
                    } for permission in role_object.permissions]
                } for role_object in roles_prefix]}
        )

    @require_all_permissions(Permission.PermissionNames.CAN_ADD_USER_ROLE)
    def post(self, **kwargs):
        """
        POST /users/roles Create a New Custom role using existing roles
        :param kwargs:
        :return:
        """
        posted_data = request.get_json(silent=True)
        if not posted_data or 'role' not in posted_data or not isinstance(posted_data['role'], dict):
            raise InvalidUsage("Request body is empty or not provided")

        role_data = posted_data.get('role')
        role_name = role_data.get('name', '')
        role_description = role_data.get('description', '')
        permission_ids = role_data.get('permissions', [])
        permission_ids = list(set(permission_ids))

        if not role_name:
            raise InvalidUsage("Valid Role Name should be provided")

        if Permission.query.filter(Permission.id.in_(permission_ids)).count() != len(permission_ids):
            raise InvalidUsage("Some or All permission ids are not valid")

        if Role.get_by_name(role_name):
            raise InvalidUsage("Role with name: %s already exists" % role_name)

        # Check if a role already exists with same set of permissions
        existing_role_with_same_permissions = Role.query.filter(
            permission_ids.__len__() == (PermissionsOfRole.query.filter(
                PermissionsOfRole.permission_id.in_(permission_ids),
                PermissionsOfRole.role_id == Role.id).count()),
            (permission_ids.__len__() == PermissionsOfRole.query.filter(
                PermissionsOfRole.role_id == Role.id).count())).first()

        if existing_role_with_same_permissions:
            raise InvalidUsage("Another role `%s` already exists with same set of "
                               "permissions" % existing_role_with_same_permissions.name)

        exclusive_permissions = PermissionsOfRole.query.with_entities(PermissionsOfRole.permission_id,
                                                                      func.count(PermissionsOfRole.role_id)).group_by(
            PermissionsOfRole.permission_id).having(func.count(PermissionsOfRole.role_id) <= 2).all()

        exclusive_permissions = {exclusive_permission[0]: exclusive_permission[1]
                                 for exclusive_permission in exclusive_permissions}

        user_role_name = request.user.role.name

        for permission_id in permission_ids:
            if permission_id in exclusive_permissions and (
                        (user_role_name == 'DOMAIN_ADMIN' and exclusive_permissions[permission_id] == 1) or
                        (user_role_name == 'ADMIN' and exclusive_permissions[permission_id] <= 2)):
                raise UnauthorizedError("Logged-in user is not authorized to create a "
                                        "role with permission_id: %s" % permission_id)

        role_object = Role(name=role_name, description=role_description)
        db.session.add(role_object)
        db.session.flush()

        for permission_id in permission_ids:
            db.session.add(PermissionsOfRole(role_id=role_object.id, permission_id=permission_id))

        db.session.commit()

        return {
            'id': role_object.id,
            'name': role_object.name
        }
Beispiel #12
0
class UserRolesApi(Resource):

    # Access token decorator
    decorators = [require_oauth()]

    @require_all_permissions(Permission.PermissionNames.CAN_GET_USER_ROLE)
    def get(self, **kwargs):
        """
        GET /users/<user_id>/roles Fetch all permissions of a user

        :return A dictionary containing role Name and permissions of that role
        :rtype: dict
        """

        requested_user_id = kwargs.get('user_id')
        requested_user = User.query.get(requested_user_id)

        if not requested_user:
            raise NotFoundError("User with user_id %s doesn't exist" % requested_user_id)

        # GET all roles of given user
        permissions = [permission.name for permission in requested_user.role.get_all_permissions_of_role()]
        return {"role_name": requested_user.role.name, "permissions": permissions}

    @require_all_permissions(Permission.PermissionNames.CAN_EDIT_USER_ROLE)
    def put(self, **kwargs):
        """
        POST /users/<user_id>/roles Add given roles to a user

        :return A dictionary containing success message
        :rtype: dict
        """

        requested_user_id = kwargs.get('user_id')
        requested_user = User.query.get(requested_user_id)

        if not requested_user:
            raise NotFoundError("User with user_id %s doesn't exist" % requested_user_id)

        posted_data = request.get_json(silent=True)
        if not posted_data or 'role' not in posted_data:
            raise InvalidUsage("Request body is empty or not provided")

        role = posted_data.get('role', '')
        if is_number(role):
            role_object = Role.query.get(int(role))
            if role_object:
                role_id = role
                role_name = role_object.name
            else:
                raise NotFoundError("Role with id:%s doesn't exist in database" % role)
        else:
            role_object = Role.get_by_name(role)
            if role_object:
                role_id = role_object.id
                role_name = role_object.name
            else:
                raise NotFoundError("Role with name:%s doesn't exist in database" % role)

        user_role_name = request.user.role.name

        if (user_role_name == 'DOMAIN_ADMIN' and role_name == 'TALENT_ADMIN') or \
                (user_role_name == 'ADMIN' and role_name in ('DOMAIN_ADMIN', 'TALENT_ADMIN')):
            raise UnauthorizedError("Logged-in user %s doesn't have appropriate permission to set "
                                    "role of user %s" % (request.user.id, requested_user.id))

        if user_role_name != 'TALENT_ADMIN' and request.user.domain_id != requested_user.domain_id:
            raise UnauthorizedError("Logged-in user cannot set roles of users of other domains")

        requested_user.role_id = role_id
        db.session.commit()

        return '', 201
Beispiel #13
0
class SourceProductResource(Resource):
    decorators = [require_oauth()]

    @require_all_permissions(Permission.PermissionNames.CAN_ADD_CANDIDATES)
    def post(self, **kwargs):
        # Validate and obtain json data from request body
        body_dict = get_json_data_if_validated(request, source_product_schema,
                                               False)

        # Normalize description & notes
        source_products = body_dict['source_products']

        created_sp_ids = []
        for sp in source_products:
            name = sp['name'].strip()
            notes = (sp.get('notes') or '').strip()

            # In case name is just a whitespace
            if not name:
                raise InvalidUsage("Source product name is required.")

            # Prevent inserting duplicate source product into db
            if name.lower() in {p.name.lower() for p in Product.query.all()}:
                continue

            new_source_product = Product(name=name, notes=notes)
            db.session.add(new_source_product)
            db.session.commit()
            created_sp_ids.append(new_source_product.id)

        return {
            'source_products': [{
                'id': sp_id
            } for sp_id in created_sp_ids]
        }, 201

    @require_all_permissions(Permission.PermissionNames.CAN_ADD_CANDIDATES)
    def get(self, **kwargs):

        source_product_id = kwargs.get('id')

        # Return a single Source Product if source product ID is provided
        if source_product_id:
            source_product = Product.get(source_product_id)
            if not source_product:
                raise InvalidUsage(
                    error_message="Source Product ID not recognized")

            return {
                'source_product': {
                    'id': source_product.id,
                    'name': source_product.name,
                    'notes': source_product.notes
                }
            }

        # Return all Source Products
        return {
            'source_products': [{
                'id': sp.id,
                'name': sp.name,
                'notes': sp.notes,
            } for sp in Product.query.all()]
        }