diff --git a/src/db/sqlite/db.rs b/src/db/sqlite/db.rs index 7d99d55..e179efc 100644 --- a/src/db/sqlite/db.rs +++ b/src/db/sqlite/db.rs @@ -11,23 +11,21 @@ use rusqlite::{Connection, OpenFlags, OptionalExtension, Transaction}; use std::collections::HashMap; const AUTHORS_TABLE: &'static str = "CREATE TABLE authors ( -id INT, +id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, creator_id TEXT, icon INT, big_icon INT, background INT, comment TEXT, -webpage TEXT, -PRIMARY KEY (id) +webpage TEXT );"; const FILES_TABLE: &'static str = "CREATE TABLE files ( -id INT, +id INTEGER PRIMARY KEY AUTOINCREMENT, path TEXT, last_modified DATETIME, etag TEXT, -url TEXT, -PRIMARY KEY (id) +url TEXT );"; const PIXIV_ARTWORK_TAGS_TABLE: &'static str = "CREATE TABLE pixiv_artwork_tags ( id INT, @@ -47,9 +45,8 @@ file_id INT, page INT );"; const TAGS_TABLE: &'static str = "CREATE TABLE tags ( -id INT, -name TEXT, -PRIMARY KEY (id) +id INTEGER PRIMARY KEY AUTOINCREMENT, +name TEXT );"; const TAGS_I18N_TABLE: &'static str = "CREATE TABLE tags_i18n ( id INT, @@ -64,12 +61,11 @@ created_at DATETIME, expired_at DATETIME );"; const USERS_TABLE: &'static str = "CREATE TABLE users ( -id INT, +id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, username TEXT, password TEXT, -is_admin BOOLEAN, -PRIMARY KEY (id) +is_admin BOOLEAN );"; const VERSION_TABLE: &'static str = "CREATE TABLE version ( id TEXT, @@ -79,7 +75,7 @@ v3 INT, v4 INT, PRIMARY KEY (id) );"; -const VERSION: [u8; 4] = [1, 0, 0, 3]; +const VERSION: [u8; 4] = [1, 0, 0, 4]; pub struct PixivDownloaderSqlite { db: Mutex, @@ -162,6 +158,14 @@ impl PixivDownloaderSqlite { tx.execute("DROP TABLE token;", [])?; tx.execute(TOKEN_TABLE, [])?; } + if db_version < [1, 0, 0, 4] { + tx.execute("DROP TABLE authors, files, tags, token, users;", [])?; + tx.execute(AUTHORS_TABLE, [])?; + tx.execute(FILES_TABLE, [])?; + tx.execute(TAGS_TABLE, [])?; + tx.execute(TOKEN_TABLE, [])?; + tx.execute(USERS_TABLE, [])?; + } self._write_version(&tx)?; tx.commit()?; } diff --git a/src/server/unittest/auth.rs b/src/server/unittest/auth.rs index 81132e2..a789aa3 100644 --- a/src/server/unittest/auth.rs +++ b/src/server/unittest/auth.rs @@ -8,7 +8,7 @@ use openssl::rsa::{Padding, Rsa}; /// Test authentification methods /// Returns token -pub async fn test(ctx: &UnitTestContext) -> Result { +pub async fn test(ctx: &UnitTestContext) -> Result<(u64, Vec), PixivDownloaderError> { let re = Request::builder().uri("/auth").body(Body::empty())?; let res = ctx.request_json(re).await?.unwrap(); assert_eq!(res["has_root_user"].as_bool(), Some(false)); @@ -58,5 +58,38 @@ pub async fn test(ctx: &UnitTestContext) -> Result "test2", + "name" => "test2", + "password" => b64_password2.as_str(), + }, + &token, + token_id, + ) + .await? + .unwrap(); + let result = JSONResult::from_json(re)?.expect("Failed to add user:"); + assert_eq!( + result, + json::object! { + "id": 1, + "name": "test2", + "username": "test2", + "is_admin": false, + } + ); + Ok((token_id, token)) } diff --git a/src/server/unittest/mod.rs b/src/server/unittest/mod.rs index b769b6f..28987b6 100644 --- a/src/server/unittest/mod.rs +++ b/src/server/unittest/mod.rs @@ -9,6 +9,7 @@ use crate::error::PixivDownloaderError; use futures_util::lock::Mutex; use hyper::{Body, Request, Response}; use json::JsonValue; +use std::collections::BTreeMap; #[cfg(test)] use std::fs::{create_dir, remove_file}; #[cfg(test)] @@ -107,6 +108,53 @@ impl UnitTestContext { .body(Body::from(par))?; self.request_json(req).await } + + pub async fn request_json2_sign( + &self, + uri: &str, + params: &JsonValue, + token: &[u8], + token_id: u64, + ) -> Result, PixivDownloaderError> { + let mut par = BTreeMap::new(); + for (key, obj) in params.entries() { + if let Some(s) = obj.as_str() { + par.insert(key.to_owned(), s.to_owned()); + } else if obj.is_array() { + for s in obj.members() { + if let Some(s) = s.as_str() { + par.insert(key.to_owned(), s.to_owned()); + } else { + par.insert(key.to_owned(), s.dump()); + } + } + } else { + par.insert(key.to_owned(), obj.dump()); + } + } + let mut sha = openssl::sha::Sha512::new(); + sha.update(token); + let mut par2 = Vec::new(); + for (key, value) in par.iter() { + sha.update(key.as_bytes()); + sha.update(value.as_bytes()); + par2.push(format!( + "{}={}", + urlparse::quote_plus(key, b"")?, + urlparse::quote_plus(value, b"")? + )); + } + let par2 = par2.join("&"); + let sign = hex::encode(sha.finish()); + let req = Request::builder() + .method("POST") + .uri(uri) + .header("Content-Type", "application/x-www-form-urlencoded") + .header("X-SIGN", sign) + .header("X-TOKEN-ID", token_id.to_string()) + .body(Body::from(par2))?; + self.request_json(req).await + } } #[proc_macros::async_timeout_test(120s)]