Browse Source

feat: support tmp token

master
hole-thu 3 years ago
parent
commit
d9aec4d613
  1. 1
      Cargo.toml
  2. 45
      src/api/mod.rs
  3. 15
      src/api/systemlog.rs
  4. 22
      src/main.rs
  5. 21
      src/random_hasher.rs

1
Cargo.toml

@ -12,3 +12,4 @@ diesel = { version = "1.4.8", features= ["sqlite", "chrono"] }
chrono = { version="0.4", features=["serde"] }
rand = "0.8.5"
dotenv = "0.15.0"
sha2 = "0.10.2"

45
src/api/mod.rs

@ -14,28 +14,46 @@ pub fn catch_401_error() -> Value {
}
pub struct CurrentUser {
id: Option<i32>, // tmp user has no id, only for block
namehash: String,
is_admin: bool,
custom_title: String,
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for CurrentUser {
type Error = ();
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
let rh = request.rocket().state::<RandomHasher>().unwrap();
let mut cu: Option<CurrentUser> = None;
if let Some(token) = request.headers().get_one("User-Token") {
let conn = establish_connection();
if let Some(user) = User::get_by_token(&conn, token) {
return request::Outcome::Success(CurrentUser {
namehash: request
.rocket()
.state::<RandomHasher>()
.unwrap()
.hash_with_salt(&user.name),
is_admin: user.is_admin,
let sp = token.split('_').collect::<Vec<&str>>();
if sp.len() == 2 && sp[0] == rh.get_tmp_token() {
let namehash = rh.hash_with_salt(sp[1]);
cu = Some(CurrentUser {
id: None,
custom_title: format!("TODO: {}", &namehash),
namehash: namehash,
is_admin: false,
});
} else {
let conn = establish_connection();
if let Some(user) = User::get_by_token(&conn, token) {
let namehash = rh.hash_with_salt(&user.name);
cu = Some(CurrentUser {
id: Some(user.id),
custom_title: format!("TODO: {}", &namehash),
namehash: namehash,
is_admin: user.is_admin,
});
}
}
}
request::Outcome::Failure((Status::Unauthorized, ()))
match cu {
Some(u) => request::Outcome::Success(u),
None => request::Outcome::Failure((Status::Unauthorized, ())),
}
}
}
@ -77,6 +95,13 @@ impl<'r> Responder<'r, 'static> for APIError {
}
}
macro_rules! look {
($s:expr) => {
format!("{}...{}", &$s[..2], &$s[$s.len() - 2..])
};
}
pub type API<T> = Result<T, APIError>;
pub mod post;
pub mod systemlog;

15
src/api/systemlog.rs

@ -0,0 +1,15 @@
use crate::api::{CurrentUser, API};
use crate::random_hasher::RandomHasher;
use chrono::SubsecRound;
use rocket::serde::json::{json, Value};
use rocket::State;
#[get("/systemlog")]
pub fn get_systemlog(user: CurrentUser, rh: &State<RandomHasher>) -> API<Value> {
Ok(json!({
"tmp_token": rh.get_tmp_token(),
"salt": look!(rh.salt),
"start_time": rh.start_time.round_subsecs(0),
"custom_title": user.custom_title,
}))
}

22
src/main.rs

@ -4,10 +4,10 @@ extern crate rocket;
#[macro_use]
extern crate diesel;
mod random_hasher;
mod api;
mod models;
mod random_hasher;
mod schema;
mod api;
use random_hasher::RandomHasher;
@ -15,14 +15,16 @@ use random_hasher::RandomHasher;
fn rocket() -> _ {
load_env();
rocket::build()
.mount("/_api", routes![
api::post::get_list,
api::post::get_one,
api::post::publish_post
])
.register("/_api", catchers![
api::catch_401_error
])
.mount(
"/_api/v1",
routes![
api::post::get_list,
api::post::get_one,
api::post::publish_post,
api::systemlog::get_systemlog,
],
)
.register("/_api", catchers![api::catch_401_error])
.manage(RandomHasher::get_random_one())
}

21
src/random_hasher.rs

@ -1,7 +1,10 @@
use chrono::{offset::Local, DateTime};
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use sha2::{Digest, Sha256};
pub struct RandomHasher {
salt: String,
pub salt: String,
pub start_time: DateTime<Local>,
}
impl RandomHasher {
@ -12,11 +15,23 @@ impl RandomHasher {
.take(16)
.map(char::from)
.collect(),
start_time: Local::now(),
}
}
pub fn hash_with_salt(&self, text: &str) -> String {
// TODO
format!("hash({}+{})", self.salt, text)
let mut h = Sha256::new();
h.update(text);
h.update(&self.salt);
format!("{:X}", h.finalize())[5..21].to_string()
}
pub fn get_tmp_token(&self) -> String {
// 每15分钟变化一次
self.hash_with_salt(&format!(
"{}_{}",
Local::now().timestamp() / 60 / 15,
self.start_time.timestamp_subsec_nanos()
))
}
}

Loading…
Cancel
Save