]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Merge branch 'release/v1.3.0' into develop
authorChocobozzz <me@florianbigard.com>
Fri, 7 Jun 2019 13:04:41 +0000 (15:04 +0200)
committerChocobozzz <me@florianbigard.com>
Fri, 7 Jun 2019 13:04:41 +0000 (15:04 +0200)
15 files changed:
client/src/app/menu/menu.component.scss
client/src/app/shared/buttons/action-dropdown.component.scss
client/src/app/shared/buttons/action-dropdown.component.ts
client/src/app/shared/forms/form-reactive.ts
client/src/app/shared/instance/instance-features-table.component.scss
client/src/app/shared/user-subscription/remote-subscribe.component.ts
client/src/app/shared/user-subscription/subscribe-button.component.html
client/src/app/shared/user-subscription/subscribe-button.component.ts
client/src/app/shared/video/video-actions-dropdown.component.ts
client/src/app/videos/+video-edit/shared/video-edit.component.ts
client/src/app/videos/+video-watch/comment/video-comment-add.component.html
client/src/app/videos/+video-watch/comment/video-comment-add.component.ts
server/controllers/api/videos/import.ts
server/controllers/static.ts
server/tests/api/videos/video-blacklist.ts

index fa9a006af1ddc1ba01f269fb3c6f314eb57acea1..06baa52d371d3e6d5ac246a506702413ac951934 100644 (file)
@@ -75,22 +75,22 @@ menu {
     .logged-in-more {
       margin-right: 20px;
 
-      my-global-icon {
-        @include apply-svg-color(var(--mainBackgroundColor));
-
+      my-global-icon.dropdown-toggle {
         cursor: pointer;
 
         &::after {
           border: none;
         }
+
+        /deep/ {
+          @include apply-svg-color(var(--menuForegroundColor));
+        }
       }
 
       .dropdown-item {
         @include dropdown-with-icon-item;
 
         my-global-icon {
-          @include apply-svg-color(var(--mainForegroundColor));
-
           width: 22px;
           height: 22px;
 
index 5073190b0bd36c1c12360879916728eb458305d2..7c2b0db71b2c53365a67b6a5b8a3e9dec771db36 100644 (file)
 
   .more-icon {
     width: 21px;
+
+    /deep/ {
+      @include apply-svg-color(var(--mainForegroundColor));
+    }
   }
 
   &.small {
index f5345831b86dd5827d28a11a14411347945ecdc1..c9dbbfda243035c10b905903ae5ba594e6f0de9e 100644 (file)
@@ -41,10 +41,4 @@ export class ActionDropdownComponent<T> {
   areActionsDisplayed (actions: DropdownAction<T>[], entry: T) {
     return actions.some(a => a.isDisplayed === undefined || a.isDisplayed(entry))
   }
-
-  handleClick (event: Event, action: DropdownAction<T>) {
-    event.preventDefault()
-
-    // action.handler(entry)
-  }
 }
index 0d40b6f4ae8715eaa172235f14e8e87dca6bbd63..6aec2937da4bf1eb5a42e7d649741781250cf38a 100644 (file)
@@ -57,7 +57,7 @@ export abstract class FormReactive {
 
       // Don't care if dirty on force check
       const isDirty = control.dirty || forceCheck === true
-      if (control && isDirty && !control.valid) {
+      if (control && isDirty && control.enabled && !control.valid) {
         const messages = validationMessages[ field ]
         for (const key of Object.keys(control.errors)) {
           formErrors[ field ] += messages[ key ] + ' '
index 90fbb5c94eb6c149aff2dbf2a607ef97dd771203..f9bec038de861f8f1aa3cc7c209dfac71b1633ba 100644 (file)
@@ -3,6 +3,7 @@
 
 table {
   font-size: 14px;
+  color: var(--mainForegroundColor);
 
   .label {
     font-weight: $font-semibold;
@@ -16,4 +17,4 @@ table {
   .glyphicon-remove {
     color: $red;
   }
-}
\ No newline at end of file
+}
index ba2a45df136897c9dbe95e9dad32be4437cdd643..63e7cd5d95390555cf6a970db56f6b78f56bf816 100644 (file)
@@ -11,7 +11,7 @@ import {
   styleUrls: ['./remote-subscribe.component.scss']
 })
 export class RemoteSubscribeComponent extends FormReactive implements OnInit {
-  @Input() account: string
+  @Input() uri: string
   @Input() interact = false
   @Input() showHelp = false
 
@@ -42,19 +42,20 @@ export class RemoteSubscribeComponent extends FormReactive implements OnInit {
     fetch(`https://${hostname}/.well-known/webfinger?resource=acct:${username}@${hostname}`)
       .then(response => response.json())
       .then(data => new Promise((resolve, reject) => {
+        console.log(data)
+
         if (data && Array.isArray(data.links)) {
-          const link: {
-            template: string
-          } = data.links.find((link: any) =>
-            link && typeof link.template === 'string' && link.rel === 'http://ostatus.org/schema/1.0/subscribe')
+          const link: { template: string } = data.links.find((link: any) => {
+            return link && typeof link.template === 'string' && link.rel === 'http://ostatus.org/schema/1.0/subscribe'
+          })
 
           if (link && link.template.includes('{uri}')) {
-            resolve(link.template.replace('{uri}', `acct:${this.account}`))
+            resolve(link.template.replace('{uri}', encodeURIComponent(this.uri)))
           }
         }
         reject()
       }))
       .then(window.open)
-      .catch(() => window.open(`https://${hostname}/authorize_interaction?acct=${this.account}`))
+      .catch(err => console.error(err))
   }
 }
index dbf6a34f08fd67c8b00e1c37eece6b230d4fddb1..d32647b4288292a685bfd635261062454a633b20 100644 (file)
@@ -41,7 +41,7 @@
       </button>
 
       <button class="dropdown-item" i18n>Subscribe with a Mastodon account:</button>
-      <my-remote-subscribe showHelp="true" account="{{ uriAccount }}"></my-remote-subscribe>
+      <my-remote-subscribe showHelp="true" [uri]="channelUri"></my-remote-subscribe>
 
       <div class="dropdown-divider"></div>
 
@@ -50,4 +50,4 @@
 
     </div>
   </div>
-</div>
\ No newline at end of file
+</div>
index ef470ee44cbaf62bb5303fc24cd6db123522fd4f..25515f6ea31cd6367673c3720ad739edefb34323 100644 (file)
@@ -28,19 +28,19 @@ export class SubscribeButtonComponent implements OnInit {
     private videoService: VideoService
   ) { }
 
-  get uri () {
+  get channelHandle () {
     return this.videoChannel.name + '@' + this.videoChannel.host
   }
 
-  get uriAccount () {
-    return this.videoChannel.ownerAccount.name + '@' + this.videoChannel.host
+  get channelUri () {
+    return this.videoChannel.url
   }
 
   ngOnInit () {
     if (this.isUserLoggedIn()) {
-      this.userSubscriptionService.doesSubscriptionExist(this.uri)
+      this.userSubscriptionService.doesSubscriptionExist(this.channelHandle)
         .subscribe(
-          res => this.subscribed = res[this.uri],
+          res => this.subscribed = res[this.channelHandle],
 
           err => this.notifier.error(err.message)
         )
@@ -56,7 +56,7 @@ export class SubscribeButtonComponent implements OnInit {
   }
 
   localSubscribe () {
-    this.userSubscriptionService.addSubscription(this.uri)
+    this.userSubscriptionService.addSubscription(this.channelHandle)
       .subscribe(
         () => {
           this.subscribed = true
@@ -78,7 +78,7 @@ export class SubscribeButtonComponent implements OnInit {
   }
 
   localUnsubscribe () {
-    this.userSubscriptionService.deleteSubscription(this.uri)
+    this.userSubscriptionService.deleteSubscription(this.channelHandle)
         .subscribe(
           () => {
             this.subscribed = false
index 0bbc783c12b6fd43dbc00d94a82c8992413ef1b6..8d4e336971f45826f9ec1478bea67436944fab07 100644 (file)
@@ -188,19 +188,16 @@ export class VideoActionsDropdownComponent implements OnChanges {
   }
 
   private buildActions () {
-    this.videoActions = []
-
-    if (this.authService.isLoggedIn()) {
-      this.videoActions.push([
+    this.videoActions = [
+      [
         {
           label: this.i18n('Save to playlist'),
           handler: () => this.playlistDropdown.toggle(),
-          isDisplayed: () => this.displayOptions.playlist,
+          isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.playlist,
           iconName: 'playlist-add'
         }
-      ])
-
-      this.videoActions.push([
+      ],
+      [
         {
           label: this.i18n('Download'),
           handler: () => this.showDownloadModal(),
@@ -211,36 +208,35 @@ export class VideoActionsDropdownComponent implements OnChanges {
           label: this.i18n('Update'),
           linkBuilder: ({ video }) => [ '/videos/update', video.uuid ],
           iconName: 'edit',
-          isDisplayed: () => this.displayOptions.update && this.isVideoUpdatable()
+          isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.update && this.isVideoUpdatable()
         },
         {
           label: this.i18n('Blacklist'),
           handler: () => this.showBlacklistModal(),
           iconName: 'no',
-          isDisplayed: () => this.displayOptions.blacklist && this.isVideoBlacklistable()
+          isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoBlacklistable()
         },
         {
           label: this.i18n('Unblacklist'),
           handler: () => this.unblacklistVideo(),
           iconName: 'undo',
-          isDisplayed: () => this.displayOptions.blacklist && this.isVideoUnblacklistable()
+          isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoUnblacklistable()
         },
         {
           label: this.i18n('Delete'),
           handler: () => this.removeVideo(),
-          isDisplayed: () => this.displayOptions.delete && this.isVideoRemovable(),
+          isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.delete && this.isVideoRemovable(),
           iconName: 'delete'
         }
-      ])
-
-      this.videoActions.push([
+      ],
+      [
         {
           label: this.i18n('Report'),
           handler: () => this.showReportModal(),
-          isDisplayed: () => this.displayOptions.report,
+          isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.report,
           iconName: 'alert'
         }
-      ])
-    }
+      ]
+    ]
   }
 }
index a2776b73dacbc2b4875203a3db8d9527bfa0f079..cea352bfbd8f0a22229e796ed829731a27f47c49 100644 (file)
@@ -193,7 +193,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
   }
 
   private trackPrivacyChange () {
-    // We will update the "support" field depending on the channel
+    // We will update the schedule input and the wait transcoding checkbox validators
     this.form.controls[ 'privacy' ]
       .valueChanges
       .pipe(map(res => parseInt(res.toString(), 10)))
index d8a7a78c4b0a9dfb7dc6a100041a0e9405e114e5..916f5d0ff478df10d227ebfb57e5200c6f8ff43b 100644 (file)
@@ -41,7 +41,7 @@
     <span i18n>
       If you have an account on Mastodon or Pleroma, you can open it directly in their interface:
     </span>
-    <my-remote-subscribe [interact]="true" [account]="getUrl()"></my-remote-subscribe>
+    <my-remote-subscribe [interact]="true" [uri]="getUri()"></my-remote-subscribe>
   </div>
   <div class="modal-footer inputs">
     <span i18n class="action-button action-button-cancel" role="button" (click)="hideVisitorModal()">
index fd85c28f2cb77c1af01ed456fa3ac8149b3e7eee..ac1d02d940dfafc20dcc9f6b08267b2c52348384 100644 (file)
@@ -8,7 +8,6 @@ import { User } from '../../../shared/users'
 import { Video } from '../../../shared/video/video.model'
 import { VideoComment } from './video-comment.model'
 import { VideoCommentService } from './video-comment.service'
-import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
 import { VideoCommentValidatorsService } from '@app/shared/forms/form-validators/video-comment-validators.service'
 import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
@@ -40,8 +39,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit {
     private videoCommentService: VideoCommentService,
     private authService: AuthService,
     private modalService: NgbModal,
-    private router: Router,
-    private i18n: I18n
+    private router: Router
   ) {
     super()
   }
@@ -124,7 +122,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit {
     return this.form.value['text']
   }
 
-  getUrl () {
+  getUri () {
     return window.location.href
   }
 
index bfb69090652a340261f80824442c34be315d16bd..dcba0e08f4a2372505de2d71615cd4eb408c2735 100644 (file)
@@ -26,6 +26,7 @@ import { sequelizeTypescript } from '../../../initializers/database'
 import { createVideoMiniatureFromExisting } from '../../../lib/thumbnail'
 import { ThumbnailType } from '../../../../shared/models/videos/thumbnail.type'
 import { ThumbnailModel } from '../../../models/video/thumbnail'
+import { UserModel } from '../../../models/account/user'
 
 const auditLogger = auditLoggerFactory('video-imports')
 const videoImportsRouter = express.Router()
@@ -107,7 +108,8 @@ async function addTorrentImport (req: express.Request, res: express.Response, to
     previewModel,
     videoChannel: res.locals.videoChannel,
     tags,
-    videoImportAttributes
+    videoImportAttributes,
+    user
   })
 
   // Create job to import the video
@@ -151,12 +153,13 @@ async function addYoutubeDLImport (req: express.Request, res: express.Response)
     userId: user.id
   }
   const videoImport = await insertIntoDB({
-    video: video,
+    video,
     thumbnailModel,
     previewModel,
     videoChannel: res.locals.videoChannel,
     tags,
-    videoImportAttributes
+    videoImportAttributes,
+    user
   })
 
   // Create job to import the video
@@ -227,9 +230,10 @@ function insertIntoDB (parameters: {
   previewModel: ThumbnailModel,
   videoChannel: VideoChannelModel,
   tags: string[],
-  videoImportAttributes: Partial<VideoImportModel>
+  videoImportAttributes: Partial<VideoImportModel>,
+  user: UserModel
 }): Bluebird<VideoImportModel> {
-  let { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes } = parameters
+  const { video, thumbnailModel, previewModel, videoChannel, tags, videoImportAttributes, user } = parameters
 
   return sequelizeTypescript.transaction(async t => {
     const sequelizeOptions = { transaction: t }
@@ -241,7 +245,7 @@ function insertIntoDB (parameters: {
     if (thumbnailModel) await videoCreated.addAndSaveThumbnail(thumbnailModel, t)
     if (previewModel) await videoCreated.addAndSaveThumbnail(previewModel, t)
 
-    await autoBlacklistVideoIfNeeded(video, videoChannel.Account.User, t)
+    await autoBlacklistVideoIfNeeded(video, user, t)
 
     // Set tags to the video
     if (tags) {
index d57dba6ce24eae3f0ee07b56d7d80b95eb0c65e8..a6b46244379bcfc0af5b490d0fbb63e07540c75d 100644 (file)
@@ -156,6 +156,19 @@ staticRouter.use('/.well-known/change-password',
   }
 )
 
+staticRouter.use('/.well-known/host-meta',
+  (_, res: express.Response) => {
+    res.type('application/xml')
+
+    const xml = '<?xml version="1.0" encoding="UTF-8"?>\n' +
+      '<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">\n' +
+      `  <Link rel="lrdd" type="application/xrd+xml" template="${WEBSERVER.URL}/.well-known/webfinger?resource={uri}"/>\n` +
+      '</XRD>'
+
+    res.send(xml).end()
+  }
+)
+
 // ---------------------------------------------------------------------------
 
 export {
index e907bbdc0dbffd4dc69f12d5646ac698fbaa3042..8760a47875d9dd358a2246e8877cb4d1fb671b25 100644 (file)
@@ -4,10 +4,11 @@ import * as chai from 'chai'
 import { orderBy } from 'lodash'
 import 'mocha'
 import {
-  addVideoToBlacklist, cleanupTests,
+  addVideoToBlacklist,
+  cleanupTests,
   createUser,
   flushAndRunMultipleServers,
-  getBlacklistedVideosList,
+  getBlacklistedVideosList, getMyUserInformation,
   getMyVideos,
   getVideosList,
   killallServers,
@@ -16,6 +17,7 @@ import {
   searchVideo,
   ServerInfo,
   setAccessTokensToServers,
+  setDefaultVideoChannel,
   updateVideo,
   updateVideoBlacklist,
   uploadVideo,
@@ -25,7 +27,8 @@ import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
 import { VideoBlacklist, VideoBlacklistType } from '../../../../shared/models/videos'
 import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
-import { UserRole } from '../../../../shared/models/users'
+import { User, UserRole, UserUpdateMe } from '../../../../shared/models/users'
+import { getMagnetURI, getYoutubeVideoUrl, importVideo } from '../../../../shared/extra-utils/videos/video-imports'
 
 const expect = chai.expect
 
@@ -351,6 +354,7 @@ describe('Test video blacklist', function () {
   describe('When auto blacklist videos', function () {
     let userWithoutFlag: string
     let userWithFlag: string
+    let channelOfUserWithoutFlag: number
 
     before(async function () {
       this.timeout(20000)
@@ -380,6 +384,10 @@ describe('Test video blacklist', function () {
         })
 
         userWithoutFlag = await userLogin(servers[0], user)
+
+        const res = await getMyUserInformation(servers[0].url, userWithoutFlag)
+        const body: User = res.body
+        channelOfUserWithoutFlag = body.videoChannels[0].id
       }
 
       {
@@ -399,7 +407,7 @@ describe('Test video blacklist', function () {
       await waitJobs(servers)
     })
 
-    it('Should auto blacklist a video', async function () {
+    it('Should auto blacklist a video on upload', async function () {
       await uploadVideo(servers[0].url, userWithoutFlag, { name: 'blacklisted' })
 
       const res = await getBlacklistedVideosList({
@@ -412,7 +420,45 @@ describe('Test video blacklist', function () {
       expect(res.body.data[0].video.name).to.equal('blacklisted')
     })
 
-    it('Should not auto blacklist a video', async function () {
+    it('Should auto blacklist a video on URL import', async function () {
+      const attributes = {
+        targetUrl: getYoutubeVideoUrl(),
+        name: 'URL import',
+        channelId: channelOfUserWithoutFlag
+      }
+      await importVideo(servers[ 0 ].url, userWithoutFlag, attributes)
+
+      const res = await getBlacklistedVideosList({
+        url: servers[ 0 ].url,
+        token: servers[ 0 ].accessToken,
+        sort: 'createdAt',
+        type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
+      })
+
+      expect(res.body.total).to.equal(2)
+      expect(res.body.data[1].video.name).to.equal('URL import')
+    })
+
+    it('Should auto blacklist a video on torrent import', async function () {
+      const attributes = {
+        magnetUri: getMagnetURI(),
+        name: 'Torrent import',
+        channelId: channelOfUserWithoutFlag
+      }
+      await importVideo(servers[ 0 ].url, userWithoutFlag, attributes)
+
+      const res = await getBlacklistedVideosList({
+        url: servers[ 0 ].url,
+        token: servers[ 0 ].accessToken,
+        sort: 'createdAt',
+        type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
+      })
+
+      expect(res.body.total).to.equal(3)
+      expect(res.body.data[2].video.name).to.equal('Torrent import')
+    })
+
+    it('Should not auto blacklist a video on upload if the user has the bypass blacklist flag', async function () {
       await uploadVideo(servers[0].url, userWithFlag, { name: 'not blacklisted' })
 
       const res = await getBlacklistedVideosList({
@@ -421,7 +467,7 @@ describe('Test video blacklist', function () {
         type: VideoBlacklistType.AUTO_BEFORE_PUBLISHED
       })
 
-      expect(res.body.total).to.equal(1)
+      expect(res.body.total).to.equal(3)
     })
   })