mirror of
https://github.com/lifegpc/pixiv_downloader.git
synced 2026-07-08 01:32:41 +08:00
Update
This commit is contained in:
@@ -228,6 +228,28 @@ impl PixivDownloaderSqlite {
|
||||
.optional()?)
|
||||
}
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
async fn _get_user_by_username(&self, username: &str) -> Result<Option<User>, SqliteError> {
|
||||
let con = self.db.lock().await;
|
||||
Ok(con
|
||||
.query_row(
|
||||
"SELECT * FROM users WHERE username = ?;",
|
||||
[username],
|
||||
|row| {
|
||||
let password: Vec<u8> = row.get(3)?;
|
||||
let password: &[u8] = &password;
|
||||
Ok(User {
|
||||
id: row.get(0)?,
|
||||
name: row.get(1)?,
|
||||
username: row.get(2)?,
|
||||
password: BytesMut::from(password),
|
||||
is_admin: row.get(4)?,
|
||||
})
|
||||
},
|
||||
)
|
||||
.optional()?)
|
||||
}
|
||||
|
||||
async fn _read_version(&self) -> Result<Option<[u8; 4]>, SqliteError> {
|
||||
let con = self.db.lock().await;
|
||||
let mut stmt = con.prepare("SELECT v1, v2, v3, v4 FROM version WHERE id='main';")?;
|
||||
@@ -239,6 +261,81 @@ impl PixivDownloaderSqlite {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
async fn _set_user(
|
||||
&self,
|
||||
id: u64,
|
||||
name: &str,
|
||||
username: &str,
|
||||
password: &[u8],
|
||||
is_admin: bool,
|
||||
) -> Result<User, SqliteError> {
|
||||
let con = self.db.lock().await;
|
||||
let has_user = con
|
||||
.query_row("SELECT * FROM users WHERE id = ?;", [id], |_| Ok(()))
|
||||
.optional()
|
||||
.is_ok();
|
||||
let has_username = con
|
||||
.query_row(
|
||||
"SELECT * FROM users WHERE username = ?;",
|
||||
[username],
|
||||
|row| {
|
||||
if has_user {
|
||||
let uid: u64 = row.get(0)?;
|
||||
Ok(uid != id)
|
||||
} else {
|
||||
Ok(true)
|
||||
}
|
||||
},
|
||||
)
|
||||
.optional()?
|
||||
.unwrap_or(false);
|
||||
if !has_user {
|
||||
if has_username {
|
||||
Err(SqliteError::UserNameAlreadyExists)
|
||||
} else {
|
||||
con.execute(
|
||||
"INSERT INTO users (name, username, password, is_admin) VALUES (?, ?, ?, ?);",
|
||||
(name, username, password, is_admin),
|
||||
)?;
|
||||
Ok(con.query_row(
|
||||
"SELECT * FROM users WHERE username = ?;",
|
||||
[username],
|
||||
|row| {
|
||||
let password: Vec<u8> = row.get(3)?;
|
||||
let password: &[u8] = &password;
|
||||
Ok(User {
|
||||
id: row.get(0)?,
|
||||
name: row.get(1)?,
|
||||
username: row.get(2)?,
|
||||
password: BytesMut::from(password),
|
||||
is_admin: row.get(4)?,
|
||||
})
|
||||
},
|
||||
)?)
|
||||
}
|
||||
} else {
|
||||
if has_username {
|
||||
Err(SqliteError::UserNameAlreadyExists)
|
||||
} else {
|
||||
con.execute("INSERT OR REPLACE INTO users (id, name, username, password, is_admin) VALUES (?, ?, ?, ?, ?);", (id, name, username, password, is_admin))?;
|
||||
Ok(
|
||||
con.query_row("SELECT * FROM users WHERE id = ?;", [id], |row| {
|
||||
let password: Vec<u8> = row.get(3)?;
|
||||
let password: &[u8] = &password;
|
||||
Ok(User {
|
||||
id: row.get(0)?,
|
||||
name: row.get(1)?,
|
||||
username: row.get(2)?,
|
||||
password: BytesMut::from(password),
|
||||
is_admin: row.get(4)?,
|
||||
})
|
||||
})?,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn _write_version<'a>(&self, ts: &Transaction<'a>) -> Result<(), SqliteError> {
|
||||
let mut stmt = ts.prepare(
|
||||
"INSERT OR REPLACE INTO version (id, v1, v2, v3, v4) VALUES ('main', ?, ?, ?, ?);",
|
||||
@@ -300,10 +397,32 @@ impl PixivDownloaderDb for PixivDownloaderSqlite {
|
||||
Ok(self._get_user(id).await?)
|
||||
}
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
async fn get_user_by_username(
|
||||
&self,
|
||||
username: &str,
|
||||
) -> Result<Option<User>, PixivDownloaderDbError> {
|
||||
Ok(self._get_user_by_username(username).await?)
|
||||
}
|
||||
|
||||
async fn init(&self) -> Result<(), PixivDownloaderDbError> {
|
||||
if !self._check_database().await? {
|
||||
self._create_table().await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
async fn set_user(
|
||||
&self,
|
||||
id: u64,
|
||||
name: &str,
|
||||
username: &str,
|
||||
password: &[u8],
|
||||
is_admin: bool,
|
||||
) -> Result<User, PixivDownloaderDbError> {
|
||||
Ok(self
|
||||
._set_user(id, name, username, password, is_admin)
|
||||
.await?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
pub enum SqliteError {
|
||||
DbError(rusqlite::Error),
|
||||
DatabaseVersionTooNew,
|
||||
UserNameAlreadyExists,
|
||||
}
|
||||
|
||||
@@ -31,6 +31,31 @@ pub trait PixivDownloaderDb {
|
||||
/// Get a user by ID
|
||||
/// * `id`: The user's ID
|
||||
async fn get_user(&self, id: u64) -> Result<Option<User>, PixivDownloaderDbError>;
|
||||
#[cfg(feature = "server")]
|
||||
/// Get a user by username
|
||||
/// * `username`: The user's username
|
||||
async fn get_user_by_username(
|
||||
&self,
|
||||
username: &str,
|
||||
) -> Result<Option<User>, PixivDownloaderDbError>;
|
||||
/// Initialize the database (create tables, migrate data, etc.)
|
||||
async fn init(&self) -> Result<(), PixivDownloaderDbError>;
|
||||
#[cfg(feature = "server")]
|
||||
/// Set a user's information by ID
|
||||
/// * `id`: The user's ID
|
||||
/// * `name`: The user's name
|
||||
/// * `username`: The user's username
|
||||
/// * `password`: The user's hashed password
|
||||
/// * `is_admin`: Whether the user is an admin
|
||||
/// # Note
|
||||
/// If the user does not exist, a new user will be created and `id` must not be applied.
|
||||
/// If the user's `username` is taked by another user, the operation must failed.
|
||||
async fn set_user(
|
||||
&self,
|
||||
id: u64,
|
||||
name: &str,
|
||||
username: &str,
|
||||
password: &[u8],
|
||||
is_admin: bool,
|
||||
) -> Result<User, PixivDownloaderDbError>;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,42 @@ impl AuthUserContext {
|
||||
.try_err3(8, gettext("Failed to add user to database:"))?;
|
||||
Ok(user.to_json2())
|
||||
} else {
|
||||
Ok(json::object! {})
|
||||
let mut is_admin = params
|
||||
.get_bool("is_admin")
|
||||
.try_err3(
|
||||
9,
|
||||
&gettext("Failed to parse <opt>:")
|
||||
.replace("<opt>", "is_admin"),
|
||||
)?
|
||||
.unwrap_or(false);
|
||||
let id = params.get_u64("id").try_err3(
|
||||
10,
|
||||
&gettext("Failed to parse <opt>:").replace("<opt>", "id"),
|
||||
)?;
|
||||
match id {
|
||||
Some(id) => {
|
||||
if id == 0 {
|
||||
is_admin = true;
|
||||
}
|
||||
let user = self
|
||||
.ctx
|
||||
.db
|
||||
.set_user(
|
||||
id,
|
||||
name,
|
||||
username,
|
||||
&hashed_password,
|
||||
is_admin,
|
||||
)
|
||||
.await
|
||||
.try_err3(
|
||||
12,
|
||||
gettext("Failed to set user in database:"),
|
||||
)?;
|
||||
Ok(user.to_json2())
|
||||
}
|
||||
None => Ok(json::object! {}),
|
||||
}
|
||||
}
|
||||
}
|
||||
None => return Err((5, gettext("No RSA key found.")).into()),
|
||||
|
||||
@@ -31,6 +31,49 @@ impl RequestParams {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get parameter and return it as boolean.
|
||||
/// * `name` - Parameter name.
|
||||
pub fn get_bool<S: AsRef<str> + ?Sized>(
|
||||
&self,
|
||||
name: &S,
|
||||
) -> Result<Option<bool>, PixivDownloaderError> {
|
||||
match self.get(name) {
|
||||
Some(v) => {
|
||||
let v = v.trim();
|
||||
if v == "true" {
|
||||
Ok(Some(true))
|
||||
} else if v == "false" {
|
||||
Ok(Some(false))
|
||||
} else {
|
||||
match v.parse::<i64>() {
|
||||
Ok(v) => return Ok(Some(v != 0)),
|
||||
Err(_) => {}
|
||||
}
|
||||
Err(gettext("Invalid boolean value.").into())
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get parameter and return it as [u64].
|
||||
/// * `name` - Parameter name.
|
||||
pub fn get_u64<S: AsRef<str> + ?Sized>(
|
||||
&self,
|
||||
name: &S,
|
||||
) -> Result<Option<u64>, PixivDownloaderError> {
|
||||
match self.get(name) {
|
||||
Some(v) => {
|
||||
let v = v.trim();
|
||||
match v.parse::<u64>() {
|
||||
Ok(v) => Ok(Some(v)),
|
||||
Err(_) => Err(gettext("Invalid unsigned 64bit integer value.").into()),
|
||||
}
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all parameters with same name.
|
||||
/// * `name` - Parameter name.
|
||||
pub fn get_all<S: AsRef<str> + ?Sized>(&self, name: &S) -> Option<&Vec<String>> {
|
||||
|
||||
Reference in New Issue
Block a user