aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/controllers/api/users/me.ts36
-rw-r--r--server/middlewares/validators/user-subscriptions.ts8
-rw-r--r--server/middlewares/validators/videos.ts2
-rw-r--r--server/models/activitypub/actor-follow.ts27
-rw-r--r--server/tests/api/check-params/user-subscriptions.ts59
-rw-r--r--server/tests/api/users/user-subscriptions.ts27
-rw-r--r--server/tests/utils/users/user-subscriptions.ts12
7 files changed, 137 insertions, 34 deletions
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts
index 403842163..2300f5dbe 100644
--- a/server/controllers/api/users/me.ts
+++ b/server/controllers/api/users/me.ts
@@ -12,7 +12,7 @@ import {
12 setDefaultPagination, 12 setDefaultPagination,
13 setDefaultSort, 13 setDefaultSort,
14 userSubscriptionAddValidator, 14 userSubscriptionAddValidator,
15 userSubscriptionRemoveValidator, 15 userSubscriptionGetValidator,
16 usersUpdateMeValidator, 16 usersUpdateMeValidator,
17 usersVideoRatingValidator 17 usersVideoRatingValidator
18} from '../../../middlewares' 18} from '../../../middlewares'
@@ -97,6 +97,17 @@ meRouter.post('/me/avatar/pick',
97 97
98// ##### Subscriptions part ##### 98// ##### Subscriptions part #####
99 99
100meRouter.get('/me/subscriptions/videos',
101 authenticate,
102 authenticate,
103 paginationValidator,
104 videosSortValidator,
105 setDefaultSort,
106 setDefaultPagination,
107 commonVideosFiltersValidator,
108 asyncMiddleware(getUserSubscriptionVideos)
109)
110
100meRouter.get('/me/subscriptions', 111meRouter.get('/me/subscriptions',
101 authenticate, 112 authenticate,
102 paginationValidator, 113 paginationValidator,
@@ -112,21 +123,16 @@ meRouter.post('/me/subscriptions',
112 asyncMiddleware(addUserSubscription) 123 asyncMiddleware(addUserSubscription)
113) 124)
114 125
115meRouter.delete('/me/subscriptions/:uri', 126meRouter.get('/me/subscriptions/:uri',
116 authenticate, 127 authenticate,
117 userSubscriptionRemoveValidator, 128 userSubscriptionGetValidator,
118 asyncMiddleware(deleteUserSubscription) 129 getUserSubscription
119) 130)
120 131
121meRouter.get('/me/subscriptions/videos', 132meRouter.delete('/me/subscriptions/:uri',
122 authenticate,
123 authenticate, 133 authenticate,
124 paginationValidator, 134 userSubscriptionGetValidator,
125 videosSortValidator, 135 asyncMiddleware(deleteUserSubscription)
126 setDefaultSort,
127 setDefaultPagination,
128 commonVideosFiltersValidator,
129 asyncMiddleware(getUserSubscriptionVideos)
130) 136)
131 137
132// --------------------------------------------------------------------------- 138// ---------------------------------------------------------------------------
@@ -153,6 +159,12 @@ async function addUserSubscription (req: express.Request, res: express.Response)
153 return res.status(204).end() 159 return res.status(204).end()
154} 160}
155 161
162function getUserSubscription (req: express.Request, res: express.Response) {
163 const subscription: ActorFollowModel = res.locals.subscription
164
165 return res.json(subscription.ActorFollowing.VideoChannel.toFormattedJSON())
166}
167
156async function deleteUserSubscription (req: express.Request, res: express.Response) { 168async function deleteUserSubscription (req: express.Request, res: express.Response) {
157 const subscription: ActorFollowModel = res.locals.subscription 169 const subscription: ActorFollowModel = res.locals.subscription
158 170
diff --git a/server/middlewares/validators/user-subscriptions.ts b/server/middlewares/validators/user-subscriptions.ts
index f331b6c34..d8c26c742 100644
--- a/server/middlewares/validators/user-subscriptions.ts
+++ b/server/middlewares/validators/user-subscriptions.ts
@@ -20,11 +20,11 @@ const userSubscriptionAddValidator = [
20 } 20 }
21] 21]
22 22
23const userSubscriptionRemoveValidator = [ 23const userSubscriptionGetValidator = [
24 param('uri').custom(isValidActorHandle).withMessage('Should have a valid URI to unfollow'), 24 param('uri').custom(isValidActorHandle).withMessage('Should have a valid URI to unfollow'),
25 25
26 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 26 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
27 logger.debug('Checking unfollow parameters', { parameters: req.params }) 27 logger.debug('Checking userSubscriptionGetValidator parameters', { parameters: req.params })
28 28
29 if (areValidationErrors(req, res)) return 29 if (areValidationErrors(req, res)) return
30 30
@@ -34,7 +34,7 @@ const userSubscriptionRemoveValidator = [
34 const user: UserModel = res.locals.oauth.token.User 34 const user: UserModel = res.locals.oauth.token.User
35 const subscription = await ActorFollowModel.loadByActorAndTargetNameAndHost(user.Account.Actor.id, name, host) 35 const subscription = await ActorFollowModel.loadByActorAndTargetNameAndHost(user.Account.Actor.id, name, host)
36 36
37 if (!subscription) { 37 if (!subscription || !subscription.ActorFollowing.VideoChannel) {
38 return res 38 return res
39 .status(404) 39 .status(404)
40 .json({ 40 .json({
@@ -52,7 +52,7 @@ const userSubscriptionRemoveValidator = [
52 52
53export { 53export {
54 userSubscriptionAddValidator, 54 userSubscriptionAddValidator,
55 userSubscriptionRemoveValidator 55 userSubscriptionGetValidator
56} 56}
57 57
58// --------------------------------------------------------------------------- 58// ---------------------------------------------------------------------------
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts
index 53c32abb8..a2c866152 100644
--- a/server/middlewares/validators/videos.ts
+++ b/server/middlewares/validators/videos.ts
@@ -137,7 +137,7 @@ const videosGetValidator = [
137 137
138 // Video private or blacklisted 138 // Video private or blacklisted
139 if (video.privacy === VideoPrivacy.PRIVATE || video.VideoBlacklist) { 139 if (video.privacy === VideoPrivacy.PRIVATE || video.VideoBlacklist) {
140 authenticate(req, res, () => { 140 return authenticate(req, res, () => {
141 const user: UserModel = res.locals.oauth.token.User 141 const user: UserModel = res.locals.oauth.token.User
142 142
143 // Only the owner or a user that have blacklist rights can see the video 143 // Only the owner or a user that have blacklist rights can see the video
diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts
index 90a8ac43c..20d3aa5fc 100644
--- a/server/models/activitypub/actor-follow.ts
+++ b/server/models/activitypub/actor-follow.ts
@@ -28,6 +28,7 @@ import { ServerModel } from '../server/server'
28import { getSort } from '../utils' 28import { getSort } from '../utils'
29import { ActorModel } from './actor' 29import { ActorModel } from './actor'
30import { VideoChannelModel } from '../video/video-channel' 30import { VideoChannelModel } from '../video/video-channel'
31import { IIncludeOptions } from '../../../node_modules/sequelize-typescript/lib/interfaces/IIncludeOptions'
31 32
32@Table({ 33@Table({
33 tableName: 'actorFollow', 34 tableName: 'actorFollow',
@@ -166,28 +167,30 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
166 } 167 }
167 168
168 static loadByActorAndTargetNameAndHost (actorId: number, targetName: string, targetHost: string, t?: Sequelize.Transaction) { 169 static loadByActorAndTargetNameAndHost (actorId: number, targetName: string, targetHost: string, t?: Sequelize.Transaction) {
169 const actorFollowingPartInclude = { 170 const actorFollowingPartInclude: IIncludeOptions = {
170 model: ActorModel, 171 model: ActorModel,
171 required: true, 172 required: true,
172 as: 'ActorFollowing', 173 as: 'ActorFollowing',
173 where: { 174 where: {
174 preferredUsername: targetName 175 preferredUsername: targetName
175 } 176 },
177 include: [
178 {
179 model: VideoChannelModel,
180 required: false
181 }
182 ]
176 } 183 }
177 184
178 if (targetHost === null) { 185 if (targetHost === null) {
179 actorFollowingPartInclude.where['serverId'] = null 186 actorFollowingPartInclude.where['serverId'] = null
180 } else { 187 } else {
181 Object.assign(actorFollowingPartInclude, { 188 actorFollowingPartInclude.include.push({
182 include: [ 189 model: ServerModel,
183 { 190 required: true,
184 model: ServerModel, 191 where: {
185 required: true, 192 host: targetHost
186 where: { 193 }
187 host: targetHost
188 }
189 }
190 ]
191 }) 194 })
192 } 195 }
193 196
diff --git a/server/tests/api/check-params/user-subscriptions.ts b/server/tests/api/check-params/user-subscriptions.ts
index 628a74476..6a6dd9a6f 100644
--- a/server/tests/api/check-params/user-subscriptions.ts
+++ b/server/tests/api/check-params/user-subscriptions.ts
@@ -61,7 +61,7 @@ describe('Test user subscriptions API validators', function () {
61 }) 61 })
62 }) 62 })
63 63
64 it('Should success with the correct parameters', async function () { 64 it('Should succeed with the correct parameters', async function () {
65 await makeGetRequest({ 65 await makeGetRequest({
66 url: server.url, 66 url: server.url,
67 path, 67 path,
@@ -94,7 +94,7 @@ describe('Test user subscriptions API validators', function () {
94 }) 94 })
95 }) 95 })
96 96
97 it('Should success with the correct parameters', async function () { 97 it('Should succeed with the correct parameters', async function () {
98 await makeGetRequest({ 98 await makeGetRequest({
99 url: server.url, 99 url: server.url,
100 path, 100 path,
@@ -140,7 +140,7 @@ describe('Test user subscriptions API validators', function () {
140 }) 140 })
141 }) 141 })
142 142
143 it('Should success with the correct parameters', async function () { 143 it('Should succeed with the correct parameters', async function () {
144 await makePostBodyRequest({ 144 await makePostBodyRequest({
145 url: server.url, 145 url: server.url,
146 path, 146 path,
@@ -151,6 +151,57 @@ describe('Test user subscriptions API validators', function () {
151 }) 151 })
152 }) 152 })
153 153
154 describe('When getting a subscription', function () {
155 it('Should fail with a non authenticated user', async function () {
156 await makeGetRequest({
157 url: server.url,
158 path: path + '/user1_channel@localhost:9001',
159 statusCodeExpected: 401
160 })
161 })
162
163 it('Should fail with bad URIs', async function () {
164 await makeGetRequest({
165 url: server.url,
166 path: path + '/root',
167 token: server.accessToken,
168 statusCodeExpected: 400
169 })
170
171 await makeGetRequest({
172 url: server.url,
173 path: path + '/root@',
174 token: server.accessToken,
175 statusCodeExpected: 400
176 })
177
178 await makeGetRequest({
179 url: server.url,
180 path: path + '/root@hello@',
181 token: server.accessToken,
182 statusCodeExpected: 400
183 })
184 })
185
186 it('Should fail with an unknown subscription', async function () {
187 await makeGetRequest({
188 url: server.url,
189 path: path + '/root1@localhost:9001',
190 token: server.accessToken,
191 statusCodeExpected: 404
192 })
193 })
194
195 it('Should succeed with the correct parameters', async function () {
196 await makeGetRequest({
197 url: server.url,
198 path: path + '/user1_channel@localhost:9001',
199 token: server.accessToken,
200 statusCodeExpected: 200
201 })
202 })
203 })
204
154 describe('When removing a subscription', function () { 205 describe('When removing a subscription', function () {
155 it('Should fail with a non authenticated user', async function () { 206 it('Should fail with a non authenticated user', async function () {
156 await makeDeleteRequest({ 207 await makeDeleteRequest({
@@ -192,7 +243,7 @@ describe('Test user subscriptions API validators', function () {
192 }) 243 })
193 }) 244 })
194 245
195 it('Should success with the correct parameters', async function () { 246 it('Should succeed with the correct parameters', async function () {
196 await makeDeleteRequest({ 247 await makeDeleteRequest({
197 url: server.url, 248 url: server.url,
198 path: path + '/user1_channel@localhost:9001', 249 path: path + '/user1_channel@localhost:9001',
diff --git a/server/tests/api/users/user-subscriptions.ts b/server/tests/api/users/user-subscriptions.ts
index ba59a9a60..2fbda6828 100644
--- a/server/tests/api/users/user-subscriptions.ts
+++ b/server/tests/api/users/user-subscriptions.ts
@@ -11,7 +11,8 @@ import {
11 addUserSubscription, 11 addUserSubscription,
12 listUserSubscriptions, 12 listUserSubscriptions,
13 listUserSubscriptionVideos, 13 listUserSubscriptionVideos,
14 removeUserSubscription 14 removeUserSubscription,
15 getUserSubscription
15} from '../../utils/users/user-subscriptions' 16} from '../../utils/users/user-subscriptions'
16 17
17const expect = chai.expect 18const expect = chai.expect
@@ -101,6 +102,30 @@ describe('Test users subscriptions', function () {
101 } 102 }
102 }) 103 })
103 104
105 it('Should get subscription', async function () {
106 {
107 const res = await getUserSubscription(servers[ 0 ].url, users[ 0 ].accessToken, 'user3_channel@localhost:9003')
108 const videoChannel: VideoChannel = res.body
109
110 expect(videoChannel.name).to.equal('user3_channel')
111 expect(videoChannel.host).to.equal('localhost:9003')
112 expect(videoChannel.displayName).to.equal('Main user3 channel')
113 expect(videoChannel.followingCount).to.equal(0)
114 expect(videoChannel.followersCount).to.equal(1)
115 }
116
117 {
118 const res = await getUserSubscription(servers[ 0 ].url, users[ 0 ].accessToken, 'root_channel@localhost:9001')
119 const videoChannel: VideoChannel = res.body
120
121 expect(videoChannel.name).to.equal('root_channel')
122 expect(videoChannel.host).to.equal('localhost:9001')
123 expect(videoChannel.displayName).to.equal('Main root channel')
124 expect(videoChannel.followingCount).to.equal(0)
125 expect(videoChannel.followersCount).to.equal(1)
126 }
127 })
128
104 it('Should list subscription videos', async function () { 129 it('Should list subscription videos', async function () {
105 { 130 {
106 const res = await listUserSubscriptionVideos(servers[0].url, servers[0].accessToken) 131 const res = await listUserSubscriptionVideos(servers[0].url, servers[0].accessToken)
diff --git a/server/tests/utils/users/user-subscriptions.ts b/server/tests/utils/users/user-subscriptions.ts
index 323e5de58..852f590cf 100644
--- a/server/tests/utils/users/user-subscriptions.ts
+++ b/server/tests/utils/users/user-subscriptions.ts
@@ -36,6 +36,17 @@ function listUserSubscriptionVideos (url: string, token: string, sort = '-create
36 }) 36 })
37} 37}
38 38
39function getUserSubscription (url: string, token: string, uri: string, statusCodeExpected = 200) {
40 const path = '/api/v1/users/me/subscriptions/' + uri
41
42 return makeGetRequest({
43 url,
44 path,
45 token,
46 statusCodeExpected
47 })
48}
49
39function removeUserSubscription (url: string, token: string, uri: string, statusCodeExpected = 204) { 50function removeUserSubscription (url: string, token: string, uri: string, statusCodeExpected = 204) {
40 const path = '/api/v1/users/me/subscriptions/' + uri 51 const path = '/api/v1/users/me/subscriptions/' + uri
41 52
@@ -52,6 +63,7 @@ function removeUserSubscription (url: string, token: string, uri: string, status
52export { 63export {
53 addUserSubscription, 64 addUserSubscription,
54 listUserSubscriptions, 65 listUserSubscriptions,
66 getUserSubscription,
55 listUserSubscriptionVideos, 67 listUserSubscriptionVideos,
56 removeUserSubscription 68 removeUserSubscription
57} 69}