Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions config/kbin_routes/admin.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
admin_users:
controller: App\Controller\Admin\AdminUserController
admin_users_active:
controller: App\Controller\Admin\AdminUsersController::active
defaults: { withFederated: false }
path: /admin/users/{withFederated}
path: /admin/users/active/{withFederated}
methods: [GET]

admin_users_inactive:
controller: App\Controller\Admin\AdminUsersController::inactive
path: /admin/users/inactive
methods: [GET]

admin_users_suspended:
controller: App\Controller\Admin\AdminUsersController::suspended
defaults: { withFederated: false }
path: /admin/users/suspended/{withFederated}
methods: [GET]

admin_users_banned:
controller: App\Controller\Admin\AdminUsersController::banned
defaults: { withFederated: false }
path: /admin/users/banned/{withFederated}
methods: [GET]

admin_reports:
Expand Down
32 changes: 0 additions & 32 deletions src/Controller/Admin/AdminUserController.php

This file was deleted.

75 changes: 75 additions & 0 deletions src/Controller/Admin/AdminUsersController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

namespace App\Controller\Admin;

use App\Controller\AbstractController;
use App\Repository\UserRepository;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Http\Attribute\IsGranted;

class AdminUsersController extends AbstractController
{
public function __construct(private readonly UserRepository $repository, private readonly RequestStack $request)
{
}

#[IsGranted('ROLE_ADMIN')]
public function active(?bool $withFederated = null)
{
return $this->render(
'admin/users.html.twig',
[
'users' => $this->repository->findAllActivePaginated(
(int) $this->request->getCurrentRequest()->get('p', 1),
!($withFederated ?? false)
),
'withFederated' => $withFederated,
]
);
}

#[IsGranted('ROLE_ADMIN')]
public function inactive()
{
return $this->render(
'admin/users.html.twig',
[
'users' => $this->repository->findAllInactivePaginated(
(int) $this->request->getCurrentRequest()->get('p', 1)
),
]
);
}

#[IsGranted('ROLE_ADMIN')]
public function suspended(?bool $withFederated = null)
{
return $this->render(
'admin/users.html.twig',
[
'users' => $this->repository->findAllSuspendedPaginated(
(int) $this->request->getCurrentRequest()->get('p', 1),
!($withFederated ?? false)
),
'withFederated' => $withFederated,
]
);
}

#[IsGranted('ROLE_ADMIN')]
public function banned(?bool $withFederated = null)
{
return $this->render(
'admin/users.html.twig',
[
'users' => $this->repository->findAllBannedPaginated(
(int) $this->request->getCurrentRequest()->get('p', 1),
!($withFederated ?? false)
),
'withFederated' => $withFederated,
]
);
}
}
97 changes: 96 additions & 1 deletion src/Repository/UserRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,69 @@ public function findBlockedUsers(int $page, User $user, int $perPage = self::PER
return $pagerfanta;
}

public function findAllPaginated(int $page, bool $onlyLocal = false): PagerfantaInterface
public function findAllActivePaginated(int $page, bool $onlyLocal = false): PagerfantaInterface
{
$builder = $this->createQueryBuilder('u');
if ($onlyLocal) {
$builder->where('u.apId IS NULL')
->andWhere('u.isVerified = true');
} else {
$builder->where('u.apId IS NOT NULL');
}
$query = $builder
->andWhere('u.visibility = :visibility')
->andWhere('u.isDeleted = false')
->andWhere('u.isBanned = false')
->setParameter('visibility', VisibilityInterface::VISIBILITY_VISIBLE)
->orderBy('u.createdAt', 'ASC')
->getQuery();

$pagerfanta = new Pagerfanta(
new QueryAdapter(
$query
)
);

try {
$pagerfanta->setMaxPerPage(self::PER_PAGE);
$pagerfanta->setCurrentPage($page);
} catch (NotValidCurrentPageException $e) {
throw new NotFoundHttpException();
}

return $pagerfanta;
}

public function findAllInactivePaginated(int $page): PagerfantaInterface
{
$builder = $this->createQueryBuilder('u');

$query = $builder->where('u.apId IS NULL')
->andWhere('u.visibility = :visibility')
->andWhere('u.isVerified = false')
->andWhere('u.isDeleted = false')
->andWhere('u.isBanned = false')
->setParameter('visibility', VisibilityInterface::VISIBILITY_VISIBLE)
->orderBy('u.createdAt', 'ASC')
->getQuery();

$pagerfanta = new Pagerfanta(
new QueryAdapter(
$query
)
);

try {
$pagerfanta->setMaxPerPage(self::PER_PAGE);
$pagerfanta->setCurrentPage($page);
} catch (NotValidCurrentPageException $e) {
throw new NotFoundHttpException();
}

return $pagerfanta;
}

public function findAllBannedPaginated(int $page, bool $onlyLocal = false): PagerfantaInterface
{
$builder = $this->createQueryBuilder('u');
if ($onlyLocal) {
Expand All @@ -248,6 +310,39 @@ public function findAllPaginated(int $page, bool $onlyLocal = false): Pagerfanta
$builder->where('u.apId IS NOT NULL');
}
$query = $builder
->andWhere('u.isBanned = true')
->andWhere('u.isDeleted = false')
->orderBy('u.createdAt', 'ASC')
->getQuery();

$pagerfanta = new Pagerfanta(
new QueryAdapter(
$query
)
);

try {
$pagerfanta->setMaxPerPage(self::PER_PAGE);
$pagerfanta->setCurrentPage($page);
} catch (NotValidCurrentPageException $e) {
throw new NotFoundHttpException();
}

return $pagerfanta;
}

public function findAllSuspendedPaginated(int $page, bool $onlyLocal = false): PagerfantaInterface
{
$builder = $this->createQueryBuilder('u');
if ($onlyLocal) {
$builder->where('u.apId IS NULL');
} else {
$builder->where('u.apId IS NOT NULL');
}
$query = $builder
->andWhere('u.visibility = :visibility')
->andWhere('u.isDeleted = false')
->setParameter('visibility', VisibilityInterface::VISIBILITY_TRASHED)
->orderBy('u.createdAt', 'ASC')
->getQuery();

Expand Down
4 changes: 2 additions & 2 deletions templates/admin/_options.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
</a>
</li>
<li>
<a href="{{ path('admin_users') }}"
class="{{ html_classes({'active': is_route_name('admin_users')}) }}">
<a href="{{ path('admin_users_active') }}"
class="{{ html_classes({'active': is_route_name('admin_users_active') or is_route_name('admin_users_inactive') or is_route_name('admin_users_suspended') or is_route_name('admin_users_banned')}) }}">
{{ 'users'|trans }}
</a>
</li>
Expand Down
53 changes: 43 additions & 10 deletions templates/admin/users.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,41 @@

{% block body %}
{% include 'admin/_options.html.twig' %}

<div class="pills">
<menu>
<li>
<a href="{{ path('admin_users_active') }}"
class="{{ html_classes({'active': is_route_name('admin_users_active')}) }}">
{{ 'admin_users_active'|trans }}
</a>
</li>
<li>
<a href="{{ path('admin_users_inactive') }}"
class="{{ html_classes({'active': is_route_name('admin_users_inactive')}) }}">
{{ 'admin_users_inactive'|trans }}
</a>
</li>
<li>
<a href="{{ path('admin_users_suspended') }}"
class="{{ html_classes({'active': is_route_name('admin_users_suspended')}) }}">
{{ 'admin_users_suspended'|trans }}
</a>
</li>
<li>
<a href="{{ path('admin_users_banned') }}"
class="{{ html_classes({'active': is_route_name('admin_users_banned')}) }}">
{{ 'admin_users_banned'|trans }}
</a>
</li>
</menu>
</div>

{% if(users.haveToPaginate is defined and users.haveToPaginate) %}
{{ pagerfanta(users, null, {'pageParameter':'[p]'}) }}
{% endif %}
<div class="section" id="content">
{% if withFederated is defined %}
<div class="flex" data-controller="selection">
<label class="select">
<select data-action="selection#changeLocation">"
Expand All @@ -26,36 +57,38 @@
</select>
</label>
</div>
{% endif %}

{% if not users|length %}
<aside class="section section--muted">
<p>{{ 'empty'|trans }}</p>
</aside>

{% else %}

<table>
<thead>
<tr>
<th>{{ 'username'|trans }}</th>
<th>{{ 'email'|trans }}</th>
<th>{{ 'created_at'|trans }}</th>
<th>{{ 'last_active'|trans }}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for user in users %}
{% if not user.isDeleted %}
<tr>
<td>{{ component('user_inline', {user: user}) }}</td>
<td>{{ user.apId ? '-' : user.email }}</td>
<td>{{ component('date', {date: user.createdAt}) }}</td>
<td>{{ component('date', {date: user.lastActive}) }}</td>
<td>
<button class="btn btn__secondary">{{ (user.isVerified or user.apId) and not user.isBanned ? 'active'|trans : 'inactive'|trans }}</button>
<button class="btn btn__secondary">{{ user.apId ? 'federated'|trans : 'local'|trans }}</button>
{% if user.isTotpAuthenticationEnabled %}
<button class="btn btn__secondary" title="{{ '2fa.user_active_tfa.title'|trans }}" aria-label="{{ '2fa.user_active_tfa.title'|trans }}"><i class="fa fa-mobile" aria-hidden="true"></i></button>
{% endif %}
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>

{% endif %}

</div>
{% if(users.haveToPaginate is defined and users.haveToPaginate) %}
{{ pagerfanta(users, null, {'pageParameter':'[p]'}) }}
Expand Down
5 changes: 4 additions & 1 deletion translations/messages.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,6 @@ meta: Meta
instance: Instance
pages: Pages
FAQ: FAQ
inactive: Inactive
type_search_term: Type search term
federation_enabled: Federation enabled
registrations_enabled: Registration enabled
Expand Down Expand Up @@ -883,3 +882,7 @@ last_failed_contact: Last failed contact
magazine_posting_restricted_to_mods: Restrict thread creation to moderators
new_user_description: This user is new (active for less than %days% days)
new_magazine_description: This magazine is new (active for less than %days% days)
admin_users_active: Active
admin_users_inactive: Inactive
admin_users_suspended: Suspended
admin_users_banned: Banned