Browse Source

feat: basic user token check

master
hole-thu 3 years ago
parent
commit
e4fbbb1b7b
  1. 2
      migrations/2022-03-15-061041_create_users/down.sql
  2. 9
      migrations/2022-03-15-061041_create_users/up.sql
  3. 60
      src/api/mod.rs
  4. 16
      src/models.rs
  5. 14
      src/schema.rs
  6. 29
      tools/migdb.py

2
migrations/2022-03-15-061041_create_users/down.sql

@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE users

9
migrations/2022-03-15-061041_create_users/up.sql

@ -0,0 +1,9 @@
-- Your SQL goes here
CREATE TABLE users (
id INTEGER NOT NULL PRIMARY KEY,
name VARCHAR NOT NULL UNIQUE,
token VARCHAR NOT NULL UNIQUE,
is_admin BOOLEAN NOT NULL DEFAULT FALSE
);
CREATE INDEX users_toekn_idx ON users (`token`);

60
src/api/mod.rs

@ -1,8 +1,9 @@
use crate::models::*;
use crate::random_hasher::RandomHasher; use crate::random_hasher::RandomHasher;
use rocket::http::Status; use rocket::http::Status;
use rocket::request::{self, FromRequest, Request}; use rocket::request::{self, FromRequest, Request};
use rocket::serde::json::{Value, json};
use rocket::response::{self, Responder}; use rocket::response::{self, Responder};
use rocket::serde::json::{json, Value};
#[catch(401)] #[catch(401)]
pub fn catch_401_error() -> Value { pub fn catch_401_error() -> Value {
@ -21,31 +22,32 @@ pub struct CurrentUser {
impl<'r> FromRequest<'r> for CurrentUser { impl<'r> FromRequest<'r> for CurrentUser {
type Error = (); type Error = ();
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
let token = request.headers().get_one("User-Token"); if let Some(token) = request.headers().get_one("User-Token") {
match token { let conn = establish_connection();
Some(t) => request::Outcome::Success(CurrentUser { if let Some(user) = User::get_by_token(&conn, token) {
namehash: request return request::Outcome::Success(CurrentUser {
.rocket() namehash: request
.state::<RandomHasher>() .rocket()
.unwrap() .state::<RandomHasher>()
.hash_with_salt(t), .unwrap()
is_admin: t == "admin", // TODO .hash_with_salt(&user.name),
}), is_admin: user.is_admin,
None => request::Outcome::Failure((Status::Unauthorized, ())), });
}
} }
request::Outcome::Failure((Status::Unauthorized, ()))
} }
} }
pub enum PolicyError { pub enum PolicyError {
IsReported, IsReported,
IsDeleted, IsDeleted,
NotAllowed NotAllowed,
} }
pub enum APIError { pub enum APIError {
DbError(diesel::result::Error), DbError(diesel::result::Error),
PcError(PolicyError) PcError(PolicyError),
} }
impl APIError { impl APIError {
@ -57,20 +59,20 @@ impl APIError {
impl<'r> Responder<'r, 'static> for APIError { impl<'r> Responder<'r, 'static> for APIError {
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> { fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
match self { match self {
APIError::DbError(e) => APIError::DbError(e) => json!({
json!({ "code": -1,
"code": -1, "msg": e.to_string()
"msg": e.to_string() })
}).respond_to(req), .respond_to(req),
APIError::PcError(e) => APIError::PcError(e) => json!({
json!({ "code": -1,
"code": -1, "msg": match e {
"msg": match e { PolicyError::IsReported => "内容被举报,处理中",
PolicyError::IsReported => "内容被举报,处理中", PolicyError::IsDeleted => "内容被删除",
PolicyError::IsDeleted => "内容被删除", PolicyError::NotAllowed => "不允许的操作",
PolicyError::NotAllowed => "不允许的操作", }
} })
}).respond_to(req), .respond_to(req),
} }
} }
} }

16
src/models.rs

@ -4,7 +4,7 @@ use chrono::NaiveDateTime;
use diesel::{insert_into, Connection, ExpressionMethods, QueryDsl, RunQueryDsl, SqliteConnection}; use diesel::{insert_into, Connection, ExpressionMethods, QueryDsl, RunQueryDsl, SqliteConnection};
use std::env; use std::env;
use crate::schema::posts; use crate::schema::*;
type MR<T> = Result<T, diesel::result::Error>; type MR<T> = Result<T, diesel::result::Error>;
@ -80,3 +80,17 @@ impl Post {
insert_into(posts::table).values(&new_post).execute(conn) insert_into(posts::table).values(&new_post).execute(conn)
} }
} }
#[derive(Queryable, Debug)]
pub struct User {
pub id: i32,
pub name: String,
pub token: String,
pub is_admin: bool,
}
impl User {
pub fn get_by_token(conn: &SqliteConnection, token: &str) -> Option<Self> {
users::table.filter(users::token.eq(token)).first(conn).ok()
}
}

14
src/schema.rs

@ -15,3 +15,17 @@ table! {
allow_search -> Bool, allow_search -> Bool,
} }
} }
table! {
users (id) {
id -> Integer,
name -> Text,
token -> Text,
is_admin -> Bool,
}
}
allow_tables_to_appear_in_same_query!(
posts,
users,
);

29
tools/migdb.py

@ -1,9 +1,13 @@
import sqlite3 import sqlite3
from datetime import datetime from datetime import datetime
def mig_post(db_old, db_new): db_old = sqlite3.connect('hole.db')
c_old = db_old.cursor() db_new = sqlite3.connect('hole_v2.db')
c_new = db_new.cursor() c_old = db_old.cursor()
c_new = db_new.cursor()
def mig_post():
rs = c_old.execute( rs = c_old.execute(
'SELECT id, name_hash, content, cw, author_title, ' 'SELECT id, name_hash, content, cw, author_title, '
'likenum, n_comments, timestamp, comment_timestamp, ' 'likenum, n_comments, timestamp, comment_timestamp, '
@ -25,13 +29,22 @@ def mig_post(db_old, db_new):
) )
db_new.commit() db_new.commit()
c_old.close()
c_new.close() def mig_user():
rs = c_old.execute('SELECT name, token FROM user')
for r in rs:
c_new.execute(
'INSERT OR REPLACE INTO users(name, token) VALUES(?, ?)',
r
)
db_new.commit()
if __name__ == '__main__': if __name__ == '__main__':
db_old = sqlite3.connect('hole.db') # mig_post()
db_new = sqlite3.connect('hole_v2.db') mig_user()
mig_post(db_old, db_new) c_old.close()
c_new.close()

Loading…
Cancel
Save