mirror of https://github.com/EasyCTF/librectf
more frontend
This commit is contained in:
parent
29fd690ad7
commit
95c71b68b2
|
@ -281,6 +281,20 @@ impl UsefulFunctions<sqlite::Sqlite> for sqlite::SqlitePooledConnection {
|
|||
}
|
||||
|
||||
impl DbConn {
|
||||
/// Tries to fetch the user with the given id.
|
||||
pub fn fetch_user_id(&self, id: i32) -> Result<User, Error> {
|
||||
use crate::schema::users::dsl;
|
||||
let query = dsl::users.filter(dsl::id.eq(id));
|
||||
match self {
|
||||
#[cfg(feature = "mysql")]
|
||||
DbConn::Mysql(conn) => query.first(conn),
|
||||
#[cfg(feature = "postgres")]
|
||||
DbConn::Postgres(conn) => query.first(conn),
|
||||
#[cfg(feature = "sqlite")]
|
||||
DbConn::Sqlite(conn) => query.first(conn),
|
||||
}
|
||||
.map_err(Error::from)
|
||||
}
|
||||
/// Tries to fetch the user with the given email. (TODO: lookup by username)
|
||||
pub fn fetch_user(&self, email: impl AsRef<str>) -> Result<User, Error> {
|
||||
use crate::schema::users::dsl;
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use tera::Context;
|
||||
use warp::Filter;
|
||||
|
||||
use crate::extractors::{get_context, navbar, Context};
|
||||
use crate::render::render_template;
|
||||
|
||||
pub fn get_index() -> Resp!() {
|
||||
warp::path::end().and_then(|| render_template("base/index.html", Context::new()))
|
||||
warp::path::end()
|
||||
.and(navbar())
|
||||
.and(get_context())
|
||||
.and_then(|ctx: Context| render_template("base/index.html", ctx.into()))
|
||||
}
|
||||
|
|
|
@ -1,20 +1,60 @@
|
|||
use core::State;
|
||||
use core::{Error, State};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use tera::Context as TeraContext;
|
||||
use warp::{Filter, Rejection};
|
||||
|
||||
use crate::session::Session;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Context(::tera::Context);
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Context(pub TeraContext);
|
||||
|
||||
fn get_context() -> impl Clone + Filter<Extract = (Context,), Error = Rejection> {
|
||||
warp::ext::get::<State>()
|
||||
.and(warp::ext::get::<Session>())
|
||||
.map(|state, session| Context::default())
|
||||
impl Deref for Context {
|
||||
type Target = TeraContext;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Context {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<TeraContext> for Context {
|
||||
fn into(self) -> TeraContext {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_context() -> impl Clone + Filter<Extract = (Context,), Error = Rejection> {
|
||||
warp::ext::get::<Context>()
|
||||
.or(warp::any().map(|| Context::default()))
|
||||
.unify()
|
||||
}
|
||||
|
||||
fn render_navbar(state: &State, session: &Session, ctx: &mut Context) -> Result<(), Error> {
|
||||
let conn = state.get_connection()?;
|
||||
|
||||
// retrieve the user data
|
||||
if let Some(user_id) = session.user_id {
|
||||
conn.fetch_user_id(user_id)
|
||||
.map(|user| ctx.insert("user", &user))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generates all of the information needed to populate the navbar.
|
||||
pub fn navbar() -> impl Clone + Filter<Extract = (), Error = Rejection> {
|
||||
get_context().map(|ctx| {}).untuple_one()
|
||||
warp::ext::get::<State>()
|
||||
.and(warp::ext::get::<Session>())
|
||||
.and(get_context())
|
||||
.map(|state: State, session: Session, mut ctx: Context| {
|
||||
render_navbar(&state, &session, &mut ctx).unwrap_or_else(|err| {
|
||||
println!("err: {:?}", err);
|
||||
});
|
||||
warp::ext::set::<Context>(ctx);
|
||||
})
|
||||
.untuple_one()
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use warp::{Filter, Rejection};
|
|||
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Session {
|
||||
pub user_id: Option<i32>,
|
||||
pub team_id: Option<i32>,
|
||||
}
|
||||
|
||||
pub fn extract() -> impl Clone + Filter<Extract = (), Error = Rejection> {
|
||||
|
@ -48,8 +49,9 @@ pub fn apply() -> impl Clone + Filter<Extract = (Option<String>,), Error = Rejec
|
|||
.map(|data| {
|
||||
jar.private(&key).add(
|
||||
Cookie::build("session", data)
|
||||
.secure(true)
|
||||
// .secure(true) // TODO: enable this based on a config
|
||||
.http_only(true)
|
||||
.path("/")
|
||||
.same_site(SameSite::Strict)
|
||||
.finish(),
|
||||
);
|
||||
|
|
|
@ -4,16 +4,18 @@ use core::{
|
|||
Error, State,
|
||||
};
|
||||
use http::uri::Uri;
|
||||
use tera::Context;
|
||||
use warp::Filter;
|
||||
use wtforms::Form;
|
||||
|
||||
use crate::extractors::navbar;
|
||||
use crate::extractors::{get_context, navbar, Context};
|
||||
use crate::render::render_template;
|
||||
use crate::session::Session;
|
||||
|
||||
pub fn get_login() -> Resp!() {
|
||||
navbar().and_then(|| render_template("users/login.html", Context::new()))
|
||||
warp::path::end()
|
||||
.and(navbar())
|
||||
.and(get_context())
|
||||
.and_then(|ctx: Context| render_template("users/login.html", ctx.into()))
|
||||
}
|
||||
|
||||
pub fn post_login() -> Resp!() {
|
||||
|
@ -39,11 +41,17 @@ pub fn post_login() -> Resp!() {
|
|||
}
|
||||
|
||||
pub fn get_profile() -> Resp!() {
|
||||
navbar().and_then(|| render_template("users/profile.html", Context::new()))
|
||||
warp::path::end()
|
||||
.and(navbar())
|
||||
.and(get_context())
|
||||
.and_then(|ctx: Context| render_template("users/profile.html", ctx.into()))
|
||||
}
|
||||
|
||||
pub fn get_register() -> Resp!() {
|
||||
navbar().and_then(|| render_template("users/register.html", Context::new()))
|
||||
warp::path::end()
|
||||
.and(navbar())
|
||||
.and(get_context())
|
||||
.and_then(|ctx: Context| render_template("users/register.html", ctx.into()))
|
||||
}
|
||||
|
||||
pub fn post_register() -> Resp!() {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<title>{% block title %}{% endblock %} - LibreCTF</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="container navbar" role="navigation" aria-label="main navigation">
|
||||
<nav class="container navbar" style="margin-bottom: 20px;" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="/"><h3>LibreCTF</h3></a>
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
|||
|
||||
<div id="navbarBasicExample" class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item">Home</a>
|
||||
<a class="navbar-item" href="/">Home</a>
|
||||
<a class="navbar-item">Documentation</a>
|
||||
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
|
@ -39,10 +39,22 @@
|
|||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons">
|
||||
<a href="/users/register" class="button is-primary"><strong>Sign up</strong></a>
|
||||
<a href="/users/login" class="button is-light">Log in</a>
|
||||
</div>
|
||||
{% if user %}
|
||||
<a class="navbar-item">My Team</a>
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link">{{ user.name }}</a>
|
||||
<div class="navbar-dropdown">
|
||||
<a class="navbar-item" href="/users/profile">Profile</a>
|
||||
<hr class="navbar-divider">
|
||||
<a class="navbar-item" href="/users/logout">Logout</a>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="buttons">
|
||||
<a href="/users/register" class="button is-primary"><strong>Sign up</strong></a>
|
||||
<a href="/users/login" class="button is-light">Log in</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,32 @@
|
|||
{% extends "layout.html" %}
|
||||
{% block title %}Register{% endblock %}
|
||||
{% block title %}Profile{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="container">
|
||||
<div class="columns">
|
||||
<div class="column is-one-quarter">
|
||||
<nav class="panel">
|
||||
<div class="panel-block">
|
||||
<p class="control has-icons-left">
|
||||
<input class="input" type="text" placeholder="search">
|
||||
<span class="icon is-left">
|
||||
<i class="fas fa-search" aria-hidden="true"></i>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="column">
|
||||
<a href="/users/settings" class="button is-link" style="float: right; margin-right: 30px;">Settings</a>
|
||||
<div class="tabs is-boxed">
|
||||
<ul>
|
||||
<li class="is-active"><a>Profile</a></li>
|
||||
<li><a>Music</a></li>
|
||||
<li><a>Videos</a></li>
|
||||
<li><a>Documents</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in New Issue