mirror of
https://code.castopod.org/adaures/castopod
synced 2025-04-23 01:01:20 +00:00
303 lines
8.3 KiB
PHP
303 lines
8.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* @copyright 2020 Ad Aures
|
|
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
|
* @link https://castopod.org/
|
|
*/
|
|
|
|
use App\Entities\Podcast;
|
|
use App\Models\ActorModel;
|
|
use App\Models\PodcastModel;
|
|
use CodeIgniter\Shield\Entities\User;
|
|
use Modules\Auth\Auth;
|
|
use Modules\Fediverse\Entities\Actor;
|
|
use Modules\Fediverse\Models\NotificationModel;
|
|
|
|
if (! function_exists('auth')) {
|
|
/**
|
|
* Provides convenient access to the main Auth class for CodeIgniter Shield.
|
|
*
|
|
* @param string|null $alias Authenticator alias
|
|
*/
|
|
function auth(?string $alias = null): Auth
|
|
{
|
|
/** @var Auth $auth */
|
|
$auth = service('auth');
|
|
|
|
return $auth->setAuthenticator($alias);
|
|
}
|
|
}
|
|
|
|
if (! function_exists('set_interact_as_actor')) {
|
|
/**
|
|
* Sets the actor id of which the user is acting as
|
|
*/
|
|
function set_interact_as_actor(int $actorId): void
|
|
{
|
|
if (auth()->loggedIn()) {
|
|
session()
|
|
->set('interact_as_actor_id', $actorId);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! function_exists('remove_interact_as_actor')) {
|
|
/**
|
|
* Removes the actor id of which the user is acting as
|
|
*/
|
|
function remove_interact_as_actor(): void
|
|
{
|
|
session()->remove('interact_as_actor_id');
|
|
}
|
|
}
|
|
|
|
if (! function_exists('interact_as_actor_id')) {
|
|
/**
|
|
* Sets the podcast id of which the user is acting as
|
|
*/
|
|
function interact_as_actor_id(): ?int
|
|
{
|
|
return session()->get('interact_as_actor_id');
|
|
}
|
|
}
|
|
|
|
if (! function_exists('interact_as_actor')) {
|
|
/**
|
|
* Get the actor the user is currently interacting as
|
|
*/
|
|
function interact_as_actor(): ?Actor
|
|
{
|
|
if (! auth()->loggedIn()) {
|
|
return null;
|
|
}
|
|
|
|
$session = session();
|
|
if (! $session->has('interact_as_actor_id')) {
|
|
return null;
|
|
}
|
|
|
|
return model(ActorModel::class, false)->getActorById($session->get('interact_as_actor_id'));
|
|
}
|
|
}
|
|
|
|
if (! function_exists('can_user_interact')) {
|
|
function can_user_interact(): bool
|
|
{
|
|
return (bool) interact_as_actor();
|
|
}
|
|
}
|
|
|
|
if (! function_exists('add_podcast_group')) {
|
|
function add_podcast_group(User $user, int $podcastId, string $group): User
|
|
{
|
|
$podcastGroup = 'podcast#' . $podcastId . '-' . $group;
|
|
|
|
return $user->addGroup($podcastGroup);
|
|
}
|
|
}
|
|
|
|
if (! function_exists('get_instance_group')) {
|
|
function get_instance_group(User $user): ?string
|
|
{
|
|
$instanceGroups = array_filter($user->getGroups() ?? [], static function ($group): bool {
|
|
return ! str_starts_with($group, 'podcast#');
|
|
});
|
|
|
|
if ($instanceGroups === []) {
|
|
return null;
|
|
}
|
|
|
|
$instanceGroup = array_shift($instanceGroups);
|
|
|
|
// Verify that a user belongs to one group only!
|
|
if ($instanceGroups !== []) {
|
|
// remove any other group the user belongs to
|
|
$user->removeGroup(...$instanceGroups);
|
|
}
|
|
|
|
return $instanceGroup;
|
|
}
|
|
}
|
|
|
|
if (! function_exists('set_instance_group')) {
|
|
function set_instance_group(User $user, string $group): User
|
|
{
|
|
// remove old instance group
|
|
if (get_instance_group($user)) {
|
|
$user->removeGroup(get_instance_group($user));
|
|
}
|
|
|
|
// set new group
|
|
return $user->addGroup($group);
|
|
}
|
|
}
|
|
|
|
if (! function_exists('get_podcast_group')) {
|
|
function get_podcast_group(User $user, int $podcastId, bool $removePrefix = true): ?string
|
|
{
|
|
$podcastGroups = array_filter($user->getGroups() ?? [], static function ($group) use ($podcastId): bool {
|
|
return str_starts_with($group, "podcast#{$podcastId}-");
|
|
});
|
|
|
|
if ($podcastGroups === []) {
|
|
return null;
|
|
}
|
|
|
|
$podcastGroup = array_shift($podcastGroups);
|
|
|
|
// Verify that a user belongs to one group only!
|
|
if ($podcastGroups !== []) {
|
|
// remove any other group the user belongs to
|
|
$user->removeGroup(...$podcastGroups);
|
|
}
|
|
|
|
if ($removePrefix) {
|
|
// strip the `podcast#{id}-` prefix when returning group
|
|
return substr((string) $podcastGroup, strlen('podcast#' . $podcastId . '-'));
|
|
}
|
|
|
|
return $podcastGroup;
|
|
}
|
|
}
|
|
|
|
if (! function_exists('set_podcast_group')) {
|
|
function set_podcast_group(User $user, int $podcastId, string $group): User
|
|
{
|
|
// remove old instance group
|
|
$user->removeGroup("podcast#{$podcastId}-" . get_podcast_group($user, $podcastId));
|
|
|
|
// set new group
|
|
return add_podcast_group($user, $podcastId, $group);
|
|
}
|
|
}
|
|
|
|
if (! function_exists('get_podcast_groups')) {
|
|
/**
|
|
* @return string[]
|
|
*/
|
|
function get_user_podcast_ids(User $user): array
|
|
{
|
|
$podcastGroups = array_filter($user->getGroups() ?? [], static function ($group): bool {
|
|
return str_starts_with($group, 'podcast#');
|
|
});
|
|
|
|
$userPodcastIds = [];
|
|
// extract all podcast ids from groups
|
|
foreach ($podcastGroups as $podcastGroup) {
|
|
// extract podcast id from group and add it to the list of ids
|
|
preg_match('~podcast#(\d+)-[a-z]+~', (string) $podcastGroup, $matches);
|
|
$userPodcastIds[] = $matches[1];
|
|
}
|
|
|
|
return $userPodcastIds;
|
|
}
|
|
}
|
|
|
|
if (! function_exists('can_podcast')) {
|
|
function can_podcast(User $user, int $podcastId, string $permission): bool
|
|
{
|
|
return $user->can('podcast#' . $podcastId . '.' . $permission);
|
|
}
|
|
}
|
|
|
|
if (! function_exists('get_user_podcasts')) {
|
|
/**
|
|
* Returns the podcasts the user is contributing to
|
|
*
|
|
* @return Podcast[]
|
|
*/
|
|
function get_user_podcasts(User $user): array
|
|
{
|
|
return (new PodcastModel())->getUserPodcasts($user->id, get_user_podcast_ids($user));
|
|
}
|
|
}
|
|
|
|
if (! function_exists('get_podcasts_user_can_interact_with')) {
|
|
/**
|
|
* @return Podcast[]
|
|
*/
|
|
function get_podcasts_user_can_interact_with(User $user): array
|
|
{
|
|
$userPodcasts = (new PodcastModel())->getUserPodcasts($user->id, get_user_podcast_ids($user));
|
|
|
|
$hasInteractAsPrivilege = interact_as_actor_id() === null;
|
|
|
|
if ($userPodcasts === []) {
|
|
if ($hasInteractAsPrivilege) {
|
|
remove_interact_as_actor();
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
$isInteractAsPrivilegeLost = true;
|
|
$podcastsUserCanInteractWith = [];
|
|
foreach ($userPodcasts as $userPodcast) {
|
|
if (can_podcast($user, $userPodcast->id, 'interact-as')) {
|
|
if (interact_as_actor_id() === $userPodcast->actor_id) {
|
|
$isInteractAsPrivilegeLost = false;
|
|
}
|
|
|
|
$podcastsUserCanInteractWith[] = $userPodcast;
|
|
}
|
|
}
|
|
|
|
if ($podcastsUserCanInteractWith === []) {
|
|
if (interact_as_actor_id() !== null) {
|
|
remove_interact_as_actor();
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
// check if user has lost the interact as privilege for current podcast actor.
|
|
// --> Remove interact as if there's no podcast actor to interact as
|
|
// or set the first podcast actor the user can interact as
|
|
if ($isInteractAsPrivilegeLost) {
|
|
set_interact_as_actor($podcastsUserCanInteractWith[0]->actor_id);
|
|
}
|
|
|
|
return $podcastsUserCanInteractWith;
|
|
}
|
|
}
|
|
|
|
if (! function_exists('get_actor_ids_with_unread_notifications')) {
|
|
/**
|
|
* Returns the ids of the user's actors that have unread notifications
|
|
*
|
|
* @return int[]
|
|
*/
|
|
function get_actor_ids_with_unread_notifications(User $user): array
|
|
{
|
|
if (($userPodcasts = get_user_podcasts($user)) === []) {
|
|
return [];
|
|
}
|
|
|
|
$unreadNotifications = (new NotificationModel())->whereIn(
|
|
'target_actor_id',
|
|
array_column($userPodcasts, 'actor_id')
|
|
)
|
|
->where('read_at', null)
|
|
->findAll();
|
|
|
|
return array_column($unreadNotifications, 'target_actor_id');
|
|
}
|
|
}
|
|
|
|
if (! function_exists('get_group_title')) {
|
|
/**
|
|
* @return array<'title'|'description', string>
|
|
*/
|
|
function get_group_info(string $group, ?int $podcastId = null): array
|
|
{
|
|
if ($podcastId === null) {
|
|
return setting('AuthGroups.instanceGroups')[$group];
|
|
}
|
|
|
|
return setting('AuthGroups.podcastGroups')[$group];
|
|
}
|
|
}
|