Merge branch 'release/2.1.0'

This commit is contained in:
Chocobozzz 2020-02-27 09:09:50 +01:00
commit 16ec5e0833
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
13 changed files with 69 additions and 42 deletions

View File

@ -1,5 +1,20 @@
# Changelog # Changelog
## v2.1.1
### Bug fixes
* Fix youtube-dl in docker image
* Fix playlist creation/update
* Fix fetch of instance config in client
* Manual approves followers only for the instance (and not accounts/channels)
* Fix avatar update
* Fix CSP for embeds
* Fix scroll of the menu on mobile
* Fix CPU usage of PostgreSQL
* Fix embed for iOS
## v2.1.0 ## v2.1.0
**Since v2.0.0** **Since v2.0.0**

View File

@ -1,6 +1,6 @@
{ {
"name": "peertube-client", "name": "peertube-client",
"version": "2.1.0", "version": "2.1.1",
"private": true, "private": true,
"license": "AGPL-3.0", "license": "AGPL-3.0",
"author": { "author": {

View File

@ -159,8 +159,11 @@ export class ServerService {
if (!this.configObservable) { if (!this.configObservable) {
this.configObservable = this.http.get<ServerConfig>(ServerService.BASE_CONFIG_URL) this.configObservable = this.http.get<ServerConfig>(ServerService.BASE_CONFIG_URL)
.pipe( .pipe(
tap(this.saveConfigLocally), tap(config => this.saveConfigLocally(config)),
tap(() => this.configLoaded = true), tap(config => {
this.config = config
this.configLoaded = true
}),
tap(() => { tap(() => {
if (this.configReset) { if (this.configReset) {
this.configReloaded.next() this.configReloaded.next()

View File

@ -254,6 +254,10 @@ menu {
@media screen and (max-width: $mobile-view) { @media screen and (max-width: $mobile-view) {
.menu-wrapper { .menu-wrapper {
width: 100% !important; width: 100% !important;
menu {
overflow-y: auto;
}
} }
.top-menu, .footer { .top-menu, .footer {

View File

@ -141,6 +141,8 @@ export class VideoPlaylistService {
return this.authHttp.post<{ videoPlaylist: { id: number } }>(VideoPlaylistService.BASE_VIDEO_PLAYLIST_URL, data) return this.authHttp.post<{ videoPlaylist: { id: number } }>(VideoPlaylistService.BASE_VIDEO_PLAYLIST_URL, data)
.pipe( .pipe(
tap(res => { tap(res => {
if (!this.myAccountPlaylistCache) return
this.myAccountPlaylistCache.total++ this.myAccountPlaylistCache.total++
this.myAccountPlaylistCache.data.push({ this.myAccountPlaylistCache.data.push({
@ -161,6 +163,8 @@ export class VideoPlaylistService {
.pipe( .pipe(
map(this.restExtractor.extractDataBool), map(this.restExtractor.extractDataBool),
tap(() => { tap(() => {
if (!this.myAccountPlaylistCache) return
const playlist = this.myAccountPlaylistCache.data.find(p => p.id === videoPlaylist.id) const playlist = this.myAccountPlaylistCache.data.find(p => p.id === videoPlaylist.id)
playlist.displayName = body.displayName playlist.displayName = body.displayName
@ -175,6 +179,8 @@ export class VideoPlaylistService {
.pipe( .pipe(
map(this.restExtractor.extractDataBool), map(this.restExtractor.extractDataBool),
tap(() => { tap(() => {
if (!this.myAccountPlaylistCache) return
this.myAccountPlaylistCache.total-- this.myAccountPlaylistCache.total--
this.myAccountPlaylistCache.data = this.myAccountPlaylistCache.data this.myAccountPlaylistCache.data = this.myAccountPlaylistCache.data
.filter(p => p.id !== videoPlaylist.id) .filter(p => p.id !== videoPlaylist.id)

View File

@ -262,6 +262,9 @@ export class PeerTubeEmbed {
private async buildDock (videoInfo: VideoDetails, configResponse: Response) { private async buildDock (videoInfo: VideoDetails, configResponse: Response) {
if (this.controls) { if (this.controls) {
// On webtorrent fallback, player may have been disposed
if (!this.player.player_) return
const title = this.title ? videoInfo.name : undefined const title = this.title ? videoInfo.name : undefined
const config: ServerConfig = await configResponse.json() const config: ServerConfig = await configResponse.json()

View File

@ -1,7 +1,7 @@
{ {
"name": "peertube", "name": "peertube",
"description": "Federated (ActivityPub) video streaming platform using P2P (BitTorrent) directly in the web browser with WebTorrent and Angular.", "description": "Federated (ActivityPub) video streaming platform using P2P (BitTorrent) directly in the web browser with WebTorrent and Angular.",
"version": "2.1.0", "version": "2.1.1",
"private": true, "private": true,
"licence": "AGPL-3.0", "licence": "AGPL-3.0",
"engines": { "engines": {

View File

@ -2,10 +2,11 @@ import * as express from 'express'
import { join } from 'path' import { join } from 'path'
import { root } from '../helpers/core-utils' import { root } from '../helpers/core-utils'
import { ACCEPT_HEADERS, STATIC_MAX_AGE } from '../initializers/constants' import { ACCEPT_HEADERS, STATIC_MAX_AGE } from '../initializers/constants'
import { asyncMiddleware } from '../middlewares' import { asyncMiddleware, embedCSP } from '../middlewares'
import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '../../shared/models/i18n/i18n' import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '../../shared/models/i18n/i18n'
import { ClientHtml } from '../lib/client-html' import { ClientHtml } from '../lib/client-html'
import { logger } from '../helpers/logger' import { logger } from '../helpers/logger'
import { CONFIG } from '@server/initializers/config'
const clientsRouter = express.Router() const clientsRouter = express.Router()
@ -19,8 +20,13 @@ clientsRouter.use('/videos/watch/:id', asyncMiddleware(generateWatchHtmlPage))
clientsRouter.use('/accounts/:nameWithHost', asyncMiddleware(generateAccountHtmlPage)) clientsRouter.use('/accounts/:nameWithHost', asyncMiddleware(generateAccountHtmlPage))
clientsRouter.use('/video-channels/:nameWithHost', asyncMiddleware(generateVideoChannelHtmlPage)) clientsRouter.use('/video-channels/:nameWithHost', asyncMiddleware(generateVideoChannelHtmlPage))
const embedCSPMiddleware = CONFIG.CSP.ENABLED
? embedCSP
: (req: express.Request, res: express.Response, next: express.NextFunction) => next()
clientsRouter.use( clientsRouter.use(
'/videos/embed', '/videos/embed',
embedCSPMiddleware,
(req: express.Request, res: express.Response) => { (req: express.Request, res: express.Response) => {
res.removeHeader('X-Frame-Options') res.removeHeader('X-Frame-Options')
res.sendFile(embedPath) res.sendFile(embedPath)

View File

@ -176,8 +176,8 @@ async function updateActorAvatarInstance (actor: MActorDefault, info: AvatarInfo
if (!info.name) return actor if (!info.name) return actor
if (actor.Avatar) { if (actor.Avatar) {
// Don't update the avatar if the filename did not change // Don't update the avatar if the file URL did not change
if (actor.Avatar.fileUrl === info.fileUrl) return actor if (info.fileUrl && actor.Avatar.fileUrl === info.fileUrl) return actor
try { try {
await actor.Avatar.destroy({ transaction: t }) await actor.Avatar.destroy({ transaction: t })

View File

@ -59,7 +59,9 @@ async function processFollow (byActor: MActorSignature, targetActorURL: string)
transaction: t transaction: t
}) })
if (actorFollow.state !== 'accepted' && CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL === false) { // Set the follow as accepted if the remote actor follows a channel or account
// Or if the instance automatically accepts followers
if (actorFollow.state !== 'accepted' && (isFollowingInstance === false || CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL === false)) {
actorFollow.state = 'accepted' actorFollow.state = 'accepted'
await actorFollow.save({ transaction: t }) await actorFollow.save({ transaction: t })
} }

View File

@ -136,8 +136,7 @@ import {
MVideoThumbnailBlacklist, MVideoThumbnailBlacklist,
MVideoWithAllFiles, MVideoWithAllFiles,
MVideoWithFile, MVideoWithFile,
MVideoWithRights, MVideoWithRights
MStreamingPlaylistFiles
} from '../../typings/models' } from '../../typings/models'
import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../typings/models/video/video-file' import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../typings/models/video/video-file'
import { MThumbnail } from '../../typings/models/video/thumbnail' import { MThumbnail } from '../../typings/models/video/thumbnail'
@ -437,42 +436,31 @@ export type AvailableForListIDsOptions = {
} }
if (options.followerActorId) { if (options.followerActorId) {
let localVideosReq: WhereOptions = {} let localVideosReq = ''
if (options.includeLocalVideos === true) { if (options.includeLocalVideos === true) {
localVideosReq = { remote: false } localVideosReq = ' UNION ALL SELECT "video"."id" FROM "video" WHERE remote IS FALSE'
} }
// Force actorId to be a number to avoid SQL injections // Force actorId to be a number to avoid SQL injections
const actorIdNumber = parseInt(options.followerActorId.toString(), 10) const actorIdNumber = parseInt(options.followerActorId.toString(), 10)
whereAnd.push({ whereAnd.push({
[Op.or]: [
{
id: { id: {
[Op.in]: Sequelize.literal( [Op.in]: Sequelize.literal(
'(' + '(' +
'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' + 'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' +
'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' + 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' +
'WHERE "actorFollow"."actorId" = ' + actorIdNumber + 'WHERE "actorFollow"."actorId" = ' + actorIdNumber +
')' ' UNION ALL ' +
)
}
},
{
id: {
[ Op.in ]: Sequelize.literal(
'(' +
'SELECT "video"."id" AS "id" FROM "video" ' + 'SELECT "video"."id" AS "id" FROM "video" ' +
'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' + 'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' +
'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' + 'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' +
'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' + 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' +
'WHERE "actorFollow"."actorId" = ' + actorIdNumber + 'WHERE "actorFollow"."actorId" = ' + actorIdNumber +
localVideosReq +
')' ')'
) )
} }
},
localVideosReq
]
}) })
} }

View File

@ -1,7 +1,7 @@
openapi: 3.0.0 openapi: 3.0.0
info: info:
title: PeerTube title: PeerTube
version: 2.1.0 version: 2.1.1
contact: contact:
name: PeerTube Community name: PeerTube Community
url: 'https://joinpeertube.org' url: 'https://joinpeertube.org'

View File

@ -7,7 +7,7 @@ ARG NPM_RUN_BUILD_OPTS
# Install dependencies # Install dependencies
RUN apt update \ RUN apt update \
&& apt install -y --no-install-recommends openssl ffmpeg gnupg gosu \ && apt install -y --no-install-recommends openssl ffmpeg python ca-certificates gnupg gosu \
&& gosu nobody true \ && gosu nobody true \
&& rm /var/lib/apt/lists/* -fR && rm /var/lib/apt/lists/* -fR