From 7efe153b0bc23e596d5019b9fb3e3e32b6cfeccd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9as=20Livet?= <andreas.livet@gmail.com>
Date: Tue, 19 Dec 2017 10:45:49 +0100
Subject: Enh #106 : Add an autoPlayVideo user attribute (#159)

Warning : I was not able to run the tests on my machine. It uses a different approach to handle databse connexion and didn't find where to configure it...

- create a migration file to add a boolean column in user table
- add autoPlayVideo attribute everywhere it is needed (both on client and server side)
- add tests
- add a way to configure this attribute in account-settings
- use the attribute in video-watch component to actually autoplay or not the video
---
 server/controllers/api/users.ts                    |  3 +++
 server/helpers/custom-validators/users.ts          | 13 +++++++++--
 server/initializers/constants.ts                   |  2 +-
 .../migrations/0130-user-autoplay-video.ts         | 27 ++++++++++++++++++++++
 server/middlewares/validators/users.ts             |  2 ++
 server/models/account/user.ts                      |  9 +++++++-
 server/tests/api/check-params/users.ts             |  9 ++++++++
 server/tests/api/users.ts                          |  9 ++++++++
 server/tests/utils/users.ts                        |  4 +++-
 9 files changed, 73 insertions(+), 5 deletions(-)
 create mode 100644 server/initializers/migrations/0130-user-autoplay-video.ts

(limited to 'server')

diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts
index d6c0e67f9..995542604 100644
--- a/server/controllers/api/users.ts
+++ b/server/controllers/api/users.ts
@@ -134,6 +134,7 @@ async function createUser (req: express.Request) {
     password: body.password,
     email: body.email,
     displayNSFW: false,
+    autoPlayVideo: true,
     role: body.role,
     videoQuota: body.videoQuota
   })
@@ -162,6 +163,7 @@ async function registerUser (req: express.Request) {
     password: body.password,
     email: body.email,
     displayNSFW: false,
+    autoPlayVideo: true,
     role: UserRole.USER,
     videoQuota: CONFIG.USER.VIDEO_QUOTA
   })
@@ -219,6 +221,7 @@ async function updateMe (req: express.Request, res: express.Response, next: expr
   if (body.password !== undefined) user.password = body.password
   if (body.email !== undefined) user.email = body.email
   if (body.displayNSFW !== undefined) user.displayNSFW = body.displayNSFW
+  if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo
 
   await user.save()
 
diff --git a/server/helpers/custom-validators/users.ts b/server/helpers/custom-validators/users.ts
index b5b5642d6..159c2a700 100644
--- a/server/helpers/custom-validators/users.ts
+++ b/server/helpers/custom-validators/users.ts
@@ -21,10 +21,18 @@ function isUserUsernameValid (value: string) {
   return exists(value) && validator.matches(value, new RegExp(`^[a-z0-9._]{${min},${max}}$`))
 }
 
-function isUserDisplayNSFWValid (value: any) {
+function isBoolean (value: any) {
   return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value))
 }
 
+function isUserDisplayNSFWValid (value: any) {
+  return isBoolean(value)
+}
+
+function isUserAutoPlayVideoValid (value: any) {
+  return isBoolean(value)
+}
+
 function isUserRoleValid (value: any) {
   return exists(value) && validator.isInt('' + value) && UserRole[value] !== undefined
 }
@@ -36,5 +44,6 @@ export {
   isUserRoleValid,
   isUserVideoQuotaValid,
   isUserUsernameValid,
-  isUserDisplayNSFWValid
+  isUserDisplayNSFWValid,
+  isUserAutoPlayVideoValid
 }
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 341086bd6..ff322730f 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -8,7 +8,7 @@ import { isTestInstance, root } from '../helpers/core-utils'
 
 // ---------------------------------------------------------------------------
 
-const LAST_MIGRATION_VERSION = 125
+const LAST_MIGRATION_VERSION = 130
 
 // ---------------------------------------------------------------------------
 
diff --git a/server/initializers/migrations/0130-user-autoplay-video.ts b/server/initializers/migrations/0130-user-autoplay-video.ts
new file mode 100644
index 000000000..9f6878e39
--- /dev/null
+++ b/server/initializers/migrations/0130-user-autoplay-video.ts
@@ -0,0 +1,27 @@
+import * as Sequelize from 'sequelize'
+import * as Promise from 'bluebird'
+
+function up (utils: {
+  transaction: Sequelize.Transaction,
+  queryInterface: Sequelize.QueryInterface,
+  sequelize: Sequelize.Sequelize
+}): Promise<void> {
+  const q = utils.queryInterface
+
+  const data = {
+    type: Sequelize.BOOLEAN,
+    allowNull: false,
+    defaultValue: true
+  }
+
+  return q.addColumn('user', 'autoPlayVideo', data)
+}
+
+function down (options) {
+  throw new Error('Not implemented.')
+}
+
+export {
+  up,
+  down
+}
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index 920176d07..a6fdbe268 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -5,6 +5,7 @@ import { isSignupAllowed, logger } from '../../helpers'
 import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc'
 import {
   isUserDisplayNSFWValid,
+  isUserAutoPlayVideoValid,
   isUserPasswordValid,
   isUserRoleValid,
   isUserUsernameValid,
@@ -86,6 +87,7 @@ const usersUpdateMeValidator = [
   body('password').optional().custom(isUserPasswordValid).withMessage('Should have a valid password'),
   body('email').optional().isEmail().withMessage('Should have a valid email attribute'),
   body('displayNSFW').optional().custom(isUserDisplayNSFWValid).withMessage('Should have a valid display Not Safe For Work attribute'),
+  body('autoPlayVideo').optional().custom(isUserAutoPlayVideoValid).withMessage('Should have a valid automatically plays video attribute'),
 
   (req: express.Request, res: express.Response, next: express.NextFunction) => {
     // TODO: Add old password verification
diff --git a/server/models/account/user.ts b/server/models/account/user.ts
index 26f04dcb5..70ed61e07 100644
--- a/server/models/account/user.ts
+++ b/server/models/account/user.ts
@@ -20,7 +20,7 @@ import {
 } from '../../helpers'
 import {
   isUserDisplayNSFWValid, isUserPasswordValid, isUserRoleValid, isUserUsernameValid,
-  isUserVideoQuotaValid
+  isUserVideoQuotaValid, isUserAutoPlayVideoValid
 } from '../../helpers/custom-validators/users'
 import { OAuthTokenModel } from '../oauth/oauth-token'
 import { getSort, throwIfNotValid } from '../utils'
@@ -82,6 +82,12 @@ export class UserModel extends Model<UserModel> {
   @Column
   displayNSFW: boolean
 
+  @AllowNull(false)
+  @Default(true)
+  @Is('UserAutoPlayVideo', value => throwIfNotValid(value, isUserAutoPlayVideoValid, 'auto play video boolean'))
+  @Column
+  autoPlayVideo: boolean
+
   @AllowNull(false)
   @Is('UserRole', value => throwIfNotValid(value, isUserRoleValid, 'role'))
   @Column
@@ -223,6 +229,7 @@ export class UserModel extends Model<UserModel> {
       username: this.username,
       email: this.email,
       displayNSFW: this.displayNSFW,
+      autoPlayVideo: this.autoPlayVideo,
       role: this.role,
       roleLabel: USER_ROLE_LABELS[ this.role ],
       videoQuota: this.videoQuota,
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts
index 1e3533bf3..72488e5c4 100644
--- a/server/tests/api/check-params/users.ts
+++ b/server/tests/api/check-params/users.ts
@@ -350,6 +350,14 @@ describe('Test users API validators', function () {
       await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
     })
 
+    it('Should fail with an invalid autoPlayVideo attribute', async function () {
+      const fields = {
+        autoPlayVideo: -1
+      }
+
+      await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
+    })
+
     it('Should fail with an non authenticated user', async function () {
       const fields = {
         password: 'my super password'
@@ -362,6 +370,7 @@ describe('Test users API validators', function () {
       const fields = {
         password: 'my super password',
         displayNSFW: true,
+        autoPlayVideo: false,
         email: 'super_email@example.com'
       }
 
diff --git a/server/tests/api/users.ts b/server/tests/api/users.ts
index b3163b1e1..67e4cc8c6 100644
--- a/server/tests/api/users.ts
+++ b/server/tests/api/users.ts
@@ -415,6 +415,15 @@ describe('Test users', function () {
       .a('number')
   })
 
+  it('Should be able to change the autoPlayVideo attribute', async function () {
+    await updateMyUser(server.url, accessTokenUser, undefined, undefined, undefined, false)
+
+    const res = await getMyUserInformation(server.url, accessTokenUser)
+    const user = res.body
+
+    expect(user.autoPlayVideo).to.be.false
+  })
+
   it('Should be able to change the email display attribute', async function () {
     await updateMyUser(server.url, accessTokenUser, undefined, undefined, 'updated@example.com')
 
diff --git a/server/tests/utils/users.ts b/server/tests/utils/users.ts
index ce04b9d96..a37d84ab4 100644
--- a/server/tests/utils/users.ts
+++ b/server/tests/utils/users.ts
@@ -111,12 +111,14 @@ function removeUser (url: string, userId: number, accessToken: string, expectedS
           .expect(expectedStatus)
 }
 
-function updateMyUser (url: string, accessToken: string, newPassword: string, displayNSFW?: boolean, email?: string) {
+function updateMyUser (url: string, accessToken: string, newPassword: string, displayNSFW?: boolean,
+  email?: string, autoPlayVideo?: boolean) {
   const path = '/api/v1/users/me'
 
   const toSend = {}
   if (newPassword !== undefined && newPassword !== null) toSend['password'] = newPassword
   if (displayNSFW !== undefined && displayNSFW !== null) toSend['displayNSFW'] = displayNSFW
+  if (autoPlayVideo !== undefined && autoPlayVideo !== null) toSend['autoPlayVideo'] = autoPlayVideo
   if (email !== undefined && email !== null) toSend['email'] = email
 
   return request(url)
-- 
cgit v1.2.3