async def get(self, request: HTTPConnection): id = request.path_params["id"] blog = await Blog.get(id) if blog is None: return abort(404, "Blog not found") if not can_edit(request): return abort(400) form = PostForm(title=blog.title, tags=blog.tags, content=blog.content) images = await encoded_existing_images(request) tags = ujson.dumps(await get_all_tags()) return templates.TemplateResponse( "blog/edit.j2", { "request": request, "form": form, "blog": blog, "existing_images": images, "existing_tags": tags, }, )
async def get(self, request: HTTPConnection): id = request.path_params["id"] writeup = await Writeup.get(id) if writeup is None: return abort(404, "Writeup not found") if not can_edit(request, writeup.author_id): return abort(400) form = WriteupForm( title=writeup.title, tags=writeup.tags, content=writeup.content, private=writeup.private, ) images = await encoded_existing_images(request) tags = orjson.dumps(await get_all_tags(True)) return templates.TemplateResponse( "writeups/edit.j2", { "request": request, "form": form, "writeup": writeup, "existing_images": images, "existing_tags": tags, }, )
async def get(self, request: HTTPConnection): id = request.path_params["id"] challenge = await Challenge.get(id) if challenge is None: return abort(404, "Challenge not found") if not can_edit(request): return abort(400) form = ChallengeForm( title=challenge.title, content=challenge.content, flag_or_answer=challenge.flag or challenge.answer, is_flag=challenge.flag is not None, hidden=challenge.hidden, depreciated=challenge.depreciated, points=challenge.points, tags=challenge.tags, ) images = await encoded_existing_images(request) tags = orjson.dumps(await get_all_tags(include_hidden=True)) return templates.TemplateResponse( "challenge/edit.j2", { "request": request, "form": form, "challenge": challenge, "existing_images": images, "existing_tags": tags, }, )
async def post(self, request: HTTPConnection): id = request.path_params["id"] blog = await Blog.get(id) if blog is None: return abort(404, "Blog not found") if not can_edit(request, blog.author_id): return abort(400) form = await request.form() form = PostForm(form) is_valid = form.validate() if not slug(form.title.data): is_valid = False form.title.errors.append( "A valid url-safe name cannot be generated for this title.") if blog.title != blog.title.data: if (await Blog.query.where( sa.or_(Blog.title == form.title.data, Blog.slug == slug(form.title.data))).gino.first() is not None): is_valid = False form.title.errors.append( f"A blog with the title '{form.title.data}' already exists." ) if is_valid: await blog.update_auto(title=form.title.data, tags=form.tags.data, content=form.content.data).apply() url = request.url_for("blog_view", slug=blog.slug) await log_edit("blog", blog.title, request.user.username, url) return redirect_response(url=url) images = await encoded_existing_images(request) tags = orjson.dumps(await get_all_tags()) return templates.TemplateResponse( "blog/edit.j2", { "request": request, "form": form, "blog": blog, "existing_images": images, "existing_tags": tags, }, )
async def delete(self, request: HTTPConnection): uuid, ext = request.path_params["file_name"] image = await Image.get(uuid) if image.filetype != ext: return abort(404) if not can_edit(request, image.author_id): return abort(400) await image.delete() return Response()
async def challenge_delete(request: HTTPConnection): id = request.path_params["id"] challenge = await Challenge.get(id) if challenge is None: return abort(404, "Challenge not found") if not can_edit(request): return abort(400) await challenge.delete() await log_delete("challenge", challenge.title, request.user.username) return redirect_response(url=request.url_for("challenge_index"))
async def blog_delete(request: HTTPConnection): id = request.path_params["id"] blog = await Blog.get(id) if blog is None: return abort(404, "Blog not found") if not can_edit(request): return abort(400) await blog.delete() await log_delete("blog", blog.name, request.user.username) return RedirectResponse(url=request.url_for("blog_index"))
async def writeups_delete(request: HTTPConnection): id = request.path_params["id"] writeup = await Writeup.get(id) if writeup is None: return abort(404, "Writeup not found") if not can_edit(request, writeup.author_id): return abort(400) await writeup.delete() await log_delete("writeup", writeup.title, request.user.username) return redirect_response(url=request.url_for("writeups_index"))
async def get(self, request: HTTPConnection): uuid, ext = request.path_params["file_name"] image = await Image.get(uuid) if image is None or image.filetype != ext: return abort(404) return Response(image.image, media_type=f"image/{image.filetype}")
async def challenge_view(request: HTTPConnection): slug = request.path_params["slug"] solves = sa.func.count(CompletedChallenge.challenge_id).label("solves") challenge = await (db.select([Challenge, solves]).select_from( Challenge.outerjoin( CompletedChallenge, (Challenge.id == CompletedChallenge.challenge_id) & (CompletedChallenge.season == CURRENT_SEASON), )).group_by(Challenge.id).where(Challenge.slug == slug).gino.load( (Challenge, ColumnLoader(solves))).first()) if challenge is None: return abort(404, "Challenge not found") challenge, solves = challenge if should_skip_challenge(challenge, request.user.is_admin): return abort(404, "Challenge not found") if request.user.is_authenticated: solved_challenge = await CompletedChallenge.query.where( (CompletedChallenge.discord_id == request.user.discord_id) & (CompletedChallenge.challenge_id == challenge.id) & (CompletedChallenge.season == CURRENT_SEASON)).gino.first() else: solved_challenge = False rendered = highlight_markdown_unsafe(challenge.content) return templates.TemplateResponse( "challenge/view.j2", { "challenge": challenge, "request": request, "rendered": rendered, "solves": solves, "submit_form": AnswerForm(), "solved_challenge": solved_challenge, }, )
async def post(self, request: HTTPConnection): id = request.path_params["id"] writeup = await Writeup.get(id) if writeup is None: return abort(404, "Writeup not found") if not can_edit(request, writeup.author_id): return abort(400) form = await request.form() form = PostForm(form) if form.validate(): await writeup.update_auto( author_id=request.user.discord_id, title=form.title.data, tags=form.tags.data, content=form.content.data, ).apply() url = request.url_for("writeups_view", slug=writeup.slug) await log_edit("writeup", writeup.title, request.user.username, url) return RedirectResponse(url=url) images = await encoded_existing_images(request) tags = ujson.dumps(await get_all_tags()) return templates.TemplateResponse( "writeups/edit.j2", { "request": request, "form": form, "writeup": writeup, "existing_images": images, "existing_tags": tags, }, )
async def get(self, request: HTTPConnection): uuid, ext = request.path_params["file_name"] image = await Image.get(uuid) if image is None or image.filetype != ext: return abort(404) headers = { "Cache-Control": "public, max-age=604800, immutable", } return Response(image.image, media_type=f"image/{image.filetype}", headers=headers)
async def blog_view(request: HTTPConnection): slug = request.path_params["slug"] blog = await Blog.query.where(Blog.slug == slug).gino.first() if blog is None: return abort(404, "Blog not found") rendered = highlight_markdown(blog.content) return templates.TemplateResponse( "blog/view.j2", {"blog": blog, "request": request, "rendered": rendered} )
async def post(self, request: HTTPConnection): id = request.path_params["id"] blog = await Blog.get(id) if blog is None: return abort(404, "Blog not found") if not can_edit(request): return abort(400) form = await request.form() form = PostForm(form) if form.validate(): await blog.update_auto( title=form.title.data, tags=form.tags.data, content=form.content.data ).apply() url = request.url_for("blog_view", slug=blog.slug) await log_edit("blog", blog.name, request.user.username, url) return RedirectResponse(url=url) images = await encoded_existing_images(request) tags = ujson.dumps(await get_all_tags()) return templates.TemplateResponse( "blog/edit.j2", { "request": request, "form": form, "blog": blog, "existing_images": images, "existing_tags": tags, }, )
async def image_upload(request: HTTPConnection): form = await request.form() file_contents = await form["file"].read() filetype = imghdr.what("dynamic", file_contents) if filetype not in {"png", "jpeg", "gif", "webp"}: return abort(400, "Bad image type") file = await Image.create( author_id=request.user.discord_id, filetype=filetype, image=file_contents ) return ORJSONResponse({"filename": f"{file.id}.{filetype}"})
async def writeups_view(request: HTTPConnection): slug = request.path_params["slug"] writeup = await Writeup.load(author=User).where(Writeup.slug == slug).gino.first() if writeup is None: return abort(404, "Writeup not found") if should_skip_writeup(writeup, request.user.is_authed): return redirect_response(url=request.url_for("need_auth")) rendered = highlight_markdown(writeup.content) return templates.TemplateResponse( "writeups/view.j2", {"writeup": writeup, "request": request, "rendered": rendered}, )
async def writeups_view(request: HTTPConnection): slug = request.path_params["slug"] writeup = await Writeup.load(author=User).where(Writeup.slug == slug ).gino.first() if writeup is None: return abort(404, "Writeup not found") rendered = highlight_markdown(writeup.content) return templates.TemplateResponse( "writeups/view.j2", { "writeup": writeup, "request": request, "rendered": rendered }, )
async def challenge_submit_answer(request: HTTPConnection): id = request.path_params["id"] form = await request.form() form = AnswerForm(form) is_valid = form.validate() answer = form.answer.data solves = sa.func.count(CompletedChallenge.challenge_id).label("solves") challenge = await (db.select([Challenge, solves]).select_from( Challenge.outerjoin( CompletedChallenge, (Challenge.id == CompletedChallenge.challenge_id) & (CompletedChallenge.season == CURRENT_SEASON), )).group_by(Challenge.id).where(Challenge.id == id).gino.load( (Challenge, ColumnLoader(solves))).first()) if challenge is None: return abort(404, "Challenge not found") challenge, solves = challenge if should_skip_challenge(challenge, request.user.is_admin): return abort(404, "Challenge not found") if (challenge.answer or challenge.flag) != answer: is_valid = False form.answer.errors.append("Incorrect answer.") # TODO? change this to a flash message if challenge.depreciated: is_valid = False form.answer.errors.append( "Correct, but this challenge is depreciated, sorry.") already_claimed = await CompletedChallenge.query.where( (CompletedChallenge.discord_id == request.user.discord_id) & (CompletedChallenge.challenge_id == challenge.id) & (CompletedChallenge.season == CURRENT_SEASON)).gino.first() if already_claimed is not None: # shouldn't see the form anyway is_valid = False form.answer.errors.append("You've already solved this challenge.") if is_valid: await CompletedChallenge.create( discord_id=request.user.discord_id, challenge_id=challenge.id, season=CURRENT_SEASON, ) return redirect_response( url=request.url_for("challenge_view", slug=challenge.slug)) rendered = highlight_markdown_unsafe(challenge.content) return templates.TemplateResponse( "challenge/view.j2", { "challenge": challenge, "request": request, "rendered": rendered, "solves": solves, "submit_form": form, }, )
async def post(self, request: HTTPConnection): id = request.path_params["id"] writeup = await Writeup.get(id) if writeup is None: return abort(404, "Writeup not found") if not can_edit(request, writeup.author_id): return abort(400) form = await request.form() form = WriteupForm(form) is_valid = form.validate() if not slug(form.title.data): is_valid = False form.title.errors.append( "A valid url-safe name cannot be generated for this title." ) if writeup.title != form.title.data: if ( await Writeup.query.where( sa.or_( Writeup.title == form.title.data, Writeup.slug == slug(form.title.data), ) ).gino.first() is not None ): is_valid = False form.title.errors.append( f"A writeup with the title conflicting with '{form.title.data}' already exists." ) if is_valid: await writeup.update_auto( title=form.title.data, tags=form.tags.data, content=form.content.data, private=form.private.data, ).apply() url = request.url_for("writeups_view", slug=writeup.slug) await log_edit("writeup", writeup.title, request.user.username, url) return redirect_response(url=url) images = await encoded_existing_images(request) tags = orjson.dumps(await get_all_tags(True)) return templates.TemplateResponse( "writeups/edit.j2", { "request": request, "form": form, "writeup": writeup, "existing_images": images, "existing_tags": tags, }, )
async def post(self, request: HTTPConnection): id = request.path_params["id"] challenge = await Challenge.get(id) if challenge is None: return abort(404, "Challenge not found") if not can_edit(request): return abort(400) form = await request.form() form = ChallengeForm(form) is_valid = form.validate() if not slug(form.title.data): is_valid = False form.title.errors.append( "A valid url-safe name cannot be generated for this title.") if challenge.title != form.title.data: if (await Challenge.query.where( sa.or_( Challenge.title == form.title.data, Challenge.slug == slug(form.title.data), )).gino.first() is not None): is_valid = False form.title.errors.append( f"A challenge with the title conflicting with '{form.title.data}' already exists." ) if is_valid: f_a = form.flag_or_answer.data flag, answer = (f_a, None) if form.is_flag.data else (None, f_a) await challenge.update_auto( title=form.title.data, content=form.content.data, flag=flag, answer=answer, hidden=form.hidden.data, depreciated=form.depreciated.data, points=form.points.data, tags=form.tags.data, ).apply() url = request.url_for("challenge_view", slug=challenge.slug) if not challenge.hidden: await log_edit("challenge", challenge.title, request.user.username, url) return redirect_response(url=url) images = await encoded_existing_images(request) tags = orjson.dumps(await get_all_tags(include_hidden=True)) return templates.TemplateResponse( "challenge/edit.j2", { "request": request, "form": form, "challenge": challenge, "existing_images": images, "existing_tags": tags, }, )