feat(server >> api): implemented an endpoint that gives the client information about their authenticated account
This commit is contained in:
parent
8f8e2c5665
commit
5db4d4869c
|
@ -19,6 +19,7 @@ env_logger = "0.11.3"
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
serde = { version = "1.0.197", features = ["default"] }
|
serde = { version = "1.0.197", features = ["default"] }
|
||||||
|
strum = { version = "0.26.2", features = ["derive"] }
|
||||||
thiserror = "1.0.58"
|
thiserror = "1.0.58"
|
||||||
uuid = { version = "1.7.0", features = ["v4"] }
|
uuid = { version = "1.7.0", features = ["v4"] }
|
||||||
tokio = { version = "1.36.0", features = ["sync"] }
|
tokio = { version = "1.36.0", features = ["sync"] }
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
pub mod invite;
|
pub mod invite;
|
||||||
|
|
||||||
use crate::backend::Backend;
|
use crate::backend::{permissions::Permission, Backend};
|
||||||
use actix_web::{post, web, HttpResponse, Responder};
|
use actix_web::{get, post, web, HttpResponse, Responder};
|
||||||
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -67,3 +68,26 @@ pub async fn auth(backend: web::Data<Backend>, body: web::Json<AuthRequest>) ->
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
struct InfoResponse {
|
||||||
|
userid: String,
|
||||||
|
permissions: Vec<Permission>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/account/info")]
|
||||||
|
pub async fn info(backend: web::Data<Backend>, bearer_auth: BearerAuth) -> impl Responder {
|
||||||
|
match backend.account_info(bearer_auth.token()).await {
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("{e}");
|
||||||
|
HttpResponse::InternalServerError().finish()
|
||||||
|
}
|
||||||
|
Ok(res) => match res {
|
||||||
|
Err(e) => e.into(),
|
||||||
|
Ok((userid, permissions)) => HttpResponse::Ok().json(InfoResponse {
|
||||||
|
userid: userid.to_string(),
|
||||||
|
permissions,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub async fn start(config: &Config, backend: Backend) -> Result<()> {
|
||||||
.app_data(data.clone())
|
.app_data(data.clone())
|
||||||
.service(endpoints::account::register)
|
.service(endpoints::account::register)
|
||||||
.service(endpoints::account::auth)
|
.service(endpoints::account::auth)
|
||||||
|
.service(endpoints::account::info)
|
||||||
.service(endpoints::account::invite::new)
|
.service(endpoints::account::invite::new)
|
||||||
.service(endpoints::relay::create)
|
.service(endpoints::relay::create)
|
||||||
.service(endpoints::relay::relay_id::user::user_id::public_key)
|
.service(endpoints::relay::relay_id::user::user_id::public_key)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
mod db_structures;
|
mod db_structures;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
mod permissions;
|
pub mod permissions;
|
||||||
mod relay;
|
mod relay;
|
||||||
mod tokens;
|
mod tokens;
|
||||||
mod user;
|
mod user;
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
use serde::Serialize;
|
||||||
|
use strum::{EnumIter, IntoEnumIterator};
|
||||||
|
|
||||||
|
#[derive(EnumIter, Debug, Serialize)]
|
||||||
pub enum Permission {
|
pub enum Permission {
|
||||||
GenerateInviteTokens,
|
GenerateInviteTokens,
|
||||||
PromoteUsers,
|
PromoteUsers,
|
||||||
|
@ -11,3 +15,19 @@ impl Permission {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Permissions(pub u16);
|
||||||
|
|
||||||
|
impl Into<Vec<Permission>> for Permissions {
|
||||||
|
fn into(self) -> Vec<Permission> {
|
||||||
|
Permission::iter()
|
||||||
|
.filter_map(|permission| {
|
||||||
|
if (self.0 & permission.as_u16()) > 0 {
|
||||||
|
Some(permission)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use crate::backend::{
|
use crate::backend::{
|
||||||
db_structures::UsersRow, error::Error, permissions::Permission, tokens::resolve_auth_token,
|
db_structures::UsersRow,
|
||||||
|
error::Error,
|
||||||
|
permissions::{Permission, Permissions},
|
||||||
|
tokens::resolve_auth_token,
|
||||||
Backend,
|
Backend,
|
||||||
};
|
};
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
@ -35,6 +38,10 @@ impl User {
|
||||||
(self.permissions & permission.as_u16()) > 0
|
(self.permissions & permission.as_u16()) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn permissions(&self) -> Vec<Permission> {
|
||||||
|
Permissions(self.permissions).into()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn verify_password(&self, password: &str) -> Result<bool> {
|
pub fn verify_password(&self, password: &str) -> Result<bool> {
|
||||||
let hash = argon2::PasswordHash::new(self.password.as_str()).map_err(|_| {
|
let hash = argon2::PasswordHash::new(self.password.as_str()).map_err(|_| {
|
||||||
anyhow::Error::msg(format!(
|
anyhow::Error::msg(format!(
|
||||||
|
@ -173,4 +180,16 @@ impl Backend {
|
||||||
|
|
||||||
Ok(Ok(token))
|
Ok(Ok(token))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn account_info(
|
||||||
|
&self,
|
||||||
|
requester: impl IntoUser,
|
||||||
|
) -> Result<Result<(Uuid, Vec<Permission>), Error>> {
|
||||||
|
let requester = match requester.into_user(&self.pool).await? {
|
||||||
|
Err(e) => return Ok(Err(e)),
|
||||||
|
Ok(user) => user,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Ok((requester.uuid, requester.permissions())))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue