Add new public_calendar additional feature

- This gives anonymous access to public events
This commit is contained in:
Hypolite Petovan 2022-11-30 17:52:19 -05:00
parent ae76fa1174
commit 84b2a35e05
6 changed files with 169 additions and 162 deletions

View file

@ -120,6 +120,12 @@ class Feature
['tagadelic', DI::l10n()->t('Tag Cloud'), DI::l10n()->t('Provide a personal tag cloud on your profile page'), false, DI::config()->get('feature_lock', 'tagadelic', false)], ['tagadelic', DI::l10n()->t('Tag Cloud'), DI::l10n()->t('Provide a personal tag cloud on your profile page'), false, DI::config()->get('feature_lock', 'tagadelic', false)],
['profile_membersince', DI::l10n()->t('Display Membership Date'), DI::l10n()->t('Display membership date in profile'), false, DI::config()->get('feature_lock', 'profile_membersince', false)], ['profile_membersince', DI::l10n()->t('Display Membership Date'), DI::l10n()->t('Display membership date in profile'), false, DI::config()->get('feature_lock', 'profile_membersince', false)],
], ],
//Advanced Calendar Settings
'advanced_calendar' => [
DI::l10n()->t('Advanced Calendar Settings'),
['public_calendar', DI::l10n()->t('Allow anonymous access to your calendar'), DI::l10n()->t('Allows anonymous visitors to consult your calendar and your public events. Contact birthday events are private to you.'), false, DI::config()->get('feature_lock', 'public_calendar', false)],
]
]; ];
// removed any locked features and remove the entire category if this makes it empty // removed any locked features and remove the entire category if this makes it empty

View file

@ -21,6 +21,7 @@
namespace Friendica\Model; namespace Friendica\Model;
use Friendica\Content\Feature;
use Friendica\Content\Text\BBCode; use Friendica\Content\Text\BBCode;
use Friendica\Core\Hook; use Friendica\Core\Hook;
use Friendica\Core\Logger; use Friendica\Core\Logger;
@ -28,8 +29,7 @@ use Friendica\Core\Renderer;
use Friendica\Core\System; use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Network\HTTPException\NotFoundException; use Friendica\Network\HTTPException;
use Friendica\Network\HTTPException\UnauthorizedException;
use Friendica\Protocol\Activity; use Friendica\Protocol\Activity;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Map; use Friendica\Util\Map;
@ -503,25 +503,30 @@ class Event
* @param string $nickname * @param string $nickname
* *
* @return array the owner array * @return array the owner array
* @throws NotFoundException The given nickname does not exist * @throws HTTPException\InternalServerErrorException
* @throws UnauthorizedException The access for the given nickname is restricted * @throws HTTPException\NotFoundException The given nickname does not exist
* @throws HTTPException\UnauthorizedException The access for the given nickname is restricted
*/ */
public static function getOwnerForNickname(string $nickname): array public static function getOwnerForNickname(string $nickname): array
{ {
$owner = User::getOwnerDataByNick($nickname); $owner = User::getOwnerDataByNick($nickname);
if (empty($owner) || $owner['account_removed'] || $owner['account_expired']) { if (empty($owner) || $owner['account_removed'] || $owner['account_expired']) {
throw new NotFoundException(DI::l10n()->t('User not found.')); throw new HTTPException\NotFoundException(DI::l10n()->t('User not found.'));
} }
if ($owner['hidewall'] && !DI::userSession()->isAuthenticated()) { if (!DI::userSession()->isAuthenticated() && $owner['hidewall']) {
throw new UnauthorizedException(DI::l10n()->t('Access to this profile has been restricted.')); throw new HTTPException\UnauthorizedException(DI::l10n()->t('Access to this profile has been restricted.'));
}
if (!DI::userSession()->isAuthenticated() && !Feature::isEnabled($owner['uid'], 'public_calendar')) {
throw new HTTPException\UnauthorizedException(DI::l10n()->t('Permission denied.'));
} }
return $owner; return $owner;
} }
/** /**
* Get an event by its event ID. * Get an event by its event ID. Checks permissions.
* *
* @param int $owner_uid The User ID of the owner of the event * @param int $owner_uid The User ID of the owner of the event
* @param int $event_id The ID of the event in the event table * @param int $event_id The ID of the event in the event table
@ -529,37 +534,32 @@ class Event
* @return array Query result * @return array Query result
* @throws \Exception * @throws \Exception
*/ */
public static function getByIdAndUid(int $owner_uid, int $event_id, string $nickname = null): array public static function getByIdAndUid(int $owner_uid, int $event_id): array
{ {
if (!empty($nickname)) {
$owner = static::getOwnerForNickname($nickname);
$owner_uid = $owner['uid'];
// get the permissions
$sql_perms = Item::getPermissionsSQLByUserId($owner_uid);
// we only want to have the events of the profile owner
$sql_extra = " AND `event`.`cid` = 0 " . $sql_perms;
} else {
$sql_extra = "";
}
// Only allow events if there is a valid owner_id. // Only allow events if there is a valid owner_id.
if ($owner_uid == 0) { if ($owner_uid == 0) {
return []; return [];
} }
// Query for the event by event id // get the permissions
$events = DBA::toArray(DBA::p("SELECT `event`.*, `post-user`.`id` AS `itemid` FROM `event` $sql_perms = Item::getPermissionsSQLByUserId($owner_uid);
LEFT JOIN `post-user` ON `post-user`.`event-id` = `event`.`id` AND `post-user`.`uid` = `event`.`uid`
WHERE `event`.`uid` = ? AND `event`.`id` = ? $sql_extra",
$owner_uid, $event_id));
// Query for the event by event id
$events = DBA::toArray(DBA::p(
"SELECT `event`.*, `post-user`.`id` AS `itemid` FROM `event`
LEFT JOIN `post-user`
ON `post-user`.`event-id` = `event`.`id`
AND `post-user`.`uid` = `event`.`uid`
WHERE `event`.`id` = ?
AND `event`.`uid` = ?
$sql_perms",
$event_id, $owner_uid
));
if (empty($events)) { if (empty($events)) {
throw new NotFoundException(DI::l10n()->t('Event not found.')); throw new HTTPException\NotFoundException(DI::l10n()->t('Event not found.'));
} else {
$events = self::removeDuplicates($events);
return $events[0];
} }
return $events[0];
} }
/** /**
@ -568,34 +568,23 @@ class Event
* @param int $owner_uid The User ID of the owner of the events. * @param int $owner_uid The User ID of the owner of the events.
* @param string|null $start Start time of the timeframe. * @param string|null $start Start time of the timeframe.
* @param string|null $finish Finish time of the timeframe. * @param string|null $finish Finish time of the timeframe.
* @param bool $ignore * @param bool|null $ignore Filters ignored events (false: unignored events, true: ignored events, null: all events)
* @param string|null $nickname
* *
* @return array Query results. * @return array Query results.
* @throws NotFoundException * @throws HTTPException\NotFoundException
* @throws UnauthorizedException * @throws HTTPException\UnauthorizedException
*/ */
public static function getListByDate(int $owner_uid, string $start = null, string $finish = null, bool $ignore = false, string $nickname = null): array public static function getListByDate(int $owner_uid, string $start = null, string $finish = null, ?bool $ignore = false): array
{ {
if (!empty($nickname)) {
$owner = static::getOwnerForNickname($nickname);
$owner_uid = $owner['uid'];
// get the permissions
$sql_perms = Item::getPermissionsSQLByUserId($owner_uid);
// we only want to have the events of the profile owner
$sql_extra = " AND `event`.`cid` = 0 " . $sql_perms;
} else {
$sql_extra = "";
}
// Only allow events if there is a valid owner_id. // Only allow events if there is a valid owner_id.
if ($owner_uid == 0) { if ($owner_uid == 0) {
return []; return [];
} }
if (empty($start) || empty($finish)) { // get the permissions
$sql_perms = Item::getPermissionsSQLByUserId($owner_uid);
if (empty($start) || empty($finish)) {
$y = intval(DateTimeFormat::localNow('Y')); $y = intval(DateTimeFormat::localNow('Y'));
$m = intval(DateTimeFormat::localNow('m')); $m = intval(DateTimeFormat::localNow('m'));
@ -607,41 +596,36 @@ class Event
} }
} }
if ($ignore === true) {
$sql_ignore = " AND `event`.`ignore` = 1";
} elseif ($ignore === false) {
$sql_ignore = " AND `event`.`ignore` = 0";
} else {
$sql_ignore = "";
}
// Query for the event by date. // Query for the event by date.
$events = DBA::toArray(DBA::p("SELECT `event`.*, `post-user`.`id` AS `itemid` FROM `event` $events = DBA::toArray(DBA::p(
LEFT JOIN `post-user` ON `post-user`.`event-id` = `event`.`id` AND `post-user`.`uid` = `event`.`uid` "SELECT `event`.*, `post-user`.`id` AS `itemid` FROM `event`
WHERE `event`.`uid` = ? AND `event`.`ignore` = ? LEFT JOIN `post-user`
AND (`finish` >= ? OR (`nofinish` AND `start` >= ?)) AND `start` <= ? ON `post-user`.`event-id` = `event`.`id`
" . $sql_extra, AND `post-user`.`uid` = `event`.`uid`
$owner_uid, $ignore, WHERE `event`.`uid` = ?
$start, $start, $finish $sql_ignore
AND (`finish` >= ? OR (`nofinish` AND `start` >= ?))
AND `start` <= ?
$sql_perms",
$owner_uid,
$start, $start,
$finish
)); ));
$events = self::removeDuplicates($events ?? []); $events = self::removeDuplicates($events);
return self::sortByDate($events); return self::sortByDate($events);
} }
/** /**
* Convert an array query results in an array which could be used by the events template. * Convert an event in an array which could be used by the event template.
*
* @param array $event_result Event query array.
* @return array Event array for the template.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function prepareListForTemplate(array $event_result): array
{
$event_list = [];
foreach ($event_result as $event) {
$event_list[] = static::prepareForItem($event);
}
return $event_list;
}
/**
* Convert an one event in an array which could be used by the events template.
* *
* @param array $event Event query array. * @param array $event Event query array.
* @return array Event array for the template. * @return array Event array for the template.
@ -687,29 +671,25 @@ class Event
[$title, $_trash] = explode("<br", BBCode::convertForUriId($event['uri-id'], Strings::escapeHtml($event['desc'])), BBCode::TWITTER_API); [$title, $_trash] = explode("<br", BBCode::convertForUriId($event['uri-id'], Strings::escapeHtml($event['desc'])), BBCode::TWITTER_API);
} }
$author_link = $event['author-link']; $event['author-link'] = Contact::magicLink($event['author-link']);
$event['summary'] = BBCode::convertForUriId($event['uri-id'], Strings::escapeHtml($event['summary']));
$event['author-link'] = Contact::magicLink($author_link); $event['desc'] = BBCode::convertForUriId($event['uri-id'], Strings::escapeHtml($event['desc']));
$event['location'] = BBCode::convertForUriId($event['uri-id'], Strings::escapeHtml($event['location']));
$html = self::getHTML($event);
$event['summary'] = BBCode::convertForUriId($event['uri-id'], Strings::escapeHtml($event['summary']));
$event['desc'] = BBCode::convertForUriId($event['uri-id'], Strings::escapeHtml($event['desc']));
$event['location'] = BBCode::convertForUriId($event['uri-id'], Strings::escapeHtml($event['location']));
return [ return [
'id' => $event['id'], 'id' => $event['id'],
'start' => $start, 'start' => $start,
'end' => $end, 'end' => $end,
'allDay' => false, 'allDay' => false,
'title' => $title, 'title' => $title,
'j' => $j, 'j' => $j,
'd' => $day, 'd' => $day,
'edit' => $edit, 'edit' => $edit,
'drop' => $drop, 'drop' => $drop,
'copy' => $copy, 'copy' => $copy,
'item' => $event, 'item' => $event,
'html' => $html, 'html' => self::getHTML($event),
'plink' => Item::getPlink($event), 'plink' => Item::getPlink($event),
]; ];
} }
@ -718,8 +698,6 @@ class Event
* *
* @param array $events Query result for events. * @param array $events Query result for events.
* @param string $format The output format (ical/csv). * @param string $format The output format (ical/csv).
*
* @param string $timezone Timezone (missing parameter!)
* @return string Content according to selected export format. * @return string Content according to selected export format.
* *
* @todo Implement timezone support * @todo Implement timezone support
@ -740,8 +718,8 @@ class Event
foreach ($events as $event) { foreach ($events as $event) {
/// @todo The time / date entries don't include any information about the /// @todo The time / date entries don't include any information about the
/// timezone the event is scheduled in :-/ /// timezone the event is scheduled in :-/
$tmp1 = strtotime($event['start']); $tmp1 = strtotime($event['start']);
$tmp2 = strtotime($event['finish']); $tmp2 = strtotime($event['finish']);
$time_format = "%H:%M:%S"; $time_format = "%H:%M:%S";
$date_format = "%Y-%m-%d"; $date_format = "%Y-%m-%d";
@ -783,21 +761,21 @@ class Event
$tmp = $event['summary']; $tmp = $event['summary'];
$tmp = str_replace(PHP_EOL, PHP_EOL . ' ', $tmp); $tmp = str_replace(PHP_EOL, PHP_EOL . ' ', $tmp);
$tmp = addcslashes($tmp, ',;'); $tmp = addcslashes($tmp, ',;');
$o .= 'SUMMARY:' . $tmp . PHP_EOL; $o .= 'SUMMARY:' . $tmp . PHP_EOL;
} }
if ($event['desc']) { if ($event['desc']) {
$tmp = $event['desc']; $tmp = $event['desc'];
$tmp = str_replace(PHP_EOL, PHP_EOL . ' ', $tmp); $tmp = str_replace(PHP_EOL, PHP_EOL . ' ', $tmp);
$tmp = addcslashes($tmp, ',;'); $tmp = addcslashes($tmp, ',;');
$o .= 'DESCRIPTION:' . $tmp . PHP_EOL; $o .= 'DESCRIPTION:' . $tmp . PHP_EOL;
} }
if ($event['location']) { if ($event['location']) {
$tmp = $event['location']; $tmp = $event['location'];
$tmp = str_replace(PHP_EOL, PHP_EOL . ' ', $tmp); $tmp = str_replace(PHP_EOL, PHP_EOL . ' ', $tmp);
$tmp = addcslashes($tmp, ',;'); $tmp = addcslashes($tmp, ',;');
$o .= 'LOCATION:' . $tmp . PHP_EOL; $o .= 'LOCATION:' . $tmp . PHP_EOL;
} }
$o .= 'END:VEVENT' . PHP_EOL; $o .= 'END:VEVENT' . PHP_EOL;
@ -923,42 +901,42 @@ class Event
$tformat = DI::l10n()->t('g:i A'); // 8:01 AM. $tformat = DI::l10n()->t('g:i A'); // 8:01 AM.
// Convert the time to different formats. // Convert the time to different formats.
$dtstart_dt = DI::l10n()->getDay(DateTimeFormat::local($item['event-start'], $dformat)); $dtstart_dt = DI::l10n()->getDay(DateTimeFormat::local($item['event-start'], $dformat));
$dtstart_title = DateTimeFormat::utc($item['event-start'], DateTimeFormat::ATOM); $dtstart_title = DateTimeFormat::utc($item['event-start'], DateTimeFormat::ATOM);
// Format: Jan till Dec. // Format: Jan till Dec.
$month_short = DI::l10n()->getDayShort(DateTimeFormat::local($item['event-start'], 'M')); $month_short = DI::l10n()->getDayShort(DateTimeFormat::local($item['event-start'], 'M'));
// Format: 1 till 31. // Format: 1 till 31.
$date_short = DateTimeFormat::local($item['event-start'], 'j'); $date_short = DateTimeFormat::local($item['event-start'], 'j');
$start_time = DateTimeFormat::local($item['event-start'], $tformat); $start_time = DateTimeFormat::local($item['event-start'], $tformat);
$start_short = DI::l10n()->getDayShort(DateTimeFormat::local($item['event-start'], $dformat_short)); $start_short = DI::l10n()->getDayShort(DateTimeFormat::local($item['event-start'], $dformat_short));
// If the option 'nofinisch' isn't set, we need to format the finish date/time. // If the option 'nofinisch' isn't set, we need to format the finish date/time.
if (!$item['event-nofinish']) { if (!$item['event-nofinish']) {
$finish = true; $finish = true;
$dtend_dt = DI::l10n()->getDay(DateTimeFormat::local($item['event-finish'], $dformat)); $dtend_dt = DI::l10n()->getDay(DateTimeFormat::local($item['event-finish'], $dformat));
$dtend_title = DateTimeFormat::utc($item['event-finish'], DateTimeFormat::ATOM); $dtend_title = DateTimeFormat::utc($item['event-finish'], DateTimeFormat::ATOM);
$end_short = DI::l10n()->getDayShort(DateTimeFormat::utc($item['event-finish'], $dformat_short)); $end_short = DI::l10n()->getDayShort(DateTimeFormat::utc($item['event-finish'], $dformat_short));
$end_time = DateTimeFormat::local($item['event-finish'], $tformat); $end_time = DateTimeFormat::local($item['event-finish'], $tformat);
// Check if start and finish time is at the same day. // Check if start and finish time is at the same day.
if (substr($dtstart_title, 0, 10) === substr($dtend_title, 0, 10)) { if (substr($dtstart_title, 0, 10) === substr($dtend_title, 0, 10)) {
$same_date = true; $same_date = true;
} }
} else { } else {
$dtend_title = ''; $dtend_title = '';
$dtend_dt = ''; $dtend_dt = '';
$end_time = ''; $end_time = '';
$end_short = ''; $end_short = '';
} }
// Format the event location. // Format the event location.
$location = self::locationToArray($item['event-location']); $location = self::locationToArray($item['event-location']);
// Construct the profile link (magic-auth). // Construct the profile link (magic-auth).
$author = ['uid' => 0, 'id' => $item['author-id'], $author = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']]; 'network' => $item['author-network'], 'url' => $item['author-link']];
$profile_link = Contact::magicLinkByContact($author); $profile_link = Contact::magicLinkByContact($author);
$tpl = Renderer::getMarkupTemplate('event_stream_item.tpl'); $tpl = Renderer::getMarkupTemplate('event_stream_item.tpl');
$return = Renderer::replaceMacros($tpl, [ $return = Renderer::replaceMacros($tpl, [
'$id' => $item['event-id'], '$id' => $item['event-id'],
'$title' => BBCode::convertForUriId($item['uri-id'], $item['event-summary']), '$title' => BBCode::convertForUriId($item['uri-id'], $item['event-summary']),
@ -1016,15 +994,15 @@ class Event
if (strpos($s, '[/map]') !== false) { if (strpos($s, '[/map]') !== false) {
$found = preg_match("/\[map\](.*?)\[\/map\]/ism", $s, $match); $found = preg_match("/\[map\](.*?)\[\/map\]/ism", $s, $match);
if (intval($found) > 0 && array_key_exists(1, $match)) { if (intval($found) > 0 && array_key_exists(1, $match)) {
$location['address'] = $match[1]; $location['address'] = $match[1];
// Remove the map bbcode from the location name. // Remove the map bbcode from the location name.
$location['name'] = str_replace($match[0], "", $s); $location['name'] = str_replace($match[0], "", $s);
} }
// Map tag with coordinates - e.g. [map=48.864716,2.349014]. // Map tag with coordinates - e.g. [map=48.864716,2.349014].
} elseif (strpos($s, '[map=') !== false) { } elseif (strpos($s, '[map=') !== false) {
$found = preg_match("/\[map=(.*?)\]/ism", $s, $match); $found = preg_match("/\[map=(.*?)\]/ism", $s, $match);
if (intval($found) > 0 && array_key_exists(1, $match)) { if (intval($found) > 0 && array_key_exists(1, $match)) {
$location['coordinates'] = $match[1]; $location['coordinates'] = $match[1];
// Remove the map bbcode from the location name. // Remove the map bbcode from the location name.
$location['name'] = str_replace($match[0], "", $s); $location['name'] = str_replace($match[0], "", $s);
} }
@ -1054,10 +1032,10 @@ class Event
{ {
// Check for duplicates // Check for duplicates
$condition = [ $condition = [
'uid' => $contact['uid'], 'uid' => $contact['uid'],
'cid' => $contact['id'], 'cid' => $contact['id'],
'start' => DateTimeFormat::utc($birthday), 'start' => DateTimeFormat::utc($birthday),
'type' => 'birthday' 'type' => 'birthday'
]; ];
if (DBA::exists('event', $condition)) { if (DBA::exists('event', $condition)) {
return false; return false;

View file

@ -23,9 +23,11 @@ namespace Friendica\Module;
use Friendica\App; use Friendica\App;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Content\Feature;
use Friendica\Core\Hook; use Friendica\Core\Hook;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\User;
class BaseProfile extends BaseModule class BaseProfile extends BaseModule
{ {
@ -87,17 +89,18 @@ class BaseProfile extends BaseModule
'id' => 'calendar-tab', 'id' => 'calendar-tab',
'accesskey' => 'c', 'accesskey' => 'c',
]; ];
// if the user is not the owner of the calendar we only show a calendar
// with the public events of the calendar owner
} else { } else {
$tabs[] = [ $owner = User::getByNickname($nickname, ['uid']);
'label' => DI::l10n()->t('Calendar'), if(DI::userSession()->isAuthenticated() || $owner && Feature::isEnabled($owner['uid'], 'public_calendar')) {
'url' => DI::baseUrl() . '/calendar/show/' . $nickname, $tabs[] = [
'sel' => $current == 'calendar' ? 'active' : '', 'label' => DI::l10n()->t('Calendar'),
'title' => DI::l10n()->t('Calendar'), 'url' => DI::baseUrl() . '/calendar/show/' . $nickname,
'id' => 'calendar-tab', 'sel' => $current == 'calendar' ? 'active' : '',
'accesskey' => 'c', 'title' => DI::l10n()->t('Calendar'),
]; 'id' => 'calendar-tab',
'accesskey' => 'c',
];
}
} }
if ($is_owner) { if ($is_owner) {

View file

@ -22,12 +22,14 @@
namespace Friendica\Module\Calendar\Event; namespace Friendica\Module\Calendar\Event;
use Friendica\App; use Friendica\App;
use Friendica\Content\Feature;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Session\Capability\IHandleUserSessions;
use Friendica\Core\System; use Friendica\Core\System;
use Friendica\Model\Event; use Friendica\Model\Event;
use Friendica\Model\Item; use Friendica\Model\Item;
use Friendica\Model\Post; use Friendica\Model\Post;
use Friendica\Model\User;
use Friendica\Module\Response; use Friendica\Module\Response;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
@ -43,24 +45,27 @@ class Get extends \Friendica\BaseModule
/** @var IHandleUserSessions */ /** @var IHandleUserSessions */
protected $session; protected $session;
public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $session, array $server, array $parameters = []) public function __construct(App $app, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $session, array $server, array $parameters = [])
{ {
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
$this->session = $session; $this->session = $session;
$this->app = $app;
} }
protected function rawContent(array $request = []) protected function rawContent(array $request = [])
{ {
if (!$this->session->getLocalUserId()) { $nickname = $this->parameters['nickname'] ?? $this->app->getLoggedInUserNickname();
if (!$nickname) {
throw new HTTPException\UnauthorizedException(); throw new HTTPException\UnauthorizedException();
} }
// get events by id or by date $owner = Event::getOwnerForNickname($nickname);
if (!empty($request['id'])) { if (!empty($request['id'])) {
$events = [Event::getByIdAndUid($this->session->getLocalUserId(), $request['id'], $this->parameters['nickname'] ?? null)]; $events = [Event::getByIdAndUid($owner['uid'], $request['id'])];
} else { } else {
$events = Event::getListByDate($this->session->getLocalUserId(), $request['start'] ?? '', $request['end'] ?? '', false, $this->parameters['nickname'] ?? null); $events = Event::getListByDate($owner['uid'], $request['start'] ?? '', $request['end'] ?? '');
} }
System::jsonExit($events ? self::map($events) : []); System::jsonExit($events ? self::map($events) : []);

View file

@ -23,11 +23,13 @@ namespace Friendica\Module\Calendar\Event;
use Friendica\App; use Friendica\App;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Content\Feature;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Session\Capability\IHandleUserSessions;
use Friendica\Core\System; use Friendica\Core\System;
use Friendica\Model\Event; use Friendica\Model\Event;
use Friendica\Model\User;
use Friendica\Module\Response; use Friendica\Module\Response;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
use Friendica\Util\Profiler; use Friendica\Util\Profiler;
@ -40,22 +42,27 @@ class Show extends BaseModule
{ {
/** @var IHandleUserSessions */ /** @var IHandleUserSessions */
protected $session; protected $session;
/** @var App */
private $app;
public function __construct(L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $session, array $server, array $parameters = []) public function __construct(App $app, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $session, array $server, array $parameters = [])
{ {
parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters);
$this->session = $session; $this->session = $session;
$this->app = $app;
} }
protected function rawContent(array $request = []) protected function rawContent(array $request = [])
{ {
if (!$this->session->getLocalUserId()) { $nickname = $this->parameters['nickname'] ?? $this->app->getLoggedInUserNickname();
throw new HTTPException\UnauthorizedException($this->t('Permission denied.')); if (!$nickname) {
throw new HTTPException\UnauthorizedException();
} }
$event = Event::getByIdAndUid($this->session->getLocalUserId(), (int)$this->parameters['id'] ?? 0, $this->parameters['nickname'] ?? ''); $owner = Event::getOwnerForNickname($nickname);
$event = Event::getByIdAndUid($owner['uid'], (int)$this->parameters['id'] ?? 0);
if (empty($event)) { if (empty($event)) {
throw new HTTPException\NotFoundException($this->t('Event not found.')); throw new HTTPException\NotFoundException($this->t('Event not found.'));
} }

View file

@ -23,6 +23,7 @@ namespace Friendica\Module\Calendar;
use Friendica\App; use Friendica\App;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Content\Feature;
use Friendica\Content\Nav; use Friendica\Content\Nav;
use Friendica\Content\Widget; use Friendica\Content\Widget;
use Friendica\Core\L10n; use Friendica\Core\L10n;
@ -30,9 +31,11 @@ use Friendica\Core\Renderer;
use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Session\Capability\IHandleUserSessions;
use Friendica\Core\Theme; use Friendica\Core\Theme;
use Friendica\Model\Event; use Friendica\Model\Event;
use Friendica\Model\User;
use Friendica\Module\BaseProfile; use Friendica\Module\BaseProfile;
use Friendica\Module\Response; use Friendica\Module\Response;
use Friendica\Module\Security\Login; use Friendica\Module\Security\Login;
use Friendica\Network\HTTPException;
use Friendica\Navigation\SystemMessages; use Friendica\Navigation\SystemMessages;
use Friendica\Util\Profiler; use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -60,7 +63,21 @@ class Show extends BaseModule
protected function content(array $request = []): string protected function content(array $request = []): string
{ {
if (!$this->session->getLocalUserId()) { $nickname = $this->parameters['nickname'] ?? $this->app->getLoggedInUserNickname();
if (!$nickname) {
throw new HTTPException\UnauthorizedException();
}
$owner = User::getOwnerDataByNick($nickname);
if (!$owner || $owner['account_expired'] || $owner['account_removed']) {
throw new HTTPException\NotFoundException($this->t('User not found.'));
}
if (!$this->session->isAuthenticated() && $owner['hidewall']) {
$this->baseUrl->redirect('profile/' . $nickname . '/restricted');
}
if (!$this->session->isAuthenticated() && !Feature::isEnabled($owner['uid'], 'public_calendar')) {
$this->sysMessages->addNotice($this->t('Permission denied.')); $this->sysMessages->addNotice($this->t('Permission denied.'));
return Login::form(); return Login::form();
} }
@ -73,35 +90,26 @@ class Show extends BaseModule
$this->page->registerFooterScript('view/asset/moment/min/moment-with-locales.min.js'); $this->page->registerFooterScript('view/asset/moment/min/moment-with-locales.min.js');
$this->page->registerFooterScript('view/asset/fullcalendar/dist/fullcalendar.min.js'); $this->page->registerFooterScript('view/asset/fullcalendar/dist/fullcalendar.min.js');
$htpl = Renderer::getMarkupTemplate('calendar/calendar_head.tpl'); $is_owner = $nickname == $this->app->getLoggedInUserNickname();
$htpl = Renderer::getMarkupTemplate('calendar/calendar_head.tpl');
$this->page['htmlhead'] .= Renderer::replaceMacros($htpl, [ $this->page['htmlhead'] .= Renderer::replaceMacros($htpl, [
'$calendar_api' => 'calendar/api/get' . (!empty($this->parameters['nickname']) ? '/' . $this->parameters['nickname'] : ''), '$calendar_api' => 'calendar/api/get' . ($is_owner ? '' : '/' . $nickname),
'$event_api' => 'calendar/event/show' . (!empty($this->parameters['nickname']) ? '/' . $this->parameters['nickname'] : ''), '$event_api' => 'calendar/event/show' . ($is_owner ? '' : '/' . $nickname),
'$modparams' => 2, '$modparams' => 2,
'$i18n' => $i18n, '$i18n' => $i18n,
]); ]);
$tabs = ''; Nav::setSelected($is_owner ? 'home' : 'calendar');
if (empty($this->parameters['nickname'])) {
Nav::setSelected('home');
$tabs = BaseProfile::getTabsHTML($this->app, 'calendar', true, $this->app->getLoggedInUserNickname(), false);
$this->page['aside'] .= Widget\CalendarExport::getHTML($this->session->getLocalUserId());
} else {
$owner = Event::getOwnerForNickname($this->parameters['nickname']);
Nav::setSelected('calendar');
// get the tab navigation bar
$tabs = BaseProfile::getTabsHTML($this->app, 'calendar', false, $owner['nickname'], $owner['hide-friends']);
if (!$is_owner) {
$this->page['aside'] .= Widget\VCard::getHTML($owner); $this->page['aside'] .= Widget\VCard::getHTML($owner);
$this->page['aside'] .= Widget\CalendarExport::getHTML($owner['uid']);
} }
$this->page['aside'] .= Widget\CalendarExport::getHTML($owner['uid']);
$tabs = BaseProfile::getTabsHTML('calendar', $is_owner, $nickname, !$is_owner && $owner['hide-friends']);
// ACL blocks are loaded in modals in frio // ACL blocks are loaded in modals in frio
$this->page->registerFooterScript(Theme::getPathForFile('asset/typeahead.js/dist/typeahead.bundle.js')); $this->page->registerFooterScript(Theme::getPathForFile('asset/typeahead.js/dist/typeahead.bundle.js'));
$this->page->registerFooterScript(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.js')); $this->page->registerFooterScript(Theme::getPathForFile('js/friendica-tagsinput/friendica-tagsinput.js'));