def session_events(session, user=None): """ :type session: Session :type user: User """ if request.method == 'GET': session = Session.objects.with_id(session) if isinstance(session.range, RelativeRange): DataModelEvent.objects(sessions=session, time__lt=session.range.start_time).update(pull__sessions=session) return DataModelEvent.objects(sessions=session).order_by('time'), HTTPStatus.OK
def query_session(session, user=None): """ :type session: Session :type user: User """ session_id = session session = Session.objects.with_id(session) if request.method == 'GET': if session: return session, HTTPStatus.OK return None, HTTPStatus.NOT_FOUND elif request.method == 'PUT': # Create a new session if it doesn't exist if not session: session = Session(id=session_id) http_status = HTTPStatus.CREATED else: http_status = HTTPStatus.OK try: session.update(**request.json) session.validate() except mongoengine.ValidationError: return {'error': 'schema validation error'}, HTTPStatus.BAD_REQUEST session.save() return None, http_status elif request.method == 'POST': if 'reset' in request.args: DataModelEvent.objects(sessions=session).update(pull__sessions=session) AnalyticResult.objects(session=session).delete() Job.objects(session=session).delete() # Remove the session state session.update(state=SessionState()) # Is this the right http error code? return None, HTTPStatus.RESET_CONTENT elif 'refresh' in request.args: for analytic_state in session.state.analytics: job = AnalyticJob.update_existing(analytic=analytic_state.analytic, mode=analytic_state.mode, user=user, session=session) job.submit() return None, HTTPStatus.RESET_CONTENT # TODO: Implement elif request.method == 'DELETE': DataModelEvent.objects(sessions=session).update(pull__sessions=session) AnalyticResult.objects(session=session).delete() Job.objects(session=session).delete() session.delete() return None, HTTPStatus.NO_CONTENT
def get_clusters(self): events = list(DataModelEvent.objects(sessions=self).no_dereference()) results = list(AnalyticResult.objects(session=self).no_dereference()) event_keys = set(_.id for _ in events) def get_neighbors(node): neighbors = [] if isinstance(node, AnalyticResult): neighbors.extend(event for event in node.events if event.id in event_keys) elif isinstance(node, DataModelEvent): # TODO: Error check to handle for events outside of current session neighbors.extend(event for event in node.links if event.id in event_keys) neighbors.extend(event for event in node.reverse_links if event.id in event_keys) return neighbors uptree = DisjointSet(events + results, get_neighbors) clusters = [] for cluster in uptree.clusters(): new_cluster = {'events': [], 'results': []} for item in cluster: if isinstance(item, AnalyticResult): new_cluster['results'].append(item) elif isinstance(item, DataModelEvent): new_cluster['events'].append(item) clusters.append(new_cluster) return clusters
def query_events(user=None): """ :type user: User """ filter = {} if request.args.get('session'): session = Session.objects.with_id(request.args.get('session')) if not session: return None, HTTPStatus.NOT_FOUND filter['sessions'] = session return DataModelEvent.objects(**filter), HTTPStatus.OK
def all_sessions(user=None): """ :type user: User """ if request.method == 'GET': query = {} if 'name' in request.args: query['name'] = request.args['name'] sessions = Session.objects(**query).order_by('name') return sessions, HTTPStatus.OK elif request.method == 'POST': if 'clone' in request.args: original = Session.objects.with_id(request.args.get('clone')) original_id = original.id if original is None: return {'error': 'source session could not be found'}, HTTPStatus.BAD_REQUEST session = original session.id = None session.name = request.json['name'] session.save(validate=True) # Clone over all of the data model events DataModelEvent.objects(sessions=original_id).update(add_to_set__sessions=session.id) for result in AnalyticResult.objects(session=original_id): result.id = None result.session = session result.uuid = result.get_uuid() result.save() else: info = request.json if info.get('range') is not None and info.get('name') is not None: time_range = DateRange.get_range(info['range']) session = Session(range=time_range, name=info['name']) session.save(validate=True) return session.id, HTTPStatus.OK
def export_session(session, user=None): session = Session.objects.with_id(session) if not isinstance(session, Session): return None, HTTPStatus.NOT_FOUND events = DataModelEvent.objects(sessions=session) results = AnalyticResult.objects(session=session) dump = [ {'collection': 'data_model_event', 'content': events}, {'collection': 'analytic_result', 'content': results}, {'collection': 'session', 'content': [session]} ] return dump, HTTPStatus.OK
def query_session_hosts(session, user=None): """ :type session: Session :type user: User """ session = Session.objects.with_id(session) if not session: return None, HTTPStatus.NOT_FOUND host_ids = set() for event in DataModelEvent.objects(sessions=session): event.update_host() if event.host: host_ids.add(event.host.id) host_list = [Host.objects.with_id(_) for _ in host_ids] return host_list, HTTPStatus.OK
def alert_graph(session, user=None): """ :type session: Session :type user: User """ if request.method == 'GET': session = Session.objects.with_id(session) if not session: return None, HTTPStatus.NOT_FOUND # Avoid too many database lookups events = {e.id: e for e in DataModelEvent.objects(sessions=session)} results = list(AnalyticResult.objects(session=session)) edges = set() result_lookup = defaultdict(list) for result in results: for event in result.events: result_lookup[event.id].append(result.id) def descendant_analytics(_event): children = [] for child_event in _event.links: # Stop once I hit an analytic if child_event.id in result_lookup: children.extend(result_lookup[child_event.id]) elif child_event.id in events: children.extend(descendant_analytics(events[child_event.id])) return children for i, result in enumerate(results): for event in result.events: for similar_result in result_lookup[event.id]: if similar_result is not result: pass if event.id in events: for edge in descendant_analytics(events[event.id]): if edge != result.id: edges.add((result.id, edge)) return {'nodes': results, 'edges': list(edges)}, HTTPStatus.OK