PHRAS-3754 admin - user detail - Record ACL tab (#4148)

* record acl tab in admin

* fix email locked, limit record right to 200

* fix

* add filter

* update

* feed element, basket element

* feed list

* feed entries

* when not expand

* some improvement
This commit is contained in:
Aina Sitraka
2022-10-26 00:21:25 +03:00
committed by GitHub
parent 19b4f6d06b
commit 69ccdefb51
10 changed files with 742 additions and 141 deletions

View File

@@ -16,16 +16,20 @@ use Alchemy\Phrasea\Controller\Controller;
use Alchemy\Phrasea\Core\Response\CSVFileResponse;
use Alchemy\Phrasea\Helper\User as UserHelper;
use Alchemy\Phrasea\Model\Entities\AuthFailure;
use Alchemy\Phrasea\Model\Entities\Feed;
use Alchemy\Phrasea\Model\Entities\FtpCredential;
use Alchemy\Phrasea\Model\Entities\User;
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
use Alchemy\Phrasea\Model\Manipulator\RegistrationManipulator;
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
use Alchemy\Phrasea\Model\NativeQueryProvider;
use Alchemy\Phrasea\Model\Repositories\FeedEntryRepository;
use Alchemy\Phrasea\Model\Repositories\FeedRepository;
use Alchemy\Phrasea\Model\Repositories\RegistrationRepository;
use Alchemy\Phrasea\Model\Repositories\UserRepository;
use Alchemy\Phrasea\Notification\Mail\MailSuccessEmailUpdate;
use Alchemy\Phrasea\Notification\Receiver;
use Doctrine\ORM\EntityManager;
use Goodby\CSV\Export\Protocol\ExporterInterface;
use Goodby\CSV\Import\Standard\Interpreter;
use Symfony\Component\HttpFoundation\Request;
@@ -39,7 +43,88 @@ class UserController extends Controller
public function editRightsAction(Request $request)
{
$rights = $this->getUserEditHelper($request);
return $this->render('admin/editusers.html.twig', $rights->get_users_rights());
return $this->render('admin/editusers.html.twig',
array_merge($rights->get_user_records_rights(),
$rights->getFeeds(),
$rights->getBasketElements(),
$rights->get_users_rights())
);
}
public function listRecordAcl(Request $request)
{
$rights = $this->getUserEditHelper($request);
$results = $rights->get_user_records_rights($request->query->get('userId'), $request->query->get('databoxId'), $request->query->get('recordId'));
return $this->app->json([
'content' => $this->render('admin/user/records_list.html.twig', ['records_acl' => $results['records_acl']]),
'total_count' => $results['total_count'],
'total_result' => count($results['records_acl'])
]);
}
public function deleteFeedEntry(Request $request)
{
/** @var EntityManager $manager */
$manager = $this->app['orm.em'];
/** @var FeedEntryRepository $feedEntryRepo */
$feedEntryRepo = $this->app['repo.feed-entries'];
/** @var Feed|null $feed */
$feedEntry = $feedEntryRepo->find($request->request->get('feedEntryId'));
if ($feedEntry == null) {
return $this->app->json(['success' => false, 'message' => 'publication not found']);
}
$manager->remove($feedEntry);
$manager->flush();
return $this->app->json(['success' => true]);
}
public function listFeedEntry(Request $request)
{
/** @var UserRepository $userRepo */
$userRepo = $this->app['repo.users'];
$user = $userRepo->find($request->query->get('userId'));
// when not expand
if ($request->query->get('feedId') == null) {
return $this->app->json(['content' => '']);
}
/** @var FeedRepository $feedsRepository */
$feedsRepository = $this->app['repo.feeds'];
/** @var Feed|null $feed */
$feed = $feedsRepository->find($request->query->get('feedId'));
if ($feed == null || $user == null) {
return $this->app->json(['content' => 'Give feed_id or user_id']);
} else {
/** @var FeedEntryRepository $feedEntryRepo */
$feedEntryRepo = $this->app['repo.feed-entries'];
$feedEntryRepo->getByUserAndFeed($user, $feed);
return $this->app->json(['content' => $this->render('admin/user/records_list.html.twig', [
'feed_entries' => $feedEntryRepo->getByUserAndFeed($user, $feed)
]),
'feed_entries_count' => $feedEntryRepo->getByUserAndFeed($user, $feed, true)
]);
}
}
public function listRecordBasket(Request $request)
{
$rights = $this->getUserEditHelper($request);
$results = $rights->getBasketElements($request->query->get('userId'), $request->query->get('databoxId'), $request->query->get('recordId'));
return $this->app->json([
'content' => $this->render('admin/user/records_list.html.twig', ['basket_elements' => $results['basket_elements']]),
'total_count' => $results['basket_elements_count'],
'total_result' => count($results['basket_elements'])
]);
}
public function resetRightsAction(Request $request)

View File

@@ -86,6 +86,10 @@ class Users implements ControllerProviderInterface, ServiceProviderInterface
->bind('users_import_csv');
$controllers->get('/import/example/rtf/', 'controller.admin.users:importRtfExampleAction')
->bind('users_import_rtf');
$controllers->get('/records-acl/', 'controller.admin.users:listRecordAcl');
$controllers->get('/feed-entry/', 'controller.admin.users:listFeedEntry');
$controllers->post('/feed-entry/delete/', 'controller.admin.users:deleteFeedEntry');
$controllers->get('/records-basket/', 'controller.admin.users:listRecordBasket');
return $controllers;
}

View File

@@ -15,8 +15,12 @@ use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Application\Helper\NotifierAware;
use Alchemy\Phrasea\Core\LazyLocator;
use Alchemy\Phrasea\Exception\InvalidArgumentException;
use Alchemy\Phrasea\Model\Entities\Feed;
use Alchemy\Phrasea\Model\Entities\User;
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
use Alchemy\Phrasea\Model\Repositories\BasketElementRepository;
use Alchemy\Phrasea\Model\Repositories\FeedEntryRepository;
use Alchemy\Phrasea\Model\Repositories\FeedRepository;
use Alchemy\Phrasea\Notification\Mail\MailSuccessEmailUpdate;
use Alchemy\Phrasea\Notification\Receiver;
use Doctrine\DBAL\Connection;
@@ -205,6 +209,133 @@ class Edit extends \Alchemy\Phrasea\Helper\Helper
return $out;
}
public function getFeeds($userId = null)
{
if (empty($userId)) {
if (count($this->users) == 1) {
$userId = current($this->users);
} else {
return [
'feeds' => [],
];
}
}
$user = $this->app['repo.users']->find($userId);
/** @var FeedRepository $feedsRepository */
$feedsRepository = $this->app['repo.feeds'];
$feeds = $feedsRepository->getUserFeed($user);
/** @var FeedEntryRepository $feedEntryRepo */
$feedEntryRepo = $this->app['repo.feed-entries'];
$feedCount = [];
/** @var Feed $feed */
foreach ($feeds as $feed) {
$feedCount[$feed->getId()] = $feedEntryRepo->getByUserAndFeed($user, $feed, true);
}
return [
'feeds' => $feedsRepository->getUserFeed($user),
'feeds_count' => $feedCount
];
}
public function getBasketElements($userId = null, $databoxId = null, $recordId = null)
{
if (empty($userId)) {
if (count($this->users) == 1) {
$userId = current($this->users);
} else {
return [
'basket_elements' => [],
];
}
}
$user = $this->app['repo.users']->find($userId);
/** @var BasketElementRepository $basketElementRepository */
$basketElementRepository = $this->app['repo.basket-elements'];
return [
'basket_elements' => $basketElementRepository->getElements($user, $databoxId, $recordId),
'basket_elements_count' => $basketElementRepository->getElementsCount($user, $databoxId, $recordId)
];
}
public function get_user_records_rights($userId = null, $databoxId = null, $recordId = null)
{
$rows = [];
$totalCount = 0;
$databoxIds = array_map(function (\databox $databox) {
return $databox->get_sbas_id();
},
$this->app->getApplicationBox()->get_databoxes()
);
if (empty($userId)) {
if (count($this->users) == 1) {
$userId = current($this->users);
} else {
return [
'records_acl' => $rows,
'total_count' => $totalCount,
'databoxIds' => $databoxIds
];
}
}
$whereClause = "WHERE rr.usr_id = :usr_id";
$params[':usr_id'] = $userId;
if (!empty($databoxId)) {
$whereClause .= " AND rr.sbas_id= :databox_id";
$params[':databox_id'] = $databoxId;
}
if (!empty($recordId)) {
$whereClause .= " AND rr.record_id= :record_id";
$params[':record_id'] = $recordId;
}
$sql = "SELECT rr.sbas_id, rr.record_id, rr.preview, rr.document, rr.`case` as type, \n"
. "IF(TRIM(p.last_name)!='' OR TRIM(p.first_name)!='', \n"
. " CONCAT_WS(' ', p.last_name, p.first_name),\n"
. " IF(TRIM(p.email)!='', p.email, p.login)\n"
. ") as pusher_name\n"
. " FROM records_rights rr \n"
. " INNER JOIN sbas ON sbas.sbas_id = rr.sbas_id\n"
. " JOIN Users as p ON p.id = rr.pusher_usr_id\n"
. $whereClause
. " ORDER BY rr.id DESC limit 200 \n"
;
$stmt = $this->app->getApplicationBox()->get_connection()->prepare($sql);
$stmt->execute($params);
$rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$stmt->closeCursor();
$sql = "SELECT count(*) as nb \n"
. " FROM records_rights rr \n"
. " INNER JOIN sbas ON sbas.sbas_id = rr.sbas_id\n"
. $whereClause
;
$stmt = $this->app->getApplicationBox()->get_connection()->prepare($sql);
$stmt->execute($params);
$totalCount = $stmt->fetchColumn();
$stmt->closeCursor();
return [
'records_acl' => $rows,
'total_count' => $totalCount,
'databoxIds' => $databoxIds
];
}
public function get_quotas()
{
$this->base_id = (int) $this->request->get('base_id');

View File

@@ -233,4 +233,50 @@ DQL;
return $builder->getQuery()->getResult();
}
public function getElements(User $user, $databoxId = null, $recordId = null, $nbElement = 200)
{
$qb = $this->createQueryBuilder('be');
$qb->innerJoin('be.basket', 'b');
$qb->where($qb->expr()->eq('b.user', ':user'));
$qb->setParameter(':user', $user);
if ($databoxId != null) {
$qb->andWhere('be.sbas_id = :databoxId');
$qb->setParameter(':databoxId', $databoxId);
}
if ($recordId != null) {
$qb->andWhere('be.record_id = :recordId');
$qb->setParameter(':recordId', $recordId);
}
$qb->orderBy('be.id', 'DESC');
$qb->setMaxResults($nbElement);
return $qb->getQuery()->getResult();
}
public function getElementsCount(User $user, $databoxId = null, $recordId = null)
{
$qb = $this->createQueryBuilder('be');
$qb->select('count(be)');
$qb->innerJoin('be.basket', 'b');
$qb->where($qb->expr()->eq('b.user', ':user'));
$qb->setParameter(':user', $user);
if ($databoxId != null) {
$qb->andWhere('be.sbas_id = :databoxId');
$qb->setParameter(':databoxId', $databoxId);
}
if ($recordId != null) {
$qb->andWhere('be.record_id = :recordId');
$qb->setParameter(':recordId', $recordId);
}
return $qb->getQuery()->getSingleScalarResult();
}
}

View File

@@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\Model\Repositories;
use Alchemy\Phrasea\Model\Entities\Feed;
use Alchemy\Phrasea\Model\Entities\FeedEntry;
use Alchemy\Phrasea\Model\Entities\User;
use Doctrine\ORM\EntityRepository;
/**
@@ -64,4 +65,24 @@ class FeedEntryRepository extends EntityRepository
return $builder->getQuery()->getSingleScalarResult();
}
public function getByUserAndFeed(User $user, Feed $feed, $isCount = false)
{
$qb = $this->createQueryBuilder('fe');
$qb->innerJoin('fe.publisher', 'fp');
$qb->where($qb->expr()->eq('fp.user', ':publisher'));
$qb->setParameter(':publisher', $user);
$qb->andWhere($qb->expr()->eq('fe.feed', ':feed'));
$qb->setParameter(':feed', $feed);
if ($isCount) {
$qb->select('count(fe)');
return $qb->getQuery()->getSingleScalarResult();
} else {
$qb->orderBy('fe.id', 'DESC');
return $qb->getQuery()->getResult();
}
}
}

View File

@@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\Model\Repositories;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Model\Entities\FeedItem;
use Alchemy\Phrasea\Model\Entities\User;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -103,4 +104,52 @@ class FeedItemRepository extends EntityRepository
return $items;
}
public function getItemsCount(User $user, $databoxId = null, $recordId = null)
{
$qb = $this->createQueryBuilder('fi');
$qb->select('count(fi)');
$qb->innerjoin('fi.entry', 'fe');
$qb->innerjoin('fe.publisher', 'fp');
$qb->where($qb->expr()->eq('fp.user', ':publisher'));
$qb->setParameter(':publisher', $user);
if ($databoxId != null) {
$qb->andWhere('fi.sbasId = :databoxId');
$qb->setParameter(':databoxId', $databoxId);
}
if ($recordId != null) {
$qb->andWhere('fi.recordId = :recordId');
$qb->setParameter(':recordId', $recordId);
}
return $qb->getQuery()->getSingleScalarResult();
}
public function getLastItems(User $user, $databoxId = null, $recordId = null, $nbItems = 200)
{
$qb = $this->createQueryBuilder('fi');
$qb->innerjoin('fi.entry', 'fe');
$qb->innerjoin('fe.publisher', 'fp');
$qb->where($qb->expr()->eq('fp.user', ':publisher'));
$qb->setParameter(':publisher', $user);
if ($databoxId != null) {
$qb->andWhere('fi.sbasId = :databoxId');
$qb->setParameter(':databoxId', $databoxId);
}
if ($recordId != null) {
$qb->andWhere('fi.recordId = :recordId');
$qb->setParameter(':recordId', $recordId);
}
$qb->orderBy('fi.id', 'DESC');
$qb->setMaxResults($nbItems);
return $qb->getQuery()->getResult();
}
}

View File

@@ -12,6 +12,7 @@
namespace Alchemy\Phrasea\Model\Repositories;
use Alchemy\Phrasea\Model\Entities\Feed;
use Alchemy\Phrasea\Model\Entities\User;
use Doctrine\ORM\EntityRepository;
/**
@@ -108,4 +109,14 @@ class FeedRepository extends EntityRepository
return $qb->getQuery()->getResult();
}
public function getUserFeed(User $user)
{
$qb = $this->createQueryBuilder('f');
$qb->innerJoin('f.publishers', 'fp');
$qb->where($qb->expr()->eq('fp.user', ':publisher'));
$qb->setParameter(':publisher', $user);
return $qb->getQuery()->getResult();
}
}

View File

@@ -472,7 +472,6 @@ class WorkerRunningJobRepository extends EntityRepository
}
return $qb->getQuery()->getSingleScalarResult();
}
public function updateStatusRunningToCanceledSinceCreated($hour = 0)