예제 #1
0
def create_invites():
    recipient = request.json['recipient']
    sender = request.json['sender']
    recipient_user = User.get_user(recipient)
    recipient_invite = None
    if len(Invite.query.filter_by(email = recipient).all()) > 0:
        recipient_invite = Invite.query.filter_by(email = recipient).one()
    sender_user = User.get_user(sender)
    # issue #120
    # To ensure no duplicate invitation is allowed, and to ensure
    # we don't corrupt user record in user table, any POST invitation
    # must check
    # (1) if user is not created in users collection - FALSE
    # (2) if user is created, BUT status is not 'invited' - FALSE
    # (3) recipient email is found in existing invitation record - FALSE
    if not recipient_user:
        return jsonify(success=False, 
                reason='recipient-not-found-in-user-record')
    elif recipient_user.get('status') != 'invited':
        return jsonify(success=False, 
                reason='recipient-already-joined')
    if recipient_invite:
        return jsonify(success=False,
                reason='duplicate-invitation-not-allowed')
    if not sender_user:
        return jsonify(success=False,
                reason='sender-not-found-in-user-record')

    invite = Invite(recipient, )

    invite_id = str(uuid.uuid4())
    # some users may not have name filled out?
    invite = {'id': invite_id,
              'recipient': recipient,
              'recipient_name': recipient_user['name'] or recipient,
              'sender': sender,
              'sender_name': sender_user['name'] or sender,
              'sent_on': None,
              'accepted_on': None,
              'status': 'pending',
              'expire_on': None,
              'max_time_allowed': request.json.get('max_time_allowed') \
                      or backend_config.get('email').get('max_time_allowed'),
              'notify_when': request.json.get('notify_when', [])}
    send_email('invite', invite, extra_data={'base_url': request.json['base_url']})
     
    invite['sent_on'] = datetime.datetime.utcnow()
    invite['expire_on'] = invite['sent_on'] + \
        datetime.timedelta(seconds=invite['max_time_allowed'])
    invites.insert(invite)
    return jsonify(success=True, invite=sanitize_invite(invite))
예제 #2
0
def get_reports_history():
    history = []
    user_email = request.args.get('user')
    scans = []
    if user_email is not None:
        user = User.get_user(user_email)
        if user is None:
            return jsonify(success=False, reason='no-such-user')

        
        # Get Sites
        for site in user.sites():
            for scan in Site.get_site_by_url(site).scans:
                scans.append(scan)

        scans.sort(key=lambda x : x.created, reverse = True)
        # Get Scans for Sites
    else:
        for site in Site.query.all():
            for scan in site.scans:
                scans.append(scan)

    for s in scans[:100]:
            history.append(summarize_scan(s))
    return jsonify(success=True, report=history)
예제 #3
0
def get_reports_sites():
    result = []
    group_name = request.args.get('group_name')
    user_email = request.args.get('user')

    if user_email is not None:
        # User specified, so return recent scans for each site/plan that the user can see
        user = User.get_user(user_email)
        if user is None:
            return jsonify(success=False, reason='no-such-user')
        if group_name:
            group = Group.get_group(group_name)
            if group is None:
                return jsonify(success=False, reason='no-such-group')

            site_list = map(lambda x: x.url, group.sites)
        else:
            site_list = user.sites()
        for site_url in sorted(site_list):
            site = Site.get_site_by_url(site_url)
            if site is not None:
                for plan in site.plans:
                    plan_name = plan.name
                    schedule = ScanSchedule.get_schedule(site.site_uuid, plan.plan_uuid)

                    crontab = None
                    scheduleEnabled = False
                    if schedule is not None:
                        crontab = schedule['crontab']
                        scheduleEnabled = schedule['enabled']

                    scans = []
                    for scan in site.scans:
                        if scan.plan is not None:
                            p = json.loads(scan.plan)
                            if p['name'] == plan_name:
                                scans.append(scan)                    

                    scan_for_site = []
                    for scan in scans:
                        config = json.loads(scan.configuration)
                        
                        if config.get('target', None) == site_url:
                            scan_for_site.append(scan)


                    o = list(sorted(scan_for_site, cmp= lambda x, y: cmp(x.created, y, created)))
                    if len(o):
                     l = [o[0]]
                    else:
                     l = []         
                    
                    if len(l) == 1:
                        scan = summarize_scan(l[0])
                        s = {v: scan.get(v) for v in ('id', 'created', 'state', 'issues')}
                        result.append({'target': site_url, 'plan': plan_name, 'scan': scan, 'crontab': crontab, 'scheduleEnabled': scheduleEnabled})
                    else:
                        result.append({'target': site_url, 'plan': plan_name, 'scan': None, 'crontab': crontab, 'scheduleEnabled': scheduleEnabled})
    return jsonify(success=True, report=result)
예제 #4
0
def get_reports_issues():
    result = []
    group_name = request.args.get('group_name')
    user_email = request.args.get('user')
    if user_email is not None:
        # User specified, so return recent scans for each site/plan that the user can see
        user = User.get_user(user_email)
        if user is None:
            return jsonify(success=False, reason='no-such-user')
        site_list = []
        if group_name:
            # get list of sites for group

            site_list = _find_sites_for_user_by_group_name(user_email, group_name)
            
            g = Group.get_group(group_name)
            if g:
                for site in g.sites:
                    site_list.append(site.url)


        else:
            site_list = User.get_user(user_email).sites()


        for site_url in sorted(site_list):
            r = {'target': site_url, 'issues': []}
            site = Site.get_site_by_url(site_url)
            if site is not None:
                scan_list = []
                for scan in site.scans:
                    scan_list.append(scan)

                if len(scan_list) > 0:
                    scan_list.sort(key=lambda x : x.created, reverse=True)
                    s = scan_list[0]
                    for session in s.sessions:
                            for issue in session.issues:
                                r['issues'].append({'severity': issue.severity,
                                                    'summary': issue.summary,
                                                    'scan': { 'id': s.scan_uuid},
                                                    'id': issue.issue_uuid})    

                
            result.append(r)
    return jsonify(success=True, report=result)
예제 #5
0
def create_group():
    group = request.json


    # perform validations on incoming data; issue#132
    if not group.get('name'):
        return jsonify(success=False, reason='name-field-is-required')

    userz = group.get('users', [])
    sitez = group.get('sites', [])

    if userz:
        for user in userz:
            if not User.get_user(user):
                return jsonify(success=False, reason='user %s does not exist'%user)
    if sitez:
        for site in sitez:
            if not Site.get_site_by_url(site):
                return jsonify(success=False, reason='site %s does not exist'%site)

    if Group.get_group(group['name']) is not None:
        return jsonify(success=False, reason='group-already-exists')

    # post-validation
    # XXX - this is a horrible hack, we should grab the default admin user / admin group instead, not just use the first user/group in the list!!!!
    admin_user = User.query.all()[0]
    admin_group = None
    if len(Group.query.all()) > 0:
        admin_group = Group.query.all()[0]
    new_group = Group(group['name'], admin_user.email, admin_group)
    new_group.created = datetime.datetime.utcnow()
    new_group.description = group.get('description', "")

    db.session.add(new_group)
    
    for user in userz:
        new_group.users.append(User.get_user(user))
        

    for site in sitez:
        new_group.sites.append(Site.get_site_by_url(site))

    db.session.commit()

    new_group = Group.get_group(group['name'])
    return jsonify(success=True, group=sanitize_group(new_group))
예제 #6
0
def delete_user(user_email):
    user = User.get_user(user_email)
    if not user:
        return jsonify(success=False, reason='no-such-user')
    # Remove the user
    db.session.delete(user)
    db.session.commit()
    return jsonify(success=True)
예제 #7
0
def update_user(user_email):
    new_user = request.json
    # Verify the incoming user: user must exist, groups must exist, role must exist

    old_user = User.get_user(user_email)
    if old_user is None:
        return jsonify(success=False, reason='unknown-user')

    if 'groups' in new_user:
        for group_name in new_user.get('groups', []):
            if not Group.get_group(group_name):
                return jsonify(success=False, reason='unknown-group')
    if 'role' in new_user:
        if new_user["role"] not in ("user", "administrator"):
            return jsonify(success=False, reason="invalid-role")
    if 'status' in new_user:
        if new_user['status'] not in ('active', 'banned'):
            return jsonify(success=False, reason='unknown-status-option')

    # Update the group memberships
    if 'groups' in new_user:
        #clear all groups
        for group in old_user.groups:
            old_user.groups.remove(group)
        #add new groups
        for group in new_user.get('groups', []):
            old_user.groups.append(Group.get_group(group))
    
    # Modify the user
    changes = {}
    if 'name' in new_user:
        old_user.name = new_user['name']
    if 'role' in new_user:
        old_user.role = new_user['role']
        
    if 'status' in new_user:
        old_user.status = new_user['status']

    db.session.commit()
    
    # Return the updated user
    user = User.get_user(user_email)
    if not user:
        return jsonify(success=False, reason='unknown-user')
    return jsonify(success=True, user=sanitize_user(user))
예제 #8
0
def get_plans_by_email(email):
    user = User.get_user(email)
    plans_by_site = map(lambda x:Site.get_site_by_url(x).plans, user.sites())
    plans = []
    for planlist in plans_by_site:
        for plan in planlist:
            if not plan in plans:
                plans.append(plan)
    return map(lambda x : x.dict(), plans)
예제 #9
0
def _find_sites_for_user_by_group_name(email, group_name):
    """ Find all sites that user has access to in a
    given group. """
    group = Group.get_group(group_name)
    user = User.get_user(email)
    if not user or not group:
        return []
    if not user in group.users:
        return []
    return map(lambda x: x.url, group.sites)
예제 #10
0
def patch_group(group_name):

    patch = request.json

    group = Group.get_group(group_name)
    
    if not group:
        return jsonify(success=False, reason='no-such-group')

    # Process the edits. These can probably be done in one operation.

    for url in patch.get('addSites', []):
        site = Site.get_site_by_url(url)
        if not site:
            return jsonoify(success = false, reason='no-such-site')
        if not site in group.sites:
            group.sites.append(site)

    for url in patch.get('removeSites', []):
        site = Site.get_site_by_url(url)
        if not site:
            return jsonoify(success = false, reason='no-such-site')
        if site in group.sites:
            group.sites.remove(site)
    
    for email in patch.get('addUsers', []):
        user = User.get_user(email)
        if not user:
            return jsonoify(success = false, reason='no-such-user')
        if not user in group.users:
            group.users.append(user)

    for user in patch.get('removeUsers', []):
        user = User.get_user(email)
        if not user:
            return jsonoify(success = false, reason='no-such-user')
        if user in group.users:
            group.users.remove(user)

    db.session.commit()
    group = Group.get_group(group_name)
    return jsonify(success=True, group=sanitize_group(group))
예제 #11
0
 def has_permission(*args, **kwargs):
     email = request.args.get('email')
     if email:
         user = User.get_user(email)
         if not user:
             return jsonify(success=False, reason='User does not exist.')
         if user.role == 'user':
             plan_name = request.view_args['plan_name']
             if not _check_plan_by_email(email, plan_name):
                 return jsonify(success=False, reason="Plan does not exist.")
     return view(*args, **kwargs) # if groupz.count is not zero, or user is admin
예제 #12
0
def create_user():
    user = request.json
    # Verify incoming user: email must not exist yet, groups must exist, role must exist
    if User.get_user(user["email"]) is not None:
        return jsonify(success=False, reason='user-already-exists')

    for group_name in user.get('groups', []):
        if not Group.get_group(group_name):
            return jsonify(success=False, reason='unknown-group')

    if user.get("role") not in ("user", "administrator"):
        return jsonify(success=False, reason="invalid-role")

    new_user = User(user.get('name'), user['email'])
    new_user.created = datetime.datetime.utcnow()
    new_user.status = 'invited' if user.get('invitation') else 'active'
    new_user.role = user['role']
    new_user.last_login = None
    api_key = str(uuid.uuid4())

    db.session.add(new_user)
    db.session.commit()

    for group_name in user.get('groups', []):
        new_user.groups.append(Group.get_group(group_name))

    db.session.commit()
    return jsonify(success=True, user=sanitize_user(new_user))
예제 #13
0
def login_user():
    email = request.json['email']
    user = User.get_user(email)
    if user:
        if user.status == 'active':
            timestamp = datetime.datetime.utcnow()
            user.last_login = timestamp
            db.session.commit()
            return jsonify(success=True, user=sanitize_user(user))
        else:
            return jsonify(success=False, reason=user.status)
    else:
        return jsonify(success=False, reason='user-does-not-exist')
예제 #14
0
def delete_invite(id):
    invitation = Invite.get_invite(id)
    if not invitation:
        return jsonify(success=False, reason='no-such-invitation')
    # do not delete users that are not invite pending (bug #123)
    email = invitation['recipient']
    user = User.get_user(email)
    if user and user.get('status') == "invited":
        db.session.remove(user)
        db.session.commit()    
        
    invites.remove({'id': id})
    return jsonify(success=True)
예제 #15
0
    def has_permission(*args, **kwargs):
        email = request.args.get('email')

        # If the task is scheduled by crontab, proceed with the task
        if email == 'cron':
            return view(*args, **kwargs)

        if email:
            user = User.get_user(email)
            if not user:
                return jsonify(success=False, reason='user-does-not-exist')
            scan = Scan.get_scan(kwargs['scan_id'])
            if user.role == 'user':
                # XX really, really fix the Scan :: Site association, but for compat we will do the json dance

                if not Scan.site in user.sites:
                    return jsonify(success=False, reason='not-found')

        return view(*args, **kwargs) # if groupz.count is not zero, or user is admin
예제 #16
0
def update_invite(id):
    timenow = datetime.datetime.utcnow()
    action = request.json['action'].lower()
    
    invitation = Invite.get_invite(id)
    if invitation:
        max_time_allowed = invitation.get('max_time_allowed') \
            or backend_config.get('invitation').get('max_time_allowed')
        recipient = invitation['recipient']
        recipient_name = invitation['recipient_name']
        sender = invitation['sender']
        sender_name = invitation['sender_name']
        sent_on = invitation['sent_on']
        accepted_on = invitation['accepted_on']
        expire_on = invitation['expire_on']

        user = User.get_user(recipient)
        if user is None:
            return jsonify(success=False, reason="user-not-created")
        if accepted_on is not None:
            return jsonify(success=False, reason="invitation-has-been-used")
        if not action in ('resend', 'accept', 'decline'):
            return jsonify(success=False, reason='invalid-action')

        if action == 'resend':
            new_id = str(uuid.uuid4())
            base_url = request.json['base_url']
            send_email('invite', invitation, extra_data={'base_url': base_url})
            # generate new record
            sent_on = datetime.datetime.utcnow()
            expire_on = sent_on + datetime.timedelta(seconds=max_time_allowed)
            invitation['id'] = new_id
            invitation['sent_on'] = sent_on
            invitation['expire_on'] = expire_on
            invites.update({'id': id}, {'$set': 
                {'sent_on': invitation['sent_on'],
                 'id': invitation['id']}})
            return jsonify(success=True, invite=sanitize_invite(invitation))
        elif action == 'accept':
            # if time now is ahead of expire_on, the delta is negative
            if (expire_on - timenow).seconds < 0:
                invitation['status'] = 'expired'
                invites.update({'id': id}, {'$set': {'status': 'expired'}})
                return jsonify(success=False, reason='invitation-expired')
            else:
                invitation['status'] = 'used'
                invitation['accepted_on'] = datetime.datetime.utcnow()
                invites.update({'id': id},{'$set': 
                    {'accepted_on': invitation['accepted_on'],
                     'status': 'used'}})
                user = User.get_user(recipient)
                user.status = 'active'
                user.email = request.json['login']
                db.session.commit()
                # if user's persona email is different
                invitation['recipient'] = request.json['login']
                # notify inviter if he chooses to receive such notification
                if "accept" in invitation['notify_when']:
                    send_email('accept', invitation)
                return jsonify(success=True, invite=sanitize_invite(invitation))
        elif action == 'decline':
            invitation['status'] = 'declined'
            invites.update({'id': id}, {'$set': {'status': 'declined'}})
            db.session.remove(user)
            db.commit()
            # notify inviter if he chooses to
            if "decline" in invitation['notify_when']:
                send_email('decline', invitation)
            return jsonify(success=True, invite=sanitize_invite(invitation))
    else:
        return jsonify(success=False, reason='invitation-does-not-exist')
예제 #17
0
def get_user(email):
    email = email.lower()
    user = User.get_user(email)
    if not user:
        return jsonify(success=False, reason='no-such-user')
    return jsonify(success=True, user=sanitize_user(user))