def view_course(course_name, course_year): user = User(session['user']) course = Courses().find_one(name=course_name, year=course_year, only_active=False) problems: List[Problem] = sorted(list( course.problem_db.find(disabled=(None, False))), key=problem_cat_getter) languages = Languages.db().find(disabled=(None, False)) if not user.is_admin(): problems = [p for p in problems if p.is_visible()] cat_problems = OrderedDict() for cat, items in groupby(problems, key=problem_cat_getter): cat_problems[cat] = list(items) return render_template_ext( 'view_course.njk', user=user, notifications=Mongo().load_notifications(user.id), course=course, languages=languages, has_categories=len(cat_problems) > 1, problems=problems, cat_problems=cat_problems, title=course.name, subtitle=course.year, breadcrumbs=Breadcrumbs.new(Link.CoursesBtn(), ), js_no_cache=['solution.js'])
def insert_test_values(): from database import Session from database.objects import User, Address, BlogPost, Keyword from random import randint letters = "abcdefghijklmnopqrstuvwxyz" s = Session() keyword = Keyword("firstpost") for n in range(100): name = "" for l in range(randint(4, 10)): letter = letters[randint(0, len(letters) - 1)] name += letter user = User(name=name, fullname=name, password="******") user.addresses = [ Address(email_address=("*****@*****.**" % name)), Address(email_address=("*****@*****.**" % name)), ] post = BlogPost(("%ss Blog Post" % name), "This is a test", user) post.keywords.append(Keyword(name)) post.keywords.append(keyword) s.add(post) s.commit() s.close()
def decorated_function(*args, **kwargs): from database.objects import User try: user = User(session['user']) if not user.is_admin(): raise Exception('Access denied') except: return redirect(Env.url_login) return f(*args, **kwargs)
def view_courses(): user = User(session['user']) courses = list(Courses().find(only_active=not user.is_admin())) return render_template_ext('view_courses.njk', title='Course list', user=user, notifications=Mongo().load_notifications( user.id), courses=courses)
def view_result(course_name, course_year, problem_id, _id=None): user = User(session['user']) if user.is_admin(): return redirect( url_for('admin_problem', course_name=course_name, course_year=course_year, problem_id=problem_id)) course = Courses().find_one(name=course_name, year=course_year, only_active=False) problem = course.problem_db[problem_id] results = list() result = None breadcrumbs = [Link.CoursesBtn(), Link.CourseBtn(course)] # TODO check access if _id: document = Mongo().result_by_id(_id) if document: # add to previous solution if already executed if document.result: results.append(document.peek()) else: result = document.peek() breadcrumbs.append(Link.ProblemBtn(course, problem)) if Env.use_database: for prev in Mongo().peek_last_n_results(20, user.id, course.id, problem.id): # push only valid result if prev.get('result') and str(prev['_id']) != str(_id): results.append(prev) if _id: for r in results: if str(r['_id']) == str(_id): r['active'] = 'active' results = sorted(results, reverse=True, key=lambda x: x.get('attempt')) return render_template_ext( 'results.njk', user=user, notifications=Mongo().read_notifications(user.id), results=results, result=result, requestReview=True, title='Problem %s' % problem.name, breadcrumbs=Breadcrumbs.new(*breadcrumbs), )
def login(data): crypto = SimpleCrypto(Env.secret_key()) json_data = crypto.decrypt_json(data) user = User.from_json(json_data) try: registered = User.db()[user.id] if registered: user.role = registered.role except: pass session['user'] = user.peek() return redirect('courses')
def get_db_result(_id): user = User(session['user']) result = Mongo().result_by_id(_id) output_dir = result.output_dir review = result.review if output_dir: for case in result.results: try: case_config = result.ref_problem[case.id] if case_config: case.attachments = case_config.get_attachments( user_dir=Env.root.joinpath(output_dir)) except AttributeError: logger.exception('attachments') pass if review: for line, comments in review.items(): for i, c in enumerate(comments): comments[i]['text'] = markdown.markdown(c['text']) mark_as_read = Mongo().mark_as_read(to=user.id, _id=_id, event='new-comment') logger.info('mark-as-read: {}', mark_as_read) return flask.json.dumps(result)
def read_notifications(): user = User(session['user']) data = request.json return flask.json.dumps( dict(notifications=Mongo().read_notifications(user.id, n_id=data['_id'])))
def process_solution(course_name, course_year): user = User(session['user']) try: course = Courses().find_one(name=course_name, year=course_year, only_active=False) problem = course.problem_db[request.form['prob-id']] lang = Languages.db()[request.form['lang-id']] solution = request.form['src'] use_docker = request.form.get('use-docker', 'off') == 'on' test_result = crates.TestResult( user=user.id, problem=problem.id, lang=lang.id, course=course.id, docker=use_docker, solution=solution, action='solve', ) # save to the db and redirect with _id insert_result = Mongo().save_result(test_result.peek()) return redirect( url_for('view_result', course_name=course.name, course_year=course.year, problem_id=problem.id, _id=str(insert_result.inserted_id))) except: logger.exception('Could not parse data')
def perma_result(_id): user = User(session['user']) document = Mongo().result_by_id(_id) course = document.ref_course problem = document.ref_problem breadcrumbs = [ Link.CoursesBtn(), Link.CourseBtn(course), Link.ProblemBtn(course, problem) ] return render_template_ext( 'view_result.njk', user=user, notifications=Mongo().load_notifications(user.id), results=[document], result=None, requestReview=False, title='Problem %s' % problem.name, breadcrumbs=Breadcrumbs.new(*breadcrumbs), js=[ '//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js', '/static/js/lib/highlightjs-line-numbers.js' ], js_no_cache=['sockets.js', 'process.js'])
def request_review(): user = User(session['user']) data = request.json _id = data['_id'] document = Mongo().result_by_id(_id) from_user = document.user or user.id # request_dt = document.review_request # type: datetime # if request_dt: # return flask.json.dumps( # dict(result='warning', message=f'Request was already sent on {request_dt:%Y-%m-%d %H:%M:%S}') # ) # notify all teachers reviewers = list() for reviewer_obj in document.ref_course.teachers: if type(reviewer_obj) is dict: reviewer = str(reviewer_obj.get('id', reviewer_obj)) else: reviewer = reviewer_obj event_document = { 'from': from_user, 'to': reviewer, 'course': document.course, 'problem': document.problem, 'document': _id, 'event': 'codereview', 'title': f'Code review requested by {from_user}', 'description': f'Student {from_user} has requested code review for the problem {document.ref_problem.id}' } if Mongo().add_notification(event_document): logger.info(f'add-notification: {event_document}') reviewers.append(reviewer) else: logger.warning( f'notification already exists: {event_document}') Mongo().update_fields(_id, review_request=datetime.datetime.now()) if reviewers: return flask.json.dumps(dict(result='ok', reviewers=reviewers)) else: return flask.json.dumps( dict(result='warning', message='Request was already sent'))
def _process_solution_by_id(_id, rerun=False): document = Mongo().result_by_id(_id) if document.result is None or rerun: _process_solution( User(dict(id=document.user)), document.action, not document.docker, document.problem, document.course, document.lang, document.solution, document._id )
def student_process_solution(data): print(data) user = User(session['user']) try: document = Mongo().result_by_id(data['_id']) _process_solution( user=user, action=document.action, skip_docker=not document.docker, problem_id=document.problem, course_id=document.course, lang_id=document.lang, src=document.solution, _id=data['_id'], ) except: logger.exception('Error while processing solution')
def view_course(course_name, course_year): user = User(session['user']) course = Courses().find_one(name=course_name, year=course_year, only_active=False) problems = list(course.problem_db.find(disabled=(None, False))) languages = Languages.db().find(disabled=(None, False)) return render_template_ext( 'submit.njk', user=user, notifications=Mongo().read_notifications(user.id), course=course, languages=languages, problems=problems, title=course.name, subtitle=course.year, breadcrumbs=Breadcrumbs.new(Link.CoursesBtn(), ), )
def admin_problem(course_name, course_year, problem_id): user = User(session['user']) course = Courses().find_one(name=course_name, year=course_year, only_active=False) problems_ids = ','.join([x.id for x in list(course.problem_db.find())]) problem = course.problem_db[problem_id] languages = Languages.db().find(disabled=(None, False)) return render_template_ext( 'problem.njk', user=user, notifications=Mongo().read_notifications(user.id), course=course, languages=languages, problem=problem, problems_ids=problems_ids, title='Manage problem %s' % problem.name, breadcrumbs=Breadcrumbs.new(Link.CoursesBtn(), Link.CourseBtn(course)), )
def perma_result(_id): user = User(session['user']) document = Mongo().result_by_id(_id) course = document.ref_course problem = document.ref_problem breadcrumbs = [ Link.CoursesBtn(), Link.CourseBtn(course), Link.ProblemBtn(course, problem) ] return render_template_ext( 'results.njk', user=user, notifications=Mongo().read_notifications(user.id), results=[document], result=None, requestReview=False, title='Problem %s' % problem.name, breadcrumbs=Breadcrumbs.new(*breadcrumbs), )
] root = pathlib.Path(__file__).resolve() files = root.parent.parent / 'files' _course_name = 'course-template' _course_config = files / 'TST.config.yaml' _solution = dict( solution_correct=files / 'problem-1-correct.py', solution_wrong=files / 'problem-1-wrong.py', solution_timeout=files / 'problem-1-timeout.py', solution_fatal=files / 'problem-1-fatal.py', ) user_root = User(dict( id='root', role='test', )) request_base = dict( user=user_root, lang='PY-367', course='TST-2019', problem='problem-1', ) solve_request_base = dict(type=ProcessRequestType.SOLVE, **request_base) generate_input_request_base = dict(type=ProcessRequestType.GENERATE_INPUT, **request_base) generate_output_request_base = dict(type=ProcessRequestType.GENERATE_OUTPUT, **request_base)
def backdoor_login(role, id=None): session['user'] = User(dict(id=id, role=role, affi='debug')) return redirect(url_for('view_courses'))
def create_user_if_not_exist(session, user): ex = session.query(exists().where(User.name == user)).scalar() if not ex: new_user = User(name=user, password='') session.add(new_user) session.commit()
config.db_password) print(connection_string) engine = create_engine(connection_string, echo=True) DBObjectBase.metadata.create_all(engine) Session = sessionmaker(bind=engine) session = Session() for replay in glob.glob(os.path.join('replays', '*.gz')): base = os.path.basename(replay) uuid = base.split('_')[-1].split('.')[0] ip = base.split('_')[0] user = -1 print(uuid, ip, user) if not session.query(exists().where(User.id == -1)).scalar(): u = User(id=-1, name='Undefined', password='') session.add(u) session.commit() if not session.query(exists().where(Model.model_hash == '0')).scalar(): u = Model(model_hash='0') session.add(u) session.commit() if not session.query(exists().where(Replay.uuid == uuid)).scalar(): r = Replay(uuid=uuid, ip=ip, user=user, model_hash='0', num_team0=1, num_players=1, is_eval=False)
def student_submit_solution(data): print(data) user = User(session['user']) try: type = str(data['type']) action = ProcessRequestType(type) skip_docker = not data.get('docker', True) except: Emittor.error('Unsupported action', [ 'Given action is not supported:', ' %s' % data['type'], '', 'Please contact [email protected]', 'if you think this is a mistake.' ]) return if not user.is_admin() and (skip_docker or action in (ProcessRequestType.GENERATE_INPUT, ProcessRequestType.GENERATE_OUTPUT)): Emittor.error('Operation not permitted', [ 'You do not have sufficient privileges to perform action:', ' %s (skip docker: %s)' % (action, skip_docker), '', 'Please contact [email protected]', 'if you want to gain the privileges.' ]) return request = processing.request.ProcessRequest( user=user, lang=data['lang'], problem=data['prob'], course=data['course'], solution=data['src'], type=action, docker=False if (skip_docker and user.is_admin()) else True, ) mongo.save_log(request.get_log_dict()) # ignore problems which are past due if request.problem.time_left < 0: return Emittor.register_events(request) Emittor.queue_status(queue_status()) time.sleep(0.1) queue.append(request) Emittor.queue_push(request) time.sleep(0.1) # put a barrier here so only certain amount fo users can process code at once # while other will see queue list with thread_lock: try: request.process() except ConfigurationException as e: if user.is_admin(): logger.exception('[visible to admin only] invalid yaml config') Emittor.exception(e) except Exception as e: logger.exception('process error:') Emittor.exception(e) finally: mongo.save_result(request.get_result_dict()) request.save_result() request.destroy() queue.remove(request) Emittor.queue_pop(request)
def add_comment(): data = request.json user = User(session['user']) # course = Courses()[data['course']] # problem = course.problem_db[data['problem']] # attempt = data['attempt'] _id = data['_id'] document = Mongo().result_by_id(_id) review = document.review or dict() now = time.time() from_user = user.id author_user = document.user for comment in data['comments']: line, text = str(comment['line']), comment['comment'] review_line = review[line] if line in review else list() review_line.append(dict( user=user.id, time=now, text=text, )) review[line] = review_line recipients = {from_user, author_user} for cmts in review.values(): for cmt in cmts: recipients.add(cmt['user']) for recipient in recipients: if recipient == from_user: logger.info('Not creating notification for self') else: event_document = { 'from': from_user, 'to': recipient, 'course': document.course, 'problem': document.problem, 'document': _id, 'event': 'new-comment', 'title': f'New comment from {from_user}', 'description': f'{document.ref_problem.id} User {from_user} commented your code in problem ' } if Mongo().add_notification(event_document): logger.info('add-notification: {}', event_document) else: logger.warning('notification already exists: {}', event_document) mark_as_read = Mongo().mark_as_read(_id=_id, event='codereview', to=None) logger.info('mark-as-read: {}', mark_as_read) update_one = Mongo().update_fields(_id, review=review) logger.info('document-updated: {}', update_one) return flask.json.dumps(dict(result='ok'))
def load_notifications(): user = User(session['user']) return flask.json.dumps( dict(notifications=Mongo().load_notifications(user.id).peek(), ))
def admin_switch_role(role, id=None): user = User(session['user']) session['user'] = User(dict(id=id or user.id, role=role, affi='debug')) return redirect('courses')
def view_result(course_name, course_year, problem_id, _id=None): user = User(session['user']) if user.is_admin(): return redirect( url_for('admin_problem', course_name=course_name, course_year=course_year, problem_id=problem_id)) course = Courses().find_one(name=course_name, year=course_year, only_active=False) problem = course.problem_db[problem_id] results = list() result = None breadcrumbs = [Link.CoursesBtn(), Link.CourseBtn(course)] # TODO check access if _id: document = Mongo().result_by_id(_id) if document: # add to previous solution if already executed if document.result: results.append(document) else: result = document breadcrumbs.append(Link.ProblemBtn(course, problem)) if Env.use_database: for prev in Mongo().peek_last_n_results(10, user.id, course.id, problem.id): # push only valid result if prev.result and str(prev._id) != str(_id): results.append(prev) if _id: for r in results: if str(r._id) == str(_id): r.active = 'active' def get_attempt(obj): try: return int(obj.attempt) except: return 0 results = sorted(results, reverse=True, key=get_attempt) return render_template_ext( 'view_result.njk', user=user, notifications=Mongo().load_notifications(user.id), results=results, result=result, requestReview=True, title='Problem %s' % problem.name, breadcrumbs=Breadcrumbs.new(*breadcrumbs), js=[ '//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js', '/static/js/lib/highlightjs-line-numbers.js' ], js_no_cache=['sockets.js', 'process.js'])