From: Chocobozzz Date: Thu, 28 Dec 2017 10:16:08 +0000 (+0100) Subject: Propagate old comment on new follow X-Git-Tag: v0.0.1-alpha~80 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=da854ddd502cd70685ef779c673b9e63757b8aa0;p=oweals%2Fpeertube.git Propagate old comment on new follow --- diff --git a/scripts/update-host.ts b/scripts/update-host.ts index 4551a4702..3fb5f1972 100755 --- a/scripts/update-host.ts +++ b/scripts/update-host.ts @@ -1,4 +1,4 @@ -import { getServerActor } from '../server/helpers' +import { getServerActor } from '../server/helpers/utils' import { initDatabaseModels } from '../server/initializers' import { ActorFollowModel } from '../server/models/activitypub/actor-follow' import { VideoModel } from '../server/models/video/video' diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts index 8c6294ff7..71e706346 100644 --- a/server/controllers/activitypub/client.ts +++ b/server/controllers/activitypub/client.ts @@ -1,14 +1,17 @@ // Intercept ActivityPub client requests import * as express from 'express' -import { activityPubCollectionPagination, pageToStartAndCount } from '../../helpers' +import { activityPubCollectionPagination } from '../../helpers/activitypub' +import { pageToStartAndCount } from '../../helpers/core-utils' import { ACTIVITY_PUB, CONFIG } from '../../initializers' import { buildVideoAnnounceToFollowers } from '../../lib/activitypub/send' import { asyncMiddleware, executeIfActivityPub, localAccountValidator } from '../../middlewares' import { videoChannelsGetValidator, videosGetValidator, videosShareValidator } from '../../middlewares/validators' +import { videoCommentGetValidator } from '../../middlewares/validators/video-comments' import { AccountModel } from '../../models/account/account' import { ActorFollowModel } from '../../models/activitypub/actor-follow' import { VideoModel } from '../../models/video/video' import { VideoChannelModel } from '../../models/video/video-channel' +import { VideoCommentModel } from '../../models/video/video-comment' import { VideoShareModel } from '../../models/video/video-share' const activityPubClientRouter = express.Router() @@ -30,7 +33,7 @@ activityPubClientRouter.get('/account/:name/following', activityPubClientRouter.get('/videos/watch/:id', executeIfActivityPub(asyncMiddleware(videosGetValidator)), - executeIfActivityPub(videoController) + executeIfActivityPub(asyncMiddleware(videoController)) ) activityPubClientRouter.get('/videos/watch/:id/announces/:accountId', @@ -38,6 +41,11 @@ activityPubClientRouter.get('/videos/watch/:id/announces/:accountId', executeIfActivityPub(asyncMiddleware(videoAnnounceController)) ) +activityPubClientRouter.get('/videos/watch/:videoId/comments/:commentId', + executeIfActivityPub(asyncMiddleware(videoCommentGetValidator)), + executeIfActivityPub(asyncMiddleware(videoCommentController)) +) + activityPubClientRouter.get('/video-channels/:id', executeIfActivityPub(asyncMiddleware(videoChannelsGetValidator)), executeIfActivityPub(asyncMiddleware(videoChannelController)) @@ -54,7 +62,8 @@ export { function accountController (req: express.Request, res: express.Response, next: express.NextFunction) { const account: AccountModel = res.locals.account - return res.json(account.toActivityPubObject()).end() + return res.json(account.toActivityPubObject()) + .end() } async function accountFollowersController (req: express.Request, res: express.Response, next: express.NextFunction) { @@ -81,10 +90,12 @@ async function accountFollowingController (req: express.Request, res: express.Re return res.json(activityPubResult) } -function videoController (req: express.Request, res: express.Response, next: express.NextFunction) { +async function videoController (req: express.Request, res: express.Response, next: express.NextFunction) { const video: VideoModel = res.locals.video - return res.json(video.toActivityPubObject()) + // We need more attributes + const videoAll = await VideoModel.loadAndPopulateAll(video.id) + return res.json(videoAll.toActivityPubObject()) } async function videoAnnounceController (req: express.Request, res: express.Response, next: express.NextFunction) { @@ -99,3 +110,9 @@ async function videoChannelController (req: express.Request, res: express.Respon return res.json(videoChannel.toActivityPubObject()) } + +async function videoCommentController (req: express.Request, res: express.Response, next: express.NextFunction) { + const videoComment: VideoCommentModel = res.locals.videoComment + + return res.json(videoComment.toActivityPubObject()) +} diff --git a/server/controllers/activitypub/inbox.ts b/server/controllers/activitypub/inbox.ts index 8332eabb1..bfcb7b369 100644 --- a/server/controllers/activitypub/inbox.ts +++ b/server/controllers/activitypub/inbox.ts @@ -1,7 +1,7 @@ import * as express from 'express' import { Activity, ActivityPubCollection, ActivityPubOrderedCollection, RootActivity } from '../../../shared' -import { logger } from '../../helpers' import { isActivityValid } from '../../helpers/custom-validators/activitypub/activity' +import { logger } from '../../helpers/logger' import { processActivities } from '../../lib/activitypub/process/process' import { asyncMiddleware, checkSignature, localAccountValidator, signatureValidator } from '../../middlewares' import { activityPubValidator } from '../../middlewares/validators/activitypub/activity' diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 5f704f0ee..2f1132904 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts @@ -1,6 +1,6 @@ import * as express from 'express' +import { isSignupAllowed } from '../../helpers/utils' -import { isSignupAllowed } from '../../helpers' import { CONFIG } from '../../initializers' import { asyncMiddleware } from '../../middlewares' import { ServerConfig } from '../../../shared' diff --git a/server/controllers/api/index.ts b/server/controllers/api/index.ts index 737ea4602..1fd44ac11 100644 --- a/server/controllers/api/index.ts +++ b/server/controllers/api/index.ts @@ -1,13 +1,11 @@ import * as express from 'express' - -import { badRequest } from '../../helpers' - -import { oauthClientsRouter } from './oauth-clients' +import { badRequest } from '../../helpers/utils' import { configRouter } from './config' +import { jobsRouter } from './jobs' +import { oauthClientsRouter } from './oauth-clients' import { serverRouter } from './server' import { usersRouter } from './users' import { videosRouter } from './videos' -import { jobsRouter } from './jobs' const apiRouter = express.Router() diff --git a/server/controllers/api/jobs.ts b/server/controllers/api/jobs.ts index 4e7cd1ee3..d9d6030a4 100644 --- a/server/controllers/api/jobs.ts +++ b/server/controllers/api/jobs.ts @@ -1,6 +1,6 @@ import * as express from 'express' import { UserRight } from '../../../shared/models/users' -import { getFormattedObjects } from '../../helpers' +import { getFormattedObjects } from '../../helpers/utils' import { asyncMiddleware, authenticate, ensureUserHasRight, jobsSortValidator, setJobsSort, setPagination } from '../../middlewares' import { paginationValidator } from '../../middlewares/validators' import { JobModel } from '../../models/job/job' diff --git a/server/controllers/api/oauth-clients.ts b/server/controllers/api/oauth-clients.ts index bc02fce90..3dcc023e6 100644 --- a/server/controllers/api/oauth-clients.ts +++ b/server/controllers/api/oauth-clients.ts @@ -1,9 +1,8 @@ import * as express from 'express' - +import { OAuthClientLocal } from '../../../shared' +import { logger } from '../../helpers/logger' import { CONFIG } from '../../initializers' -import { logger } from '../../helpers' import { asyncMiddleware } from '../../middlewares' -import { OAuthClientLocal } from '../../../shared' import { OAuthClientModel } from '../../models/oauth/oauth-client' const oauthClientsRouter = express.Router() diff --git a/server/controllers/api/server/follows.ts b/server/controllers/api/server/follows.ts index ae5413b75..c87107197 100644 --- a/server/controllers/api/server/follows.ts +++ b/server/controllers/api/server/follows.ts @@ -1,11 +1,12 @@ import * as express from 'express' import { UserRight } from '../../../../shared/models/users' -import { - getFormattedObjects, getServerActor, loadActorUrlOrGetFromWebfinger, logger, retryTransactionWrapper, - sanitizeHost -} from '../../../helpers' +import { sanitizeHost } from '../../../helpers/core-utils' +import { retryTransactionWrapper } from '../../../helpers/database-utils' +import { logger } from '../../../helpers/logger' +import { getFormattedObjects, getServerActor } from '../../../helpers/utils' +import { loadActorUrlOrGetFromWebfinger } from '../../../helpers/webfinger' import { REMOTE_SCHEME, sequelizeTypescript, SERVER_ACTOR_NAME } from '../../../initializers' -import { getOrCreateActorAndServerAndModel } from '../../../lib/activitypub' +import { getOrCreateActorAndServerAndModel } from '../../../lib/activitypub/actor' import { sendFollow, sendUndoFollow } from '../../../lib/activitypub/send' import { asyncMiddleware, authenticate, ensureUserHasRight, paginationValidator, removeFollowingValidator, setBodyHostsPort, diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts index 3106df9b9..75393ad17 100644 --- a/server/controllers/api/users.ts +++ b/server/controllers/api/users.ts @@ -1,26 +1,14 @@ import * as express from 'express' import { UserCreate, UserRight, UserRole, UserUpdate, UserUpdateMe, UserVideoRate as FormattedUserVideoRate } from '../../../shared' -import { getFormattedObjects, logger, retryTransactionWrapper } from '../../helpers' +import { retryTransactionWrapper } from '../../helpers/database-utils' +import { logger } from '../../helpers/logger' +import { getFormattedObjects } from '../../helpers/utils' import { CONFIG } from '../../initializers' import { createUserAccountAndChannel } from '../../lib/user' import { - asyncMiddleware, - authenticate, - ensureUserHasRight, - ensureUserRegistrationAllowed, - paginationValidator, - setPagination, - setUsersSort, - setVideosSort, - token, - usersAddValidator, - usersGetValidator, - usersRegisterValidator, - usersRemoveValidator, - usersSortValidator, - usersUpdateMeValidator, - usersUpdateValidator, - usersVideoRatingValidator + asyncMiddleware, authenticate, ensureUserHasRight, ensureUserRegistrationAllowed, paginationValidator, setPagination, setUsersSort, + setVideosSort, token, usersAddValidator, usersGetValidator, usersRegisterValidator, usersRemoveValidator, usersSortValidator, + usersUpdateMeValidator, usersUpdateValidator, usersVideoRatingValidator } from '../../middlewares' import { videosSortValidator } from '../../middlewares/validators' import { AccountVideoRateModel } from '../../models/account/account-video-rate' diff --git a/server/controllers/api/videos/abuse.ts b/server/controllers/api/videos/abuse.ts index fecdaf5a3..e78f0f6fc 100644 --- a/server/controllers/api/videos/abuse.ts +++ b/server/controllers/api/videos/abuse.ts @@ -1,17 +1,13 @@ import * as express from 'express' import { UserRight, VideoAbuseCreate } from '../../../../shared' -import { getFormattedObjects, logger, retryTransactionWrapper } from '../../../helpers' +import { retryTransactionWrapper } from '../../../helpers/database-utils' +import { logger } from '../../../helpers/logger' +import { getFormattedObjects } from '../../../helpers/utils' import { sequelizeTypescript } from '../../../initializers' import { sendVideoAbuse } from '../../../lib/activitypub/send' import { - asyncMiddleware, - authenticate, - ensureUserHasRight, - paginationValidator, - setPagination, - setVideoAbusesSort, - videoAbuseReportValidator, - videoAbusesSortValidator + asyncMiddleware, authenticate, ensureUserHasRight, paginationValidator, setPagination, setVideoAbusesSort, + videoAbuseReportValidator, videoAbusesSortValidator } from '../../../middlewares' import { AccountModel } from '../../../models/account/account' import { VideoModel } from '../../../models/video/video' diff --git a/server/controllers/api/videos/blacklist.ts b/server/controllers/api/videos/blacklist.ts index d08c6e13f..c9087fd97 100644 --- a/server/controllers/api/videos/blacklist.ts +++ b/server/controllers/api/videos/blacklist.ts @@ -1,17 +1,11 @@ import * as express from 'express' -import { logger, getFormattedObjects } from '../../../helpers' +import { BlacklistedVideo, UserRight } from '../../../../shared' +import { logger } from '../../../helpers/logger' +import { getFormattedObjects } from '../../../helpers/utils' import { - authenticate, - ensureUserHasRight, - videosBlacklistAddValidator, - videosBlacklistRemoveValidator, - paginationValidator, - blacklistSortValidator, - setBlacklistSort, - setPagination, - asyncMiddleware + asyncMiddleware, authenticate, blacklistSortValidator, ensureUserHasRight, paginationValidator, setBlacklistSort, setPagination, + videosBlacklistAddValidator, videosBlacklistRemoveValidator } from '../../../middlewares' -import { BlacklistedVideo, UserRight } from '../../../../shared' import { VideoBlacklistModel } from '../../../models/video/video-blacklist' const blacklistRouter = express.Router() diff --git a/server/controllers/api/videos/channel.ts b/server/controllers/api/videos/channel.ts index cc00d9f8d..7c62b5476 100644 --- a/server/controllers/api/videos/channel.ts +++ b/server/controllers/api/videos/channel.ts @@ -1,20 +1,14 @@ import * as express from 'express' import { VideoChannelCreate, VideoChannelUpdate } from '../../../../shared' -import { getFormattedObjects, logger, resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers' +import { retryTransactionWrapper } from '../../../helpers/database-utils' +import { logger } from '../../../helpers/logger' +import { getFormattedObjects, resetSequelizeInstance } from '../../../helpers/utils' import { sequelizeTypescript } from '../../../initializers' import { setAsyncActorKeys } from '../../../lib/activitypub' import { createVideoChannel } from '../../../lib/video-channel' import { - asyncMiddleware, - authenticate, - listVideoAccountChannelsValidator, - paginationValidator, - setPagination, - setVideoChannelsSort, - videoChannelsAddValidator, - videoChannelsGetValidator, - videoChannelsRemoveValidator, - videoChannelsSortValidator, + asyncMiddleware, authenticate, listVideoAccountChannelsValidator, paginationValidator, setPagination, setVideoChannelsSort, + videoChannelsAddValidator, videoChannelsGetValidator, videoChannelsRemoveValidator, videoChannelsSortValidator, videoChannelsUpdateValidator } from '../../../middlewares' import { AccountModel } from '../../../models/account/account' diff --git a/server/controllers/api/videos/comment.ts b/server/controllers/api/videos/comment.ts index 276948098..b11da2ef7 100644 --- a/server/controllers/api/videos/comment.ts +++ b/server/controllers/api/videos/comment.ts @@ -1,6 +1,7 @@ import * as express from 'express' import { VideoCommentCreate } from '../../../../shared/models/videos/video-comment.model' -import { getFormattedObjects, retryTransactionWrapper } from '../../../helpers' +import { retryTransactionWrapper } from '../../../helpers/database-utils' +import { getFormattedObjects } from '../../../helpers/utils' import { sequelizeTypescript } from '../../../initializers' import { buildFormattedCommentTree, createVideoComment } from '../../../lib/video-comment' import { asyncMiddleware, authenticate, paginationValidator, setPagination, setVideoCommentThreadsSort } from '../../../middlewares' diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 8e54d95ab..11e3da5cc 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts @@ -2,44 +2,21 @@ import * as express from 'express' import * as multer from 'multer' import { extname, join } from 'path' import { VideoCreate, VideoPrivacy, VideoUpdate } from '../../../../shared' +import { renamePromise } from '../../../helpers/core-utils' +import { retryTransactionWrapper } from '../../../helpers/database-utils' +import { getVideoFileHeight } from '../../../helpers/ffmpeg-utils' +import { logger } from '../../../helpers/logger' +import { generateRandomString, getFormattedObjects, getServerActor, resetSequelizeInstance } from '../../../helpers/utils' import { - generateRandomString, - getFormattedObjects, - getVideoFileHeight, - logger, - renamePromise, - resetSequelizeInstance, - retryTransactionWrapper -} from '../../../helpers' -import { getServerActor } from '../../../helpers/utils' -import { - CONFIG, - sequelizeTypescript, - VIDEO_CATEGORIES, - VIDEO_LANGUAGES, - VIDEO_LICENCES, - VIDEO_MIMETYPE_EXT, + CONFIG, sequelizeTypescript, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_MIMETYPE_EXT, VIDEO_PRIVACIES } from '../../../initializers' -import { - fetchRemoteVideoDescription, - getVideoActivityPubUrl, - shareVideoByServerAndChannel -} from '../../../lib/activitypub' +import { fetchRemoteVideoDescription, getVideoActivityPubUrl, shareVideoByServerAndChannel } from '../../../lib/activitypub' import { sendCreateVideo, sendCreateViewToOrigin, sendCreateViewToVideoFollowers, sendUpdateVideo } from '../../../lib/activitypub/send' import { transcodingJobScheduler } from '../../../lib/jobs/transcoding-job-scheduler' import { - asyncMiddleware, - authenticate, - paginationValidator, - setPagination, - setVideosSort, - videosAddValidator, - videosGetValidator, - videosRemoveValidator, - videosSearchValidator, - videosSortValidator, - videosUpdateValidator + asyncMiddleware, authenticate, paginationValidator, setPagination, setVideosSort, videosAddValidator, videosGetValidator, + videosRemoveValidator, videosSearchValidator, videosSortValidator, videosUpdateValidator } from '../../../middlewares' import { TagModel } from '../../../models/video/tag' import { VideoModel } from '../../../models/video/video' diff --git a/server/controllers/api/videos/rate.ts b/server/controllers/api/videos/rate.ts index 48b744b0c..b470f27f6 100644 --- a/server/controllers/api/videos/rate.ts +++ b/server/controllers/api/videos/rate.ts @@ -1,6 +1,7 @@ import * as express from 'express' import { UserVideoRateUpdate } from '../../../../shared' -import { logger, retryTransactionWrapper } from '../../../helpers' +import { retryTransactionWrapper } from '../../../helpers/database-utils' +import { logger } from '../../../helpers/logger' import { sequelizeTypescript, VIDEO_RATE_TYPES } from '../../../initializers' import { sendVideoRateChangeToFollowers, sendVideoRateChangeToOrigin } from '../../../lib/activitypub' import { asyncMiddleware, authenticate, videoRateValidator } from '../../../middlewares' diff --git a/server/controllers/client.ts b/server/controllers/client.ts index 9a72fe8e0..39e046727 100644 --- a/server/controllers/client.ts +++ b/server/controllers/client.ts @@ -1,15 +1,9 @@ +import * as Bluebird from 'bluebird' import * as express from 'express' import { join } from 'path' import * as validator from 'validator' -import * as Bluebird from 'bluebird' -import { - CONFIG, - STATIC_PATHS, - STATIC_MAX_AGE, - OPENGRAPH_AND_OEMBED_COMMENT, - EMBED_SIZE -} from '../initializers' -import { root, readFileBufferPromise, escapeHTML } from '../helpers' +import { escapeHTML, readFileBufferPromise, root } from '../helpers/core-utils' +import { CONFIG, EMBED_SIZE, OPENGRAPH_AND_OEMBED_COMMENT, STATIC_MAX_AGE, STATIC_PATHS } from '../initializers' import { asyncMiddleware } from '../middlewares' import { VideoModel } from '../models/video/video' diff --git a/server/helpers/custom-validators/activitypub/actor.ts b/server/helpers/custom-validators/activitypub/actor.ts index ec8da3350..630bace30 100644 --- a/server/helpers/custom-validators/activitypub/actor.ts +++ b/server/helpers/custom-validators/activitypub/actor.ts @@ -46,7 +46,8 @@ function isActorPrivateKeyValid (privateKey: string) { } function isRemoteActorValid (remoteActor: any) { - return isActivityPubUrlValid(remoteActor.id) && + return exists(remoteActor) && + isActivityPubUrlValid(remoteActor.id) && isActorTypeValid(remoteActor.type) && isActivityPubUrlValid(remoteActor.following) && isActivityPubUrlValid(remoteActor.followers) && diff --git a/server/helpers/custom-validators/activitypub/announce.ts b/server/helpers/custom-validators/activitypub/announce.ts index 1baea4f60..7dd1d6988 100644 --- a/server/helpers/custom-validators/activitypub/announce.ts +++ b/server/helpers/custom-validators/activitypub/announce.ts @@ -2,7 +2,6 @@ import { isActivityPubUrlValid, isBaseActivityValid } from './misc' import { isVideoTorrentCreateActivityValid } from './videos' function isAnnounceActivityValid (activity: any) { - console.log(activity) return isBaseActivityValid(activity, 'Announce') && ( isVideoTorrentCreateActivityValid(activity.object) || diff --git a/server/helpers/custom-validators/activitypub/index.ts b/server/helpers/custom-validators/activitypub/index.ts deleted file mode 100644 index ba411f1c6..000000000 --- a/server/helpers/custom-validators/activitypub/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './actor' -export * from './activity' -export * from './misc' -export * from './signature' -export * from './undo' -export * from './video-channels' -export * from './videos' -export * from './view' diff --git a/server/helpers/index.ts b/server/helpers/index.ts deleted file mode 100644 index d96bc48e9..000000000 --- a/server/helpers/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * from './activitypub' -export * from './core-utils' -export * from './logger' -export * from './ffmpeg-utils' -export * from './database-utils' -export * from './peertube-crypto' -export * from './requests' -export * from './utils' -export * from './webfinger' diff --git a/server/helpers/requests.ts b/server/helpers/requests.ts index 4b1deeadc..ce185a2c0 100644 --- a/server/helpers/requests.ts +++ b/server/helpers/requests.ts @@ -1,8 +1,14 @@ import * as Promise from 'bluebird' import { createWriteStream } from 'fs' import * as request from 'request' +import { ACTIVITY_PUB } from '../initializers' + +function doRequest (requestOptions: request.CoreOptions & request.UriOptions & { activityPub?: boolean }) { + if (requestOptions.activityPub === true) { + if (!Array.isArray(requestOptions.headers)) requestOptions.headers = {} + requestOptions.headers['accept'] = ACTIVITY_PUB.ACCEPT_HEADER + } -function doRequest (requestOptions: request.CoreOptions & request.UriOptions) { return new Promise<{ response: request.RequestResponse, body: any }>((res, rej) => { request(requestOptions, (err, response, body) => err ? rej(err) : res({ response, body })) }) diff --git a/server/helpers/webfinger.ts b/server/helpers/webfinger.ts index 76444fbe3..de8d52c9b 100644 --- a/server/helpers/webfinger.ts +++ b/server/helpers/webfinger.ts @@ -2,7 +2,7 @@ import * as WebFinger from 'webfinger.js' import { WebFingerData } from '../../shared' import { ActorModel } from '../models/activitypub/actor' import { isTestInstance } from './core-utils' -import { isActivityPubUrlValid } from './custom-validators/activitypub' +import { isActivityPubUrlValid } from './custom-validators/activitypub/misc' const webfinger = new WebFinger({ webfist_fallback: false, diff --git a/server/initializers/checker.ts b/server/initializers/checker.ts index 7e76990b5..45647ab1d 100644 --- a/server/initializers/checker.ts +++ b/server/initializers/checker.ts @@ -1,5 +1,5 @@ import * as config from 'config' -import { promisify0 } from '../helpers' +import { promisify0 } from '../helpers/core-utils' import { UserModel } from '../models/account/user' import { ApplicationModel } from '../models/application/application' import { OAuthClientModel } from '../models/oauth/oauth-client' diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts index ee3c9dfd9..58713c2c4 100644 --- a/server/initializers/installer.ts +++ b/server/initializers/installer.ts @@ -1,6 +1,7 @@ import * as passwordGenerator from 'password-generator' import { UserRole } from '../../shared' -import { logger, mkdirpPromise, rimrafPromise } from '../helpers' +import { mkdirpPromise, rimrafPromise } from '../helpers/core-utils' +import { logger } from '../helpers/logger' import { createApplicationActor, createUserAccountAndChannel } from '../lib/user' import { UserModel } from '../models/account/user' import { ApplicationModel } from '../models/application/application' diff --git a/server/initializers/migrations/0135-video-channel-actor.ts b/server/initializers/migrations/0135-video-channel-actor.ts index 9b5acb338..033f43b68 100644 --- a/server/initializers/migrations/0135-video-channel-actor.ts +++ b/server/initializers/migrations/0135-video-channel-actor.ts @@ -1,6 +1,6 @@ import * as Sequelize from 'sequelize' import { DataType } from 'sequelize-typescript' -import { createPrivateAndPublicKeys } from '../../helpers' +import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' async function up (utils: { transaction: Sequelize.Transaction, diff --git a/server/initializers/migrator.ts b/server/initializers/migrator.ts index bb2539fc8..29310b913 100644 --- a/server/initializers/migrator.ts +++ b/server/initializers/migrator.ts @@ -1,5 +1,6 @@ import * as path from 'path' -import { logger, readdirPromise } from '../helpers' +import { readdirPromise } from '../helpers/core-utils' +import { logger } from '../helpers/logger' import { LAST_MIGRATION_VERSION } from './constants' import { sequelizeTypescript } from './database' diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index ff0a291e8..e590dc72d 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts @@ -3,9 +3,12 @@ import { Transaction } from 'sequelize' import * as url from 'url' import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub' import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' -import { createPrivateAndPublicKeys, doRequest, logger, retryTransactionWrapper } from '../../helpers' -import { isRemoteActorValid } from '../../helpers/custom-validators/activitypub' -import { ACTIVITY_PUB, CONFIG, sequelizeTypescript } from '../../initializers' +import { isRemoteActorValid } from '../../helpers/custom-validators/activitypub/actor' +import { retryTransactionWrapper } from '../../helpers/database-utils' +import { logger } from '../../helpers/logger' +import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' +import { doRequest } from '../../helpers/requests' +import { CONFIG, sequelizeTypescript } from '../../initializers' import { AccountModel } from '../../models/account/account' import { ActorModel } from '../../models/activitypub/actor' import { ServerModel } from '../../models/server/server' @@ -115,22 +118,15 @@ async function fetchRemoteActor (actorUrl: string): Promise { + logger.debug('Checking videoCommentGetValidator parameters.', { parameters: req.params }) + + if (areValidationErrors(req, res)) return + if (!await isVideoExist(req.params.videoId, res)) return + if (!await isVideoCommentExist(req.params.commentId, res.locals.video, res)) return + + return next() + } +] + // --------------------------------------------------------------------------- export { listVideoCommentThreadsValidator, listVideoThreadCommentsValidator, addVideoCommentThreadValidator, - addVideoCommentReplyValidator + addVideoCommentReplyValidator, + videoCommentGetValidator } // --------------------------------------------------------------------------- @@ -109,7 +125,7 @@ async function isVideoCommentThreadExist (id: number, video: VideoModel, res: ex } async function isVideoCommentExist (id: number, video: VideoModel, res: express.Response) { - const videoComment = await VideoCommentModel.loadById(id) + const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id) if (!videoComment) { res.status(404) diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index b52d5f285..bffc50322 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts @@ -2,22 +2,13 @@ import * as express from 'express' import 'express-validator' import { body, param, query } from 'express-validator/check' import { UserRight, VideoPrivacy } from '../../../shared' -import { getDurationFromVideoFile, logger } from '../../helpers' import { isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc' import { - isVideoAbuseReasonValid, - isVideoCategoryValid, - isVideoDescriptionValid, - isVideoExist, - isVideoFile, - isVideoLanguageValid, - isVideoLicenceValid, - isVideoNameValid, - isVideoNSFWValid, - isVideoPrivacyValid, - isVideoRatingTypeValid, - isVideoTagsValid + isVideoAbuseReasonValid, isVideoCategoryValid, isVideoDescriptionValid, isVideoExist, isVideoFile, isVideoLanguageValid, + isVideoLicenceValid, isVideoNameValid, isVideoNSFWValid, isVideoPrivacyValid, isVideoRatingTypeValid, isVideoTagsValid } from '../../helpers/custom-validators/videos' +import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' +import { logger } from '../../helpers/logger' import { CONSTRAINTS_FIELDS } from '../../initializers' import { UserModel } from '../../models/account/user' import { VideoModel } from '../../models/video/video' diff --git a/server/middlewares/validators/webfinger.ts b/server/middlewares/validators/webfinger.ts index 894c72498..3dbec6e44 100644 --- a/server/middlewares/validators/webfinger.ts +++ b/server/middlewares/validators/webfinger.ts @@ -1,7 +1,8 @@ import * as express from 'express' import { query } from 'express-validator/check' -import { getHostWithPort, logger } from '../../helpers' import { isWebfingerResourceValid } from '../../helpers/custom-validators/webfinger' +import { logger } from '../../helpers/logger' +import { getHostWithPort } from '../../helpers/utils' import { ActorModel } from '../../models/activitypub/actor' import { areValidationErrors } from './utils' diff --git a/server/models/account/user.ts b/server/models/account/user.ts index 1d5759ea3..d7e09e328 100644 --- a/server/models/account/user.ts +++ b/server/models/account/user.ts @@ -4,11 +4,11 @@ import { Scopes, Table, UpdatedAt } from 'sequelize-typescript' import { hasUserRight, USER_ROLE_LABELS, UserRight } from '../../../shared' -import { comparePassword, cryptPassword } from '../../helpers' import { isUserAutoPlayVideoValid, isUserDisplayNSFWValid, isUserPasswordValid, isUserRoleValid, isUserUsernameValid, isUserVideoQuotaValid } from '../../helpers/custom-validators/users' +import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto' import { OAuthTokenModel } from '../oauth/oauth-token' import { getSort, throwIfNotValid } from '../utils' import { VideoChannelModel } from '../video/video-channel' diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts index e7eb35e2c..3d96b3706 100644 --- a/server/models/activitypub/actor.ts +++ b/server/models/activitypub/actor.ts @@ -7,11 +7,12 @@ import { } from 'sequelize-typescript' import { ActivityPubActorType } from '../../../shared/models/activitypub' import { Avatar } from '../../../shared/models/avatars/avatar.model' -import { activityPubContextify } from '../../helpers' +import { activityPubContextify } from '../../helpers/activitypub' import { - isActivityPubUrlValid, isActorFollowersCountValid, isActorFollowingCountValid, isActorPreferredUsernameValid, - isActorPrivateKeyValid, isActorPublicKeyValid -} from '../../helpers/custom-validators/activitypub' + isActorFollowersCountValid, isActorFollowingCountValid, isActorPreferredUsernameValid, isActorPrivateKeyValid, + isActorPublicKeyValid +} from '../../helpers/custom-validators/activitypub/actor' +import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' import { ACTIVITY_PUB_ACTOR_TYPES, AVATARS_DIR, CONFIG, CONSTRAINTS_FIELDS } from '../../initializers' import { AccountModel } from '../account/account' import { AvatarModel } from '../avatar/avatar' diff --git a/server/models/oauth/oauth-token.ts b/server/models/oauth/oauth-token.ts index 995fa33d5..9d1b63813 100644 --- a/server/models/oauth/oauth-token.ts +++ b/server/models/oauth/oauth-token.ts @@ -1,5 +1,5 @@ import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' -import { logger } from '../../helpers' +import { logger } from '../../helpers/logger' import { AccountModel } from '../account/account' import { UserModel } from '../account/user' import { OAuthClientModel } from './oauth-client' diff --git a/server/models/server/server.ts b/server/models/server/server.ts index edfd8010b..d35aa0ca4 100644 --- a/server/models/server/server.ts +++ b/server/models/server/server.ts @@ -1,7 +1,7 @@ import * as Sequelize from 'sequelize' import { AllowNull, Column, CreatedAt, Default, Is, IsInt, Max, Model, Table, UpdatedAt } from 'sequelize-typescript' -import { logger } from '../../helpers' import { isHostValid } from '../../helpers/custom-validators/servers' +import { logger } from '../../helpers/logger' import { SERVERS_SCORE } from '../../initializers' import { throwIfNotValid } from '../utils' diff --git a/server/models/video/video-blacklist.ts b/server/models/video/video-blacklist.ts index 6db562719..3adcec149 100644 --- a/server/models/video/video-blacklist.ts +++ b/server/models/video/video-blacklist.ts @@ -1,5 +1,5 @@ import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' -import { SortType } from '../../helpers' +import { SortType } from '../../helpers/utils' import { getSortOnModel } from '../utils' import { VideoModel } from './video' diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts index 8ceeb563a..1992c2dd8 100644 --- a/server/models/video/video-comment.ts +++ b/server/models/video/video-comment.ts @@ -5,7 +5,7 @@ import { } from 'sequelize-typescript' import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object' import { VideoComment } from '../../../shared/models/videos/video-comment.model' -import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub' +import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' import { CONSTRAINTS_FIELDS } from '../../initializers' import { AccountModel } from '../account/account' import { ActorModel } from '../activitypub/actor' @@ -16,6 +16,7 @@ import { VideoModel } from './video' enum ScopeNames { WITH_ACCOUNT = 'WITH_ACCOUNT', WITH_IN_REPLY_TO = 'WITH_IN_REPLY_TO', + WITH_VIDEO = 'WITH_VIDEO', ATTRIBUTES_FOR_API = 'ATTRIBUTES_FOR_API' } @@ -56,7 +57,15 @@ enum ScopeNames { include: [ { model: () => VideoCommentModel, - as: 'InReplyTo' + as: 'InReplyToVideoComment' + } + ] + }, + [ScopeNames.WITH_VIDEO]: { + include: [ + { + model: () => VideoModel, + required: false } ] } @@ -108,7 +117,7 @@ export class VideoCommentModel extends Model { foreignKey: { allowNull: true }, - as: 'InReplyTo', + as: 'InReplyToVideoComment', onDelete: 'CASCADE' }) InReplyToVideoComment: VideoCommentModel @@ -155,6 +164,20 @@ export class VideoCommentModel extends Model { return VideoCommentModel.findOne(query) } + static loadByIdAndPopulateVideoAndAccountAndReply (id: number, t?: Sequelize.Transaction) { + const query: IFindOptions = { + where: { + id + } + } + + if (t !== undefined) query.transaction = t + + return VideoCommentModel + .scope([ ScopeNames.WITH_VIDEO, ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_IN_REPLY_TO ]) + .findOne(query) + } + static loadByUrl (url: string, t?: Sequelize.Transaction) { const query: IFindOptions = { where: { @@ -238,8 +261,10 @@ export class VideoCommentModel extends Model { id: this.url, content: this.text, inReplyTo, + updated: this.updatedAt.toISOString(), published: this.createdAt.toISOString(), - url: this.url + url: this.url, + attributedTo: this.Account.Actor.url } } } diff --git a/server/models/video/video.ts b/server/models/video/video.ts index b6a2ce6b5..2504ae58a 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -5,65 +5,25 @@ import * as parseTorrent from 'parse-torrent' import { join } from 'path' import * as Sequelize from 'sequelize' import { - AfterDestroy, - AllowNull, - BelongsTo, - BelongsToMany, - Column, - CreatedAt, - DataType, - Default, - ForeignKey, - HasMany, - IFindOptions, - Is, - IsInt, - IsUUID, - Min, - Model, - Scopes, - Table, - UpdatedAt + AfterDestroy, AllowNull, BelongsTo, BelongsToMany, Column, CreatedAt, DataType, Default, ForeignKey, HasMany, IFindOptions, Is, + IsInt, IsUUID, Min, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' import { IIncludeOptions } from 'sequelize-typescript/lib/interfaces/IIncludeOptions' import { VideoPrivacy, VideoResolution } from '../../../shared' import { VideoTorrentObject } from '../../../shared/models/activitypub/objects' import { Video, VideoDetails } from '../../../shared/models/videos' +import { activityPubCollection } from '../../helpers/activitypub' +import { createTorrentPromise, renamePromise, statPromise, unlinkPromise, writeFilePromise } from '../../helpers/core-utils' +import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' import { - activityPubCollection, - createTorrentPromise, - generateImageFromVideoFile, - getVideoFileHeight, - logger, - renamePromise, - statPromise, - transcode, - unlinkPromise, - writeFilePromise -} from '../../helpers' -import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub' -import { - isVideoCategoryValid, - isVideoDescriptionValid, - isVideoDurationValid, - isVideoLanguageValid, - isVideoLicenceValid, - isVideoNameValid, - isVideoNSFWValid, - isVideoPrivacyValid + isVideoCategoryValid, isVideoDescriptionValid, isVideoDurationValid, isVideoLanguageValid, isVideoLicenceValid, isVideoNameValid, + isVideoNSFWValid, isVideoPrivacyValid } from '../../helpers/custom-validators/videos' +import { generateImageFromVideoFile, getVideoFileHeight, transcode } from '../../helpers/ffmpeg-utils' +import { logger } from '../../helpers/logger' import { - API_VERSION, - CONFIG, - CONSTRAINTS_FIELDS, - PREVIEWS_SIZE, - REMOTE_SCHEME, - STATIC_PATHS, - THUMBNAILS_SIZE, - VIDEO_CATEGORIES, - VIDEO_LANGUAGES, - VIDEO_LICENCES, - VIDEO_PRIVACIES + API_VERSION, CONFIG, CONSTRAINTS_FIELDS, PREVIEWS_SIZE, REMOTE_SCHEME, STATIC_PATHS, THUMBNAILS_SIZE, VIDEO_CATEGORIES, + VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../initializers' import { getAnnounceActivityPubUrl } from '../../lib/activitypub' import { sendDeleteVideo } from '../../lib/activitypub/send' @@ -75,6 +35,7 @@ import { getSort, throwIfNotValid } from '../utils' import { TagModel } from './tag' import { VideoAbuseModel } from './video-abuse' import { VideoChannelModel } from './video-channel' +import { VideoCommentModel } from './video-comment' import { VideoFileModel } from './video-file' import { VideoShareModel } from './video-share' import { VideoTagModel } from './video-tag' @@ -85,7 +46,8 @@ enum ScopeNames { WITH_TAGS = 'WITH_TAGS', WITH_FILES = 'WITH_FILES', WITH_SHARES = 'WITH_SHARES', - WITH_RATES = 'WITH_RATES' + WITH_RATES = 'WITH_RATES', + WITH_COMMENTS = 'WITH_COMMENTS' } @Scopes({ @@ -151,6 +113,13 @@ enum ScopeNames { include: [ () => AccountModel ] } ] + }, + [ScopeNames.WITH_COMMENTS]: { + include: [ + { + model: () => VideoCommentModel + } + ] } }) @Table({ @@ -322,6 +291,15 @@ export class VideoModel extends Model { }) AccountVideoRates: AccountVideoRateModel[] + @HasMany(() => VideoCommentModel, { + foreignKey: { + name: 'videoId', + allowNull: false + }, + onDelete: 'cascade' + }) + VideoComments: VideoCommentModel[] + @AfterDestroy static removeFilesAndSendDelete (instance: VideoModel) { const tasks = [] @@ -417,7 +395,8 @@ export class VideoModel extends Model { include: [ AccountModel ] }, VideoFileModel, - TagModel + TagModel, + VideoCommentModel ] } @@ -536,7 +515,7 @@ export class VideoModel extends Model { } return VideoModel - .scope([ ScopeNames.WITH_RATES, ScopeNames.WITH_SHARES, ScopeNames.WITH_TAGS, ScopeNames.WITH_FILES, ScopeNames.WITH_ACCOUNT ]) + .scope([ ScopeNames.WITH_TAGS, ScopeNames.WITH_FILES, ScopeNames.WITH_ACCOUNT ]) .findById(id, options) } @@ -561,7 +540,27 @@ export class VideoModel extends Model { } return VideoModel - .scope([ ScopeNames.WITH_RATES, ScopeNames.WITH_SHARES, ScopeNames.WITH_TAGS, ScopeNames.WITH_FILES, ScopeNames.WITH_ACCOUNT ]) + .scope([ ScopeNames.WITH_TAGS, ScopeNames.WITH_FILES, ScopeNames.WITH_ACCOUNT ]) + .findOne(options) + } + + static loadAndPopulateAll (id: number) { + const options = { + order: [ [ 'Tags', 'name', 'ASC' ] ], + where: { + id + } + } + + return VideoModel + .scope([ + ScopeNames.WITH_RATES, + ScopeNames.WITH_SHARES, + ScopeNames.WITH_TAGS, + ScopeNames.WITH_FILES, + ScopeNames.WITH_ACCOUNT, + ScopeNames.WITH_COMMENTS + ]) .findOne(options) } @@ -865,6 +864,17 @@ export class VideoModel extends Model { sharesObject = activityPubCollection(shares) } + let commentsObject + if (Array.isArray(this.VideoComments)) { + const comments: string[] = [] + + for (const videoComment of this.VideoComments) { + comments.push(videoComment.url) + } + + commentsObject = activityPubCollection(comments) + } + const url = [] for (const file of this.VideoFiles) { url.push({ @@ -925,6 +935,7 @@ export class VideoModel extends Model { likes: likesObject, dislikes: dislikesObject, shares: sharesObject, + comments: commentsObject, attributedTo: [ { type: 'Group', diff --git a/shared/models/activitypub/objects/video-comment-object.ts b/shared/models/activitypub/objects/video-comment-object.ts index fc2a9e837..785fbbc0d 100644 --- a/shared/models/activitypub/objects/video-comment-object.ts +++ b/shared/models/activitypub/objects/video-comment-object.ts @@ -4,5 +4,7 @@ export interface VideoCommentObject { content: string inReplyTo: string published: string + updated: string url: string + attributedTo: string } diff --git a/shared/models/activitypub/objects/video-torrent-object.ts b/shared/models/activitypub/objects/video-torrent-object.ts index 1405f7748..5ccc80bcb 100644 --- a/shared/models/activitypub/objects/video-torrent-object.ts +++ b/shared/models/activitypub/objects/video-torrent-object.ts @@ -27,5 +27,6 @@ export interface VideoTorrentObject { likes?: ActivityPubOrderedCollection dislikes?: ActivityPubOrderedCollection shares?: ActivityPubOrderedCollection + comments?: ActivityPubOrderedCollection attributedTo: ActivityPubAttributedTo[] }