Last active
February 1, 2016 07:18
-
-
Save SkylerLipthay/668b80a2177955681dc6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
orm_model! { | |
table = "admins"; | |
fields = { | |
*id: i64, | |
company_id: i64, | |
name: String, | |
email: String, | |
password: Password, | |
password_reset_token: Option<String>, | |
created_at: DateTime, | |
updated_at: DateTime | |
}; | |
extensions = { | |
// Here, `AdminName`, `AdminEmail`, etc. are generated by the `orm_model!` macro by | |
// camel-casing the `fields` given above. | |
ValidateLength<AdminName, String> = ValidateLength::new(2..256), | |
ValidateLength<AdminEmail, String> = ValidateLength::new(3..256), | |
ValidatePresence<AdminPassword, Password> = ValidatePresence::new(), | |
ValidateUniqueness<AdminEmail, String> = ValidateUniqueness::new(), | |
Timestamps<AdminCreatedAt, AdminUpdatedAt> = Timestamps::new(), | |
}; | |
pub struct Admin; | |
} | |
impl Admin { | |
pub fn generate_reset_password_token(&mut self) { | |
self.set_password_reset_token(Some(thread_rng().gen_ascii_chars().take(32).collect())); | |
} | |
} | |
pub struct UnpackAdmin; | |
impl Deserialize<Admin> for UnpackAdmin { | |
fn deserialize(map: &::params::Map, admin: &mut Admin) -> Result<(), Error> { | |
try!(AdminName::deserialize_permit(map, admin)); | |
try!(AdminEmail::deserialize_permit(map, admin)); | |
try!(AdminPassword::deserialize_permit(map, admin)); | |
Ok(()) | |
} | |
} | |
pub struct UnpackLogin; | |
impl Deserialize<Admin> for UnpackLogin { | |
fn deserialize(map: &::params::Map, admin: &mut Admin) -> Result<(), Error> { | |
try!(AdminEmail::deserialize_require(map, admin)); | |
try!(AdminPassword::deserialize_require(map, admin)); | |
Ok(()) | |
} | |
} | |
// let admin = try!(Admin::deserialize::<UnpackLogin>(&request_params.get("login_credentials"))); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Validates the length (in unicode characters) of a string is within a range. | |
pub struct ValidateLength<M, F, S> | |
where M: Model, F: ModelField<M, S>, S: AsOption<String> + Value | |
{ | |
m: PhantomData<fn(M)>, | |
f: PhantomData<F>, | |
s: PhantomData<S>, | |
min: usize, | |
max: usize, | |
} | |
impl<M, F, S> ValidateLength<M, F, S> | |
where M: Model, F: ModelField<M, S>, S: AsOption<String> + Value | |
{ | |
pub fn new<R: RangeArgument<usize>>(range: R) -> ValidateLength<M, F, S> { | |
ValidateLength { | |
m: PhantomData, | |
f: PhantomData, | |
s: PhantomData, | |
min: range.start().map(|v| *v).unwrap_or(0), | |
max: range.end().map(|v| *v).unwrap_or(::std::usize::MAX), | |
} | |
} | |
} | |
impl<M, F, S> Extension<M> for ValidateLength<M, F, S> | |
where M: Model, F: ModelField<M, S>, S: AsOption<String> + Value | |
{ | |
fn validate(&self, model: &mut M, tree: &mut ValidationTree) -> Result<(), Error> { | |
let field = F::field(model); | |
if !field.has_changed() { | |
return Ok(()); | |
} | |
let value = match field.get_opt().map(|v| v.as_option()) { | |
Some(Some(value)) => value, | |
None if model.is_new_record() && self.min > 0 => { | |
tree.add_with_field::<F, _>("cannot be blank".into()); | |
return Ok(()); | |
}, | |
_ => return Ok(()), | |
}; | |
let length = value.chars().count(); | |
if length == 0 && self.min > 0 { | |
tree.add_with_field::<F, _>("cannot be blank".into()); | |
} else if length < self.min { | |
let error = format!("must be at least {} characters", self.min); | |
tree.add_with_field::<F, _>(error.into()); | |
} else if length > self.max { | |
let error = format!("cannot be over {} characters", self.max); | |
tree.add_with_field::<F, _>(error.into()); | |
} | |
Ok(()) | |
} | |
} | |
pub struct ValidateUniqueness<M: Model, F: ModelField<M, V>, V: Value> { | |
m: PhantomData<fn(M)>, | |
f: PhantomData<F>, | |
v: PhantomData<V>, | |
} | |
impl<M: Model, F: ModelField<M, V>, V: Value> ValidateUniqueness<M, F, V> { | |
pub fn new() -> ValidateUniqueness<M, F, V> { | |
ValidateUniqueness { m: PhantomData, f: PhantomData, v: PhantomData } | |
} | |
} | |
impl<M: Model, F: ModelField<M, V>, V: Value> Extension<M> for ValidateUniqueness<M, F, V> { | |
fn validate_db<C: Connection>(&self, model: &mut M, tree: &mut ValidationTree, conn: &C) | |
-> Result<(), Error> | |
{ | |
if !F::field(model).has_changed() { | |
return Ok(()); | |
} | |
// TODO: Scoped finder with `ValidateUniqueness::scoped(|finder| ...)` | |
let transaction = try!(conn.transaction()); | |
if try!(M::find().one(&transaction)).is_some() { | |
tree.add_with_field::<F, _>("is already in use".into()); | |
} | |
Ok(()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment