@@ -610,6 +610,28 @@ defmodule Mobilizon.GraphQL.Resolvers.User do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unban_account(_parent, %{user_id: user_id}, %{
|
||||||
|
context: %{
|
||||||
|
current_user: %User{role: role},
|
||||||
|
current_actor: %Actor{} = moderator_actor
|
||||||
|
}
|
||||||
|
})
|
||||||
|
when is_moderator(role) do
|
||||||
|
with %User{disabled: true} = user <- Users.get_user(user_id),
|
||||||
|
{:ok, %User{} = updated_user} <-
|
||||||
|
Users.unban_user(user) do
|
||||||
|
Admin.log_action(moderator_actor, "unsuspend", user)
|
||||||
|
{:ok, updated_user}
|
||||||
|
else
|
||||||
|
%User{disabled: false} ->
|
||||||
|
{:error, dgettext("errors", "User already enabled")}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unban_account(_parent, _args, _resolution) do
|
||||||
|
{:error, dgettext("errors", "You need to be logged-in and moderator to unban an account")}
|
||||||
|
end
|
||||||
|
|
||||||
def delete_account(_parent, %{user_id: user_id}, %{
|
def delete_account(_parent, %{user_id: user_id}, %{
|
||||||
context: %{
|
context: %{
|
||||||
current_user: %User{role: role},
|
current_user: %User{role: role},
|
||||||
|
|||||||
@@ -467,6 +467,13 @@ defmodule Mobilizon.GraphQL.Schema.UserType do
|
|||||||
resolve(&User.delete_account/3)
|
resolve(&User.delete_account/3)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@desc "Unban an account"
|
||||||
|
field :unban_account, :user do
|
||||||
|
arg(:user_id, :id, description: "The user's ID")
|
||||||
|
middleware(Rajska.QueryAuthorization, permit: :moderator, scope: false)
|
||||||
|
resolve(&User.unban_account/3)
|
||||||
|
end
|
||||||
|
|
||||||
@desc "Set user settings"
|
@desc "Set user settings"
|
||||||
field :set_user_settings, :user_settings do
|
field :set_user_settings, :user_settings do
|
||||||
arg(:timezone, :timezone, description: "The timezone for this user")
|
arg(:timezone, :timezone, description: "The timezone for this user")
|
||||||
|
|||||||
@@ -170,6 +170,15 @@ defmodule Mobilizon.Users do
|
|||||||
|
|
||||||
@delete_user_default_options [reserve_email: true]
|
@delete_user_default_options [reserve_email: true]
|
||||||
|
|
||||||
|
@spec unban_user(User.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
|
||||||
|
def unban_user(%User{} = user) do
|
||||||
|
user
|
||||||
|
|> User.changeset(%{
|
||||||
|
disabled: false
|
||||||
|
})
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Deletes an user.
|
Deletes an user.
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,14 @@ export const DELETE_ACCOUNT_AS_MODERATOR = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const UNBAN_ACCOUNT_AS_MODERATOR = gql`
|
||||||
|
mutation UnbanAccount($userId: ID) {
|
||||||
|
unbanAccount(userId: $userId) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const CURRENT_USER_CLIENT = gql`
|
export const CURRENT_USER_CLIENT = gql`
|
||||||
query CurrentUserClient {
|
query CurrentUserClient {
|
||||||
currentUser @client {
|
currentUser @client {
|
||||||
|
|||||||
@@ -370,6 +370,7 @@
|
|||||||
"Do not receive any mail": "Do not receive any mail",
|
"Do not receive any mail": "Do not receive any mail",
|
||||||
"Do you really want to ban the account \u00ab\u00a0{emailAccount}\u00a0\u00bb\u00a0?": "Do you really want to ban the account \u00ab\u00a0{emailAccount}\u00a0\u00bb\u00a0?",
|
"Do you really want to ban the account \u00ab\u00a0{emailAccount}\u00a0\u00bb\u00a0?": "Do you really want to ban the account \u00ab\u00a0{emailAccount}\u00a0\u00bb\u00a0?",
|
||||||
"Do you really want to ban this account? All of the user's profiles will be deleted.": "Do you really want to ban this account? All of the user's profiles will be deleted.",
|
"Do you really want to ban this account? All of the user's profiles will be deleted.": "Do you really want to ban this account? All of the user's profiles will be deleted.",
|
||||||
|
"Do you really want to unban this account? The user will be able to log-in again.":"Do you really want to unban this account? The user will be able to log-in again.",
|
||||||
"Do you really want to suspend this profile? All of the profiles content will be deleted.": "Do you really want to suspend this profile? All of the profiles content will be deleted.",
|
"Do you really want to suspend this profile? All of the profiles content will be deleted.": "Do you really want to suspend this profile? All of the profiles content will be deleted.",
|
||||||
"Do you wish to {create_event} or {explore_events}?": "Do you wish to {create_event} or {explore_events}?",
|
"Do you wish to {create_event} or {explore_events}?": "Do you wish to {create_event} or {explore_events}?",
|
||||||
"Do you wish to {create_group} or {explore_groups}?": "Do you wish to {create_group} or {explore_groups}?",
|
"Do you wish to {create_group} or {explore_groups}?": "Do you wish to {create_group} or {explore_groups}?",
|
||||||
@@ -1334,6 +1335,9 @@
|
|||||||
"Unable to load event for participation. The error details are provided below:": "Unable to load event for participation. The error details are provided below:",
|
"Unable to load event for participation. The error details are provided below:": "Unable to load event for participation. The error details are provided below:",
|
||||||
"Unable to save your participation in this browser.": "Unable to save your participation in this browser.",
|
"Unable to save your participation in this browser.": "Unable to save your participation in this browser.",
|
||||||
"Unable to update the profile. The avatar picture may be too heavy.": "Unable to update the profile. The avatar picture may be too heavy.",
|
"Unable to update the profile. The avatar picture may be too heavy.": "Unable to update the profile. The avatar picture may be too heavy.",
|
||||||
|
"Unban": "Unban",
|
||||||
|
"Unban the account": "Unban the account",
|
||||||
|
"Unban the account?": "Unban the account?",
|
||||||
"Underline": "Underline",
|
"Underline": "Underline",
|
||||||
"Undo": "Undo",
|
"Undo": "Undo",
|
||||||
"Unfollow": "Unfollow",
|
"Unfollow": "Unfollow",
|
||||||
|
|||||||
@@ -368,6 +368,7 @@
|
|||||||
"Do not receive any mail": "Ne pas recevoir d'e-mail",
|
"Do not receive any mail": "Ne pas recevoir d'e-mail",
|
||||||
"Do you really want to ban the account « {emailAccount} » ?": "Voulez-vous vraiment bannir le compte « {emailAccount} » ?",
|
"Do you really want to ban the account « {emailAccount} » ?": "Voulez-vous vraiment bannir le compte « {emailAccount} » ?",
|
||||||
"Do you really want to ban this account? All of the user's profiles will be deleted.": "Voulez-vous vraiment bannir ce compte ? Tous les profils de cet·te utilisateur·ice seront supprimés.",
|
"Do you really want to ban this account? All of the user's profiles will be deleted.": "Voulez-vous vraiment bannir ce compte ? Tous les profils de cet·te utilisateur·ice seront supprimés.",
|
||||||
|
"Do you really want to unban this account? The user will be able to log-in again.":"Voulez-vous vraiment débannir ce compte ? L'utilisateur pourra à nouveau se connecter.",
|
||||||
"Do you really want to suspend this profile? All of the profiles content will be deleted.": "Voulez-vous vraiment suspendre ce profil ? Tout le contenu du profil sera supprimé.",
|
"Do you really want to suspend this profile? All of the profiles content will be deleted.": "Voulez-vous vraiment suspendre ce profil ? Tout le contenu du profil sera supprimé.",
|
||||||
"Do you wish to {create_event} or {explore_events}?": "Voulez-vous {create_event} ou {explore_events} ?",
|
"Do you wish to {create_event} or {explore_events}?": "Voulez-vous {create_event} ou {explore_events} ?",
|
||||||
"Do you wish to {create_group} or {explore_groups}?": "Voulez-vous {create_group} ou {explore_groups} ?",
|
"Do you wish to {create_group} or {explore_groups}?": "Voulez-vous {create_group} ou {explore_groups} ?",
|
||||||
@@ -1341,6 +1342,9 @@
|
|||||||
"Unable to load event for participation. The error details are provided below:": "Impossible de charger l'événement pour la participation. Les détails de l'erreur sont disponibles ci-dessous :",
|
"Unable to load event for participation. The error details are provided below:": "Impossible de charger l'événement pour la participation. Les détails de l'erreur sont disponibles ci-dessous :",
|
||||||
"Unable to save your participation in this browser.": "Échec de la sauvegarde de votre participation dans ce navigateur.",
|
"Unable to save your participation in this browser.": "Échec de la sauvegarde de votre participation dans ce navigateur.",
|
||||||
"Unable to update the profile. The avatar picture may be too heavy.": "Impossible de mettre à jour le profil. L'image d'avatar est probablement trop lourde.",
|
"Unable to update the profile. The avatar picture may be too heavy.": "Impossible de mettre à jour le profil. L'image d'avatar est probablement trop lourde.",
|
||||||
|
"Unban": "Débannir",
|
||||||
|
"Unban the account": "Débannir le compte",
|
||||||
|
"Unban the account?": "Débannir le compte?",
|
||||||
"Underline": "Souligné",
|
"Underline": "Souligné",
|
||||||
"Undo": "Annuler",
|
"Undo": "Annuler",
|
||||||
"Unfollow": "Ne plus suivre",
|
"Unfollow": "Ne plus suivre",
|
||||||
|
|||||||
@@ -188,12 +188,16 @@
|
|||||||
t("Ban")
|
t("Ban")
|
||||||
}}</o-button>
|
}}</o-button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-else>
|
||||||
v-else
|
<div
|
||||||
class="p-4 mb-4 text-sm text-red-700 bg-red-100 rounded-lg"
|
class="p-4 mb-4 text-sm text-red-700 bg-red-100 rounded-lg"
|
||||||
role="alert"
|
role="alert"
|
||||||
>
|
>
|
||||||
{{ t("The user has been banned") }}
|
{{ t("The user has been banned") }}
|
||||||
|
</div>
|
||||||
|
<o-button @click="unbanAccount" variant="danger">{{
|
||||||
|
t("Unban")
|
||||||
|
}}</o-button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -339,7 +343,11 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { formatBytes } from "@/utils/datetime";
|
import { formatBytes } from "@/utils/datetime";
|
||||||
import { ICurrentUserRole } from "@/types/enums";
|
import { ICurrentUserRole } from "@/types/enums";
|
||||||
import { GET_USER, DELETE_ACCOUNT_AS_MODERATOR } from "../../graphql/user";
|
import {
|
||||||
|
GET_USER,
|
||||||
|
DELETE_ACCOUNT_AS_MODERATOR,
|
||||||
|
UNBAN_ACCOUNT_AS_MODERATOR,
|
||||||
|
} from "../../graphql/user";
|
||||||
import RouteName from "../../router/name";
|
import RouteName from "../../router/name";
|
||||||
import { IUser } from "../../types/current-user.model";
|
import { IUser } from "../../types/current-user.model";
|
||||||
import EmptyContent from "../../components/Utils/EmptyContent.vue";
|
import EmptyContent from "../../components/Utils/EmptyContent.vue";
|
||||||
@@ -484,6 +492,11 @@ const { mutate: deleteUserAccount } = useMutation<
|
|||||||
{ userId: string }
|
{ userId: string }
|
||||||
>(DELETE_ACCOUNT_AS_MODERATOR);
|
>(DELETE_ACCOUNT_AS_MODERATOR);
|
||||||
|
|
||||||
|
const { mutate: unbanUserAccount } = useMutation<
|
||||||
|
{ unbanProfile: { id: string } },
|
||||||
|
{ userId: string }
|
||||||
|
>(UNBAN_ACCOUNT_AS_MODERATOR);
|
||||||
|
|
||||||
const dialog = inject<Dialog>("dialog");
|
const dialog = inject<Dialog>("dialog");
|
||||||
|
|
||||||
const deleteAccount = async (): Promise<void> => {
|
const deleteAccount = async (): Promise<void> => {
|
||||||
@@ -504,6 +517,24 @@ const deleteAccount = async (): Promise<void> => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const unbanAccount = async (): Promise<void> => {
|
||||||
|
dialog?.confirm({
|
||||||
|
title: t("Unban the account?"),
|
||||||
|
message: t(
|
||||||
|
"Do you really want to unban this account? The user will be able to log-in again."
|
||||||
|
),
|
||||||
|
confirmText: t("Unban the account"),
|
||||||
|
cancelText: t("Cancel"),
|
||||||
|
variant: "danger",
|
||||||
|
onConfirm: async () => {
|
||||||
|
unbanUserAccount({
|
||||||
|
userId: props.id,
|
||||||
|
});
|
||||||
|
return router.push({ name: RouteName.USERS });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const acceptAccount = async () => {
|
const acceptAccount = async () => {
|
||||||
isRoleChangeModalActive.value = false;
|
isRoleChangeModalActive.value = false;
|
||||||
await updateUser({
|
await updateUser({
|
||||||
|
|||||||
Reference in New Issue
Block a user