backend: remove user api

This commit is contained in:
L-Nafaryus 2024-03-23 00:13:01 +05:00
parent 117efffea2
commit 1b0e5d53c2
Signed by: L-Nafaryus
GPG Key ID: 582F8B0866B294A1
7 changed files with 54 additions and 11 deletions

View File

@ -7,7 +7,7 @@ const password = defineModel("password");
const errorMessage = ref(null); const errorMessage = ref(null);
async function login() { async function login() {
await fetch(import.meta.hot ? "http://localhost:54600/api/v1/login_user" : "/api/v1/login_user", { await fetch(import.meta.hot ? "http://localhost:54600/api/v1/user/login" : "/api/v1/user/login", {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",

View File

@ -9,13 +9,12 @@ const is_admin = ref(null);
const errorMessage = ref(null); const errorMessage = ref(null);
onMounted(async () => { onMounted(async () => {
const asd = await fetch(import.meta.hot ? "http://localhost:54600/api/v1/me" : "/api/v1/me", { const asd = await fetch(import.meta.hot ? "http://localhost:54600/api/v1/user/profile" : "/api/v1/user/profile", {
method: "GET", method: "GET",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
credentials: "include", credentials: "include",
mode: "cors",
}) })
.then(async response => { .then(async response => {
const isJson = response.headers.get('content-type')?.includes('application/json'); const isJson = response.headers.get('content-type')?.includes('application/json');
@ -26,9 +25,9 @@ onMounted(async () => {
return Promise.reject(error); return Promise.reject(error);
} }
name.value = data.data.user.name; name.value = data.user.name;
email.value = data.data.user.email; email.value = data.user.email;
is_admin.value = data.data.user.is_admin; is_admin.value = data.user.is_admin;
}) })
.catch(error => { .catch(error => {
errorMessage.value = error; errorMessage.value = error;

View File

View File

@ -4,6 +4,7 @@ use serde_json::json;
#[derive(Debug)] #[derive(Debug)]
pub enum AuthError<E> { pub enum AuthError<E> {
InternalError(E), InternalError(E),
InternalE,
MissingCredentials, MissingCredentials,
InvalidCredentials, InvalidCredentials,
MissingToken, MissingToken,
@ -15,6 +16,7 @@ impl<E: std::error::Error> IntoResponse for AuthError<E> {
fn into_response(self) -> axum::response::Response { fn into_response(self) -> axum::response::Response {
let (status, message) = match self { let (status, message) = match self {
Self::InternalError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()), Self::InternalError(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
Self::InternalE => (StatusCode::INTERNAL_SERVER_ERROR, "Internal E".to_string()),
Self::MissingCredentials => { Self::MissingCredentials => {
(StatusCode::BAD_REQUEST, "Missing credentials".to_string()) (StatusCode::BAD_REQUEST, "Missing credentials".to_string())
} }

View File

@ -31,6 +31,7 @@ pub fn routes(state: Arc<AppState>) -> Router {
Router::new() Router::new()
.route("/v1/healthcheck", get(healthcheck)) .route("/v1/healthcheck", get(healthcheck))
.route("/v1/user/register", post(user::register)) .route("/v1/user/register", post(user::register))
.route("/v1/user/remove", post(user::remove))
.route("/v1/user/login", post(user::login)) .route("/v1/user/login", post(user::login))
.route("/v1/user/logout", get(user::logout)) .route("/v1/user/logout", get(user::logout))
.route("/v1/user/profile", get(user::profile).route_layer(jwt)) .route("/v1/user/profile", get(user::profile).route_layer(jwt))

View File

@ -34,6 +34,11 @@ pub struct FilteredUser {
pub is_admin: bool, pub is_admin: bool,
} }
#[derive(serde::Deserialize)]
pub struct RemoveUser {
pub id: String,
}
impl FilteredUser { impl FilteredUser {
pub fn from(user: &User) -> Self { pub fn from(user: &User) -> Self {
FilteredUser { FilteredUser {
@ -67,11 +72,34 @@ pub async fn register(
.map_err(AuthError::InternalError)?; .map_err(AuthError::InternalError)?;
Ok(Json(json!({ Ok(Json(json!({
"status": "success", "status": StatusCode::OK.to_string(),
"user": FilteredUser::from(&user) "user": FilteredUser::from(&user)
}))) })))
} }
pub async fn remove(
State(state): State<Arc<AppState>>,
Json(body): Json<RemoveUser>,
) -> Result<impl IntoResponse, AuthError<impl std::error::Error>> {
let user = User::find(
&state.database,
User::by_id(uuid::Uuid::parse_str(&body.id).map_err(|_| AuthError::InvalidCredentials)?),
)
.await
.map_err(AuthError::InternalError)?;
let user = match user {
Some(user) => user,
None => return Err(AuthError::MissingUser),
};
User::remove(&state.database, user)
.await
.map_err(|_| AuthError::InternalE)?;
Ok(Json(json!({"status": StatusCode::OK.to_string()})))
}
pub async fn login( pub async fn login(
State(state): State<Arc<AppState>>, State(state): State<Arc<AppState>>,
Json(body): Json<LoginUser>, Json(body): Json<LoginUser>,

View File

@ -90,15 +90,15 @@ impl User {
pub fn by_email(email: String) -> BoxedQuery<'static> { pub fn by_email(email: String) -> BoxedQuery<'static> {
users::table users::table
.select(User::as_select())
.into_boxed() .into_boxed()
.select(User::as_select())
.filter(users::email.eq(email)) .filter(users::email.eq(email))
} }
pub fn by_id(id: uuid::Uuid) -> BoxedQuery<'static> { pub fn by_id(id: uuid::Uuid) -> BoxedQuery<'static> {
users::table users::table
.select(User::as_select())
.into_boxed() .into_boxed()
.select(User::as_select())
.filter(users::id.eq(id)) .filter(users::id.eq(id))
} }
@ -116,6 +116,19 @@ impl User {
Ok(user) Ok(user)
} }
#[allow(unused_variables)] pub async fn remove(
pub fn remove(pool: Pool, email: String) {} pool: &Pool,
user: User,
) -> Result<(), DatabaseError<impl std::error::Error>> {
let connection = pool.get().await.map_err(DatabaseError::Connection)?;
connection
.interact(move |connection| {
diesel::delete(users::table.filter(users::id.eq(user.id))).execute(connection)
})
.await
.map_err(|_| DatabaseError::Interaction)?
.map_err(|_| DatabaseError::Interaction)?;
Ok(())
}
} }