This commit is contained in:
2022-09-25 06:24:45 +00:00
committed by GitHub
parent cea025482f
commit 89e08ab968
8 changed files with 95 additions and 6 deletions

View File

@@ -1,5 +1,6 @@
| Name | Description | Type | | Name | Description | Type |
|:----:|:-----------:|:----:| |:----:|:-----------:|:----:|
| id | Token id | integer |
| user_id | User id | integer | | user_id | User id | integer |
| token | Token | string | | token | Token | string |
| created_at | Creation time | datetime | | created_at | Creation time | datetime |

View File

@@ -1,6 +1,8 @@
pub mod config; pub mod config;
#[cfg(feature = "db_sqlite")] #[cfg(feature = "db_sqlite")]
pub mod sqlite; pub mod sqlite;
#[cfg(feature = "server")]
pub mod token;
pub mod traits; pub mod traits;
#[cfg(feature = "server")] #[cfg(feature = "server")]
pub mod user; pub mod user;
@@ -11,6 +13,8 @@ pub use config::PixivDownloaderDbConfig;
pub use config::PixivDownloaderSqliteConfig; pub use config::PixivDownloaderSqliteConfig;
#[cfg(feature = "db_sqlite")] #[cfg(feature = "db_sqlite")]
pub use sqlite::{PixivDownloaderSqlite, SqliteError}; pub use sqlite::{PixivDownloaderSqlite, SqliteError};
#[cfg(feature = "server")]
pub use token::Token;
pub use traits::PixivDownloaderDb; pub use traits::PixivDownloaderDb;
#[cfg(feature = "server")] #[cfg(feature = "server")]
pub use user::User; pub use user::User;

View File

@@ -1,8 +1,8 @@
#[cfg(feature = "server")]
use super::super::User;
use super::super::{ use super::super::{
PixivDownloaderDb, PixivDownloaderDbConfig, PixivDownloaderDbError, PixivDownloaderSqliteConfig, PixivDownloaderDb, PixivDownloaderDbConfig, PixivDownloaderDbError, PixivDownloaderSqliteConfig,
}; };
#[cfg(feature = "server")]
use super::super::{Token, User};
use super::SqliteError; use super::SqliteError;
use bytes::BytesMut; use bytes::BytesMut;
use futures_util::lock::Mutex; use futures_util::lock::Mutex;
@@ -56,10 +56,12 @@ lang TEXT,
translated TEXT translated TEXT
);"; );";
const TOKEN_TABLE: &'static str = "CREATE TABLE token ( const TOKEN_TABLE: &'static str = "CREATE TABLE token (
id INT,
user_id INT, user_id INT,
token TEXT, token TEXT,
created_at DATETIME, created_at DATETIME,
expired_at DATETIME expired_at DATETIME,
PRIMARY KEY (id)
);"; );";
const USERS_TABLE: &'static str = "CREATE TABLE users ( const USERS_TABLE: &'static str = "CREATE TABLE users (
id INT, id INT,
@@ -77,13 +79,14 @@ v3 INT,
v4 INT, v4 INT,
PRIMARY KEY (id) PRIMARY KEY (id)
);"; );";
const VERSION: [u8; 4] = [1, 0, 0, 2]; const VERSION: [u8; 4] = [1, 0, 0, 3];
pub struct PixivDownloaderSqlite { pub struct PixivDownloaderSqlite {
db: Mutex<Connection>, db: Mutex<Connection>,
} }
impl PixivDownloaderSqlite { impl PixivDownloaderSqlite {
#[cfg(feature = "server")]
async fn _add_root_user( async fn _add_root_user(
&self, &self,
name: &str, name: &str,
@@ -127,6 +130,10 @@ impl PixivDownloaderSqlite {
if db_version < [1, 0, 0, 2] { if db_version < [1, 0, 0, 2] {
tx.execute("ALTER TABLE users ADD is_admin BOOLEAN;", [])?; tx.execute("ALTER TABLE users ADD is_admin BOOLEAN;", [])?;
} }
if db_version < [1, 0, 0, 3] {
tx.execute("DROP TABLE token;", [])?;
tx.execute(TOKEN_TABLE, [])?;
}
self._write_version(&tx)?; self._write_version(&tx)?;
tx.commit()?; tx.commit()?;
} }
@@ -187,6 +194,22 @@ impl PixivDownloaderSqlite {
Ok(tables) Ok(tables)
} }
#[cfg(feature = "server")]
async fn get_token(&self, id: u64) -> Result<Option<Token>, SqliteError> {
let con = self.db.lock().await;
Ok(con
.query_row("SELECT * FROM token WHERE id = ?;", [id], |row| {
Ok(Token {
id: row.get(0)?,
user_id: row.get(1)?,
token: row.get(2)?,
created_at: row.get(3)?,
expired_at: row.get(4)?,
})
})
.optional()?)
}
#[cfg(feature = "server")] #[cfg(feature = "server")]
async fn _get_user(&self, id: u64) -> Result<Option<User>, SqliteError> { async fn _get_user(&self, id: u64) -> Result<Option<User>, SqliteError> {
let con = self.db.lock().await; let con = self.db.lock().await;
@@ -267,6 +290,11 @@ impl PixivDownloaderDb for PixivDownloaderSqlite {
Ok(self.get_user(0).await?.expect("Root user not found:")) Ok(self.get_user(0).await?.expect("Root user not found:"))
} }
#[cfg(feature = "server")]
async fn get_token(&self, id: u64) -> Result<Option<Token>, PixivDownloaderDbError> {
Ok(self.get_token(id).await?)
}
#[cfg(feature = "server")] #[cfg(feature = "server")]
async fn get_user(&self, id: u64) -> Result<Option<User>, PixivDownloaderDbError> { async fn get_user(&self, id: u64) -> Result<Option<User>, PixivDownloaderDbError> {
Ok(self._get_user(id).await?) Ok(self._get_user(id).await?)

15
src/db/token.rs Normal file
View File

@@ -0,0 +1,15 @@
use chrono::{DateTime, Utc};
/// A token in the database
pub struct Token {
/// The token ID
pub id: u64,
/// The user ID of the token
pub user_id: u64,
/// The token
pub token: String,
/// The token's creation time
pub created_at: DateTime<Utc>,
/// The token's expiration time
pub expired_at: DateTime<Utc>,
}

View File

@@ -1,7 +1,7 @@
use super::PixivDownloaderDbConfig; use super::PixivDownloaderDbConfig;
use super::PixivDownloaderDbError; use super::PixivDownloaderDbError;
#[cfg(feature = "server")] #[cfg(feature = "server")]
use super::User; use super::{Token, User};
#[async_trait] #[async_trait]
pub trait PixivDownloaderDb { pub trait PixivDownloaderDb {
@@ -24,6 +24,10 @@ pub trait PixivDownloaderDb {
password: &[u8], password: &[u8],
) -> Result<User, PixivDownloaderDbError>; ) -> Result<User, PixivDownloaderDbError>;
#[cfg(feature = "server")] #[cfg(feature = "server")]
/// Get token by ID
/// * `id` - The token ID
async fn get_token(&self, id: u64) -> Result<Option<Token>, PixivDownloaderDbError>;
#[cfg(feature = "server")]
/// Get a user by ID /// Get a user by ID
/// * `id`: The user's ID /// * `id`: The user's ID
async fn get_user(&self, id: u64) -> Result<Option<User>, PixivDownloaderDbError>; async fn get_user(&self, id: u64) -> Result<Option<User>, PixivDownloaderDbError>;

View File

@@ -27,6 +27,7 @@ pub enum PixivDownloaderError {
JSONError(json::Error), JSONError(json::Error),
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
OpenSSLError(openssl::error::ErrorStack), OpenSSLError(openssl::error::ErrorStack),
ParseIntError(std::num::ParseIntError),
} }
impl From<&str> for PixivDownloaderError { impl From<&str> for PixivDownloaderError {

View File

@@ -37,7 +37,10 @@ impl AuthUserContext {
.await .await
.try_err3(-1002, gettext("Failed to get parameters:"))?; .try_err3(-1002, gettext("Failed to get parameters:"))?;
if root_user.is_some() { if root_user.is_some() {
// # TODO auth self.ctx
.verify_token(&req, &params)
.await
.try_err3(-403, gettext("Failed to verify the token:"))?;
} }
match &self.action { match &self.action {
Some(act) => match act { Some(act) => match act {

View File

@@ -1,9 +1,12 @@
use super::auth::RSAKey; use super::auth::RSAKey;
use super::cors::CorsContext; use super::cors::CorsContext;
use super::params::RequestParams;
use crate::db::{open_and_init_database, PixivDownloaderDb}; use crate::db::{open_and_init_database, PixivDownloaderDb};
use crate::error::PixivDownloaderError;
use crate::get_helper; use crate::get_helper;
use crate::gettext; use crate::gettext;
use futures_util::lock::Mutex; use futures_util::lock::Mutex;
use hyper::{Body, Request};
pub struct ServerContext { pub struct ServerContext {
pub cors: CorsContext, pub cors: CorsContext,
@@ -22,4 +25,34 @@ impl ServerContext {
rsa_key: Mutex::new(None), rsa_key: Mutex::new(None),
} }
} }
pub async fn verify_token(
&self,
req: &Request<Body>,
params: &RequestParams,
) -> Result<(), PixivDownloaderError> {
let mut token_id = None;
match req.headers().get("X-TOKEN-ID") {
Some(v) => {
token_id.replace(v.to_str()?.to_owned());
}
None => match params.get("token_id") {
Some(v) => {
token_id.replace(v.to_owned());
}
None => {}
},
}
let token_id = match token_id {
Some(token_id) => token_id,
None => return Err(PixivDownloaderError::from(gettext("Token id not found."))),
}
.parse::<u64>()?;
let token = self
.db
.get_token(token_id)
.await?
.ok_or(gettext("Token not found."))?;
Ok(())
}
} }