Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(meetings): Add endpoint to get writable calendars and the defaul… #13964

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions appinfo/routes/routesSettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@
['name' => 'Settings#setSIPSettings', 'url' => '/api/{apiVersion}/settings/sip', 'verb' => 'POST', 'requirements' => $requirements],
/** @see \OCA\Talk\Controller\SettingsController::setUserSetting() */
['name' => 'Settings#setUserSetting', 'url' => '/api/{apiVersion}/settings/user', 'verb' => 'POST', 'requirements' => $requirements],
/** @see \OCA\Talk\Controller\SettingsController::getPersonalCalendars() */
['name' => 'Settings#getPersonalCalendars', 'url' => '/api/{apiVersion}/personal-calendars', 'verb' => 'GET', 'requirements' => $requirements],
],
];
86 changes: 86 additions & 0 deletions lib/Controller/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,38 @@

namespace OCA\Talk\Controller;

use OCA\Talk\ResponseDefinitions;
use OCA\Talk\Settings\BeforePreferenceSetEventListener;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\OpenAPI;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\Calendar\IManager;
use OCP\Constants;
use OCP\Files\IRootFolder;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IRequest;
use Psr\Log\LoggerInterface;

/**
* @psalm-import-type TalkCalendar from ResponseDefinitions
*/
class SettingsController extends OCSController {

public function __construct(
string $appName,
IRequest $request,
protected IRootFolder $rootFolder,
protected IDBConnection $db,
protected IConfig $config,
protected IGroupManager $groupManager,
protected LoggerInterface $logger,
protected BeforePreferenceSetEventListener $preferenceListener,
protected IManager $calendarManager,
protected ?string $userId,
) {
parent::__construct($appName, $request);
Expand Down Expand Up @@ -86,4 +95,81 @@ public function setSIPSettings(

return new DataResponse(null);
}

/**
* Get writable calendars and the default calendar
*
* Required capability: `schedule-meeting`
*
* @return DataResponse<Http::STATUS_OK, array{defaultCalendarUri: ?string, calendars: list<TalkCalendar>}, array{}>
*
* 200: Get a list of calendars
*/
#[NoAdminRequired]
public function getPersonalCalendars(): DataResponse {
$calendars = $this->calendarManager->getCalendarsForPrincipal('principals/users/' . $this->userId);

$defaultCalendarUri = $selectedCalendarUri = null;
$selectedCalendar = $this->getSchedulingCalendarFromPropertiesTable($this->userId);
if ($selectedCalendar !== false) {
$parts = explode('/', rtrim($selectedCalendar, '/'));
if (count($parts) === 3 && $parts[0] === 'calendars' && $parts[1] === $this->userId) {
$selectedCalendarUri = $parts[2];
}
}

$hasPersonal = false;
$list = [];
foreach ($calendars as $calendar) {
if ($calendar->isDeleted()) {
continue;
}

if (!($calendar->getPermissions() & Constants::PERMISSION_CREATE)) {
continue;
}

if ($calendar->getUri() === 'personal') {
$hasPersonal = true;
}

if ($selectedCalendarUri === $calendar->getUri()) {
$defaultCalendarUri = $selectedCalendarUri;
}

$list[] = [
'uri' => $calendar->getUri(),
'name' => $calendar->getDisplayName() ?? $calendar->getUri(),
'color' => $calendar->getDisplayColor(),
];
}

return new DataResponse([
'defaultCalendarUri' => $defaultCalendarUri ?? ($hasPersonal ? 'personal' : null),
'calendars' => $list,
]);
}

/**
* @param string $userId
* @return false|string
*/
protected function getSchedulingCalendarFromPropertiesTable(string $userId) {
$propertyPath = 'principals/users/' . $userId;
$propertyName = '{urn:ietf:params:xml:ns:caldav}schedule-default-calendar-URL';

$query = $this->db->getQueryBuilder();
$query->select('propertyvalue')
->from('properties')
->where($query->expr()->eq('userid', $query->createNamedParameter($userId)))
->andWhere($query->expr()->eq('propertypath', $query->createNamedParameter($propertyPath)))
->andWhere($query->expr()->eq('propertyname', $query->createNamedParameter($propertyName)))
->setMaxResults(1);

$result = $query->executeQuery();
$property = $result->fetchOne();
$result->closeCursor();

return $property;
Comment on lines +157 to +173
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should go through the DAV app to get the default calendar URI, or you can use the user config:

$uri = $this->appConfig->getUserValue($userId, 'dav', 'defaultCalendar', CalDavBackend::PERSONAL_CALENDAR_URI);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, should use that preference,
but going through the dav app is to risky as it's all private api

Copy link
Member Author

@nickvergessen nickvergessen Dec 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I toggled this:
grafik

But there is no value in oc_preferences:
grafik

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also only find delete and get for that preference, no set anywhere:
grafik

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@st3iny any ideas?

}
}
6 changes: 6 additions & 0 deletions lib/ResponseDefinitions.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
* secret: string,
* }
*
* @psalm-type TalkCalendar = array{
* uri: string,
* name: string,
* color: ?string,
* }
*
* @psalm-type TalkCallPeer = array{
* actorId: string,
* actorType: string,
Expand Down
110 changes: 110 additions & 0 deletions openapi-full.json
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,26 @@
}
]
},
"Calendar": {
"type": "object",
"required": [
"uri",
"name",
"color"
],
"properties": {
"uri": {
"type": "string"
},
"name": {
"type": "string"
},
"color": {
"type": "string",
"nullable": true
}
}
},
"CallPeer": {
"type": "object",
"required": [
Expand Down Expand Up @@ -17680,6 +17700,96 @@
}
}
},
"/ocs/v2.php/apps/spreed/api/{apiVersion}/personal-calendars": {
"get": {
"operationId": "settings-get-personal-calendars",
"summary": "Get writable calendars and the default calendar",
"description": "Required capability: `schedule-meeting`",
"tags": [
"settings"
],
"security": [
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"parameters": [
{
"name": "apiVersion",
"in": "path",
"required": true,
"schema": {
"type": "string",
"enum": [
"v1"
],
"default": "v1"
}
},
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"200": {
"description": "Get a list of calendars",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"defaultCalendarUri",
"calendars"
],
"properties": {
"defaultCalendarUri": {
"type": "string",
"nullable": true
},
"calendars": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Calendar"
}
}
}
}
}
}
}
}
}
}
}
}
}
},
"/ocs/v2.php/apps/spreed/api/{apiVersion}/signaling/settings": {
"get": {
"operationId": "signaling-get-settings",
Expand Down
110 changes: 110 additions & 0 deletions openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,26 @@
}
}
},
"Calendar": {
"type": "object",
"required": [
"uri",
"name",
"color"
],
"properties": {
"uri": {
"type": "string"
},
"name": {
"type": "string"
},
"color": {
"type": "string",
"nullable": true
}
}
},
"CallPeer": {
"type": "object",
"required": [
Expand Down Expand Up @@ -17820,6 +17840,96 @@
}
}
},
"/ocs/v2.php/apps/spreed/api/{apiVersion}/personal-calendars": {
"get": {
"operationId": "settings-get-personal-calendars",
"summary": "Get writable calendars and the default calendar",
"description": "Required capability: `schedule-meeting`",
"tags": [
"settings"
],
"security": [
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"parameters": [
{
"name": "apiVersion",
"in": "path",
"required": true,
"schema": {
"type": "string",
"enum": [
"v1"
],
"default": "v1"
}
},
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"200": {
"description": "Get a list of calendars",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"defaultCalendarUri",
"calendars"
],
"properties": {
"defaultCalendarUri": {
"type": "string",
"nullable": true
},
"calendars": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Calendar"
}
}
}
}
}
}
}
}
}
}
}
}
}
},
"/ocs/v2.php/apps/spreed/api/{apiVersion}/signaling/settings": {
"get": {
"operationId": "signaling-get-settings",
Expand Down
Loading
Loading