From 2e3a0215d051dca1f7c8ef423564c8d37a255f77 Mon Sep 17 00:00:00 2001
From: Chocobozzz <me@florianbigard.com>
Date: Thu, 15 Mar 2018 14:31:08 +0100
Subject: [PATCH] Add short description in config

---
 .../edit-custom-config.component.html                | 11 +++++++++++
 .../edit-custom-config.component.scss                |  4 ++++
 .../edit-custom-config.component.ts                  |  7 ++++++-
 client/src/app/core/server/server.service.ts         |  1 +
 .../shared/forms/form-validators/custom-config.ts    |  7 +++++++
 config/default.yaml                                  |  1 +
 config/production.yaml.example                       |  1 +
 server/controllers/api/config.ts                     |  5 +++++
 server/initializers/constants.ts                     |  1 +
 .../job-queue/handlers/activitypub-http-broadcast.ts |  2 +-
 .../job-queue/handlers/activitypub-http-unicast.ts   |  4 ++--
 server/models/activitypub/actor-follow.ts            |  2 +-
 server/tests/api/check-params/config.ts              |  1 +
 server/tests/api/server/config.ts                    | 12 ++++++++++++
 shared/models/server/about.model.ts                  |  1 +
 shared/models/server/custom-config.model.ts          |  1 +
 shared/models/server/customization.model.ts          |  8 --------
 shared/models/server/server-config.model.ts          |  1 +
 support/doc/production.md                            |  2 ++
 19 files changed, 59 insertions(+), 13 deletions(-)
 delete mode 100644 shared/models/server/customization.model.ts

diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
index c7ddaaf01..6658a095d 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
@@ -15,6 +15,17 @@
     </div>
   </div>
 
+  <div class="form-group">
+    <label for="instanceShortDescription">Short description</label>
+    <textarea
+        id="instanceShortDescription" formControlName="instanceShortDescription"
+        [ngClass]="{ 'input-error': formErrors['instanceShortDescription'] }"
+    ></textarea>
+    <div *ngIf="formErrors.instanceShortDescription" class="form-error">
+      {{ formErrors.instanceShortDescription }}
+    </div>
+  </div>
+
   <div class="form-group">
     <label for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help>
     <my-markdown-textarea
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
index e72f30c69..e81044554 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
@@ -34,4 +34,8 @@ textarea {
   @include peertube-textarea(500px, 150px);
 
   display: block;
+
+  &#instanceShortDescription {
+    height: 100px;
+  }
 }
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
index c38bc326a..9ab8b08d0 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
@@ -8,7 +8,7 @@ import { FormReactive, USER_VIDEO_QUOTA } from '@app/shared'
 import {
   ADMIN_EMAIL,
   CACHE_PREVIEWS_SIZE,
-  INSTANCE_NAME,
+  INSTANCE_NAME, INSTANCE_SHORT_DESCRIPTION,
   SIGNUP_LIMIT,
   TRANSCODING_THREADS
 } from '@app/shared/forms/form-validators/custom-config'
@@ -44,6 +44,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
   form: FormGroup
   formErrors = {
     instanceName: '',
+    instanceShortDescription: '',
     instanceDescription: '',
     instanceTerms: '',
     instanceDefaultClientRoute: '',
@@ -56,6 +57,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
     customizationCSS: ''
   }
   validationMessages = {
+    instanceShortDescription: INSTANCE_SHORT_DESCRIPTION.MESSAGES,
     instanceName: INSTANCE_NAME.MESSAGES,
     cachePreviewsSize: CACHE_PREVIEWS_SIZE.MESSAGES,
     signupLimit: SIGNUP_LIMIT.MESSAGES,
@@ -84,6 +86,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
   buildForm () {
     const formGroupData = {
       instanceName: [ '', INSTANCE_NAME.VALIDATORS ],
+      instanceShortDescription: [ '', INSTANCE_SHORT_DESCRIPTION.VALIDATORS ],
       instanceDescription: [ '' ],
       instanceTerms: [ '' ],
       instanceDefaultClientRoute: [ '' ],
@@ -158,6 +161,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
     const data: CustomConfig = {
       instance: {
         name: this.form.value['instanceName'],
+        shortDescription: this.form.value['instanceShortDescription'],
         description: this.form.value['instanceDescription'],
         terms: this.form.value['instanceTerms'],
         defaultClientRoute: this.form.value['instanceDefaultClientRoute'],
@@ -214,6 +218,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
   private updateForm () {
     const data = {
       instanceName: this.customConfig.instance.name,
+      instanceShortDescription: this.customConfig.instance.shortDescription,
       instanceDescription: this.customConfig.instance.description,
       instanceTerms: this.customConfig.instance.terms,
       instanceDefaultClientRoute: this.customConfig.instance.defaultClientRoute,
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts
index 2135c3268..bd85d9f0f 100644
--- a/client/src/app/core/server/server.service.ts
+++ b/client/src/app/core/server/server.service.ts
@@ -21,6 +21,7 @@ export class ServerService {
   private config: ServerConfig = {
     instance: {
       name: 'PeerTube',
+      shortDescription: '',
       defaultClientRoute: '',
       customizations: {
         javascript: '',
diff --git a/client/src/app/shared/forms/form-validators/custom-config.ts b/client/src/app/shared/forms/form-validators/custom-config.ts
index a0966a9a7..c9cef2e09 100644
--- a/client/src/app/shared/forms/form-validators/custom-config.ts
+++ b/client/src/app/shared/forms/form-validators/custom-config.ts
@@ -7,6 +7,13 @@ export const INSTANCE_NAME = {
   }
 }
 
+export const INSTANCE_SHORT_DESCRIPTION = {
+  VALIDATORS: [ Validators.max(250) ],
+  MESSAGES: {
+    'max': 'Short description should not be longer than 250 characters.'
+  }
+}
+
 export const CACHE_PREVIEWS_SIZE = {
   VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
   MESSAGES: {
diff --git a/config/default.yaml b/config/default.yaml
index 5389f1164..48e5bd067 100644
--- a/config/default.yaml
+++ b/config/default.yaml
@@ -72,6 +72,7 @@ transcoding:
 
 instance:
   name: 'PeerTube'
+  short_description: 'PeerTube, a federated (ActivityPub) video streaming platform using P2P (BitTorrent) directly in the web browser with WebTorrent and Angular.'
   description: 'Welcome to this PeerTube instance!' # Support markdown
   terms: 'No terms for now.' # Support markdown
   default_client_route: '/videos/trending'
diff --git a/config/production.yaml.example b/config/production.yaml.example
index 2f28501b3..45eeffec7 100644
--- a/config/production.yaml.example
+++ b/config/production.yaml.example
@@ -85,6 +85,7 @@ transcoding:
 
 instance:
   name: 'PeerTube'
+  short_description: 'PeerTube, a federated (ActivityPub) video streaming platform using P2P (BitTorrent) directly in the web browser with WebTorrent and Angular.'
   description: '' # Support markdown
   terms: '' # Support markdown
   default_client_route: '/videos/trending'
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index a25d7a157..62a783982 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -44,6 +44,7 @@ async function getConfig (req: express.Request, res: express.Response, next: exp
   const json: ServerConfig = {
     instance: {
       name: CONFIG.INSTANCE.NAME,
+      shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
       defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
       customizations: {
         javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT,
@@ -85,6 +86,7 @@ function getAbout (req: express.Request, res: express.Response, next: express.Ne
   const about: About = {
     instance: {
       name: CONFIG.INSTANCE.NAME,
+      shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
       description: CONFIG.INSTANCE.DESCRIPTION,
       terms: CONFIG.INSTANCE.TERMS
     }
@@ -116,8 +118,10 @@ async function updateCustomConfig (req: express.Request, res: express.Response,
   const toUpdateJSON = omit(toUpdate, 'videoQuota')
   toUpdateJSON.user['video_quota'] = toUpdate.user.videoQuota
   toUpdateJSON.instance['default_client_route'] = toUpdate.instance.defaultClientRoute
+  toUpdateJSON.instance['short_description'] = toUpdate.instance.shortDescription
   delete toUpdate.user.videoQuota
   delete toUpdate.instance.defaultClientRoute
+  delete toUpdate.instance.shortDescription
 
   await writeFilePromise(CONFIG.CUSTOM_FILE, JSON.stringify(toUpdateJSON, undefined, 2))
 
@@ -139,6 +143,7 @@ function customConfig (): CustomConfig {
   return {
     instance: {
       name: CONFIG.INSTANCE.NAME,
+      shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
       description: CONFIG.INSTANCE.DESCRIPTION,
       terms: CONFIG.INSTANCE.TERMS,
       defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 5946bcd11..d12d96803 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -157,6 +157,7 @@ const CONFIG = {
   },
   INSTANCE: {
     get NAME () { return config.get<string>('instance.name') },
+    get SHORT_DESCRIPTION () { return config.get<string>('instance.short_description') },
     get DESCRIPTION () { return config.get<string>('instance.description') },
     get TERMS () { return config.get<string>('instance.terms') },
     get DEFAULT_CLIENT_ROUTE () { return config.get<string>('instance.default_client_route') },
diff --git a/server/lib/job-queue/handlers/activitypub-http-broadcast.ts b/server/lib/job-queue/handlers/activitypub-http-broadcast.ts
index 159856cda..78878fc01 100644
--- a/server/lib/job-queue/handlers/activitypub-http-broadcast.ts
+++ b/server/lib/job-queue/handlers/activitypub-http-broadcast.ts
@@ -39,7 +39,7 @@ async function processActivityPubHttpBroadcast (job: kue.Job) {
     }
   }
 
-  return ActorFollowModel.updateActorFollowsScoreAndRemoveBadOnes(goodUrls, badUrls, undefined)
+  return ActorFollowModel.updateActorFollowsScore(goodUrls, badUrls, undefined)
 }
 
 // ---------------------------------------------------------------------------
diff --git a/server/lib/job-queue/handlers/activitypub-http-unicast.ts b/server/lib/job-queue/handlers/activitypub-http-unicast.ts
index 9b4188c50..e1e1824e5 100644
--- a/server/lib/job-queue/handlers/activitypub-http-unicast.ts
+++ b/server/lib/job-queue/handlers/activitypub-http-unicast.ts
@@ -28,9 +28,9 @@ async function processActivityPubHttpUnicast (job: kue.Job) {
 
   try {
     await doRequest(options)
-    ActorFollowModel.updateActorFollowsScoreAndRemoveBadOnes([ uri ], [], undefined)
+    ActorFollowModel.updateActorFollowsScore([ uri ], [], undefined)
   } catch (err) {
-    ActorFollowModel.updateActorFollowsScoreAndRemoveBadOnes([], [ uri ], undefined)
+    ActorFollowModel.updateActorFollowsScore([], [ uri ], undefined)
 
     throw err
   }
diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts
index 3c11d1b67..d3c438626 100644
--- a/server/models/activitypub/actor-follow.ts
+++ b/server/models/activitypub/actor-follow.ts
@@ -111,7 +111,7 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
     if (numberOfActorFollowsRemoved) logger.info('Removed bad %d actor follows.', numberOfActorFollowsRemoved)
   }
 
-  static updateActorFollowsScoreAndRemoveBadOnes (goodInboxes: string[], badInboxes: string[], t: Sequelize.Transaction) {
+  static updateActorFollowsScore (goodInboxes: string[], badInboxes: string[], t: Sequelize.Transaction) {
     if (goodInboxes.length === 0 && badInboxes.length === 0) return
 
     logger.info('Updating %d good actor follows and %d bad actor follows scores.', goodInboxes.length, badInboxes.length)
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts
index ca8239270..3fe517fad 100644
--- a/server/tests/api/check-params/config.ts
+++ b/server/tests/api/check-params/config.ts
@@ -16,6 +16,7 @@ describe('Test config API validators', function () {
   const updateParams: CustomConfig = {
     instance: {
       name: 'PeerTube updated',
+      shortDescription: 'my short description',
       description: 'my super description',
       terms: 'my super terms',
       defaultClientRoute: '/videos/recently-added',
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts
index 271a57275..e17588142 100644
--- a/server/tests/api/server/config.ts
+++ b/server/tests/api/server/config.ts
@@ -52,6 +52,10 @@ describe('Test config', function () {
     const data = res.body as CustomConfig
 
     expect(data.instance.name).to.equal('PeerTube')
+    expect(data.instance.shortDescription).to.equal(
+      'PeerTube, a federated (ActivityPub) video streaming platform using P2P (BitTorrent) directly in the web browser ' +
+      'with WebTorrent and Angular.'
+    )
     expect(data.instance.description).to.equal('Welcome to this PeerTube instance!')
     expect(data.instance.terms).to.equal('No terms for now.')
     expect(data.instance.defaultClientRoute).to.equal('/videos/trending')
@@ -75,6 +79,7 @@ describe('Test config', function () {
     const newCustomConfig = {
       instance: {
         name: 'PeerTube updated',
+        shortDescription: 'my short description',
         description: 'my super description',
         terms: 'my super terms',
         defaultClientRoute: '/videos/recently-added',
@@ -116,6 +121,7 @@ describe('Test config', function () {
     const data = res.body
 
     expect(data.instance.name).to.equal('PeerTube updated')
+    expect(data.instance.shortDescription).to.equal('my short description')
     expect(data.instance.description).to.equal('my super description')
     expect(data.instance.terms).to.equal('my super terms')
     expect(data.instance.defaultClientRoute).to.equal('/videos/recently-added')
@@ -146,6 +152,7 @@ describe('Test config', function () {
     const data = res.body
 
     expect(data.instance.name).to.equal('PeerTube updated')
+    expect(data.instance.shortDescription).to.equal('my short description')
     expect(data.instance.description).to.equal('my super description')
     expect(data.instance.terms).to.equal('my super terms')
     expect(data.instance.defaultClientRoute).to.equal('/videos/recently-added')
@@ -170,6 +177,7 @@ describe('Test config', function () {
     const data: About = res.body
 
     expect(data.instance.name).to.equal('PeerTube updated')
+    expect(data.instance.shortDescription).to.equal('my short description')
     expect(data.instance.description).to.equal('my super description')
     expect(data.instance.terms).to.equal('my super terms')
   })
@@ -183,6 +191,10 @@ describe('Test config', function () {
     const data = res.body
 
     expect(data.instance.name).to.equal('PeerTube')
+    expect(data.instance.shortDescription).to.equal(
+      'PeerTube, a federated (ActivityPub) video streaming platform using P2P (BitTorrent) directly in the web browser ' +
+      'with WebTorrent and Angular.'
+    )
     expect(data.instance.description).to.equal('Welcome to this PeerTube instance!')
     expect(data.instance.terms).to.equal('No terms for now.')
     expect(data.instance.defaultClientRoute).to.equal('/videos/trending')
diff --git a/shared/models/server/about.model.ts b/shared/models/server/about.model.ts
index 7d11da850..10dff8b8f 100644
--- a/shared/models/server/about.model.ts
+++ b/shared/models/server/about.model.ts
@@ -1,6 +1,7 @@
 export interface About {
   instance: {
     name: string
+    shortDescription: string
     description: string
     terms: string
   }
diff --git a/shared/models/server/custom-config.model.ts b/shared/models/server/custom-config.model.ts
index 7f3e2df02..b4d24cfbe 100644
--- a/shared/models/server/custom-config.model.ts
+++ b/shared/models/server/custom-config.model.ts
@@ -1,6 +1,7 @@
 export interface CustomConfig {
   instance: {
     name: string
+    shortDescription: string
     description: string
     terms: string
     defaultClientRoute: string
diff --git a/shared/models/server/customization.model.ts b/shared/models/server/customization.model.ts
deleted file mode 100644
index 4e4d0d193..000000000
--- a/shared/models/server/customization.model.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface Customization {
-  instance: {
-    customization: {
-      javascript: string
-      css: string
-    }
-  }
-}
diff --git a/shared/models/server/server-config.model.ts b/shared/models/server/server-config.model.ts
index a30c24eb9..c6fa651a8 100644
--- a/shared/models/server/server-config.model.ts
+++ b/shared/models/server/server-config.model.ts
@@ -3,6 +3,7 @@ export interface ServerConfig {
 
   instance: {
     name: string
+    shortDescription: string
     defaultClientRoute: string
     customizations: {
       javascript: string
diff --git a/support/doc/production.md b/support/doc/production.md
index 14042cddf..db0c8d99f 100644
--- a/support/doc/production.md
+++ b/support/doc/production.md
@@ -152,6 +152,8 @@ logs. You can set another password with:
 $ cd /var/www/peertube/peertube-latest && NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run reset-password -- -u root
 ```
 
+Now you can subscribe to the mailing list for PeerTube administrators: https://framalistes.org/sympa/subscribe/peertube-admin
+
 ## Upgrade
 
 #### Auto (minor versions only)