diff --git a/CHANGELOG.md b/CHANGELOG.md index 3149476bb..4887614a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # 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 **Since v2.0.0** diff --git a/client/package.json b/client/package.json index b9ddf7042..024e0b1d9 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "peertube-client", - "version": "2.1.0", + "version": "2.1.1", "private": true, "license": "AGPL-3.0", "author": { diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index cdcbcb528..3997ce6db 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts @@ -159,8 +159,11 @@ export class ServerService { if (!this.configObservable) { this.configObservable = this.http.get(ServerService.BASE_CONFIG_URL) .pipe( - tap(this.saveConfigLocally), - tap(() => this.configLoaded = true), + tap(config => this.saveConfigLocally(config)), + tap(config => { + this.config = config + this.configLoaded = true + }), tap(() => { if (this.configReset) { this.configReloaded.next() diff --git a/client/src/app/menu/menu.component.scss b/client/src/app/menu/menu.component.scss index 2963d4d19..b05173751 100644 --- a/client/src/app/menu/menu.component.scss +++ b/client/src/app/menu/menu.component.scss @@ -254,6 +254,10 @@ menu { @media screen and (max-width: $mobile-view) { .menu-wrapper { width: 100% !important; + + menu { + overflow-y: auto; + } } .top-menu, .footer { diff --git a/client/src/app/shared/video-playlist/video-playlist.service.ts b/client/src/app/shared/video-playlist/video-playlist.service.ts index bae6f9e04..38d915c6b 100644 --- a/client/src/app/shared/video-playlist/video-playlist.service.ts +++ b/client/src/app/shared/video-playlist/video-playlist.service.ts @@ -141,6 +141,8 @@ export class VideoPlaylistService { return this.authHttp.post<{ videoPlaylist: { id: number } }>(VideoPlaylistService.BASE_VIDEO_PLAYLIST_URL, data) .pipe( tap(res => { + if (!this.myAccountPlaylistCache) return + this.myAccountPlaylistCache.total++ this.myAccountPlaylistCache.data.push({ @@ -161,6 +163,8 @@ export class VideoPlaylistService { .pipe( map(this.restExtractor.extractDataBool), tap(() => { + if (!this.myAccountPlaylistCache) return + const playlist = this.myAccountPlaylistCache.data.find(p => p.id === videoPlaylist.id) playlist.displayName = body.displayName @@ -175,6 +179,8 @@ export class VideoPlaylistService { .pipe( map(this.restExtractor.extractDataBool), tap(() => { + if (!this.myAccountPlaylistCache) return + this.myAccountPlaylistCache.total-- this.myAccountPlaylistCache.data = this.myAccountPlaylistCache.data .filter(p => p.id !== videoPlaylist.id) diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index c91ae08b9..5213443fc 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts @@ -262,6 +262,9 @@ export class PeerTubeEmbed { private async buildDock (videoInfo: VideoDetails, configResponse: Response) { if (this.controls) { + // On webtorrent fallback, player may have been disposed + if (!this.player.player_) return + const title = this.title ? videoInfo.name : undefined const config: ServerConfig = await configResponse.json() diff --git a/package.json b/package.json index dee9840c7..49d9faf97 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "peertube", "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, "licence": "AGPL-3.0", "engines": { diff --git a/server/controllers/client.ts b/server/controllers/client.ts index dc3ff18fc..56685f102 100644 --- a/server/controllers/client.ts +++ b/server/controllers/client.ts @@ -2,10 +2,11 @@ import * as express from 'express' import { join } from 'path' import { root } from '../helpers/core-utils' 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 { ClientHtml } from '../lib/client-html' import { logger } from '../helpers/logger' +import { CONFIG } from '@server/initializers/config' const clientsRouter = express.Router() @@ -19,8 +20,13 @@ clientsRouter.use('/videos/watch/:id', asyncMiddleware(generateWatchHtmlPage)) clientsRouter.use('/accounts/:nameWithHost', asyncMiddleware(generateAccountHtmlPage)) 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( '/videos/embed', + embedCSPMiddleware, (req: express.Request, res: express.Response) => { res.removeHeader('X-Frame-Options') res.sendFile(embedPath) diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index f802658cf..0b21de0ca 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts @@ -176,8 +176,8 @@ async function updateActorAvatarInstance (actor: MActorDefault, info: AvatarInfo if (!info.name) return actor if (actor.Avatar) { - // Don't update the avatar if the filename did not change - if (actor.Avatar.fileUrl === info.fileUrl) return actor + // Don't update the avatar if the file URL did not change + if (info.fileUrl && actor.Avatar.fileUrl === info.fileUrl) return actor try { await actor.Avatar.destroy({ transaction: t }) diff --git a/server/lib/activitypub/process/process-follow.ts b/server/lib/activitypub/process/process-follow.ts index 85f22d654..db7fb8568 100644 --- a/server/lib/activitypub/process/process-follow.ts +++ b/server/lib/activitypub/process/process-follow.ts @@ -59,7 +59,9 @@ async function processFollow (byActor: MActorSignature, targetActorURL: string) 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' await actorFollow.save({ transaction: t }) } diff --git a/server/models/video/video.ts b/server/models/video/video.ts index eacffe186..a91a7663d 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -136,8 +136,7 @@ import { MVideoThumbnailBlacklist, MVideoWithAllFiles, MVideoWithFile, - MVideoWithRights, - MStreamingPlaylistFiles + MVideoWithRights } from '../../typings/models' import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../typings/models/video/video-file' import { MThumbnail } from '../../typings/models/video/thumbnail' @@ -437,42 +436,31 @@ export type AvailableForListIDsOptions = { } if (options.followerActorId) { - let localVideosReq: WhereOptions = {} + let localVideosReq = '' 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 const actorIdNumber = parseInt(options.followerActorId.toString(), 10) whereAnd.push({ - [Op.or]: [ - { - id: { - [ Op.in ]: Sequelize.literal( - '(' + - 'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' + - 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' + - 'WHERE "actorFollow"."actorId" = ' + actorIdNumber + - ')' - ) - } - }, - { - id: { - [ Op.in ]: Sequelize.literal( - '(' + - 'SELECT "video"."id" AS "id" FROM "video" ' + - 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + - 'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' + - 'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' + - 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' + - 'WHERE "actorFollow"."actorId" = ' + actorIdNumber + - ')' - ) - } - }, - localVideosReq - ] + id: { + [Op.in]: Sequelize.literal( + '(' + + 'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' + + 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' + + 'WHERE "actorFollow"."actorId" = ' + actorIdNumber + + ' UNION ALL ' + + 'SELECT "video"."id" AS "id" FROM "video" ' + + 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + + 'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' + + 'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' + + 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' + + 'WHERE "actorFollow"."actorId" = ' + actorIdNumber + + localVideosReq + + ')' + ) + } }) } diff --git a/support/doc/api/openapi.yaml b/support/doc/api/openapi.yaml index f1cfb81a4..85f1102b4 100644 --- a/support/doc/api/openapi.yaml +++ b/support/doc/api/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.0.0 info: title: PeerTube - version: 2.1.0 + version: 2.1.1 contact: name: PeerTube Community url: 'https://joinpeertube.org' diff --git a/support/docker/production/Dockerfile.buster b/support/docker/production/Dockerfile.buster index 515aeb5f1..414bf9aac 100644 --- a/support/docker/production/Dockerfile.buster +++ b/support/docker/production/Dockerfile.buster @@ -7,7 +7,7 @@ ARG NPM_RUN_BUILD_OPTS # Install dependencies 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 \ && rm /var/lib/apt/lists/* -fR