
This version comes with the benefit of having much more concise exec_map functionality among other things This commit and the following ones also move db-lib to using a more 'try' based approach
142 lines
4.8 KiB
Rust
142 lines
4.8 KiB
Rust
use mysql_async::{params, Pool};
|
|
use mysql_async::prelude::Queryable;
|
|
use mysql_async::Error as SqlError;
|
|
|
|
|
|
use crate::{UBigInt, Integer, VarChar};
|
|
use crate::{PublicMember, Member, Response};
|
|
|
|
use rand::RngCore;
|
|
|
|
|
|
pub const STATUS_ONLINE: Integer = 0;
|
|
pub const STATUS_OFFLINE: Integer = 1;
|
|
pub const STATUS_AWAY: Integer = 2;
|
|
pub const STATUS_DO_NOT_DISTURB: Integer = 3;
|
|
|
|
impl Member {
|
|
pub async fn get(p: &Pool, id: UBigInt) -> Result<Response<Self>, SqlError> {
|
|
//! @returns Row on success
|
|
//! @returns Other on failure
|
|
let mut conn = p.get_conn().await?;
|
|
|
|
let q = "SELECT secret, name, status, permissions FROM members WHERE id = :id";
|
|
let params = params!{"id" => id};
|
|
|
|
let row: Option<(VarChar, VarChar, Integer, UBigInt)> =
|
|
conn.exec_first(q, params).await?;
|
|
if let Some((secret, name, status, permissions)) = row {
|
|
Ok(Response::Row(Member {
|
|
id, secret, name, status, permissions
|
|
}))
|
|
} else {
|
|
Ok(Response::Empty)
|
|
}
|
|
}
|
|
|
|
|
|
pub async fn filter(p: &Pool, status: Integer) -> Result<Response<PublicMember>, SqlError> {
|
|
//! @params status i32
|
|
//! @returns Response::Set(PublicMember)
|
|
if !(status == STATUS_ONLINE || status == STATUS_AWAY || status == STATUS_OFFLINE || status == STATUS_DO_NOT_DISTURB) {
|
|
Ok(Response::RestrictedInput(format!("Invalid status")))
|
|
} else {
|
|
let mut conn = p.get_conn().await?;
|
|
let q =
|
|
"SELECT id, name, status, permissions FROM members
|
|
WHERE status = :stat LIMIT 100"; // high limit for now
|
|
|
|
let params = params!{"stat" => status};
|
|
let members = conn.exec_map(q, params, |(id, name , status, permissions)| {
|
|
PublicMember {
|
|
id, name, status, permissions
|
|
}
|
|
}).await?;
|
|
Ok(Response::Set(members))
|
|
}
|
|
}
|
|
pub async fn add(p: &Pool, name: &str, secret: &str, perms: u64) -> Result<Response<Self>, SqlError> {
|
|
//! @param {pool} p
|
|
//! @param {&str} name of new user
|
|
//! @param {&str} encrypted secret : userland auth module should have a function for this
|
|
//! @param {u64} permissions mask
|
|
|
|
//! @returns : on_succes => Ok(Response<Member>)
|
|
//! @returns : on_partial_succes => Ok(Response<Member>)
|
|
//! @returns : on_failure => Err(SomeBS)
|
|
let mut conn = p.get_conn().await?;
|
|
|
|
let id: u64 = rand::rngs::OsRng.next_u64();
|
|
conn.exec_drop(
|
|
"INSERT INTO members(secret, name, status, permissions)
|
|
VALUES(:id, :secret, :name, :status, :permissions)",
|
|
mysql_async::params!{
|
|
"id" => id,
|
|
"secret" => secret.clone(),
|
|
"name" => name.clone(),
|
|
"status" => STATUS_ONLINE,
|
|
"permissions" => perms
|
|
}).await?;
|
|
|
|
return Ok(Response::Row(Self {
|
|
id,
|
|
secret: secret.into(),
|
|
name: name.into(),
|
|
status: STATUS_ONLINE,
|
|
permissions: perms
|
|
}))
|
|
}
|
|
|
|
pub async fn update_perms(p: &Pool, uid: UBigInt, permissions: UBigInt) -> Result<UBigInt, SqlError> {
|
|
//! @return on_sucess Ok(NewPermisionsMask)
|
|
//! @throws Err(SqlError)
|
|
let mut conn = p.get_conn().await?;
|
|
conn.exec_drop(
|
|
"UPDATE members SET permissions = :perms WHERE id = :id",
|
|
params!{
|
|
"id" => uid,
|
|
"perms" => permissions
|
|
}).await?;
|
|
|
|
Ok(permissions)
|
|
}
|
|
|
|
pub async fn update_nick(p: &Pool, uid: UBigInt, new_nick: &str) -> Result<(), SqlError> {
|
|
let mut conn = p.get_conn().await?;
|
|
|
|
conn.exec_drop(
|
|
"UPDATE members SET name = :nick WHERE id = id",
|
|
params!{
|
|
"id" => uid,
|
|
"nick" => new_nick
|
|
}).await?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl PublicMember {
|
|
pub async fn get_online(p: &Pool, status: Integer) -> Result<Response<Self>, SqlError> {
|
|
let valid_status = status == STATUS_ONLINE ||
|
|
status == STATUS_AWAY ||
|
|
status == STATUS_OFFLINE ||
|
|
status == STATUS_DO_NOT_DISTURB;
|
|
|
|
if !valid_status {
|
|
return Ok(Response::RestrictedInput(format!("Invalid status value")));
|
|
} else {
|
|
let mut conn = p.get_conn().await?;
|
|
let q = "SELECT id, name, permissions FROM members
|
|
WHERE status = :status LIMIT 1000";
|
|
|
|
let params = params!{"status" => status};
|
|
let members = conn.exec_map(q, params, |(id, name, permissions)| {
|
|
PublicMember { id, name, permissions, status }
|
|
}).await?;
|
|
|
|
return Ok(Response::Set(members));
|
|
}
|
|
}
|
|
}
|
|
|