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))
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)
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)
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)
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))
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)
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))
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)
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)
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))
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
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))
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')
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)
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
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')
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))