mirror of https://github.com/EasyCTF/librectf
...
This commit is contained in:
parent
f2fb3bbc1c
commit
fabd64a42e
|
@ -47,6 +47,28 @@ name = "autocfg"
|
|||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.9.3"
|
||||
|
@ -218,6 +240,7 @@ dependencies = [
|
|||
name = "core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bcrypt 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"diesel 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -701,6 +724,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "librectf"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core 0.1.0",
|
||||
"diesel 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1241,6 +1265,11 @@ dependencies = [
|
|||
"untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
|
@ -2033,6 +2062,8 @@ dependencies = [
|
|||
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
|
||||
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
|
||||
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
|
||||
"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"
|
||||
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
|
||||
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
||||
"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
|
||||
"checksum bcrypt 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a426ab63025c1d21e4e12a218c915fa22097b89ab7ed5765fa803101e004b27"
|
||||
|
@ -2163,6 +2194,7 @@ dependencies = [
|
|||
"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
|
||||
"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861"
|
||||
"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a"
|
||||
"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
||||
"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
|
||||
|
|
|
@ -11,6 +11,7 @@ members = [
|
|||
]
|
||||
|
||||
[dependencies]
|
||||
backtrace = "0.3"
|
||||
diesel = { version = "1.4", optional = true }
|
||||
env_logger = "0.6"
|
||||
structopt = "0.2"
|
||||
|
|
2
Justfile
2
Justfile
|
@ -2,4 +2,4 @@ doc:
|
|||
cargo watch -x 'doc --no-deps --document-private-items'
|
||||
|
||||
run:
|
||||
RUST_LOG="frontend=info" cargo watch -x 'run -- run --bind-addr 0.0.0.0:3000 --database-uri=sqlite:///home/michael/Projects/openctf/test.db --secret-key asdfasdfasdfasdfasdfasdfasdfasdf'
|
||||
RUST_LOG="core=info,warp=info,frontend=info" cargo watch -x 'run -- run --bind-addr 0.0.0.0:3000 --database-uri=sqlite:///home/michael/Projects/openctf/test.db --secret-key asdfasdfasdfasdfasdfasdfasdfasdf'
|
||||
|
|
|
@ -5,6 +5,7 @@ authors = ["Michael Zhang <iptq@protonmail.com>"]
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
backtrace = "0.3"
|
||||
bcrypt = "0.3"
|
||||
chrono = "0.4"
|
||||
diesel = { version = "1.4", features = ["extras"] }
|
||||
|
|
|
@ -1,39 +1,66 @@
|
|||
use std::borrow::Cow;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use backtrace::Backtrace;
|
||||
use warp::{Rejection, Reply};
|
||||
|
||||
/// ErrorExt trait, based on the avocado lib.
|
||||
pub trait ErrorExt: StdError {
|
||||
/// Similar to `std::error::Error::source()`, but with richer type info.
|
||||
fn reason(&self) -> Option<&(dyn ErrorExt + 'static)> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns the deepest possible backtrace, if any.
|
||||
fn backtrace(&self) -> Option<&Backtrace> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Structured error kind.
|
||||
fn kind(&self) -> ErrorKind;
|
||||
|
||||
/// Until subtrait coercions are implemented, this helper method
|
||||
/// should return the receiver as an `&std::error::Error` trait object.
|
||||
fn as_std_error(&self) -> &(dyn StdError + 'static);
|
||||
}
|
||||
|
||||
/// An error caused by the user.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum UserError {
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum UserErrorKind {
|
||||
/// The user supplied bad credentials during login.
|
||||
BadUsernameOrPassword,
|
||||
}
|
||||
|
||||
/// An error.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Error {
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum ErrorKind {
|
||||
#[doc(hidden)]
|
||||
Bcrypt(Arc<::bcrypt::BcryptError>),
|
||||
Bcrypt,
|
||||
#[doc(hidden)]
|
||||
Diesel(Arc<::diesel::result::Error>),
|
||||
Diesel,
|
||||
#[doc(hidden)]
|
||||
Migrations(Arc<::diesel_migrations::RunMigrationsError>),
|
||||
Migrations,
|
||||
#[doc(hidden)]
|
||||
R2d2(Arc<::r2d2::Error>),
|
||||
R2d2,
|
||||
#[doc(hidden)]
|
||||
Tera(Arc<::tera::ErrorKind>),
|
||||
Tera,
|
||||
|
||||
/// An error caused by the user.
|
||||
///
|
||||
/// During rendering, other errors will result in a 500 page, while user
|
||||
/// errors will be propagated to the generated page and presented to the
|
||||
/// user.
|
||||
User(UserError),
|
||||
// DEBUG
|
||||
#[doc(hidden)]
|
||||
Unit,
|
||||
User(UserErrorKind),
|
||||
}
|
||||
|
||||
/// The main error trait of the crate.
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
kind: ErrorKind,
|
||||
message: Cow<'static, str>,
|
||||
backtrace: Option<Backtrace>,
|
||||
cause: Option<Box<dyn ErrorExt + Send + Sync + 'static>>,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
|
@ -45,6 +72,62 @@ impl Error {
|
|||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an error that was caused by a user
|
||||
pub fn user<M>(message: M, kind: UserErrorKind) -> Self
|
||||
where
|
||||
M: Into<Cow<'static, str>>,
|
||||
{
|
||||
Error {
|
||||
kind: ErrorKind::User(kind),
|
||||
message: message.into(),
|
||||
backtrace: None,
|
||||
cause: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a message from just a message and a kind
|
||||
pub fn new<M>(message: M, kind: ErrorKind) -> Self
|
||||
where
|
||||
M: Into<Cow<'static, str>>,
|
||||
{
|
||||
Error {
|
||||
message: message.into(),
|
||||
kind,
|
||||
backtrace: None,
|
||||
cause: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Chains an error with a cause
|
||||
pub fn with_cause<M, E>(message: M, cause: E) -> Self
|
||||
where
|
||||
M: Into<Cow<'static, str>>,
|
||||
E: ErrorExt + Send + Sync + 'static,
|
||||
{
|
||||
let kind = cause.kind();
|
||||
let message = message.into();
|
||||
let backtrace = Some(match cause.backtrace() {
|
||||
Some(backtrace) => backtrace.clone(),
|
||||
None => Backtrace::new(),
|
||||
});
|
||||
let cause: Option<Box<dyn ErrorExt + Send + Sync + 'static>> = Some(Box::new(cause));
|
||||
Error {
|
||||
kind,
|
||||
message,
|
||||
backtrace,
|
||||
cause,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorExt for Error {
|
||||
fn kind(&self) -> ErrorKind {
|
||||
self.kind
|
||||
}
|
||||
fn as_std_error(&self) -> &(dyn StdError + 'static) {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
|
@ -56,38 +139,42 @@ impl fmt::Display for Error {
|
|||
|
||||
impl StdError for Error {}
|
||||
|
||||
impl From<::bcrypt::BcryptError> for Error {
|
||||
fn from(err: ::bcrypt::BcryptError) -> Self {
|
||||
Error::Bcrypt(Arc::new(err))
|
||||
}
|
||||
/// Implementing `ErrorExt` and `From` boilerplate.
|
||||
macro_rules! impl_error_type {
|
||||
($ty:path, $kind:ident, $message:expr) => {
|
||||
impl From<$ty> for Error {
|
||||
fn from(error: $ty) -> Self {
|
||||
Self::with_cause($message, error)
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorExt for $ty {
|
||||
fn kind(&self) -> ErrorKind {
|
||||
ErrorKind::$kind
|
||||
}
|
||||
|
||||
fn as_std_error(&self) -> &(dyn StdError + 'static) {
|
||||
self
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl From<::diesel::result::Error> for Error {
|
||||
fn from(err: ::diesel::result::Error) -> Self {
|
||||
Error::Diesel(Arc::new(err))
|
||||
}
|
||||
}
|
||||
impl_error_type!(::bcrypt::BcryptError, Bcrypt, "bcrypt error");
|
||||
impl_error_type!(::diesel::result::Error, Diesel, "diesel error");
|
||||
impl_error_type!(
|
||||
::diesel_migrations::RunMigrationsError,
|
||||
Migrations,
|
||||
"migrations error"
|
||||
);
|
||||
impl_error_type!(::r2d2::Error, R2d2, "r2d2 error");
|
||||
|
||||
impl From<::diesel_migrations::RunMigrationsError> for Error {
|
||||
fn from(err: ::diesel_migrations::RunMigrationsError) -> Self {
|
||||
Error::Migrations(Arc::new(err))
|
||||
impl ErrorExt for ::tera::Error {
|
||||
fn kind(&self) -> ErrorKind {
|
||||
ErrorKind::Tera
|
||||
}
|
||||
}
|
||||
|
||||
impl From<::r2d2::Error> for Error {
|
||||
fn from(err: ::r2d2::Error) -> Self {
|
||||
Error::R2d2(Arc::new(err))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<::tera::Error> for Error {
|
||||
fn from(err: ::tera::Error) -> Self {
|
||||
Error::Tera(Arc::new(err.kind))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<()> for Error {
|
||||
fn from(_: ()) -> Self {
|
||||
Error::Unit
|
||||
fn as_std_error(&self) -> &(dyn StdError + 'static) {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,5 +27,5 @@ pub mod users;
|
|||
|
||||
pub use crate::config::Config;
|
||||
pub use crate::db::{DatabaseUri, DbConn, DbPool};
|
||||
pub use crate::errors::{Error, UserError};
|
||||
pub use crate::errors::{Error, ErrorKind, UserErrorKind};
|
||||
pub use crate::state::State;
|
||||
|
|
|
@ -4,7 +4,7 @@ use wtforms::Form;
|
|||
|
||||
use crate::db::DbConn;
|
||||
use crate::models::{NewUser, User};
|
||||
use crate::{Error, UserError};
|
||||
use crate::{Error, UserErrorKind};
|
||||
|
||||
/// The struct behind the form used in the login page.
|
||||
#[derive(Form, Serialize, Deserialize)]
|
||||
|
@ -16,7 +16,7 @@ pub struct LoginForm {
|
|||
|
||||
/// Attempts to log in a user using a LoginForm. Upon success, the user struct
|
||||
/// associated with that account is returned. If the user supplies bad
|
||||
/// credentials, a `UserError::BadUsernameOrPassword` will be returned.
|
||||
/// credentials, a `UserErrorKind::BadUsernameOrPassword` will be returned.
|
||||
pub fn login_user(db: &DbConn, form: &LoginForm) -> Result<User, Error> {
|
||||
db.fetch_user(&form.email)
|
||||
.and_then(|user| {
|
||||
|
@ -28,7 +28,10 @@ pub fn login_user(db: &DbConn, form: &LoginForm) -> Result<User, Error> {
|
|||
if result {
|
||||
Ok(user)
|
||||
} else {
|
||||
Err(Error::User(UserError::BadUsernameOrPassword))
|
||||
Err(Error::user(
|
||||
"bad username or password",
|
||||
UserErrorKind::BadUsernameOrPassword,
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -44,7 +47,7 @@ pub struct RegisterForm {
|
|||
|
||||
/// Attempts to create a user using the given information. If the user tries
|
||||
/// to create an account with an email or username that already exists, then
|
||||
/// a `UserError` will be generated. (TODO: implement this)
|
||||
/// a `UserErrorKind` will be generated. (TODO: implement this)
|
||||
pub fn register_user(db: &DbConn, form: &RegisterForm) -> Result<i32, Error> {
|
||||
let password = bcrypt::hash(form.password.to_owned(), bcrypt::DEFAULT_COST)?;
|
||||
let new_user = NewUser {
|
||||
|
|
|
@ -4,7 +4,7 @@ use tera::Context as TeraContext;
|
|||
use warp::{Filter, Rejection};
|
||||
|
||||
use crate::session::Session;
|
||||
pub use warp::ext::get as get;
|
||||
pub use warp::ext::get;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Context(pub TeraContext);
|
||||
|
@ -36,7 +36,7 @@ pub fn get_context() -> impl Clone + Filter<Extract = (Context,), Error = Reject
|
|||
|
||||
fn render_navbar(session: &Session, ctx: &mut Context) -> Result<(), Error> {
|
||||
// retrieve the user data
|
||||
if let Some(user) = &session.user {
|
||||
if let Some(user) = session.get_user() {
|
||||
ctx.insert("user", &user);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use core::Error;
|
||||
use core::{Error, ErrorKind};
|
||||
use tera::Context;
|
||||
use warp::Rejection;
|
||||
|
||||
|
@ -7,6 +7,6 @@ use crate::Renderer;
|
|||
pub fn render_template(path: impl AsRef<str>, ctx: Context) -> Result<String, Rejection> {
|
||||
Renderer
|
||||
.render(path.as_ref(), ctx)
|
||||
.map_err(Error::from)
|
||||
.map_err(|_err| Error::new("render error", ErrorKind::Tera))
|
||||
.map_err(warp::reject::custom)
|
||||
}
|
||||
|
|
|
@ -15,31 +15,65 @@ pub struct SessionRepr {
|
|||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Session {
|
||||
pub(crate) struct SessionInner {
|
||||
pub user: Option<User>,
|
||||
pub team: Option<Team>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Session(pub(crate) Option<SessionInner>);
|
||||
|
||||
impl Session {
|
||||
fn init(&mut self) {
|
||||
if let None = self.0 {
|
||||
self.0 = Some(SessionInner::default());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_team(&mut self, team: Team) {
|
||||
self.init();
|
||||
if let Some(ref mut inner) = &mut self.0 {
|
||||
inner.team = Some(team);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_team(&self) -> Option<&Team> {
|
||||
self.0.as_ref().and_then(|inner| inner.team.as_ref())
|
||||
}
|
||||
|
||||
pub fn set_user(&mut self, user: User) {
|
||||
self.init();
|
||||
if let Some(ref mut inner) = &mut self.0 {
|
||||
inner.user = Some(user);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_user(&self) -> Option<&User> {
|
||||
self.0.as_ref().and_then(|inner| inner.user.as_ref())
|
||||
}
|
||||
|
||||
pub fn try_from(conn: &DbConn, repr: SessionRepr) -> Result<Session, Error> {
|
||||
let user = repr.user_id.and_then(|id| conn.fetch_user_id(id).ok());
|
||||
let team = user
|
||||
.as_ref()
|
||||
.and_then(|user| user.team_id)
|
||||
.and_then(|id| conn.fetch_team_id(id).ok());
|
||||
Ok(Session { user, team })
|
||||
}
|
||||
pub fn repr(self) -> SessionRepr {
|
||||
SessionRepr {
|
||||
user_id: self.user.map(|user| user.id),
|
||||
team_id: self.team.map(|team| team.id),
|
||||
|
||||
let mut session = Session::default();
|
||||
if let Some(user) = user {
|
||||
session.set_user(user);
|
||||
}
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match (&self.user, &self.team) {
|
||||
(None, None) => true,
|
||||
_ => false,
|
||||
if let Some(team) = team {
|
||||
session.set_team(team);
|
||||
}
|
||||
Ok(session)
|
||||
}
|
||||
|
||||
pub fn repr(&self) -> Option<SessionRepr> {
|
||||
self.0.as_ref().map(|inner| SessionRepr {
|
||||
user_id: inner.user.as_ref().map(|user| user.id),
|
||||
team_id: inner.team.as_ref().map(|team| team.id),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use core::models::Team;
|
|||
use http::uri::Uri;
|
||||
use warp::Filter;
|
||||
|
||||
use crate::extractors::{get_context, get, navbar, Context};
|
||||
use crate::extractors::{get, get_context, navbar, Context};
|
||||
use crate::guards::require_login;
|
||||
use crate::render::render_template;
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use core::{
|
||||
models::User,
|
||||
users::{LoginForm, RegisterForm},
|
||||
Error, State,
|
||||
Error, State, UserErrorKind,
|
||||
};
|
||||
use http::uri::Uri;
|
||||
use warp::Filter;
|
||||
use wtforms::Form;
|
||||
|
||||
use crate::extractors::{get_context, get, navbar, Context};
|
||||
use crate::extractors::{get, get_context, navbar, Context};
|
||||
use crate::render::render_template;
|
||||
use crate::session::Session;
|
||||
|
||||
|
@ -22,7 +22,12 @@ pub fn post_login() -> Resp!() {
|
|||
warp::body::form()
|
||||
.and_then(|form: LoginForm| {
|
||||
form.validate()
|
||||
.map_err(Error::from)
|
||||
.map_err(|_| {
|
||||
Error::user(
|
||||
"bad username or password",
|
||||
UserErrorKind::BadUsernameOrPassword,
|
||||
)
|
||||
})
|
||||
.map_err(warp::reject::custom)
|
||||
})
|
||||
.and(get::<State>())
|
||||
|
@ -34,7 +39,7 @@ pub fn post_login() -> Resp!() {
|
|||
})
|
||||
.and(get::<Session>())
|
||||
.map(|user: User, mut session: Session| {
|
||||
session.user = Some(user);
|
||||
session.set_user(user);
|
||||
warp::ext::set::<Session>(session);
|
||||
warp::redirect::redirect(Uri::from_static("/users/profile"))
|
||||
})
|
||||
|
@ -65,7 +70,12 @@ pub fn post_register() -> Resp!() {
|
|||
warp::body::form()
|
||||
.and_then(|form: RegisterForm| {
|
||||
form.validate()
|
||||
.map_err(Error::from)
|
||||
.map_err(|_| {
|
||||
Error::user(
|
||||
"bad registration info",
|
||||
UserErrorKind::BadUsernameOrPassword,
|
||||
)
|
||||
})
|
||||
.map_err(warp::reject::custom)
|
||||
})
|
||||
.and(get::<State>())
|
||||
|
|
21
src/main.rs
21
src/main.rs
|
@ -2,7 +2,8 @@ use std::io;
|
|||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use core::{DatabaseUri, State};
|
||||
use backtrace::Backtrace;
|
||||
use core::{DatabaseUri, Error, State};
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
|
@ -44,10 +45,7 @@ struct RunOpts {
|
|||
secret_key: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
let opt = Opt::from_args();
|
||||
|
||||
fn run(opt: Opt) -> Result<(), Error> {
|
||||
match opt.command {
|
||||
Commands::Migrate(opts) => {
|
||||
let db = opts
|
||||
|
@ -69,4 +67,17 @@ fn main() {
|
|||
warp::serve(frontend::routes(state)).run(opts.addr);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
let backtrace = Backtrace::new();
|
||||
let opt = Opt::from_args();
|
||||
match run(opt) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
println!("backtrace: {:?}", backtrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue