From 6040f87d143a5fa01db79867ece8197c3ce7be47 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 4 Dec 2018 16:02:49 +0100 Subject: Add tmp and redundancy directories --- server/controllers/api/users/me.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'server/controllers/api/users') diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts index 82299747d..47f2c9ec7 100644 --- a/server/controllers/api/users/me.ts +++ b/server/controllers/api/users/me.ts @@ -42,7 +42,7 @@ import { AccountModel } from '../../../models/account/account' const auditLogger = auditLoggerFactory('users-me') -const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.AVATARS_DIR }) +const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR }) const meRouter = express.Router() @@ -348,7 +348,7 @@ async function updateMe (req: express.Request, res: express.Response, next: expr return res.sendStatus(204) } -async function updateMyAvatar (req: express.Request, res: express.Response, next: express.NextFunction) { +async function updateMyAvatar (req: express.Request, res: express.Response) { const avatarPhysicalFile = req.files[ 'avatarfile' ][ 0 ] const user: UserModel = res.locals.oauth.token.user const oldUserAuditView = new UserAuditView(user.toFormattedJSON()) -- cgit v1.2.3 From 4e74e8032be8293ffe3cb3c30528d4ef7c11a798 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 5 Dec 2018 14:36:05 +0100 Subject: Remove inferred type --- server/controllers/api/users/me.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'server/controllers/api/users') diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts index 47f2c9ec7..d2456346b 100644 --- a/server/controllers/api/users/me.ts +++ b/server/controllers/api/users/me.ts @@ -238,7 +238,7 @@ async function getUserSubscriptionVideos (req: express.Request, res: express.Res nsfw: buildNSFWFilter(res, req.query.nsfw), filter: req.query.filter as VideoFilter, withFiles: false, - actorId: user.Account.Actor.id, + followerActorId: user.Account.Actor.id, user }) -- cgit v1.2.3 From 14e2014acc1362cfbb770c051a7254b156cd8efb Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 11 Dec 2018 14:52:50 +0100 Subject: Support additional video extensions --- server/controllers/api/users/me.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'server/controllers/api/users') diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts index d2456346b..f712b0f0b 100644 --- a/server/controllers/api/users/me.ts +++ b/server/controllers/api/users/me.ts @@ -2,7 +2,7 @@ import * as express from 'express' import 'multer' import { UserUpdateMe, UserVideoRate as FormattedUserVideoRate } from '../../../../shared' import { getFormattedObjects } from '../../../helpers/utils' -import { CONFIG, IMAGE_MIMETYPE_EXT, sequelizeTypescript } from '../../../initializers' +import { CONFIG, MIMETYPES, sequelizeTypescript } from '../../../initializers' import { sendUpdateActor } from '../../../lib/activitypub/send' import { asyncMiddleware, @@ -42,7 +42,7 @@ import { AccountModel } from '../../../models/account/account' const auditLogger = auditLoggerFactory('users-me') -const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR }) +const reqAvatarFile = createReqFiles([ 'avatarfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR }) const meRouter = express.Router() -- cgit v1.2.3 From 8b9a525a180cc9f3a98c334cc052dcfc8f36dcd4 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 17 Dec 2018 15:52:38 +0100 Subject: Add history on server side Add ability to disable, clear and list user videos history --- server/controllers/api/users/index.ts | 2 ++ server/controllers/api/users/me.ts | 1 + server/controllers/api/users/my-history.ts | 57 ++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 server/controllers/api/users/my-history.ts (limited to 'server/controllers/api/users') diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts index 87fab4a40..bc24792a2 100644 --- a/server/controllers/api/users/index.ts +++ b/server/controllers/api/users/index.ts @@ -38,6 +38,7 @@ import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../h import { meRouter } from './me' import { deleteUserToken } from '../../../lib/oauth-model' import { myBlocklistRouter } from './my-blocklist' +import { myVideosHistoryRouter } from './my-history' const auditLogger = auditLoggerFactory('users') @@ -55,6 +56,7 @@ const askSendEmailLimiter = new RateLimit({ const usersRouter = express.Router() usersRouter.use('/', myBlocklistRouter) +usersRouter.use('/', myVideosHistoryRouter) usersRouter.use('/', meRouter) usersRouter.get('/autocomplete', diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts index f712b0f0b..8a3208160 100644 --- a/server/controllers/api/users/me.ts +++ b/server/controllers/api/users/me.ts @@ -330,6 +330,7 @@ async function updateMe (req: express.Request, res: express.Response, next: expr if (body.nsfwPolicy !== undefined) user.nsfwPolicy = body.nsfwPolicy if (body.webTorrentEnabled !== undefined) user.webTorrentEnabled = body.webTorrentEnabled if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo + if (body.videosHistoryEnabled !== undefined) user.videosHistoryEnabled = body.videosHistoryEnabled await sequelizeTypescript.transaction(async t => { const userAccount = await AccountModel.load(user.Account.id) diff --git a/server/controllers/api/users/my-history.ts b/server/controllers/api/users/my-history.ts new file mode 100644 index 000000000..6cd782c47 --- /dev/null +++ b/server/controllers/api/users/my-history.ts @@ -0,0 +1,57 @@ +import * as express from 'express' +import { + asyncMiddleware, + asyncRetryTransactionMiddleware, + authenticate, + paginationValidator, + setDefaultPagination, + userHistoryRemoveValidator +} from '../../../middlewares' +import { UserModel } from '../../../models/account/user' +import { getFormattedObjects } from '../../../helpers/utils' +import { UserVideoHistoryModel } from '../../../models/account/user-video-history' +import { sequelizeTypescript } from '../../../initializers' + +const myVideosHistoryRouter = express.Router() + +myVideosHistoryRouter.get('/me/history/videos', + authenticate, + paginationValidator, + setDefaultPagination, + asyncMiddleware(listMyVideosHistory) +) + +myVideosHistoryRouter.post('/me/history/videos/remove', + authenticate, + userHistoryRemoveValidator, + asyncRetryTransactionMiddleware(removeUserHistory) +) + +// --------------------------------------------------------------------------- + +export { + myVideosHistoryRouter +} + +// --------------------------------------------------------------------------- + +async function listMyVideosHistory (req: express.Request, res: express.Response) { + const user: UserModel = res.locals.oauth.token.User + + const resultList = await UserVideoHistoryModel.listForApi(user, req.query.start, req.query.count) + + return res.json(getFormattedObjects(resultList.data, resultList.total)) +} + +async function removeUserHistory (req: express.Request, res: express.Response) { + const user: UserModel = res.locals.oauth.token.User + const beforeDate = req.body.beforeDate || null + + await sequelizeTypescript.transaction(t => { + return UserVideoHistoryModel.removeHistoryBefore(user, beforeDate, t) + }) + + // Do not send the delete to other instances, we delete OUR copy of this video abuse + + return res.type('json').status(204).end() +} -- cgit v1.2.3 From cef534ed53e4518fe0acf581bfe880788d42fc36 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 26 Dec 2018 10:36:24 +0100 Subject: Add user notification base code --- server/controllers/api/users/index.ts | 2 + server/controllers/api/users/my-notifications.ts | 84 ++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 server/controllers/api/users/my-notifications.ts (limited to 'server/controllers/api/users') diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts index bc24792a2..98be46ea2 100644 --- a/server/controllers/api/users/index.ts +++ b/server/controllers/api/users/index.ts @@ -39,6 +39,7 @@ import { meRouter } from './me' import { deleteUserToken } from '../../../lib/oauth-model' import { myBlocklistRouter } from './my-blocklist' import { myVideosHistoryRouter } from './my-history' +import { myNotificationsRouter } from './my-notifications' const auditLogger = auditLoggerFactory('users') @@ -55,6 +56,7 @@ const askSendEmailLimiter = new RateLimit({ }) const usersRouter = express.Router() +usersRouter.use('/', myNotificationsRouter) usersRouter.use('/', myBlocklistRouter) usersRouter.use('/', myVideosHistoryRouter) usersRouter.use('/', meRouter) diff --git a/server/controllers/api/users/my-notifications.ts b/server/controllers/api/users/my-notifications.ts new file mode 100644 index 000000000..cef1d237c --- /dev/null +++ b/server/controllers/api/users/my-notifications.ts @@ -0,0 +1,84 @@ +import * as express from 'express' +import 'multer' +import { + asyncMiddleware, + asyncRetryTransactionMiddleware, + authenticate, + paginationValidator, + setDefaultPagination, + setDefaultSort, + userNotificationsSortValidator +} from '../../../middlewares' +import { UserModel } from '../../../models/account/user' +import { getFormattedObjects } from '../../../helpers/utils' +import { UserNotificationModel } from '../../../models/account/user-notification' +import { meRouter } from './me' +import { + markAsReadUserNotificationsValidator, + updateNotificationSettingsValidator +} from '../../../middlewares/validators/user-notifications' +import { UserNotificationSetting } from '../../../../shared/models/users' +import { UserNotificationSettingModel } from '../../../models/account/user-notification-setting' + +const myNotificationsRouter = express.Router() + +meRouter.put('/me/notification-settings', + authenticate, + updateNotificationSettingsValidator, + asyncRetryTransactionMiddleware(updateNotificationSettings) +) + +myNotificationsRouter.get('/me/notifications', + authenticate, + paginationValidator, + userNotificationsSortValidator, + setDefaultSort, + setDefaultPagination, + asyncMiddleware(listUserNotifications) +) + +myNotificationsRouter.post('/me/notifications/read', + authenticate, + markAsReadUserNotificationsValidator, + asyncMiddleware(markAsReadUserNotifications) +) + +export { + myNotificationsRouter +} + +// --------------------------------------------------------------------------- + +async function updateNotificationSettings (req: express.Request, res: express.Response) { + const user: UserModel = res.locals.oauth.token.User + const body: UserNotificationSetting = req.body + + const query = { + where: { + userId: user.id + } + } + + await UserNotificationSettingModel.update({ + newVideoFromSubscription: body.newVideoFromSubscription, + newCommentOnMyVideo: body.newCommentOnMyVideo + }, query) + + return res.status(204).end() +} + +async function listUserNotifications (req: express.Request, res: express.Response) { + const user: UserModel = res.locals.oauth.token.User + + const resultList = await UserNotificationModel.listForApi(user.id, req.query.start, req.query.count, req.query.sort) + + return res.json(getFormattedObjects(resultList.data, resultList.total)) +} + +async function markAsReadUserNotifications (req: express.Request, res: express.Response) { + const user: UserModel = res.locals.oauth.token.User + + await UserNotificationModel.markAsRead(user.id, req.body.ids) + + return res.status(204).end() +} -- cgit v1.2.3 From dc13348070d808d0ba3feb56a435b835c2e7e791 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 2 Jan 2019 16:37:43 +0100 Subject: Add import finished and video published notifs --- server/controllers/api/users/my-notifications.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'server/controllers/api/users') diff --git a/server/controllers/api/users/my-notifications.ts b/server/controllers/api/users/my-notifications.ts index cef1d237c..4b81777a4 100644 --- a/server/controllers/api/users/my-notifications.ts +++ b/server/controllers/api/users/my-notifications.ts @@ -14,10 +14,11 @@ import { getFormattedObjects } from '../../../helpers/utils' import { UserNotificationModel } from '../../../models/account/user-notification' import { meRouter } from './me' import { + listUserNotificationsValidator, markAsReadUserNotificationsValidator, updateNotificationSettingsValidator } from '../../../middlewares/validators/user-notifications' -import { UserNotificationSetting } from '../../../../shared/models/users' +import { UserNotificationSetting, UserNotificationSettingValue } from '../../../../shared/models/users' import { UserNotificationSettingModel } from '../../../models/account/user-notification-setting' const myNotificationsRouter = express.Router() @@ -34,6 +35,7 @@ myNotificationsRouter.get('/me/notifications', userNotificationsSortValidator, setDefaultSort, setDefaultPagination, + listUserNotificationsValidator, asyncMiddleware(listUserNotifications) ) @@ -61,7 +63,11 @@ async function updateNotificationSettings (req: express.Request, res: express.Re await UserNotificationSettingModel.update({ newVideoFromSubscription: body.newVideoFromSubscription, - newCommentOnMyVideo: body.newCommentOnMyVideo + newCommentOnMyVideo: body.newCommentOnMyVideo, + videoAbuseAsModerator: body.videoAbuseAsModerator, + blacklistOnMyVideo: body.blacklistOnMyVideo, + myVideoPublished: body.myVideoPublished, + myVideoImportFinished: body.myVideoImportFinished }, query) return res.status(204).end() @@ -70,7 +76,7 @@ async function updateNotificationSettings (req: express.Request, res: express.Re async function listUserNotifications (req: express.Request, res: express.Response) { const user: UserModel = res.locals.oauth.token.User - const resultList = await UserNotificationModel.listForApi(user.id, req.query.start, req.query.count, req.query.sort) + const resultList = await UserNotificationModel.listForApi(user.id, req.query.start, req.query.count, req.query.sort, req.query.unread) return res.json(getFormattedObjects(resultList.data, resultList.total)) } -- cgit v1.2.3 From f7cc67b455a12ccae9b0ea16876d166720364357 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 4 Jan 2019 08:56:20 +0100 Subject: Add new follow, mention and user registered notifs --- server/controllers/api/users/index.ts | 3 +++ server/controllers/api/users/my-notifications.ts | 15 ++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'server/controllers/api/users') diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts index 98be46ea2..9e6a019f6 100644 --- a/server/controllers/api/users/index.ts +++ b/server/controllers/api/users/index.ts @@ -40,6 +40,7 @@ import { deleteUserToken } from '../../../lib/oauth-model' import { myBlocklistRouter } from './my-blocklist' import { myVideosHistoryRouter } from './my-history' import { myNotificationsRouter } from './my-notifications' +import { Notifier } from '../../../lib/notifier' const auditLogger = auditLoggerFactory('users') @@ -213,6 +214,8 @@ async function registerUser (req: express.Request, res: express.Response) { await sendVerifyUserEmail(user) } + Notifier.Instance.notifyOnNewUserRegistration(user) + return res.type('json').status(204).end() } diff --git a/server/controllers/api/users/my-notifications.ts b/server/controllers/api/users/my-notifications.ts index 4b81777a4..d74d26add 100644 --- a/server/controllers/api/users/my-notifications.ts +++ b/server/controllers/api/users/my-notifications.ts @@ -18,7 +18,7 @@ import { markAsReadUserNotificationsValidator, updateNotificationSettingsValidator } from '../../../middlewares/validators/user-notifications' -import { UserNotificationSetting, UserNotificationSettingValue } from '../../../../shared/models/users' +import { UserNotificationSetting } from '../../../../shared/models/users' import { UserNotificationSettingModel } from '../../../models/account/user-notification-setting' const myNotificationsRouter = express.Router() @@ -53,7 +53,7 @@ export { async function updateNotificationSettings (req: express.Request, res: express.Response) { const user: UserModel = res.locals.oauth.token.User - const body: UserNotificationSetting = req.body + const body = req.body const query = { where: { @@ -61,14 +61,19 @@ async function updateNotificationSettings (req: express.Request, res: express.Re } } - await UserNotificationSettingModel.update({ + const values: UserNotificationSetting = { newVideoFromSubscription: body.newVideoFromSubscription, newCommentOnMyVideo: body.newCommentOnMyVideo, videoAbuseAsModerator: body.videoAbuseAsModerator, blacklistOnMyVideo: body.blacklistOnMyVideo, myVideoPublished: body.myVideoPublished, - myVideoImportFinished: body.myVideoImportFinished - }, query) + myVideoImportFinished: body.myVideoImportFinished, + newFollow: body.newFollow, + newUserRegistration: body.newUserRegistration, + commentMention: body.commentMention, + } + + await UserNotificationSettingModel.update(values, query) return res.status(204).end() } -- cgit v1.2.3 From 2f1548fda32c3ba9e53913270394eedfacd55986 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 8 Jan 2019 11:26:41 +0100 Subject: Add notifications in the client --- server/controllers/api/users/my-notifications.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'server/controllers/api/users') diff --git a/server/controllers/api/users/my-notifications.ts b/server/controllers/api/users/my-notifications.ts index d74d26add..76cf97587 100644 --- a/server/controllers/api/users/my-notifications.ts +++ b/server/controllers/api/users/my-notifications.ts @@ -45,6 +45,11 @@ myNotificationsRouter.post('/me/notifications/read', asyncMiddleware(markAsReadUserNotifications) ) +myNotificationsRouter.post('/me/notifications/read-all', + authenticate, + asyncMiddleware(markAsReadAllUserNotifications) +) + export { myNotificationsRouter } @@ -70,7 +75,7 @@ async function updateNotificationSettings (req: express.Request, res: express.Re myVideoImportFinished: body.myVideoImportFinished, newFollow: body.newFollow, newUserRegistration: body.newUserRegistration, - commentMention: body.commentMention, + commentMention: body.commentMention } await UserNotificationSettingModel.update(values, query) @@ -93,3 +98,11 @@ async function markAsReadUserNotifications (req: express.Request, res: express.R return res.status(204).end() } + +async function markAsReadAllUserNotifications (req: express.Request, res: express.Response) { + const user: UserModel = res.locals.oauth.token.User + + await UserNotificationModel.markAllAsRead(user.id) + + return res.status(204).end() +} -- cgit v1.2.3 From cf405589f06a9ac9d5a05b09bf2183fbf88d56d7 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 14 Jan 2019 10:44:59 +0100 Subject: Move subscriptions controllers in its own file --- server/controllers/api/users/index.ts | 2 + server/controllers/api/users/me.ts | 156 +-------------------- server/controllers/api/users/my-subscriptions.ts | 170 +++++++++++++++++++++++ 3 files changed, 174 insertions(+), 154 deletions(-) create mode 100644 server/controllers/api/users/my-subscriptions.ts (limited to 'server/controllers/api/users') diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts index 9e6a019f6..dbe0718d4 100644 --- a/server/controllers/api/users/index.ts +++ b/server/controllers/api/users/index.ts @@ -41,6 +41,7 @@ import { myBlocklistRouter } from './my-blocklist' import { myVideosHistoryRouter } from './my-history' import { myNotificationsRouter } from './my-notifications' import { Notifier } from '../../../lib/notifier' +import { mySubscriptionsRouter } from './my-subscriptions' const auditLogger = auditLoggerFactory('users') @@ -58,6 +59,7 @@ const askSendEmailLimiter = new RateLimit({ const usersRouter = express.Router() usersRouter.use('/', myNotificationsRouter) +usersRouter.use('/', mySubscriptionsRouter) usersRouter.use('/', myBlocklistRouter) usersRouter.use('/', myVideosHistoryRouter) usersRouter.use('/', meRouter) diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts index 8a3208160..94a2b8732 100644 --- a/server/controllers/api/users/me.ts +++ b/server/controllers/api/users/me.ts @@ -8,36 +8,23 @@ import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, - commonVideosFiltersValidator, paginationValidator, setDefaultPagination, setDefaultSort, - userSubscriptionAddValidator, - userSubscriptionGetValidator, usersUpdateMeValidator, usersVideoRatingValidator } from '../../../middlewares' -import { - areSubscriptionsExistValidator, - deleteMeValidator, - userSubscriptionsSortValidator, - videoImportsSortValidator, - videosSortValidator -} from '../../../middlewares/validators' +import { deleteMeValidator, videoImportsSortValidator, videosSortValidator } from '../../../middlewares/validators' import { AccountVideoRateModel } from '../../../models/account/account-video-rate' import { UserModel } from '../../../models/account/user' import { VideoModel } from '../../../models/video/video' import { VideoSortField } from '../../../../client/src/app/shared/video/sort-field.type' -import { buildNSFWFilter, createReqFiles } from '../../../helpers/express-utils' +import { createReqFiles } from '../../../helpers/express-utils' import { UserVideoQuota } from '../../../../shared/models/users/user-video-quota.model' import { updateAvatarValidator } from '../../../middlewares/validators/avatar' import { updateActorAvatarFile } from '../../../lib/avatar' import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger' import { VideoImportModel } from '../../../models/video/video-import' -import { VideoFilter } from '../../../../shared/models/videos/video-query.type' -import { ActorFollowModel } from '../../../models/activitypub/actor-follow' -import { JobQueue } from '../../../lib/job-queue' -import { logger } from '../../../helpers/logger' import { AccountModel } from '../../../models/account/account' const auditLogger = auditLoggerFactory('users-me') @@ -98,51 +85,6 @@ meRouter.post('/me/avatar/pick', asyncRetryTransactionMiddleware(updateMyAvatar) ) -// ##### Subscriptions part ##### - -meRouter.get('/me/subscriptions/videos', - authenticate, - paginationValidator, - videosSortValidator, - setDefaultSort, - setDefaultPagination, - commonVideosFiltersValidator, - asyncMiddleware(getUserSubscriptionVideos) -) - -meRouter.get('/me/subscriptions/exist', - authenticate, - areSubscriptionsExistValidator, - asyncMiddleware(areSubscriptionsExist) -) - -meRouter.get('/me/subscriptions', - authenticate, - paginationValidator, - userSubscriptionsSortValidator, - setDefaultSort, - setDefaultPagination, - asyncMiddleware(getUserSubscriptions) -) - -meRouter.post('/me/subscriptions', - authenticate, - userSubscriptionAddValidator, - asyncMiddleware(addUserSubscription) -) - -meRouter.get('/me/subscriptions/:uri', - authenticate, - userSubscriptionGetValidator, - getUserSubscription -) - -meRouter.delete('/me/subscriptions/:uri', - authenticate, - userSubscriptionGetValidator, - asyncRetryTransactionMiddleware(deleteUserSubscription) -) - // --------------------------------------------------------------------------- export { @@ -151,100 +93,6 @@ export { // --------------------------------------------------------------------------- -async function areSubscriptionsExist (req: express.Request, res: express.Response) { - const uris = req.query.uris as string[] - const user = res.locals.oauth.token.User as UserModel - - const handles = uris.map(u => { - let [ name, host ] = u.split('@') - if (host === CONFIG.WEBSERVER.HOST) host = null - - return { name, host, uri: u } - }) - - const results = await ActorFollowModel.listSubscribedIn(user.Account.Actor.id, handles) - - const existObject: { [id: string ]: boolean } = {} - for (const handle of handles) { - const obj = results.find(r => { - const server = r.ActorFollowing.Server - - return r.ActorFollowing.preferredUsername === handle.name && - ( - (!server && !handle.host) || - (server.host === handle.host) - ) - }) - - existObject[handle.uri] = obj !== undefined - } - - return res.json(existObject) -} - -async function addUserSubscription (req: express.Request, res: express.Response) { - const user = res.locals.oauth.token.User as UserModel - const [ name, host ] = req.body.uri.split('@') - - const payload = { - name, - host, - followerActorId: user.Account.Actor.id - } - - JobQueue.Instance.createJob({ type: 'activitypub-follow', payload }) - .catch(err => logger.error('Cannot create follow job for subscription %s.', req.body.uri, err)) - - return res.status(204).end() -} - -function getUserSubscription (req: express.Request, res: express.Response) { - const subscription: ActorFollowModel = res.locals.subscription - - return res.json(subscription.ActorFollowing.VideoChannel.toFormattedJSON()) -} - -async function deleteUserSubscription (req: express.Request, res: express.Response) { - const subscription: ActorFollowModel = res.locals.subscription - - await sequelizeTypescript.transaction(async t => { - return subscription.destroy({ transaction: t }) - }) - - return res.type('json').status(204).end() -} - -async function getUserSubscriptions (req: express.Request, res: express.Response) { - const user = res.locals.oauth.token.User as UserModel - const actorId = user.Account.Actor.id - - const resultList = await ActorFollowModel.listSubscriptionsForApi(actorId, req.query.start, req.query.count, req.query.sort) - - return res.json(getFormattedObjects(resultList.data, resultList.total)) -} - -async function getUserSubscriptionVideos (req: express.Request, res: express.Response, next: express.NextFunction) { - const user = res.locals.oauth.token.User as UserModel - const resultList = await VideoModel.listForApi({ - start: req.query.start, - count: req.query.count, - sort: req.query.sort, - includeLocalVideos: false, - categoryOneOf: req.query.categoryOneOf, - licenceOneOf: req.query.licenceOneOf, - languageOneOf: req.query.languageOneOf, - tagsOneOf: req.query.tagsOneOf, - tagsAllOf: req.query.tagsAllOf, - nsfw: buildNSFWFilter(res, req.query.nsfw), - filter: req.query.filter as VideoFilter, - withFiles: false, - followerActorId: user.Account.Actor.id, - user - }) - - return res.json(getFormattedObjects(resultList.data, resultList.total)) -} - async function getUserVideos (req: express.Request, res: express.Response, next: express.NextFunction) { const user = res.locals.oauth.token.User as UserModel const resultList = await VideoModel.listUserVideosForApi( diff --git a/server/controllers/api/users/my-subscriptions.ts b/server/controllers/api/users/my-subscriptions.ts new file mode 100644 index 000000000..accca6d52 --- /dev/null +++ b/server/controllers/api/users/my-subscriptions.ts @@ -0,0 +1,170 @@ +import * as express from 'express' +import 'multer' +import { getFormattedObjects } from '../../../helpers/utils' +import { CONFIG, sequelizeTypescript } from '../../../initializers' +import { + asyncMiddleware, + asyncRetryTransactionMiddleware, + authenticate, + commonVideosFiltersValidator, + paginationValidator, + setDefaultPagination, + setDefaultSort, + userSubscriptionAddValidator, + userSubscriptionGetValidator +} from '../../../middlewares' +import { areSubscriptionsExistValidator, userSubscriptionsSortValidator, videosSortValidator } from '../../../middlewares/validators' +import { UserModel } from '../../../models/account/user' +import { VideoModel } from '../../../models/video/video' +import { buildNSFWFilter } from '../../../helpers/express-utils' +import { VideoFilter } from '../../../../shared/models/videos/video-query.type' +import { ActorFollowModel } from '../../../models/activitypub/actor-follow' +import { JobQueue } from '../../../lib/job-queue' +import { logger } from '../../../helpers/logger' + +const mySubscriptionsRouter = express.Router() + +mySubscriptionsRouter.get('/me/subscriptions/videos', + authenticate, + paginationValidator, + videosSortValidator, + setDefaultSort, + setDefaultPagination, + commonVideosFiltersValidator, + asyncMiddleware(getUserSubscriptionVideos) +) + +mySubscriptionsRouter.get('/me/subscriptions/exist', + authenticate, + areSubscriptionsExistValidator, + asyncMiddleware(areSubscriptionsExist) +) + +mySubscriptionsRouter.get('/me/subscriptions', + authenticate, + paginationValidator, + userSubscriptionsSortValidator, + setDefaultSort, + setDefaultPagination, + asyncMiddleware(getUserSubscriptions) +) + +mySubscriptionsRouter.post('/me/subscriptions', + authenticate, + userSubscriptionAddValidator, + asyncMiddleware(addUserSubscription) +) + +mySubscriptionsRouter.get('/me/subscriptions/:uri', + authenticate, + userSubscriptionGetValidator, + getUserSubscription +) + +mySubscriptionsRouter.delete('/me/subscriptions/:uri', + authenticate, + userSubscriptionGetValidator, + asyncRetryTransactionMiddleware(deleteUserSubscription) +) + +// --------------------------------------------------------------------------- + +export { + mySubscriptionsRouter +} + +// --------------------------------------------------------------------------- + +async function areSubscriptionsExist (req: express.Request, res: express.Response) { + const uris = req.query.uris as string[] + const user = res.locals.oauth.token.User as UserModel + + const handles = uris.map(u => { + let [ name, host ] = u.split('@') + if (host === CONFIG.WEBSERVER.HOST) host = null + + return { name, host, uri: u } + }) + + const results = await ActorFollowModel.listSubscribedIn(user.Account.Actor.id, handles) + + const existObject: { [id: string ]: boolean } = {} + for (const handle of handles) { + const obj = results.find(r => { + const server = r.ActorFollowing.Server + + return r.ActorFollowing.preferredUsername === handle.name && + ( + (!server && !handle.host) || + (server.host === handle.host) + ) + }) + + existObject[handle.uri] = obj !== undefined + } + + return res.json(existObject) +} + +async function addUserSubscription (req: express.Request, res: express.Response) { + const user = res.locals.oauth.token.User as UserModel + const [ name, host ] = req.body.uri.split('@') + + const payload = { + name, + host, + followerActorId: user.Account.Actor.id + } + + JobQueue.Instance.createJob({ type: 'activitypub-follow', payload }) + .catch(err => logger.error('Cannot create follow job for subscription %s.', req.body.uri, err)) + + return res.status(204).end() +} + +function getUserSubscription (req: express.Request, res: express.Response) { + const subscription: ActorFollowModel = res.locals.subscription + + return res.json(subscription.ActorFollowing.VideoChannel.toFormattedJSON()) +} + +async function deleteUserSubscription (req: express.Request, res: express.Response) { + const subscription: ActorFollowModel = res.locals.subscription + + await sequelizeTypescript.transaction(async t => { + return subscription.destroy({ transaction: t }) + }) + + return res.type('json').status(204).end() +} + +async function getUserSubscriptions (req: express.Request, res: express.Response) { + const user = res.locals.oauth.token.User as UserModel + const actorId = user.Account.Actor.id + + const resultList = await ActorFollowModel.listSubscriptionsForApi(actorId, req.query.start, req.query.count, req.query.sort) + + return res.json(getFormattedObjects(resultList.data, resultList.total)) +} + +async function getUserSubscriptionVideos (req: express.Request, res: express.Response, next: express.NextFunction) { + const user = res.locals.oauth.token.User as UserModel + const resultList = await VideoModel.listForApi({ + start: req.query.start, + count: req.query.count, + sort: req.query.sort, + includeLocalVideos: false, + categoryOneOf: req.query.categoryOneOf, + licenceOneOf: req.query.licenceOneOf, + languageOneOf: req.query.languageOneOf, + tagsOneOf: req.query.tagsOneOf, + tagsAllOf: req.query.tagsAllOf, + nsfw: buildNSFWFilter(res, req.query.nsfw), + filter: req.query.filter as VideoFilter, + withFiles: false, + followerActorId: user.Account.Actor.id, + user + }) + + return res.json(getFormattedObjects(resultList.data, resultList.total)) +} -- cgit v1.2.3