mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-06-22 10:52:00 +02:00
* REST API: new links collection allowing to link application entries with each other or attach files
This commit is contained in:
parent
a75ee01b58
commit
587004b173
@ -1104,6 +1104,11 @@ class CalDAV extends HTTP_WebDAV_Server
|
|||||||
}
|
}
|
||||||
if (($handler = $this->app_handler($app)))
|
if (($handler = $this->app_handler($app)))
|
||||||
{
|
{
|
||||||
|
// handle links for all apps supporting links
|
||||||
|
if (preg_match('#/'.$app.'/'.$id.'/links/?$#', $options['path']) && self::isJSON())
|
||||||
|
{
|
||||||
|
return $handler->getLinks($options, $id);
|
||||||
|
}
|
||||||
return $handler->get($options,$id,$user);
|
return $handler->get($options,$id,$user);
|
||||||
}
|
}
|
||||||
error_log(__METHOD__."(".array2string($options).") 501 Not Implemented");
|
error_log(__METHOD__."(".array2string($options).") 501 Not Implemented");
|
||||||
@ -1536,6 +1541,12 @@ class CalDAV extends HTTP_WebDAV_Server
|
|||||||
|
|
||||||
if (($handler = $this->app_handler($app)))
|
if (($handler = $this->app_handler($app)))
|
||||||
{
|
{
|
||||||
|
// handle links for all apps supporting links
|
||||||
|
if (preg_match('#/'.$app.'/'.$id.'/links/#', $options['path']))
|
||||||
|
{
|
||||||
|
return $handler->createLink($options, $id);
|
||||||
|
}
|
||||||
|
|
||||||
// managed attachments
|
// managed attachments
|
||||||
if (isset($_GET['action']) && substr($_GET['action'], 0, 11) === 'attachment-')
|
if (isset($_GET['action']) && substr($_GET['action'], 0, 11) === 'attachment-')
|
||||||
{
|
{
|
||||||
@ -2079,6 +2090,11 @@ class CalDAV extends HTTP_WebDAV_Server
|
|||||||
}
|
}
|
||||||
if (($handler = $this->app_handler($app)))
|
if (($handler = $this->app_handler($app)))
|
||||||
{
|
{
|
||||||
|
// handle links for all apps supporting links
|
||||||
|
if (preg_match('#/'.$app.'/'.$id.'/links/(-?\d+)$#', $options['path'], $matches))
|
||||||
|
{
|
||||||
|
return $handler->deleteLink($options, $id, $matches[1]);
|
||||||
|
}
|
||||||
$status = $handler->delete($options,$id,$user);
|
$status = $handler->delete($options,$id,$user);
|
||||||
// set default stati: true --> 204 No Content, false --> should be already handled
|
// set default stati: true --> 204 No Content, false --> should be already handled
|
||||||
if (is_bool($status)) $status = $status ? '204 No Content' : '400 Something went wrong';
|
if (is_bool($status)) $status = $status ? '204 No Content' : '400 Something went wrong';
|
||||||
@ -2317,7 +2333,7 @@ class CalDAV extends HTTP_WebDAV_Server
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Api\WebDAV\Server encodes %, # and ? again, which leads to storing e.g. '%' as '%25'
|
// Api\WebDAV\Server encodes %, # and ? again, which leads to storing e.g. '%' as '%25'
|
||||||
$id = strtr(array_pop($parts), array(
|
$id = strtr(array_shift($parts), array(
|
||||||
'%25' => '%',
|
'%25' => '%',
|
||||||
'%23' => '#',
|
'%23' => '#',
|
||||||
'%3F' => '?',
|
'%3F' => '?',
|
||||||
@ -2373,13 +2389,15 @@ class CalDAV extends HTTP_WebDAV_Server
|
|||||||
* Check if request is a possibly large, binary file upload:
|
* Check if request is a possibly large, binary file upload:
|
||||||
* - CalDAV managed attachments or
|
* - CalDAV managed attachments or
|
||||||
* - Mail REST API attachment upload
|
* - Mail REST API attachment upload
|
||||||
|
* - REST API attachment upload to /$app/$id/links/
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected static function isFileUpload()
|
protected static function isFileUpload()
|
||||||
{
|
{
|
||||||
return (isset($_GET['action']) && in_array($_GET['action'], array('attachment-add', 'attachment-update'))) ||
|
return (isset($_GET['action']) && in_array($_GET['action'], array('attachment-add', 'attachment-update'))) ||
|
||||||
strpos($_SERVER['REQUEST_URI'], '/mail/attachments/');
|
strpos($_SERVER['REQUEST_URI'], '/mail/attachments/') ||
|
||||||
|
strpos($_SERVER['REQUEST_URI'], '/links/') && $_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['CONTENT_TYPE'] !== 'application/json';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -776,4 +776,132 @@ abstract class Handler
|
|||||||
}
|
}
|
||||||
return $this->base_uri().$path.$token;
|
return $this->base_uri().$path.$token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a link to another app's entry or add an attachment
|
||||||
|
*
|
||||||
|
* @param array $options
|
||||||
|
* @param string $app
|
||||||
|
* @param $id
|
||||||
|
* @param int|null $user
|
||||||
|
* @return string with http status
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function createLink(array $options, string $id)
|
||||||
|
{
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
if (!Api\Link::get_registry($this->app, 'title'))
|
||||||
|
{
|
||||||
|
return '501 Not implemented';
|
||||||
|
}
|
||||||
|
// check edit-access
|
||||||
|
if (!is_array($status = $this->_common_get_put_delete('PUT', $options, $id)))
|
||||||
|
{
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
// are we linking with another app's entry
|
||||||
|
if (substr($options['path'], -1) === '/' && $options['content_type'] === 'application/json')
|
||||||
|
{
|
||||||
|
$json = $options['content'] ?? stream_get_contents($options['stream']);
|
||||||
|
$data = json_decode($json, true, 2, JSON_THROW_ON_ERROR);
|
||||||
|
if (empty($data['app']) || empty($data['id']) || !($link = Api\Link::link($this->app, $id, $data['app'], $data['id'], $data['remark'] ?? null)))
|
||||||
|
{
|
||||||
|
return '422 Unprocessable Content';
|
||||||
|
}
|
||||||
|
// if a special relation is given, set it
|
||||||
|
if (!empty($data['rel']))
|
||||||
|
{
|
||||||
|
$this->setLinkRelation($id, $link, $data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!is_resource($options['stream']) && isset($options['content']) &&
|
||||||
|
($options['stream'] = fopen('php://temp', 'r+')))
|
||||||
|
{
|
||||||
|
fwrite($options['stream'], $options['content']);
|
||||||
|
fseek($options['stream'], 0);
|
||||||
|
}
|
||||||
|
if (!is_resource($options['stream']) || !($link = Api\Link::attach_file($this->app, $id, [
|
||||||
|
'tmp_name' => $options['stream'],
|
||||||
|
'type' => $options['content_type'],
|
||||||
|
'name' => explode('/links/', $options['path'], 2)[1] ?? throw new \InvalidArgumentException('Missing filename'),
|
||||||
|
])))
|
||||||
|
{
|
||||||
|
return '422 Unprocessable Content';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
header('Location: '.Api\Framework::getUrl(Api\Framework::link('/groupdav.php/'.
|
||||||
|
$GLOBALS['egw_info']['user']['account_lid'].'/'.$this->app.'/'.$id.'/links/'.$link)));
|
||||||
|
return '201 Created';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setting the link relation
|
||||||
|
*
|
||||||
|
* Does nothing in general, but can be overwritten by apps e.g. InfoLog for "egroupware.org-primary"
|
||||||
|
*
|
||||||
|
* @param string|int $id
|
||||||
|
* @param int $link_id
|
||||||
|
* @param array $data values for keys "app", "id", "rel", "remark"
|
||||||
|
* @throws Api\Exception\NotFound if $id is not found or readable
|
||||||
|
* @throws Api\Exception on other errors like storing
|
||||||
|
*/
|
||||||
|
protected function setLinkRelation(string $id, int $link_id, array $data)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Links to and from an app-entry
|
||||||
|
*
|
||||||
|
* @param array $options
|
||||||
|
* @param string $id
|
||||||
|
* @return string with http status
|
||||||
|
*/
|
||||||
|
public function getLinks(array $options, string $id)
|
||||||
|
{
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
if (!Api\Link::get_registry($this->app, 'title') || !($type = Api\CalDAV::isJSON()))
|
||||||
|
{
|
||||||
|
return '501 Not implemented';
|
||||||
|
}
|
||||||
|
// check read-access
|
||||||
|
if (!is_array($status = $this->_common_get_put_delete('GET', $options, $id)))
|
||||||
|
{
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
echo Api\CalDAV::json_encode(['responses' => Api\CalDAV\JsBase::getLinks($options['path'], $this->app, $id)], $type === 'pretty');
|
||||||
|
return '200 Ok';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete one link or attachment from an entry
|
||||||
|
*
|
||||||
|
* @param array $options
|
||||||
|
* @param string $id
|
||||||
|
* @param int $link_id
|
||||||
|
* @return string with http status
|
||||||
|
*/
|
||||||
|
public function deleteLink(array $options, string $id, int $link_id)
|
||||||
|
{
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
if (!Api\Link::get_registry($this->app, 'title'))
|
||||||
|
{
|
||||||
|
return '501 Not implemented';
|
||||||
|
}
|
||||||
|
// check edit-access, we use PUT, as we are NOT deleting the entry itself, but a link to it or attachment
|
||||||
|
if (!is_array($status = $this->_common_get_put_delete('PUT', $options, $id)))
|
||||||
|
{
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
if (!($link = Api\Link::get_link($link_id)) ||
|
||||||
|
!($link_id < 0 && $this->app === $link['app2'] && $id == $link['id2'] ||
|
||||||
|
$link_id > 0 && ($this->app === $link['link_app1'] && $id == $link['link_id1'] ||
|
||||||
|
$this->app === $link['link_app2'] && $id == $link['link_id2'])))
|
||||||
|
{
|
||||||
|
return '404 Not Found';
|
||||||
|
}
|
||||||
|
return Api\Link::unlink($link_id) ? '204 No Content' : '400 Something went wrong';
|
||||||
|
}
|
||||||
}
|
}
|
@ -292,6 +292,47 @@ class JsBase
|
|||||||
return $cat_ids ? implode(',', $cat_ids) : null;
|
return $cat_ids ? implode(',', $cat_ids) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get links / link-objects
|
||||||
|
*
|
||||||
|
* @param string $prefix
|
||||||
|
* @param string $app
|
||||||
|
* @param string $id
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function getLinks(string $prefix, string $app, string $id)
|
||||||
|
{
|
||||||
|
$links = [];
|
||||||
|
foreach(Api\Link::get_links($app, $id, '', 'link_lastmod DESC', true) as $link_id => $data)
|
||||||
|
{
|
||||||
|
$path = rtrim($prefix, '/').'/'.$link_id;
|
||||||
|
if ($data['app'] === 'file')
|
||||||
|
{
|
||||||
|
$links[$path] = array_filter([
|
||||||
|
self::AT_TYPE => 'Link',
|
||||||
|
'href' => Api\Framework::getUrl(Api\Framework::link('/webdav.php/apps/'.$app.'/'.$id.'/'.$data['id'])),
|
||||||
|
'contentType' => $data['type'],
|
||||||
|
'size' => $data['size'],
|
||||||
|
'title' => Api\Link::title($data['app'], $data['id']),
|
||||||
|
'egroupware.org-remark' => $data['remark'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$links[$path] = array_filter([
|
||||||
|
self::AT_TYPE => 'Link',
|
||||||
|
'href' => Api\Framework::getUrl(Api\Framework::link('/groupdav.php/'.$GLOBALS['egw_info']['user']['account_lid'].'/'.$data['app'].'/'.$data['id'])),
|
||||||
|
'contentType' => 'application/json',
|
||||||
|
'title' => Api\Link::title($data['app'], $data['id']),
|
||||||
|
'egroupware.org-app' => $data['app'],
|
||||||
|
'egroupware.org-id' => $data['id'],
|
||||||
|
'egroupware.org-remark' => $data['remark'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $links;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Patch JsCard
|
* Patch JsCard
|
||||||
*
|
*
|
||||||
|
@ -668,7 +668,7 @@ class Link extends Link\Storage
|
|||||||
* @param string $app2 ='' app of second endpoint
|
* @param string $app2 ='' app of second endpoint
|
||||||
* @param string $id2 ='' id in $app2
|
* @param string $id2 ='' id in $app2
|
||||||
* @param boolean $hold_for_purge Don't really delete the link, just mark it as deleted and wait for final delete
|
* @param boolean $hold_for_purge Don't really delete the link, just mark it as deleted and wait for final delete
|
||||||
* @return the number of links deleted
|
* @return int the number of links deleted
|
||||||
*/
|
*/
|
||||||
static function unlink($link_id,$app='',$id='',$owner=0,$app2='',$id2='',$hold_for_purge=false)
|
static function unlink($link_id,$app='',$id='',$owner=0,$app2='',$id2='',$hold_for_purge=false)
|
||||||
{
|
{
|
||||||
@ -685,7 +685,7 @@ class Link extends Link\Storage
|
|||||||
* @param string $app2 ='' app of second endpoint, or !file (other !app are not yet supported!)
|
* @param string $app2 ='' app of second endpoint, or !file (other !app are not yet supported!)
|
||||||
* @param string $id2 ='' id in $app2
|
* @param string $id2 ='' id in $app2
|
||||||
* @param boolean $hold_for_purge Don't really delete the link, just mark it as deleted and wait for final delete
|
* @param boolean $hold_for_purge Don't really delete the link, just mark it as deleted and wait for final delete
|
||||||
* @return the number of links deleted
|
* @return int|boolean the number of links deleted
|
||||||
*/
|
*/
|
||||||
static function unlink2($link_id,$app,&$id,$owner=0,$app2='',$id2='',$hold_for_purge=false)
|
static function unlink2($link_id,$app,&$id,$owner=0,$app2='',$id2='',$hold_for_purge=false)
|
||||||
{
|
{
|
||||||
@ -1142,7 +1142,7 @@ class Link extends Link\Storage
|
|||||||
* @param string $app app-name
|
* @param string $app app-name
|
||||||
* @param string $name name / key in the registry, eg. 'view'
|
* @param string $name name / key in the registry, eg. 'view'
|
||||||
* @param boolean|array|string|int $url_id format entries like "add", "edit", "view" for actions "url" incl. an ID
|
* @param boolean|array|string|int $url_id format entries like "add", "edit", "view" for actions "url" incl. an ID
|
||||||
* array to add arbitray parameter eg. ['some_id' => '$id']
|
* array to add arbitrary parameter eg. ['some_id' => '$id']
|
||||||
* @return boolean|string false if $app is not registered, otherwise string with the value for $name
|
* @return boolean|string false if $app is not registered, otherwise string with the value for $name
|
||||||
*/
|
*/
|
||||||
static function get_registry($app, $name, $url_id=false)
|
static function get_registry($app, $name, $url_id=false)
|
||||||
|
116
doc/REST-CalDAV-CardDAV/Links-and-attachments.md
Normal file
116
doc/REST-CalDAV-CardDAV/Links-and-attachments.md
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
# EGroupware REST API for Links and attachments
|
||||||
|
* linking application entries to other application entries
|
||||||
|
* attaching files to application entries
|
||||||
|
* listing, creating and deleting links and attachments
|
||||||
|
|
||||||
|
Authentication is via Basic Auth with username and a password, or a token valid for:
|
||||||
|
- either just the given user or all users
|
||||||
|
- CalDAV/CardDAV Sync (REST API)
|
||||||
|
- application the link or attachment is created for
|
||||||
|
|
||||||
|
### Following schema is used for JSON encoding of links and attachments
|
||||||
|
|
||||||
|
* @type: `Link`
|
||||||
|
* href: string URI to linked entry or attachments
|
||||||
|
* title: string title of link
|
||||||
|
* contentType: string `application/json` for links, content-type of attachments
|
||||||
|
* size: size of attachments
|
||||||
|
* egroupware.org-remark: string
|
||||||
|
* egroupware.org-app: string application name of the linked entry
|
||||||
|
* egroupware.org-id: string application ID of the linked entry
|
||||||
|
* rel: string `egroupware.org-primary` to mark a primary link for InfoLog entries
|
||||||
|
|
||||||
|
### Supported request methods and examples
|
||||||
|
|
||||||
|
* **GET** to application entry collections to return all links and attachments
|
||||||
|
<details>
|
||||||
|
<summary>Example: Getting all links and attachments of a given application entry</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
curl https://example.org/egroupware/groupdav.php/<username>/<app>/<id>/links/ -H "Accept: application/pretty+json" --user <username>
|
||||||
|
HTTP/1.1 200 Ok
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"responses": {
|
||||||
|
"/<username>/<app>/<id>/links/<link-id>": {
|
||||||
|
"@type": "Link",
|
||||||
|
"href": "https://example.org/egroupware/groupdav.php/ralf/addressbook/46",
|
||||||
|
"contentType": "application/json",
|
||||||
|
"title": "EGroupware GmbH: Becker, Ralf",
|
||||||
|
"egroupware.org-app": "addressbook",
|
||||||
|
"egroupware.org-id": "46",
|
||||||
|
"egroupware.org-remark": "Testing ;)"
|
||||||
|
},
|
||||||
|
"/<username>/<app>/<id>/links/<link-id>": {
|
||||||
|
"@type": "Link",
|
||||||
|
"href": "https://example.org/egroupware/groupdav.php/ralf/infolog/1161",
|
||||||
|
"contentType": "application/json",
|
||||||
|
"title": "Test mit primärem Link (#1161)",
|
||||||
|
"egroupware.org-app": "infolog",
|
||||||
|
"egroupware.org-id": "1161"
|
||||||
|
},
|
||||||
|
"/<username>/<app>/<id>/links/<attachment-id>": {
|
||||||
|
"@type": "Link",
|
||||||
|
"href": "https://example.org/egroupware/webdav.php/apps/timesheet/199/image.svg",
|
||||||
|
"contentType": "image/svg+xml",
|
||||||
|
"size": 17167,
|
||||||
|
"title": "image.svg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
* **POST** request to upload an attachment or link with another application entry
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Example: Adding a PDF as attachment to an application entry</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -i 'https://example.org/egroupware/groupdav.php/<username>/<app>/<id>/links/<filename>' -H "Content-Type: application/pdf" --data-binary @<path-to-pdf> --user <username>
|
||||||
|
|
||||||
|
HTTP/1.1 204 Created
|
||||||
|
Location: https://example.org/egroupware/groupdav.php/<username>/<app>/<id>/links/<attachment-id>
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Example: Creating a link from one application entry to another</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -i 'https://example.org/egroupware/groupdav.php/<username>/<app>/<id>/links/' -H "Content-Type: application/json" --data-binary @- --user <username> <<<EOF
|
||||||
|
{"application":"<2nd-app>","id":<2nd-app-id>,"remark":"This is a test ;)"}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
HTTP/1.1 204 Created
|
||||||
|
Location: https://example.org/egroupware/groupdav.php/<username>/<app>/<id>/links/<link-id>
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Example: Creating the primary link for an InfoLog entry</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -i 'https://example.org/egroupware/groupdav.php/<username>/infolog/<id>/links/' -H "Content-Type: application/json" --data-binary @- --user <username> <<<EOF
|
||||||
|
{"application":"<2nd-app>","id":<2nd-app-id>,"rel":"egroupware.org-primary"}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
HTTP/1.1 204 Created
|
||||||
|
Location: https://example.org/egroupware/groupdav.php/<username>/infolog/<id>/links/<link-id>
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
* **DELETE** request to remove a link or attachment
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Example: deleting an attachment or link</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -X DELETE 'https://example.org/egroupware/groupdav.php/<app>/<id>/links/<link-or-attachment-id>' --user <username>
|
||||||
|
|
||||||
|
HTTP/1.1 201 No Content
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
> one can use ```Accept: application/pretty+json``` to receive pretty-printed JSON eg. for debugging and exploring the API
|
@ -49,6 +49,10 @@ from the data of an ```allprop``` PROPFIND, allow browsing CalDAV/CardDAV tree w
|
|||||||
* view and reply to eml files and
|
* view and reply to eml files and
|
||||||
* vacation handling
|
* vacation handling
|
||||||
- [Timesheet](Timesheet.md)
|
- [Timesheet](Timesheet.md)
|
||||||
|
- [Links and attachments](Links-and-attachments.md)
|
||||||
|
* linking application entries to other application entries
|
||||||
|
* attaching files to application entries
|
||||||
|
* listing, creating and deleting links and attachments
|
||||||
|
|
||||||
> For the REST API you always have to send an "Accept: application/json" header and for POST & PUT requests additionally
|
> For the REST API you always have to send an "Accept: application/json" header and for POST & PUT requests additionally
|
||||||
> a "Content-Type: application/json" header, otherwise you talk to the CalDAV/CardDAV server and don't get the response you expect!
|
> a "Content-Type: application/json" header, otherwise you talk to the CalDAV/CardDAV server and don't get the response you expect!
|
||||||
|
@ -13,6 +13,7 @@ Following schema is used for JSON encoding of timesheets
|
|||||||
* start: UTCDateTime e.g. `2020-02-03T14:35:37Z`
|
* start: UTCDateTime e.g. `2020-02-03T14:35:37Z`
|
||||||
* duration: integer in minutes
|
* duration: integer in minutes
|
||||||
* quantity: double
|
* quantity: double
|
||||||
|
* project: string
|
||||||
* unitprice: double
|
* unitprice: double
|
||||||
* category: category object with a single(!) category-name e.g. `{"category name": true}`
|
* category: category object with a single(!) category-name e.g. `{"category name": true}`
|
||||||
* owner: string with either email or username or integer ID
|
* owner: string with either email or username or integer ID
|
||||||
|
@ -934,4 +934,29 @@ class infolog_groupdav extends Api\CalDAV\Handler
|
|||||||
);
|
);
|
||||||
return $settings;
|
return $settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setting the link relation to make an application link InfoLogs primary link
|
||||||
|
*
|
||||||
|
* @param string|int $id
|
||||||
|
* @param int $link_id
|
||||||
|
* @param array $data values for keys "app", "id", "rel", "remark"
|
||||||
|
* @throws Api\Exception\NotFound if $id is not found or readable
|
||||||
|
* @throws Api\Exception on other errors like storing
|
||||||
|
*/
|
||||||
|
protected function setLinkRelation(string $id, int $link_id, array $data)
|
||||||
|
{
|
||||||
|
if (!($info = $this->read($id)) ||)
|
||||||
|
{
|
||||||
|
throw new Api\Exception\NotFound();
|
||||||
|
}
|
||||||
|
$info['info_link_id'] = $link_id;
|
||||||
|
$info['info_from'] = Link::titel($data['app'], $data['id']);
|
||||||
|
$info['info_custom_from'] = false;
|
||||||
|
|
||||||
|
if (!$this->bo->write($info))
|
||||||
|
{
|
||||||
|
throw new Api\Exception("Error storing InfoLog");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -711,6 +711,6 @@ class ApiHandler extends Api\CalDAV\Handler
|
|||||||
*/
|
*/
|
||||||
function check_access($acl, $entry)
|
function check_access($acl, $entry)
|
||||||
{
|
{
|
||||||
return $this->bo->check_acl($acl, is_array($entry) ? $entry+['ts_onwer' => $entry['owner']] : $entry);
|
return $this->bo->check_acl($acl, is_array($entry) ? $entry+['ts_owner' => $entry['owner']] : $entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user