You've already forked AstralRinth
forked from didirus/AstralRinth
Allow admins to view user email (#3261)
This commit is contained in:
61
apps/frontend/src/pages/admin/user_email.vue
Normal file
61
apps/frontend/src/pages/admin/user_email.vue
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<div class="normal-page no-sidebar">
|
||||||
|
<h1>User account request</h1>
|
||||||
|
<div class="normal-page__content">
|
||||||
|
<div class="card flex flex-col gap-3">
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<label for="name">
|
||||||
|
<span class="text-lg font-semibold text-contrast">
|
||||||
|
User email
|
||||||
|
<span class="text-brand-red">*</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="name"
|
||||||
|
v-model="userEmail"
|
||||||
|
type="email"
|
||||||
|
maxlength="64"
|
||||||
|
:placeholder="`Enter user email...`"
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<ButtonStyled color="brand">
|
||||||
|
<button @click="getUserFromEmail">
|
||||||
|
<MailIcon aria-hidden="true" />
|
||||||
|
Get user account
|
||||||
|
</button>
|
||||||
|
</ButtonStyled>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ButtonStyled } from "@modrinth/ui";
|
||||||
|
import { MailIcon } from "@modrinth/assets";
|
||||||
|
|
||||||
|
const userEmail = ref("");
|
||||||
|
|
||||||
|
async function getUserFromEmail() {
|
||||||
|
startLoading();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await useBaseFetch(`user_email?email=${encodeURIComponent(userEmail.value)}`, {
|
||||||
|
method: "GET",
|
||||||
|
apiVersion: 3,
|
||||||
|
});
|
||||||
|
|
||||||
|
await navigateTo(`/user/${result.username}`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
addNotification({
|
||||||
|
group: "main",
|
||||||
|
title: "An error occurred",
|
||||||
|
text: err.data.description,
|
||||||
|
type: "error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
stopLoading();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
22
apps/labrinth/.sqlx/query-68619337ef34b588af21a40e5a60b54ce3a1dad45fb50bbc24a3ea34d2506578.json
generated
Normal file
22
apps/labrinth/.sqlx/query-68619337ef34b588af21a40e5a60b54ce3a1dad45fb50bbc24a3ea34d2506578.json
generated
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n SELECT id FROM users\n WHERE LOWER(email) = LOWER($1)\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Int8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "68619337ef34b588af21a40e5a60b54ce3a1dad45fb50bbc24a3ea34d2506578"
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ use crate::{
|
|||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
cfg.route("user", web::get().to(user_auth_get));
|
cfg.route("user", web::get().to(user_auth_get));
|
||||||
cfg.route("users", web::get().to(users_get));
|
cfg.route("users", web::get().to(users_get));
|
||||||
|
cfg.route("user_email", web::get().to(admin_user_email));
|
||||||
|
|
||||||
cfg.service(
|
cfg.service(
|
||||||
web::scope("user")
|
web::scope("user")
|
||||||
@@ -44,6 +45,62 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct UserEmailQuery {
|
||||||
|
pub email: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn admin_user_email(
|
||||||
|
req: HttpRequest,
|
||||||
|
pool: web::Data<PgPool>,
|
||||||
|
redis: web::Data<RedisPool>,
|
||||||
|
session_queue: web::Data<AuthQueue>,
|
||||||
|
email: web::Query<UserEmailQuery>,
|
||||||
|
) -> Result<HttpResponse, ApiError> {
|
||||||
|
let user = get_user_from_headers(
|
||||||
|
&req,
|
||||||
|
&**pool,
|
||||||
|
&redis,
|
||||||
|
&session_queue,
|
||||||
|
Some(&[Scopes::SESSION_ACCESS]),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map(|x| x.1)?;
|
||||||
|
|
||||||
|
if !user.role.is_admin() {
|
||||||
|
return Err(ApiError::CustomAuthentication(
|
||||||
|
"You do not have permission to get a user from their email!"
|
||||||
|
.to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let user_id = sqlx::query!(
|
||||||
|
"
|
||||||
|
SELECT id FROM users
|
||||||
|
WHERE LOWER(email) = LOWER($1)
|
||||||
|
",
|
||||||
|
email.email
|
||||||
|
)
|
||||||
|
.fetch_optional(&**pool)
|
||||||
|
.await?
|
||||||
|
.map(|x| x.id)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
ApiError::InvalidInput(
|
||||||
|
"The email provided is not associated with a user!".to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let user =
|
||||||
|
User::get_id(crate::database::models::UserId(user_id), &**pool, &redis)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if let Some(user) = user {
|
||||||
|
Ok(HttpResponse::Ok().json(user))
|
||||||
|
} else {
|
||||||
|
Err(ApiError::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn projects_list(
|
pub async fn projects_list(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
info: web::Path<(String,)>,
|
info: web::Path<(String,)>,
|
||||||
|
|||||||
Reference in New Issue
Block a user