def get_buyer_dashboard_data_for_team_overview():
    """Buyer dashboard (Team overview) (role=buyer)
    ---
    tags:
      - dashboard
    definitions:
      BuyerDashboardTeamOverviewItems:
        type: object
        properties:
            items:
              type: array
              items:
                $ref: '#/definitions/BuyerDashboardTeamOverviewItem'
            organisation:
              type: string
      BuyerDashboardTeamOverviewItem:
        type: object
        properties:
          email:
            type: string
          name:
            type: string
    responses:
      200:
        description: Buyer dashboard data for the 'Team overview' tab
        schema:
          $ref: '#/definitions/BuyerDashboardTeamOverviewItems'
    """
    organisation = users.get_user_organisation(get_email_domain(current_user.email_address))
    team_members = users.get_team_members(current_user.get_id(), get_email_domain(current_user.email_address))

    return jsonify(items=team_members, organisation=organisation), 200
def get_buyer_dashboard_data_for_team_overview():
    """Buyer dashboard (Team overview) (role=buyer)
    ---
    tags:
      - dashboard
    definitions:
      BuyerDashboardTeamOverviewItems:
        type: object
        properties:
            items:
              type: array
              items:
                $ref: '#/definitions/BuyerDashboardTeamOverviewItem'
            organisation:
              type: string
      BuyerDashboardTeamOverviewItem:
        type: object
        properties:
          email:
            type: string
          name:
            type: string
    responses:
      200:
        description: Buyer dashboard data for the 'Team overview' tab
        schema:
          $ref: '#/definitions/BuyerDashboardTeamOverviewItems'
    """
    organisation = users.get_user_organisation(
        get_email_domain(current_user.email_address))
    team_members = users.get_team_members(
        current_user.get_id(), get_email_domain(current_user.email_address))

    return jsonify(items=team_members, organisation=organisation), 200
    def validate_basics(self):
        errors = []
        if not self.team.name or not self.team.name.replace(' ', ''):
            errors.append({
                'message': 'A team name is required.',
                'severity': 'error',
                'step': 'about',
                'id': 'T001'
            })

        if self.team.email_address:
            if '@' not in self.team.email_address or self.team.email_address.count(
                    '@') > 1:
                errors.append({
                    'message': 'Please add a valid email address.',
                    'severity': 'error',
                    'step': 'about',
                    'id': 'T002'
                })

            if get_email_domain(self.team.email_address) != self.domain:
                errors.append({
                    'message':
                    'You must use an email address ending in @{}.'.format(
                        self.domain),
                    'severity':
                    'error',
                    'step':
                    'about',
                    'id':
                    'T003'
                })

        return errors
def is_duplicate_user(email_address):
    domain = get_email_domain(email_address)
    if domain in current_app.config['GENERIC_EMAIL_DOMAINS']:
        return False

    supplier_code = db.session.execute(
        """
        select distinct(supplier_code) from vuser
        where email_domain = :domain
    """, {
            'domain': domain
        }).fetchone()

    if (supplier_code and supplier_code[0]):
        send_existing_seller_notification(email_address, supplier_code[0])
        duplicate_audit_event(email_address,
                              {'supplier_code': supplier_code[0]})
        return True

    application_id = db.session.execute(
        """
        select distinct(application_id) from vuser
        where email_domain = :domain
    """, {
            'domain': domain
        }).fetchone()

    if (application_id and application_id[0]):
        duplicate_audit_event(email_address,
                              {'application_id': application_id[0]})
        send_existing_application_notification(
            email_address=email_address, application_id=application_id[0])
        return True

    return False
Example #5
0
def get_team_members():
    """Supplier dashboard (Team) (role=supplier)
    ---
    tags:
      - dashboard
    definitions:
      SellerDashboardTeamItems:
        type: object
        properties:
            teams:
              type: array
              items:
                $ref: '#/definitions/SellerDashboardTeamItem'
      SellerDashboardTeamItem:
        type: object
        properties:
          email:
            type: string
          name:
            type: string
    responses:
      200:
        description: Seller dashboard data for the 'Team' tab
        schema:
          $ref: '#/definitions/SellerDashboardTeamItems'
    """
    team_members = users.get_team_members(
        current_user.get_id(), get_email_domain(current_user.email_address))

    return jsonify(teams={'items': team_members}), 200
def get_team(team_id):
    team = team_service.get_team(team_id)
    if not team:
        raise NotFoundError('Team {} does not exist'.format(team_id))

    team_member = team_member_service.find(
        is_team_lead=True,
        team_id=team_id,
        user_id=current_user.id
    ).one_or_none()

    if not team_member:
        raise UnauthorisedError('Only team leads can edit a team')

    domain = get_email_domain(current_user.email_address)

    if team['teamMembers'] is not None:
        for user_id, team_member in team['teamMembers'].iteritems():
            missing_permissions = [permission for permission in permission_types
                                   if permission not in team_member['permissions']]

            for permission in missing_permissions:
                team_member['permissions'][permission] = False

    team.update(domain=domain)

    return team
Example #7
0
    def validate_basics(self):
        errors = []
        if not self.team.name or not self.team.name.replace(' ', ''):
            errors.append({
                'message': 'A team name is required.',
                'severity': 'error',
                'step': 'about',
                'id': 'T001'
            })

        if self.team.email_address:
            if not is_valid_email(self.team.email_address):
                errors.append({
                    'message': 'Please add a valid email address.',
                    'severity': 'error',
                    'step': 'about',
                    'id': 'T002'
                })

            if get_email_domain(self.team.email_address) not in self.agency_domains:
                errors.append({
                    'message': 'You must use an email address ending in @{}.'.format(', @'.join(self.agency_domains)),
                    'severity': 'error',
                    'step': 'about',
                    'id': 'T003'
                })

        return errors
Example #8
0
def can_view_referral(created_by, supplier_code, referral_domain,
                      current_user):
    return (current_user.role == 'buyer'
            and created_by == int(current_user.get_id())
            or current_user.role == 'supplier'
            and supplier_code == current_user.supplier_code
            or current_user.role == 'admin' and referral_domain
            == get_email_domain(current_user.email_address))
def get_buyer_dashboard_data_for_team_briefs():
    """Buyer dashboard (Team briefs) (role=buyer)
    ---
    tags:
      - dashboard
    definitions:
      BuyerDashboardTeamItems:
        type: object
        properties:
            items:
              type: array
              items:
                $ref: '#/definitions/BuyerDashboardTeamItem'
            organisation:
              type: string
      BuyerDashboardTeamItem:
        type: object
        properties:
          author:
            type: string
          closed_at:
            type: string
            nullable: true
          framework:
            type: string
          id:
            type: integer
          lot:
            type: string
          name:
            type: string
          status:
            type: string
    responses:
      200:
        description: Buyer dashboard data for the 'Team briefs' tab
        schema:
          $ref: '#/definitions/BuyerDashboardTeamItems'
    """
    organisation = users.get_user_organisation(
        get_email_domain(current_user.email_address))
    team_briefs = briefs.get_team_briefs(
        current_user.get_id(), get_email_domain(current_user.email_address))

    return jsonify(items=team_briefs, organisation=organisation), 200
def get_buyer_dashboard_data_for_team_briefs():
    """Buyer dashboard (Team briefs) (role=buyer)
    ---
    tags:
      - dashboard
    definitions:
      BuyerDashboardTeamItems:
        type: object
        properties:
            items:
              type: array
              items:
                $ref: '#/definitions/BuyerDashboardTeamItem'
            organisation:
              type: string
      BuyerDashboardTeamItem:
        type: object
        properties:
          author:
            type: string
          closed_at:
            type: string
            nullable: true
          framework:
            type: string
          id:
            type: integer
          lot:
            type: string
          name:
            type: string
          status:
            type: string
    responses:
      200:
        description: Buyer dashboard data for the 'Team briefs' tab
        schema:
          $ref: '#/definitions/BuyerDashboardTeamItems'
    """
    organisation = users.get_user_organisation(get_email_domain(current_user.email_address))
    team_briefs = briefs.get_team_briefs(current_user.get_id(), get_email_domain(current_user.email_address))

    return jsonify(items=team_briefs, organisation=organisation), 200
Example #11
0
def login():
    """Login user
    ---
    tags:
      - auth
    security:
      - basicAuth: []
    consumes:
      - application/json
    parameters:
      - name: body
        in: body
        required: true
        schema:
          id: LoginUser
          required:
            - emailAddress
            - password
          properties:
            emailAddress:
              type: string
            password:
              type: string
    responses:
      200:
        description: User
        schema:
          $ref: '#/definitions/UserInfo'
    """
    json_payload = request.get_json()
    email_address = json_payload.get('emailAddress', None)
    user = User.get_by_email_address(email_address.lower())

    if user is None or (user.supplier and user.supplier.status == 'deleted'):
        return jsonify(message='User does not exist'), 403
    elif encryption.authenticate_user(json_payload.get('password', None),
                                      user) and user.active:
        user.logged_in_at = datetime.utcnow()
        user.failed_login_count = 0
        db.session.add(user)
        db.session.commit()

        login_user(user)

        user.user_organisation = users.get_user_organisation(
            get_email_domain(email_address))

        return jsonify(user_info(user))
    else:
        user.failed_login_count += 1
        db.session.add(user)
        db.session.commit()

        return jsonify(message="Could not authorize user"), 403
def buyer_dashboard():
    status = request.args.get('status', None)
    result = buyer_dashboard_business.get_briefs(current_user.id, status)
    counts = buyer_dashboard_business.get_brief_counts(current_user.id)

    email_domain = get_email_domain(current_user.email_address)
    organisation = users.get_user_organisation(email_domain)

    return jsonify(
        briefs=result,
        brief_counts=counts,
        organisation=organisation
    ), 200
def find_team_members():
    keywords = request.args.get('keywords') or ''
    exclude = request.args.get('exclude') or ''

    if keywords:
        results = team_business.search_team_members(
            current_user,
            get_email_domain(current_user.email_address),
            keywords=keywords,
            exclude=exclude.split(','))

        return jsonify(users=results), 200
    else:
        abort('You must provide a keywords param.')
def get_people_overview():
    people_overview = {}
    user = users.get(current_user.id)
    completed_teams = team_service.get_teams_for_user(user.id)
    domain = get_email_domain(user.email_address)

    people = users.get_buyer_team_members(domain)
    people_overview.update(users=people)

    organisation = users.get_user_organisation(domain)
    people_overview.update(organisation=organisation)

    completed_teams_count = len(completed_teams)
    people_overview.update(completedTeamsCount=completed_teams_count)

    return people_overview
def get_teams_overview():
    teams_overview = {}
    user = users.get(current_user.id)
    completed_teams = team_service.get_teams_for_user(user.id)
    email_domain = get_email_domain(user.email_address)

    overview = team_service.get_teams_overview(user.id, email_domain)
    teams_overview.update(overview=overview)

    organisation = users.get_user_organisation(email_domain)
    teams_overview.update(organisation=organisation)

    completed_teams_count = len(completed_teams)
    teams_overview.update(completedTeamsCount=completed_teams_count)

    return teams_overview
Example #16
0
def signup():
    """Signup user
    ---
    tags:
      - auth
    consumes:
      - application/json
    parameters:
      - name: body
        in: body
        required: true
        schema:
          id: SignupUser
          required:
            - name
            - email_address
            - user_type
          properties:
            name:
              type: string
            email_address:
              type: string
            user_type:
              type: string
            employment_status:
              type: string
            line_manager_name:
              type: string
            line_manager_email:
              type: string
            framework:
              type: string
    responses:
      200:
        description: User
        schema:
          $ref: '#/definitions/UserInfo'
    """
    json_payload = request.get_json()
    name = json_payload.get('name', None)
    email_address = json_payload.get('email_address', None)
    user_type = json_payload.get('user_type', None)
    employment_status = json_payload.get('employment_status', None)
    line_manager_name = json_payload.get('line_manager_name', None)
    line_manager_email = json_payload.get('line_manager_email', None)
    framework = json_payload.get('framework', 'digital-marketplace')

    user = User.query.filter(
        User.email_address == email_address.lower()).first()

    if user is not None:
        send_user_existing_password_reset_email(user.name, email_address)
        return jsonify(
            email_address=email_address,
            message="Email invite sent successfully"
        ), 200

    if user_type == 'seller' or user_type == 'applicant':
        if is_duplicate_user(email_address):
            return jsonify(
                email_address=email_address,
                message='An account with this email domain already exists'
            ), 409

    if user_type == 'buyer' and not has_whitelisted_email_domain(get_email_domain(email_address)):
        return jsonify(
            email_address=email_address,
            message="A buyer account must have a valid government entity email domain"
        ), 403

    user_data = {
        'name': name,
        'user_type': user_type,
        'framework': framework,
        'employment_status': employment_status
    }
    claim = user_claims_service.make_claim(type='signup', email_address=email_address, data=user_data)
    if not claim:
        return jsonify(message="There was an issue completing the signup process."), 500

    publish_tasks.user_claim.delay(
        publish_tasks.compress_user_claim(claim),
        'created'
    )

    if employment_status == 'contractor':
        try:
            send_account_activation_manager_email(
                token=claim.token,
                manager_name=line_manager_name,
                manager_email=line_manager_email,
                applicant_name=name,
                applicant_email=email_address,
                framework=framework
            )
            return jsonify(
                email_address=email_address,
                message="Email invite sent successfully"
            ), 200

        except EmailError:
            return jsonify(message='An error occured when trying to send an email'), 500

    if employment_status == 'employee' or user_type == 'seller':
        try:
            send_account_activation_email(
                token=claim.token,
                email_address=email_address,
                framework=framework
            )
            return jsonify(
                email_address=email_address,
                message="Email invite sent successfully"
            ), 200

        except EmailError:
            return jsonify(
                email_address=email_address,
                message='An error occured when trying to send an email'
            ), 500

    else:
        return jsonify(
            email_address=email_address,
            message='An error occured when trying to send an email'
        ), 400
def add_user(data):
    if data is None:
        raise DataError('create_user requires a data arg')

    name = data.get('name')
    password = data.get('password')
    role = data.get('user_type')
    email_address = data.get('email_address', None)
    framework_slug = data.get('framework', 'digital-marketplace')

    if email_address is None:
        email_address = data.get('emailAddress', None)

    if 'hashpw' in data and not data['hashpw']:
        password = password
    else:
        password = encryption.hashpw(password)

    if role == 'seller':
        role = 'applicant'

    now = datetime.utcnow()
    user = User(email_address=email_address.lower(),
                phone_number=data.get('phoneNumber', None),
                name=name,
                role=role,
                password=password,
                active=True,
                created_at=now,
                updated_at=now,
                password_changed_at=now)

    audit_data = {}

    if "supplier_code" in data and data['supplier_code']:
        user.supplier_code = data['supplier_code']
        user.role = 'supplier'
        audit_data['supplier_code'] = user.supplier_code

    if user.role == 'supplier' and user.supplier_code is None:
        raise ValueError(
            "'supplier_code' is required for users with 'supplier' role")

    if user.role != 'supplier' and user.supplier_code is not None:
        raise ValueError(
            "'supplier_code' is only valid for users with 'supplier' role, not '{}'"
            .format(user.role))

    if "application_id" in data:
        user.application_id = data['application_id']
    elif user.supplier_code is not None:
        appl = Application.query.filter_by(
            supplier_code=user.supplier_code).first()
        user.application_id = appl and appl.id or None

    if user.role == 'applicant' and user.application_id is None:
        raise ValueError(
            "'application id' is required for users with 'applicant' role")
    elif user.role != 'applicant' and user.role != 'supplier' and user.application_id is not None:
        raise ValueError(
            "'application_id' is only valid for users with applicant' or 'supplier' role, not '{}'"
            .format(user.role))

    if user.role == 'buyer':
        agency = agency_service.get_or_add_agency(
            get_email_domain(email_address))
        user.agency_id = agency.id

    db.session.add(user)
    db.session.flush()

    framework = Framework.query.filter(
        Framework.slug == framework_slug).first()
    db.session.add(UserFramework(user_id=user.id, framework_id=framework.id))

    audit = AuditEvent(audit_type=AuditTypes.create_user,
                       user=email_address.lower(),
                       data=audit_data,
                       db_object=user)

    db.session.add(audit)
    db.session.commit()

    user = db.session.query(User).options(
        noload('*')).filter(User.id == user.id).one_or_none()
    publish_tasks.user.delay(publish_tasks.compress_user(user), 'created')

    return user
Example #18
0
 def create_referral(self, service_type_price_id, requested_by, details):
     return self.create(service_type_price_id=service_type_price_id,
                        domain=get_email_domain(requested_by.email_address),
                        created_by=requested_by.id,
                        details=details)
 def __init__(self, team, current_user):
     self.team = team
     self.current_user = current_user
     self.domain = get_email_domain(current_user.email_address)
Example #20
0
def signup():
    """Signup user
    ---
    tags:
      - auth
    consumes:
      - application/json
    parameters:
      - name: body
        in: body
        required: true
        schema:
          id: SignupUser
          required:
            - name
            - email_address
            - user_type
          properties:
            name:
              type: string
            email_address:
              type: string
            user_type:
              type: string
            employment_status:
              type: string
            line_manager_name:
              type: string
            line_manager_email:
              type: string
            framework:
              type: string
    responses:
      200:
        description: User
        schema:
          $ref: '#/definitions/UserInfo'
    """
    json_payload = request.get_json()
    name = json_payload.get('name', None)
    email_address = json_payload.get('email_address', None)
    user_type = json_payload.get('user_type', None)
    employment_status = json_payload.get('employment_status', None)
    line_manager_name = json_payload.get('line_manager_name', None)
    line_manager_email = json_payload.get('line_manager_email', None)
    framework = json_payload.get('framework', 'digital-marketplace')

    user = User.query.filter(
        User.email_address == email_address.lower()).first()

    if user is not None:
        return jsonify(
            email_address=email_address,
            message="A user with the email address '{}' already exists".format(
                email_address)), 409

    if user_type == 'seller' or user_type == 'applicant':
        if is_duplicate_user(email_address):
            return jsonify(
                email_address=email_address,
                message='An account with this email domain already exists'
            ), 409

    # New ORAMS users don't need their email domain checked as that's done manually
    if framework == 'orams':
        try:
            orams_send_account_activation_admin_email(name, email_address,
                                                      framework)
            return jsonify(email_address=email_address,
                           message="Email invite sent successfully"), 200

        except EmailError:
            return jsonify(
                message='An error occured when trying to send an email'), 500

    if user_type == 'buyer' and not has_whitelisted_email_domain(
            get_email_domain(email_address)):
        return jsonify(
            email_address=email_address,
            message=
            "A buyer account must have a valid government entity email domain"
        ), 403

    if employment_status == 'contractor':
        try:
            send_account_activation_manager_email(
                manager_name=line_manager_name,
                manager_email=line_manager_email,
                applicant_name=name,
                applicant_email=email_address,
                framework=framework)
            return jsonify(email_address=email_address,
                           message="Email invite sent successfully"), 200

        except EmailError:
            return jsonify(
                message='An error occured when trying to send an email'), 500

    if employment_status == 'employee' or user_type == 'seller':
        try:
            send_account_activation_email(name=name,
                                          email_address=email_address,
                                          user_type=user_type,
                                          framework=framework)
            return jsonify(email_address=email_address,
                           message="Email invite sent successfully"), 200

        except EmailError:
            return jsonify(
                email_address=email_address,
                message='An error occured when trying to send an email'), 500

    else:
        return jsonify(
            email_address=email_address,
            message='An error occured when trying to send an email'), 400
def create_user():

    json_payload = get_json_from_request()
    json_has_required_keys(json_payload, ["users"])
    json_payload = json_payload["users"]
    validate_user_json_or_400(json_payload)
    email_address = json_payload.get('email_address', None)
    if email_address is None:
        email_address = json_payload.get('emailAddress', None)

    user = User.query.filter(
        User.email_address == email_address.lower()).first()

    if user:
        abort(409, "User already exists")

    if 'hashpw' in json_payload and not json_payload['hashpw']:
        password = json_payload['password']
    else:
        password = encryption.hashpw(json_payload['password'])

    now = datetime.utcnow()
    user = User(
        email_address=email_address.lower(),
        phone_number=json_payload.get('phoneNumber') or None,
        name=json_payload['name'],
        role=json_payload['role'],
        password=password,
        active=True,
        created_at=now,
        updated_at=now,
        password_changed_at=now
    )

    audit_data = {}

    if "supplierCode" in json_payload:
        user.supplier_code = json_payload['supplierCode']
        audit_data['supplier_code'] = user.supplier_code

    check_supplier_role(user.role, user.supplier_code)

    if "application_id" in json_payload:
        user.application_id = json_payload['application_id']
    elif user.supplier_code is not None:
        appl = Application.query.filter_by(supplier_code=user.supplier_code).first()
        user.application_id = appl and appl.id or None

    check_applicant_role(user.role, user.application_id)

    try:
        db.session.add(user)
        db.session.flush()

        audit = AuditEvent(
            audit_type=AuditTypes.create_user,
            user=email_address.lower(),
            data=audit_data,
            db_object=user
        )

        db.session.add(audit)
        db.session.commit()

        user = db.session.query(User).options(noload('*')).filter(User.id == user.id).one_or_none()
        publish_tasks.user.delay(
            publish_tasks.compress_user(user),
            'created'
        )

        if user.role == 'buyer':
            notification_message = 'Domain: {}'.format(
                get_email_domain(email_address)
            )

            notification_text = 'A new buyer has signed up'
            notify_team(notification_text, notification_message)

    except IntegrityError:
        db.session.rollback()
        abort(400, "Invalid supplier code or application id")
    except DataError:
        db.session.rollback()
        abort(400, "Invalid user role")

    return jsonify(users=user.serialize()), 201