parent
d8b4caf4aa
commit
24a3b8c638
|
@ -4,6 +4,7 @@ This file is manually updated. Please file an issue if something is missing.
|
||||||
|
|
||||||
## v4.10.0, v3.10.0 (unreleased)
|
## v4.10.0, v3.10.0 (unreleased)
|
||||||
|
|
||||||
|
- **Feature**: Allow sharing albums using public links
|
||||||
- **Feature**: Allow sharing albums with groups
|
- **Feature**: Allow sharing albums with groups
|
||||||
- Fix folder share title and remove footer
|
- Fix folder share title and remove footer
|
||||||
- Other minor fixes
|
- Other minor fixes
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
function getWildcard($param) {
|
function getWildcard($param)
|
||||||
|
{
|
||||||
return [
|
return [
|
||||||
'requirements' => [ $param => '.*' ],
|
'requirements' => [$param => '.*'],
|
||||||
'defaults' => [ $param => '' ]
|
'defaults' => [$param => '']
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function w($base, $param) {
|
function w($base, $param)
|
||||||
|
{
|
||||||
return array_merge($base, getWildcard($param));
|
return array_merge($base, getWildcard($param));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,15 +32,18 @@ return [
|
||||||
// Public folder share
|
// Public folder share
|
||||||
['name' => 'Public#showShare', 'url' => '/s/{token}', 'verb' => 'GET'],
|
['name' => 'Public#showShare', 'url' => '/s/{token}', 'verb' => 'GET'],
|
||||||
[
|
[
|
||||||
'name' => 'Public#showAuthenticate',
|
'name' => 'Public#showAuthenticate',
|
||||||
'url' => '/s/{token}/authenticate/{redirect}',
|
'url' => '/s/{token}/authenticate/{redirect}',
|
||||||
'verb' => 'GET',
|
'verb' => 'GET',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'Public#authenticate',
|
'name' => 'Public#authenticate',
|
||||||
'url' => '/s/{token}/authenticate/{redirect}',
|
'url' => '/s/{token}/authenticate/{redirect}',
|
||||||
'verb' => 'POST',
|
'verb' => 'POST',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// Public album share
|
||||||
|
['name' => 'PublicAlbum#showShare', 'url' => '/a/{token}', 'verb' => 'GET'],
|
||||||
|
|
||||||
// API Routes
|
// API Routes
|
||||||
['name' => 'Days#days', 'url' => '/api/days', 'verb' => 'GET'],
|
['name' => 'Days#days', 'url' => '/api/days', 'verb' => 'GET'],
|
||||||
|
|
|
@ -29,8 +29,6 @@ use OCA\Memories\Db\TimelineRoot;
|
||||||
use OCA\Memories\Exif;
|
use OCA\Memories\Exif;
|
||||||
use OCP\App\IAppManager;
|
use OCP\App\IAppManager;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
use OCP\AppFramework\Http;
|
|
||||||
use OCP\AppFramework\Http\JSONResponse;
|
|
||||||
use OCP\Files\File;
|
use OCP\Files\File;
|
||||||
use OCP\Files\Folder;
|
use OCP\Files\Folder;
|
||||||
use OCP\Files\IRootFolder;
|
use OCP\Files\IRootFolder;
|
||||||
|
@ -46,6 +44,7 @@ class ApiBase extends Controller
|
||||||
protected IRootFolder $rootFolder;
|
protected IRootFolder $rootFolder;
|
||||||
protected IAppManager $appManager;
|
protected IAppManager $appManager;
|
||||||
protected TimelineQuery $timelineQuery;
|
protected TimelineQuery $timelineQuery;
|
||||||
|
protected IDBConnection $connection;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IRequest $request,
|
IRequest $request,
|
||||||
|
@ -65,14 +64,14 @@ class ApiBase extends Controller
|
||||||
$this->timelineQuery = new TimelineQuery($connection);
|
$this->timelineQuery = new TimelineQuery($connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get logged in user's UID or throw HTTP error */
|
/** Get logged in user's UID or throw exception */
|
||||||
protected function getUID(): string
|
protected function getUID(): string
|
||||||
{
|
{
|
||||||
$user = $this->userSession->getUser();
|
$user = $this->userSession->getUser();
|
||||||
if ($this->getShareToken()) {
|
if ($this->getShareToken()) {
|
||||||
$user = null;
|
$user = null;
|
||||||
} elseif (null === $user) {
|
} elseif (null === $user) {
|
||||||
return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED);
|
throw new \Exception('User not logged in');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $user ? $user->getUID() : '';
|
return $user ? $user->getUID() : '';
|
||||||
|
@ -81,11 +80,17 @@ class ApiBase extends Controller
|
||||||
/** Get the TimelineRoot object relevant to the request */
|
/** Get the TimelineRoot object relevant to the request */
|
||||||
protected function getRequestRoot()
|
protected function getRequestRoot()
|
||||||
{
|
{
|
||||||
|
$user = $this->userSession->getUser();
|
||||||
$root = new TimelineRoot();
|
$root = new TimelineRoot();
|
||||||
|
|
||||||
// Albums have no folder
|
// Albums have no folder
|
||||||
if ($this->request->getParam('album')) {
|
if ($this->albumsIsEnabled() && $this->request->getParam('album')) {
|
||||||
return $root;
|
if (null !== $user) {
|
||||||
|
return $root;
|
||||||
|
}
|
||||||
|
if (($token = $this->getShareToken()) && $this->timelineQuery->getAlbumByLink($token)) {
|
||||||
|
return $root;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public shared folder
|
// Public shared folder
|
||||||
|
@ -96,7 +101,6 @@ class ApiBase extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anything else needs a user
|
// Anything else needs a user
|
||||||
$user = $this->userSession->getUser();
|
|
||||||
if (null === $user) {
|
if (null === $user) {
|
||||||
throw new \Exception('User not logged in');
|
throw new \Exception('User not logged in');
|
||||||
}
|
}
|
||||||
|
@ -143,7 +147,7 @@ class ApiBase extends Controller
|
||||||
|
|
||||||
// Check both user folder and album
|
// Check both user folder and album
|
||||||
return $this->getUserFolderFile($fileId) ??
|
return $this->getUserFolderFile($fileId) ??
|
||||||
$this->getAlbumFile($fileId);
|
$this->getAlbumFile($fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,6 +193,24 @@ class ApiBase extends Controller
|
||||||
protected function getShareFile(int $id): ?File
|
protected function getShareFile(int $id): ?File
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
// Album share
|
||||||
|
if ($this->request->getParam('album')) {
|
||||||
|
$album = $this->timelineQuery->getAlbumByLink($this->getShareToken());
|
||||||
|
if (null === $album) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$owner = $this->timelineQuery->albumHasFile($album['album_id'], $id);
|
||||||
|
if (!$owner) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$folder = $this->rootFolder->getUserFolder($owner);
|
||||||
|
|
||||||
|
return $this->getOneFileFromFolder($folder, $id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Folder share
|
||||||
if ($share = $this->getShareNode()) {
|
if ($share = $this->getShareNode()) {
|
||||||
return $this->getOneFileFromFolder($share, $id);
|
return $this->getOneFileFromFolder($share, $id);
|
||||||
}
|
}
|
||||||
|
@ -220,7 +242,7 @@ class ApiBase extends Controller
|
||||||
|
|
||||||
protected function getShareToken()
|
protected function getShareToken()
|
||||||
{
|
{
|
||||||
return $this->request->getParam('folder_share');
|
return $this->request->getParam('token');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getShareObject()
|
protected function getShareObject()
|
||||||
|
@ -242,8 +264,10 @@ class ApiBase extends Controller
|
||||||
$session = \OC::$server->get(\OCP\ISession::class);
|
$session = \OC::$server->get(\OCP\ISession::class);
|
||||||
|
|
||||||
// https://github.com/nextcloud/server/blob/0447b53bda9fe95ea0cbed765aa332584605d652/lib/public/AppFramework/PublicShareController.php#L119
|
// https://github.com/nextcloud/server/blob/0447b53bda9fe95ea0cbed765aa332584605d652/lib/public/AppFramework/PublicShareController.php#L119
|
||||||
if ($session->get('public_link_authenticated_token') !== $token
|
if (
|
||||||
|| $session->get('public_link_authenticated_password_hash') !== $password) {
|
$session->get('public_link_authenticated_token') !== $token
|
||||||
|
|| $session->get('public_link_authenticated_password_hash') !== $password
|
||||||
|
) {
|
||||||
throw new \Exception('Share is password protected and user is not authenticated');
|
throw new \Exception('Share is password protected and user is not authenticated');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,11 @@ class DaysController extends ApiBase
|
||||||
public function days(): JSONResponse
|
public function days(): JSONResponse
|
||||||
{
|
{
|
||||||
// Get the folder to show
|
// Get the folder to show
|
||||||
$uid = $this->getUID();
|
try {
|
||||||
|
$uid = $this->getUID();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_PRECONDITION_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
// Get the folder to show
|
// Get the folder to show
|
||||||
$root = null;
|
$root = null;
|
||||||
|
@ -183,6 +187,13 @@ class DaysController extends ApiBase
|
||||||
$transforms[] = [$this->timelineQuery, 'transformExtraFields', $fields];
|
$transforms[] = [$this->timelineQuery, 'transformExtraFields', $fields];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter for one album
|
||||||
|
if ($this->albumsIsEnabled()) {
|
||||||
|
if ($albumId = $this->request->getParam('album')) {
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformAlbumFilter', $albumId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Other transforms not allowed for public shares
|
// Other transforms not allowed for public shares
|
||||||
if (null === $this->userSession->getUser()) {
|
if (null === $this->userSession->getUser()) {
|
||||||
return $transforms;
|
return $transforms;
|
||||||
|
@ -226,13 +237,6 @@ class DaysController extends ApiBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter for one album
|
|
||||||
if ($this->albumsIsEnabled()) {
|
|
||||||
if ($albumId = $this->request->getParam('album')) {
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformAlbumFilter', $albumId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit number of responses for day query
|
// Limit number of responses for day query
|
||||||
$limit = $this->request->getParam('limit');
|
$limit = $this->request->getParam('limit');
|
||||||
if ($limit) {
|
if ($limit) {
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OCA\Memories\Controller;
|
||||||
|
|
||||||
|
use OCA\Files\Event\LoadSidebar;
|
||||||
|
use OCA\Memories\Db\TimelineQuery;
|
||||||
|
use OCP\App\IAppManager;
|
||||||
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http\ContentSecurityPolicy;
|
||||||
|
use OCP\AppFramework\Http\Template\PublicTemplateResponse;
|
||||||
|
use OCP\AppFramework\Http\TemplateResponse;
|
||||||
|
use OCP\AppFramework\Services\IInitialState;
|
||||||
|
use OCP\EventDispatcher\IEventDispatcher;
|
||||||
|
use OCP\IConfig;
|
||||||
|
use OCP\IDBConnection;
|
||||||
|
use OCP\Util;
|
||||||
|
|
||||||
|
class PublicAlbumController extends Controller
|
||||||
|
{
|
||||||
|
protected $appName;
|
||||||
|
protected IEventDispatcher $eventDispatcher;
|
||||||
|
protected IInitialState $initialState;
|
||||||
|
protected IAppManager $appManager;
|
||||||
|
protected IConfig $config;
|
||||||
|
protected IDBConnection $connection;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
string $appName,
|
||||||
|
IEventDispatcher $eventDispatcher,
|
||||||
|
IInitialState $initialState,
|
||||||
|
IAppManager $appManager,
|
||||||
|
IConfig $config,
|
||||||
|
IDBConnection $connection
|
||||||
|
) {
|
||||||
|
$this->appName = $appName;
|
||||||
|
$this->eventDispatcher = $eventDispatcher;
|
||||||
|
$this->initialState = $initialState;
|
||||||
|
$this->appManager = $appManager;
|
||||||
|
$this->config = $config;
|
||||||
|
$this->connection = $connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @PublicPage
|
||||||
|
*
|
||||||
|
* @NoCSRFRequired
|
||||||
|
*/
|
||||||
|
public function showShare(string $token): TemplateResponse
|
||||||
|
{
|
||||||
|
\OC_User::setIncognitoMode(true);
|
||||||
|
|
||||||
|
// Validate token exists
|
||||||
|
$timelineQuery = new TimelineQuery($this->connection);
|
||||||
|
$album = $timelineQuery->getAlbumByLink($token);
|
||||||
|
if (!$album) {
|
||||||
|
return new TemplateResponse('core', '404', [], 'guest');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scripts
|
||||||
|
Util::addScript($this->appName, 'memories-main');
|
||||||
|
$this->eventDispatcher->dispatchTyped(new LoadSidebar());
|
||||||
|
|
||||||
|
$this->initialState->provideInitialState('version', $this->appManager->getAppInfo('memories')['version']);
|
||||||
|
$this->initialState->provideInitialState('notranscode', $this->config->getSystemValue('memories.no_transcode', 'UNSET'));
|
||||||
|
|
||||||
|
$policy = new ContentSecurityPolicy();
|
||||||
|
$policy->addAllowedWorkerSrcDomain("'self'");
|
||||||
|
$policy->addAllowedScriptDomain("'self'");
|
||||||
|
|
||||||
|
// Video player
|
||||||
|
$policy->addAllowedWorkerSrcDomain('blob:');
|
||||||
|
$policy->addAllowedScriptDomain('blob:');
|
||||||
|
$policy->addAllowedMediaDomain('blob:');
|
||||||
|
|
||||||
|
// Image editor
|
||||||
|
$policy->addAllowedConnectDomain('data:');
|
||||||
|
|
||||||
|
// Allow nominatim for metadata
|
||||||
|
$policy->addAllowedConnectDomain('nominatim.openstreetmap.org');
|
||||||
|
$policy->addAllowedFrameDomain('www.openstreetmap.org');
|
||||||
|
|
||||||
|
$response = new PublicTemplateResponse($this->appName, 'main');
|
||||||
|
$response->setHeaderTitle($album['name']);
|
||||||
|
$response->setFooterVisible(false); // wth is that anyway?
|
||||||
|
$response->setContentSecurityPolicy($policy);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
|
@ -117,6 +117,24 @@ trait TimelineQueryAlbums
|
||||||
return $dayIds;
|
return $dayIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an album has a file.
|
||||||
|
*
|
||||||
|
* @return bool|string owner of file
|
||||||
|
*/
|
||||||
|
public function albumHasFile(int $albumId, int $fileId)
|
||||||
|
{
|
||||||
|
$query = $this->connection->getQueryBuilder();
|
||||||
|
$query->select('owner')->from('photos_albums_files')->where(
|
||||||
|
$query->expr()->andX(
|
||||||
|
$query->expr()->eq('file_id', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)),
|
||||||
|
$query->expr()->eq('album_id', $query->createNamedParameter($albumId, IQueryBuilder::PARAM_INT)),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $query->executeQuery()->fetchOne();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a file belongs to a user through an album.
|
* Check if a file belongs to a user through an album.
|
||||||
*
|
*
|
||||||
|
@ -159,25 +177,28 @@ trait TimelineQueryAlbums
|
||||||
*/
|
*/
|
||||||
public function getAlbumIfAllowed(string $uid, string $albumId)
|
public function getAlbumIfAllowed(string $uid, string $albumId)
|
||||||
{
|
{
|
||||||
|
$album = null;
|
||||||
|
|
||||||
// Split name and uid
|
// Split name and uid
|
||||||
$parts = explode('/', $albumId);
|
$parts = explode('/', $albumId);
|
||||||
if (2 !== \count($parts)) {
|
if (2 === \count($parts)) {
|
||||||
return null;
|
$albumUid = $parts[0];
|
||||||
}
|
$albumName = $parts[1];
|
||||||
$albumUid = $parts[0];
|
|
||||||
$albumName = $parts[1];
|
|
||||||
|
|
||||||
// Check if owner
|
// Check if owner
|
||||||
$query = $this->connection->getQueryBuilder();
|
$query = $this->connection->getQueryBuilder();
|
||||||
$query->select('*')->from('photos_albums')->where(
|
$query->select('*')->from('photos_albums')->where(
|
||||||
$query->expr()->andX(
|
$query->expr()->andX(
|
||||||
$query->expr()->eq('name', $query->createNamedParameter($albumName)),
|
$query->expr()->eq('name', $query->createNamedParameter($albumName)),
|
||||||
$query->expr()->eq('user', $query->createNamedParameter($albumUid)),
|
$query->expr()->eq('user', $query->createNamedParameter($albumUid)),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$album = $query->executeQuery()->fetch();
|
$album = $query->executeQuery()->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Album not found: it could be a link token at best
|
||||||
if (!$album) {
|
if (!$album) {
|
||||||
return null;
|
return $this->getAlbumByLink($albumId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if user is owner
|
// Check if user is owner
|
||||||
|
@ -200,6 +221,24 @@ trait TimelineQueryAlbums
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get album object by token.
|
||||||
|
* Returns false if album link does not exist.
|
||||||
|
*/
|
||||||
|
public function getAlbumByLink(string $token)
|
||||||
|
{
|
||||||
|
$query = $this->connection->getQueryBuilder();
|
||||||
|
$query->select('*')->from('photos_albums', 'pa')
|
||||||
|
->innerJoin('pa', $this->collaboratorsTable(), 'pc', $query->expr()->andX(
|
||||||
|
$query->expr()->eq('pc.album_id', 'pa.album_id'),
|
||||||
|
$query->expr()->eq('collaborator_id', $query->createNamedParameter($token)),
|
||||||
|
$query->expr()->eq('collaborator_type', $query->createNamedParameter(3)), // = TYPE_LINK
|
||||||
|
))
|
||||||
|
;
|
||||||
|
|
||||||
|
return $query->executeQuery()->fetch() ?: null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get full list of fileIds in album.
|
* Get full list of fileIds in album.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -140,7 +140,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
showNavigation(): boolean {
|
showNavigation(): boolean {
|
||||||
return this.$route.name !== "folder-share";
|
return !this.$route.name?.endsWith("-share");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -286,12 +286,12 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
doRouteChecks() {
|
doRouteChecks() {
|
||||||
if (this.$route.name === "folder-share") {
|
if (this.$route.name.endsWith("-share")) {
|
||||||
this.putFolderShareToken(<string>this.$route.params.token);
|
this.putShareToken(<string>this.$route.params.token);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
putFolderShareToken(token: string) {
|
putShareToken(token: string) {
|
||||||
// Viewer looks for an input with ID sharingToken with the value as the token
|
// Viewer looks for an input with ID sharingToken with the value as the token
|
||||||
// Create this element or update it otherwise files not gonna open
|
// Create this element or update it otherwise files not gonna open
|
||||||
// https://github.com/nextcloud/viewer/blob/a8c46050fb687dcbb48a022a15a5d1275bf54a8e/src/utils/davUtils.js#L61
|
// https://github.com/nextcloud/viewer/blob/a8c46050fb687dcbb48a022a15a5d1275bf54a8e/src/utils/davUtils.js#L61
|
||||||
|
|
|
@ -264,7 +264,7 @@ export default defineComponent({
|
||||||
|
|
||||||
/** Public route that can't modify anything */
|
/** Public route that can't modify anything */
|
||||||
routeIsPublic() {
|
routeIsPublic() {
|
||||||
return this.$route.name === "folder-share";
|
return this.$route.name?.endsWith("-share");
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Trigger to update props from selection set */
|
/** Trigger to update props from selection set */
|
||||||
|
|
|
@ -266,7 +266,9 @@ export default defineComponent({
|
||||||
return this.$route.name === "archive";
|
return this.$route.name === "archive";
|
||||||
},
|
},
|
||||||
isMonthView(): boolean {
|
isMonthView(): boolean {
|
||||||
return this.$route.name === "albums";
|
return (
|
||||||
|
this.$route.name === "albums" || this.$route.name === "album-share"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
/** Get view name for dynamic top matter */
|
/** Get view name for dynamic top matter */
|
||||||
viewName(): string {
|
viewName(): string {
|
||||||
|
|
|
@ -421,7 +421,7 @@ export default defineComponent({
|
||||||
async copyPublicLink() {
|
async copyPublicLink() {
|
||||||
await navigator.clipboard.writeText(
|
await navigator.clipboard.writeText(
|
||||||
`${window.location.protocol}//${window.location.host}${generateUrl(
|
`${window.location.protocol}//${window.location.host}${generateUrl(
|
||||||
`apps/photos/public/${this.publicLink.id}`
|
`apps/memories/a/${this.publicLink.id}`
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
this.publicLinkCopied = true;
|
this.publicLinkCopied = true;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
:album-name="album.basename"
|
:album-name="album.basename"
|
||||||
:collaborators="album.collaborators"
|
:collaborators="album.collaborators"
|
||||||
:public-link="album.publicLink"
|
:public-link="album.publicLink"
|
||||||
|
:allow-public-link="true"
|
||||||
v-slot="{ collaborators }"
|
v-slot="{ collaborators }"
|
||||||
>
|
>
|
||||||
<NcButton
|
<NcButton
|
||||||
|
|
|
@ -283,7 +283,7 @@ export default defineComponent({
|
||||||
|
|
||||||
/** Route is public */
|
/** Route is public */
|
||||||
routeIsPublic(): boolean {
|
routeIsPublic(): boolean {
|
||||||
return this.$route.name === "folder-share";
|
return this.$route.name?.endsWith("-share");
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Route is album */
|
/** Route is album */
|
||||||
|
|
|
@ -120,5 +120,14 @@ export default new Router({
|
||||||
rootTitle: t("memories", "Shared Folder"),
|
rootTitle: t("memories", "Shared Folder"),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: "/a/:token",
|
||||||
|
component: Timeline,
|
||||||
|
name: "album-share",
|
||||||
|
props: (route) => ({
|
||||||
|
rootTitle: t("memories", "Shared Album"),
|
||||||
|
}),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,7 +9,10 @@ function tok(url: string) {
|
||||||
const route = vueroute();
|
const route = vueroute();
|
||||||
if (route.name === "folder-share") {
|
if (route.name === "folder-share") {
|
||||||
const token = <string>route.params.token;
|
const token = <string>route.params.token;
|
||||||
url = API.Q(url, `folder_share=${token}`);
|
url = API.Q(url, `token=${token}`);
|
||||||
|
} else if (route.name === "album-share") {
|
||||||
|
const token = <string>route.params.token;
|
||||||
|
url = API.Q(url, `token=${token}&album=${token}`);
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue