diff options
author | Chocobozzz <me@florianbigard.com> | 2018-08-16 15:25:20 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-08-27 09:41:54 +0200 |
commit | 06a05d5f4784a7cbb27aa1188385b5679845dad8 (patch) | |
tree | ac197f3ed0768529456225ad76c912f22bc55e29 /server/controllers/api | |
parent | 4bda2e47bbc937c401ddcf14c1be53c70481a294 (diff) | |
download | PeerTube-06a05d5f4784a7cbb27aa1188385b5679845dad8.tar.gz PeerTube-06a05d5f4784a7cbb27aa1188385b5679845dad8.tar.zst PeerTube-06a05d5f4784a7cbb27aa1188385b5679845dad8.zip |
Add subscriptions endpoints to REST API
Diffstat (limited to 'server/controllers/api')
-rw-r--r-- | server/controllers/api/accounts.ts | 1 | ||||
-rw-r--r-- | server/controllers/api/search.ts | 5 | ||||
-rw-r--r-- | server/controllers/api/server/follows.ts | 17 | ||||
-rw-r--r-- | server/controllers/api/users/index.ts | 3 | ||||
-rw-r--r-- | server/controllers/api/users/me.ts | 114 | ||||
-rw-r--r-- | server/controllers/api/video-channel.ts | 1 | ||||
-rw-r--r-- | server/controllers/api/videos/index.ts | 1 |
7 files changed, 123 insertions, 19 deletions
diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index 0117fc8c6..308970abc 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts | |||
@@ -78,6 +78,7 @@ async function listAccountVideos (req: express.Request, res: express.Response, n | |||
78 | start: req.query.start, | 78 | start: req.query.start, |
79 | count: req.query.count, | 79 | count: req.query.count, |
80 | sort: req.query.sort, | 80 | sort: req.query.sort, |
81 | includeLocalVideos: false, | ||
81 | categoryOneOf: req.query.categoryOneOf, | 82 | categoryOneOf: req.query.categoryOneOf, |
82 | licenceOneOf: req.query.licenceOneOf, | 83 | licenceOneOf: req.query.licenceOneOf, |
83 | languageOneOf: req.query.languageOneOf, | 84 | languageOneOf: req.query.languageOneOf, |
diff --git a/server/controllers/api/search.ts b/server/controllers/api/search.ts index f810c7452..7a7504b7d 100644 --- a/server/controllers/api/search.ts +++ b/server/controllers/api/search.ts | |||
@@ -36,7 +36,10 @@ export { searchRouter } | |||
36 | async function searchVideos (req: express.Request, res: express.Response) { | 36 | async function searchVideos (req: express.Request, res: express.Response) { |
37 | const query: VideosSearchQuery = req.query | 37 | const query: VideosSearchQuery = req.query |
38 | 38 | ||
39 | const options = Object.assign(query, { nsfw: buildNSFWFilter(res, query.nsfw) }) | 39 | const options = Object.assign(query, { |
40 | includeLocalVideos: true, | ||
41 | nsfw: buildNSFWFilter(res, query.nsfw) | ||
42 | }) | ||
40 | const resultList = await VideoModel.searchAndPopulateAccountAndServer(options) | 43 | const resultList = await VideoModel.searchAndPopulateAccountAndServer(options) |
41 | 44 | ||
42 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | 45 | return res.json(getFormattedObjects(resultList.data, resultList.total)) |
diff --git a/server/controllers/api/server/follows.ts b/server/controllers/api/server/follows.ts index e78361c9a..23308445f 100644 --- a/server/controllers/api/server/follows.ts +++ b/server/controllers/api/server/follows.ts | |||
@@ -2,7 +2,7 @@ import * as express from 'express' | |||
2 | import { UserRight } from '../../../../shared/models/users' | 2 | import { UserRight } from '../../../../shared/models/users' |
3 | import { logger } from '../../../helpers/logger' | 3 | import { logger } from '../../../helpers/logger' |
4 | import { getFormattedObjects, getServerActor } from '../../../helpers/utils' | 4 | import { getFormattedObjects, getServerActor } from '../../../helpers/utils' |
5 | import { sequelizeTypescript } from '../../../initializers' | 5 | import { sequelizeTypescript, SERVER_ACTOR_NAME } from '../../../initializers' |
6 | import { sendUndoFollow } from '../../../lib/activitypub/send' | 6 | import { sendUndoFollow } from '../../../lib/activitypub/send' |
7 | import { | 7 | import { |
8 | asyncMiddleware, | 8 | asyncMiddleware, |
@@ -74,9 +74,16 @@ async function listFollowers (req: express.Request, res: express.Response, next: | |||
74 | 74 | ||
75 | async function followInstance (req: express.Request, res: express.Response, next: express.NextFunction) { | 75 | async function followInstance (req: express.Request, res: express.Response, next: express.NextFunction) { |
76 | const hosts = req.body.hosts as string[] | 76 | const hosts = req.body.hosts as string[] |
77 | const follower = await getServerActor() | ||
77 | 78 | ||
78 | for (const host of hosts) { | 79 | for (const host of hosts) { |
79 | JobQueue.Instance.createJob({ type: 'activitypub-follow', payload: { host } }) | 80 | const payload = { |
81 | host, | ||
82 | name: SERVER_ACTOR_NAME, | ||
83 | followerActorId: follower.id | ||
84 | } | ||
85 | |||
86 | JobQueue.Instance.createJob({ type: 'activitypub-follow', payload }) | ||
80 | .catch(err => logger.error('Cannot create follow job for %s.', host, err)) | 87 | .catch(err => logger.error('Cannot create follow job for %s.', host, err)) |
81 | } | 88 | } |
82 | 89 | ||
@@ -92,11 +99,5 @@ async function removeFollow (req: express.Request, res: express.Response, next: | |||
92 | await follow.destroy({ transaction: t }) | 99 | await follow.destroy({ transaction: t }) |
93 | }) | 100 | }) |
94 | 101 | ||
95 | // Destroy the actor that will destroy video channels, videos and video files too | ||
96 | // This could be long so don't wait this task | ||
97 | const following = follow.ActorFollowing | ||
98 | following.destroy() | ||
99 | .catch(err => logger.error('Cannot destroy actor that we do not follow anymore %s.', following.url, { err })) | ||
100 | |||
101 | return res.status(204).end() | 102 | return res.status(204).end() |
102 | } | 103 | } |
diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts index 105244ddd..608d439ac 100644 --- a/server/controllers/api/users/index.ts +++ b/server/controllers/api/users/index.ts | |||
@@ -29,7 +29,6 @@ import { usersAskResetPasswordValidator, usersBlockingValidator, usersResetPassw | |||
29 | import { UserModel } from '../../../models/account/user' | 29 | import { UserModel } from '../../../models/account/user' |
30 | import { OAuthTokenModel } from '../../../models/oauth/oauth-token' | 30 | import { OAuthTokenModel } from '../../../models/oauth/oauth-token' |
31 | import { auditLoggerFactory, UserAuditView } from '../../../helpers/audit-logger' | 31 | import { auditLoggerFactory, UserAuditView } from '../../../helpers/audit-logger' |
32 | import { videosRouter } from '../videos' | ||
33 | import { meRouter } from './me' | 32 | import { meRouter } from './me' |
34 | 33 | ||
35 | const auditLogger = auditLoggerFactory('users') | 34 | const auditLogger = auditLoggerFactory('users') |
@@ -41,7 +40,7 @@ const loginRateLimiter = new RateLimit({ | |||
41 | }) | 40 | }) |
42 | 41 | ||
43 | const usersRouter = express.Router() | 42 | const usersRouter = express.Router() |
44 | videosRouter.use('/', meRouter) | 43 | usersRouter.use('/', meRouter) |
45 | 44 | ||
46 | usersRouter.get('/', | 45 | usersRouter.get('/', |
47 | authenticate, | 46 | authenticate, |
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts index 1e096a35d..403842163 100644 --- a/server/controllers/api/users/me.ts +++ b/server/controllers/api/users/me.ts | |||
@@ -7,23 +7,35 @@ import { sendUpdateActor } from '../../../lib/activitypub/send' | |||
7 | import { | 7 | import { |
8 | asyncMiddleware, | 8 | asyncMiddleware, |
9 | authenticate, | 9 | authenticate, |
10 | commonVideosFiltersValidator, | ||
10 | paginationValidator, | 11 | paginationValidator, |
11 | setDefaultPagination, | 12 | setDefaultPagination, |
12 | setDefaultSort, | 13 | setDefaultSort, |
14 | userSubscriptionAddValidator, | ||
15 | userSubscriptionRemoveValidator, | ||
13 | usersUpdateMeValidator, | 16 | usersUpdateMeValidator, |
14 | usersVideoRatingValidator | 17 | usersVideoRatingValidator |
15 | } from '../../../middlewares' | 18 | } from '../../../middlewares' |
16 | import { deleteMeValidator, videoImportsSortValidator, videosSortValidator } from '../../../middlewares/validators' | 19 | import { |
20 | deleteMeValidator, | ||
21 | userSubscriptionsSortValidator, | ||
22 | videoImportsSortValidator, | ||
23 | videosSortValidator | ||
24 | } from '../../../middlewares/validators' | ||
17 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' | 25 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' |
18 | import { UserModel } from '../../../models/account/user' | 26 | import { UserModel } from '../../../models/account/user' |
19 | import { VideoModel } from '../../../models/video/video' | 27 | import { VideoModel } from '../../../models/video/video' |
20 | import { VideoSortField } from '../../../../client/src/app/shared/video/sort-field.type' | 28 | import { VideoSortField } from '../../../../client/src/app/shared/video/sort-field.type' |
21 | import { createReqFiles } from '../../../helpers/express-utils' | 29 | import { buildNSFWFilter, createReqFiles } from '../../../helpers/express-utils' |
22 | import { UserVideoQuota } from '../../../../shared/models/users/user-video-quota.model' | 30 | import { UserVideoQuota } from '../../../../shared/models/users/user-video-quota.model' |
23 | import { updateAvatarValidator } from '../../../middlewares/validators/avatar' | 31 | import { updateAvatarValidator } from '../../../middlewares/validators/avatar' |
24 | import { updateActorAvatarFile } from '../../../lib/avatar' | 32 | import { updateActorAvatarFile } from '../../../lib/avatar' |
25 | import { auditLoggerFactory, UserAuditView } from '../../../helpers/audit-logger' | 33 | import { auditLoggerFactory, UserAuditView } from '../../../helpers/audit-logger' |
26 | import { VideoImportModel } from '../../../models/video/video-import' | 34 | import { VideoImportModel } from '../../../models/video/video-import' |
35 | import { VideoFilter } from '../../../../shared/models/videos/video-query.type' | ||
36 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | ||
37 | import { JobQueue } from '../../../lib/job-queue' | ||
38 | import { logger } from '../../../helpers/logger' | ||
27 | 39 | ||
28 | const auditLogger = auditLoggerFactory('users-me') | 40 | const auditLogger = auditLoggerFactory('users-me') |
29 | 41 | ||
@@ -83,6 +95,40 @@ meRouter.post('/me/avatar/pick', | |||
83 | asyncMiddleware(updateMyAvatar) | 95 | asyncMiddleware(updateMyAvatar) |
84 | ) | 96 | ) |
85 | 97 | ||
98 | // ##### Subscriptions part ##### | ||
99 | |||
100 | meRouter.get('/me/subscriptions', | ||
101 | authenticate, | ||
102 | paginationValidator, | ||
103 | userSubscriptionsSortValidator, | ||
104 | setDefaultSort, | ||
105 | setDefaultPagination, | ||
106 | asyncMiddleware(getUserSubscriptions) | ||
107 | ) | ||
108 | |||
109 | meRouter.post('/me/subscriptions', | ||
110 | authenticate, | ||
111 | userSubscriptionAddValidator, | ||
112 | asyncMiddleware(addUserSubscription) | ||
113 | ) | ||
114 | |||
115 | meRouter.delete('/me/subscriptions/:uri', | ||
116 | authenticate, | ||
117 | userSubscriptionRemoveValidator, | ||
118 | asyncMiddleware(deleteUserSubscription) | ||
119 | ) | ||
120 | |||
121 | meRouter.get('/me/subscriptions/videos', | ||
122 | authenticate, | ||
123 | authenticate, | ||
124 | paginationValidator, | ||
125 | videosSortValidator, | ||
126 | setDefaultSort, | ||
127 | setDefaultPagination, | ||
128 | commonVideosFiltersValidator, | ||
129 | asyncMiddleware(getUserSubscriptionVideos) | ||
130 | ) | ||
131 | |||
86 | // --------------------------------------------------------------------------- | 132 | // --------------------------------------------------------------------------- |
87 | 133 | ||
88 | export { | 134 | export { |
@@ -91,6 +137,62 @@ export { | |||
91 | 137 | ||
92 | // --------------------------------------------------------------------------- | 138 | // --------------------------------------------------------------------------- |
93 | 139 | ||
140 | async function addUserSubscription (req: express.Request, res: express.Response) { | ||
141 | const user = res.locals.oauth.token.User as UserModel | ||
142 | const [ name, host ] = req.body.uri.split('@') | ||
143 | |||
144 | const payload = { | ||
145 | name, | ||
146 | host, | ||
147 | followerActorId: user.Account.Actor.id | ||
148 | } | ||
149 | |||
150 | JobQueue.Instance.createJob({ type: 'activitypub-follow', payload }) | ||
151 | .catch(err => logger.error('Cannot create follow job for subscription %s.', req.body.uri, err)) | ||
152 | |||
153 | return res.status(204).end() | ||
154 | } | ||
155 | |||
156 | async function deleteUserSubscription (req: express.Request, res: express.Response) { | ||
157 | const subscription: ActorFollowModel = res.locals.subscription | ||
158 | |||
159 | await sequelizeTypescript.transaction(async t => { | ||
160 | return subscription.destroy({ transaction: t }) | ||
161 | }) | ||
162 | |||
163 | return res.type('json').status(204).end() | ||
164 | } | ||
165 | |||
166 | async function getUserSubscriptions (req: express.Request, res: express.Response) { | ||
167 | const user = res.locals.oauth.token.User as UserModel | ||
168 | const actorId = user.Account.Actor.id | ||
169 | |||
170 | const resultList = await ActorFollowModel.listSubscriptionsForApi(actorId, req.query.start, req.query.count, req.query.sort) | ||
171 | |||
172 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | ||
173 | } | ||
174 | |||
175 | async function getUserSubscriptionVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
176 | const user = res.locals.oauth.token.User as UserModel | ||
177 | const resultList = await VideoModel.listForApi({ | ||
178 | start: req.query.start, | ||
179 | count: req.query.count, | ||
180 | sort: req.query.sort, | ||
181 | includeLocalVideos: false, | ||
182 | categoryOneOf: req.query.categoryOneOf, | ||
183 | licenceOneOf: req.query.licenceOneOf, | ||
184 | languageOneOf: req.query.languageOneOf, | ||
185 | tagsOneOf: req.query.tagsOneOf, | ||
186 | tagsAllOf: req.query.tagsAllOf, | ||
187 | nsfw: buildNSFWFilter(res, req.query.nsfw), | ||
188 | filter: req.query.filter as VideoFilter, | ||
189 | withFiles: false, | ||
190 | actorId: user.Account.Actor.id | ||
191 | }) | ||
192 | |||
193 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | ||
194 | } | ||
195 | |||
94 | async function getUserVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | 196 | async function getUserVideos (req: express.Request, res: express.Response, next: express.NextFunction) { |
95 | const user = res.locals.oauth.token.User as UserModel | 197 | const user = res.locals.oauth.token.User as UserModel |
96 | const resultList = await VideoModel.listUserVideosForApi( | 198 | const resultList = await VideoModel.listUserVideosForApi( |
@@ -150,7 +252,7 @@ async function getUserVideoRating (req: express.Request, res: express.Response, | |||
150 | videoId, | 252 | videoId, |
151 | rating | 253 | rating |
152 | } | 254 | } |
153 | res.json(json) | 255 | return res.json(json) |
154 | } | 256 | } |
155 | 257 | ||
156 | async function deleteMe (req: express.Request, res: express.Response) { | 258 | async function deleteMe (req: express.Request, res: express.Response) { |
@@ -207,9 +309,5 @@ async function updateMyAvatar (req: express.Request, res: express.Response, next | |||
207 | oldUserAuditView | 309 | oldUserAuditView |
208 | ) | 310 | ) |
209 | 311 | ||
210 | return res | 312 | return res.json({ avatar: avatar.toFormattedJSON() }) |
211 | .json({ | ||
212 | avatar: avatar.toFormattedJSON() | ||
213 | }) | ||
214 | .end() | ||
215 | } | 313 | } |
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts index 023ebbedf..6ffc09f87 100644 --- a/server/controllers/api/video-channel.ts +++ b/server/controllers/api/video-channel.ts | |||
@@ -215,6 +215,7 @@ async function listVideoChannelVideos (req: express.Request, res: express.Respon | |||
215 | start: req.query.start, | 215 | start: req.query.start, |
216 | count: req.query.count, | 216 | count: req.query.count, |
217 | sort: req.query.sort, | 217 | sort: req.query.sort, |
218 | includeLocalVideos: false, | ||
218 | categoryOneOf: req.query.categoryOneOf, | 219 | categoryOneOf: req.query.categoryOneOf, |
219 | licenceOneOf: req.query.licenceOneOf, | 220 | licenceOneOf: req.query.licenceOneOf, |
220 | languageOneOf: req.query.languageOneOf, | 221 | languageOneOf: req.query.languageOneOf, |
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 92c6ee697..e973aa43f 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -414,6 +414,7 @@ async function listVideos (req: express.Request, res: express.Response, next: ex | |||
414 | start: req.query.start, | 414 | start: req.query.start, |
415 | count: req.query.count, | 415 | count: req.query.count, |
416 | sort: req.query.sort, | 416 | sort: req.query.sort, |
417 | includeLocalVideos: true, | ||
417 | categoryOneOf: req.query.categoryOneOf, | 418 | categoryOneOf: req.query.categoryOneOf, |
418 | licenceOneOf: req.query.licenceOneOf, | 419 | licenceOneOf: req.query.licenceOneOf, |
419 | languageOneOf: req.query.languageOneOf, | 420 | languageOneOf: req.query.languageOneOf, |