Add ability for admins to set default p2p policy
This commit is contained in:
parent
c77fdc605b
commit
a9bfa85d2c
59 changed files with 789 additions and 415 deletions
21
client/e2e/src/po/anonymous-settings.po.ts
Normal file
21
client/e2e/src/po/anonymous-settings.po.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { getCheckbox } from '../utils'
|
||||
|
||||
export class AnonymousSettingsPage {
|
||||
|
||||
async openSettings () {
|
||||
const link = await $$('.menu-link').filter(async i => {
|
||||
return await i.getText() === 'My settings'
|
||||
}).then(links => links[0])
|
||||
|
||||
await link.click()
|
||||
|
||||
await $('my-user-video-settings').waitForDisplayed()
|
||||
}
|
||||
|
||||
async clickOnP2PCheckbox () {
|
||||
const p2p = getCheckbox('p2pEnabled')
|
||||
await p2p.waitForClickable()
|
||||
|
||||
await p2p.click()
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { go } from '../utils'
|
||||
import { getCheckbox, go } from '../utils'
|
||||
|
||||
export class MyAccountPage {
|
||||
|
||||
|
@ -27,6 +27,21 @@ export class MyAccountPage {
|
|||
await nsfw.scrollIntoView(false) // Avoid issues with fixed header on firefox
|
||||
await nsfw.selectByAttribute('value', newValue)
|
||||
|
||||
await this.submitVideoSettings()
|
||||
}
|
||||
|
||||
async clickOnP2PCheckbox () {
|
||||
const p2p = getCheckbox('p2pEnabled')
|
||||
|
||||
await p2p.waitForClickable()
|
||||
await p2p.scrollIntoView(false) // Avoid issues with fixed header on firefox
|
||||
|
||||
await p2p.click()
|
||||
|
||||
await this.submitVideoSettings()
|
||||
}
|
||||
|
||||
private async submitVideoSettings () {
|
||||
const submit = $('my-user-video-settings input[type=submit]')
|
||||
await submit.scrollIntoView(false)
|
||||
await submit.click()
|
|
@ -1,5 +1,5 @@
|
|||
import { join } from 'path'
|
||||
import { clickOnCheckbox } from '../utils'
|
||||
import { getCheckbox, selectCustomSelect } from '../utils'
|
||||
|
||||
export class VideoUploadPage {
|
||||
async navigateTo () {
|
||||
|
@ -32,7 +32,7 @@ export class VideoUploadPage {
|
|||
}
|
||||
|
||||
setAsNSFW () {
|
||||
return clickOnCheckbox('nsfw')
|
||||
return getCheckbox('nsfw').click()
|
||||
}
|
||||
|
||||
async validSecondUploadStep (videoName: string) {
|
||||
|
@ -47,6 +47,10 @@ export class VideoUploadPage {
|
|||
})
|
||||
}
|
||||
|
||||
setAsPublic () {
|
||||
return selectCustomSelect('privacy', 'Public')
|
||||
}
|
||||
|
||||
private getSecondStepSubmitButton () {
|
||||
return $('.submit-container my-button')
|
||||
}
|
||||
|
|
|
@ -39,12 +39,23 @@ export class VideoWatchPage {
|
|||
return $('my-video-comment-add').isExisting()
|
||||
}
|
||||
|
||||
isPrivacyWarningDisplayed () {
|
||||
return $('my-privacy-concerns').isDisplayed()
|
||||
}
|
||||
|
||||
async goOnAssociatedEmbed () {
|
||||
let url = await browser.getUrl()
|
||||
url = url.replace('/w/', '/videos/embed/')
|
||||
url = url.replace(':3333', ':9001')
|
||||
|
||||
return go(url)
|
||||
await go(url)
|
||||
await $('.vjs-big-play-button').waitForDisplayed()
|
||||
}
|
||||
|
||||
async isEmbedWarningDisplayed () {
|
||||
const text = await $('.vjs-dock-description').getText()
|
||||
|
||||
return !!text.trim()
|
||||
}
|
||||
|
||||
goOnP2PMediaLoaderEmbed () {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { LoginPage } from '../po/login.po'
|
||||
import { MyAccountPage } from '../po/my-account'
|
||||
import { MyAccountPage } from '../po/my-account.po'
|
||||
import { PlayerPage } from '../po/player.po'
|
||||
import { VideoListPage } from '../po/video-list.po'
|
||||
import { VideoUpdatePage } from '../po/video-update.po'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { LoginPage } from '../po/login.po'
|
||||
import { VideoUploadPage } from '../po/video-upload.po'
|
||||
import { VideoWatchPage } from '../po/video-watch.po'
|
||||
import { isMobileDevice, isSafari, waitServerUp } from '../utils'
|
||||
import { go, isMobileDevice, isSafari, waitServerUp } from '../utils'
|
||||
|
||||
describe('Custom server defaults', () => {
|
||||
let videoUploadPage: VideoUploadPage
|
||||
|
@ -10,9 +10,7 @@ describe('Custom server defaults', () => {
|
|||
|
||||
before(async () => {
|
||||
await waitServerUp()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
loginPage = new LoginPage()
|
||||
videoUploadPage = new VideoUploadPage()
|
||||
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
|
||||
|
@ -20,18 +18,69 @@ describe('Custom server defaults', () => {
|
|||
await browser.maximizeWindow()
|
||||
})
|
||||
|
||||
it('Should upload a video with custom default values', async function () {
|
||||
await loginPage.loginAsRootUser()
|
||||
await videoUploadPage.navigateTo()
|
||||
await videoUploadPage.uploadVideo()
|
||||
await videoUploadPage.validSecondUploadStep('video')
|
||||
describe('Publish default values', function () {
|
||||
before(async function () {
|
||||
await loginPage.loginAsRootUser()
|
||||
})
|
||||
|
||||
await videoWatchPage.waitWatchVideoName('video')
|
||||
it('Should upload a video with custom default values', async function () {
|
||||
await videoUploadPage.navigateTo()
|
||||
await videoUploadPage.uploadVideo()
|
||||
await videoUploadPage.validSecondUploadStep('video')
|
||||
|
||||
expect(await videoWatchPage.getPrivacy()).toBe('Internal')
|
||||
expect(await videoWatchPage.getLicence()).toBe('Attribution - Non Commercial')
|
||||
expect(await videoWatchPage.isDownloadEnabled()).toBeFalsy()
|
||||
expect(await videoWatchPage.areCommentsEnabled()).toBeFalsy()
|
||||
await videoWatchPage.waitWatchVideoName('video')
|
||||
|
||||
expect(await videoWatchPage.getPrivacy()).toBe('Internal')
|
||||
expect(await videoWatchPage.getLicence()).toBe('Attribution - Non Commercial')
|
||||
expect(await videoWatchPage.isDownloadEnabled()).toBeFalsy()
|
||||
expect(await videoWatchPage.areCommentsEnabled()).toBeFalsy()
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await loginPage.logout()
|
||||
})
|
||||
})
|
||||
|
||||
describe('P2P', function () {
|
||||
let videoUrl: string
|
||||
|
||||
async function goOnVideoWatchPage () {
|
||||
await go(videoUrl)
|
||||
await videoWatchPage.waitWatchVideoName('video')
|
||||
}
|
||||
|
||||
async function checkP2P (enabled: boolean) {
|
||||
await goOnVideoWatchPage()
|
||||
expect(await videoWatchPage.isPrivacyWarningDisplayed()).toEqual(enabled)
|
||||
|
||||
await videoWatchPage.goOnAssociatedEmbed()
|
||||
expect(await videoWatchPage.isEmbedWarningDisplayed()).toEqual(enabled)
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
await loginPage.loginAsRootUser()
|
||||
await videoUploadPage.navigateTo()
|
||||
await videoUploadPage.uploadVideo()
|
||||
await videoUploadPage.setAsPublic()
|
||||
await videoUploadPage.validSecondUploadStep('video')
|
||||
|
||||
await videoWatchPage.waitWatchVideoName('video')
|
||||
|
||||
videoUrl = await browser.getUrl()
|
||||
})
|
||||
|
||||
beforeEach(async function () {
|
||||
await goOnVideoWatchPage()
|
||||
})
|
||||
|
||||
it('Should have P2P disabled for a logged in user', async function () {
|
||||
await checkP2P(false)
|
||||
})
|
||||
|
||||
it('Should have P2P disabled for anonymous users', async function () {
|
||||
await loginPage.logout()
|
||||
|
||||
await checkP2P(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
82
client/e2e/src/suites-local/user-settings.e2e-spec.ts
Normal file
82
client/e2e/src/suites-local/user-settings.e2e-spec.ts
Normal file
|
@ -0,0 +1,82 @@
|
|||
import { AnonymousSettingsPage } from '../po/anonymous-settings.po'
|
||||
import { LoginPage } from '../po/login.po'
|
||||
import { MyAccountPage } from '../po/my-account.po'
|
||||
import { VideoUploadPage } from '../po/video-upload.po'
|
||||
import { VideoWatchPage } from '../po/video-watch.po'
|
||||
import { go, isMobileDevice, isSafari, waitServerUp } from '../utils'
|
||||
|
||||
describe('User settings', () => {
|
||||
let videoUploadPage: VideoUploadPage
|
||||
let loginPage: LoginPage
|
||||
let videoWatchPage: VideoWatchPage
|
||||
let myAccountPage: MyAccountPage
|
||||
let anonymousSettingsPage: AnonymousSettingsPage
|
||||
|
||||
before(async () => {
|
||||
await waitServerUp()
|
||||
|
||||
loginPage = new LoginPage()
|
||||
videoUploadPage = new VideoUploadPage()
|
||||
videoWatchPage = new VideoWatchPage(isMobileDevice(), isSafari())
|
||||
myAccountPage = new MyAccountPage()
|
||||
anonymousSettingsPage = new AnonymousSettingsPage()
|
||||
|
||||
await browser.maximizeWindow()
|
||||
})
|
||||
|
||||
describe('P2P', function () {
|
||||
let videoUrl: string
|
||||
|
||||
async function goOnVideoWatchPage () {
|
||||
await go(videoUrl)
|
||||
await videoWatchPage.waitWatchVideoName('video')
|
||||
}
|
||||
|
||||
async function checkP2P (enabled: boolean) {
|
||||
await goOnVideoWatchPage()
|
||||
expect(await videoWatchPage.isPrivacyWarningDisplayed()).toEqual(enabled)
|
||||
|
||||
await videoWatchPage.goOnAssociatedEmbed()
|
||||
expect(await videoWatchPage.isEmbedWarningDisplayed()).toEqual(enabled)
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
await loginPage.loginAsRootUser()
|
||||
await videoUploadPage.navigateTo()
|
||||
await videoUploadPage.uploadVideo()
|
||||
await videoUploadPage.validSecondUploadStep('video')
|
||||
|
||||
await videoWatchPage.waitWatchVideoName('video')
|
||||
|
||||
videoUrl = await browser.getUrl()
|
||||
})
|
||||
|
||||
beforeEach(async function () {
|
||||
await goOnVideoWatchPage()
|
||||
})
|
||||
|
||||
it('Should have P2P enabled for a logged in user', async function () {
|
||||
await checkP2P(true)
|
||||
})
|
||||
|
||||
it('Should disable P2P for a logged in user', async function () {
|
||||
await myAccountPage.navigateToMySettings()
|
||||
await myAccountPage.clickOnP2PCheckbox()
|
||||
|
||||
await checkP2P(false)
|
||||
})
|
||||
|
||||
it('Should have P2P enabled for anonymous users', async function () {
|
||||
await loginPage.logout()
|
||||
|
||||
await checkP2P(true)
|
||||
})
|
||||
|
||||
it('Should disable P2P for an anonymous user', async function () {
|
||||
await anonymousSettingsPage.openSettings()
|
||||
await anonymousSettingsPage.clickOnP2PCheckbox()
|
||||
|
||||
await checkP2P(false)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,6 +1,6 @@
|
|||
import { AdminConfigPage } from '../po/admin-config.po'
|
||||
import { LoginPage } from '../po/login.po'
|
||||
import { MyAccountPage } from '../po/my-account'
|
||||
import { MyAccountPage } from '../po/my-account.po'
|
||||
import { VideoListPage } from '../po/video-list.po'
|
||||
import { VideoSearchPage } from '../po/video-search.po'
|
||||
import { VideoUploadPage } from '../po/video-upload.po'
|
||||
|
|
|
@ -1,7 +1,22 @@
|
|||
function clickOnCheckbox (name: string) {
|
||||
return $(`my-peertube-checkbox[inputname=${name}] label`).click()
|
||||
function getCheckbox (name: string) {
|
||||
return $(`my-peertube-checkbox[inputname=${name}] label`)
|
||||
}
|
||||
|
||||
async function selectCustomSelect (id: string, valueLabel: string) {
|
||||
await $(`[formcontrolname=${id}] .ng-arrow-wrapper`).click()
|
||||
|
||||
const option = await $$(`[formcontrolname=${id}] .ng-option`).filter(async o => {
|
||||
const text = await o.getText()
|
||||
|
||||
return text.trimStart().startsWith(valueLabel)
|
||||
}).then(options => options[0])
|
||||
|
||||
await option.waitForDisplayed()
|
||||
|
||||
return option.click()
|
||||
}
|
||||
|
||||
export {
|
||||
clickOnCheckbox
|
||||
getCheckbox,
|
||||
selectCustomSelect
|
||||
}
|
||||
|
|
|
@ -55,6 +55,9 @@ function buildConfig (suiteFile: string = undefined) {
|
|||
comments_enabled: false,
|
||||
privacy: 4,
|
||||
licence: 4
|
||||
},
|
||||
p2p: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { Component, Input, OnInit } from '@angular/core'
|
||||
import { ServerService } from '@app/core'
|
||||
import { ServerService, User, UserService } from '@app/core'
|
||||
import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
|
||||
import { HTMLServerConfig, Video } from '@shared/models'
|
||||
import { getStoredP2PEnabled } from '../../../../../assets/player/peertube-player-local-storage'
|
||||
import { isWebRTCDisabled } from '../../../../../assets/player/utils'
|
||||
import { isP2PEnabled } from '../../../../../assets/player/utils'
|
||||
|
||||
@Component({
|
||||
selector: 'my-privacy-concerns',
|
||||
|
@ -15,33 +14,32 @@ export class PrivacyConcernsComponent implements OnInit {
|
|||
|
||||
@Input() video: Video
|
||||
|
||||
display = true
|
||||
display = false
|
||||
|
||||
private serverConfig: HTMLServerConfig
|
||||
|
||||
constructor (
|
||||
private serverService: ServerService
|
||||
private serverService: ServerService,
|
||||
private userService: UserService
|
||||
) { }
|
||||
|
||||
ngOnInit () {
|
||||
this.serverConfig = this.serverService.getHTMLConfig()
|
||||
|
||||
if (isWebRTCDisabled() || this.isTrackerDisabled() || this.isP2PDisabled() || this.alreadyAccepted()) {
|
||||
this.display = false
|
||||
}
|
||||
this.userService.getAnonymousOrLoggedUser()
|
||||
.subscribe(user => this.updateDisplay(user))
|
||||
}
|
||||
|
||||
acceptedPrivacyConcern () {
|
||||
peertubeLocalStorage.setItem(PrivacyConcernsComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY, 'true')
|
||||
|
||||
this.display = false
|
||||
}
|
||||
|
||||
private isTrackerDisabled () {
|
||||
return this.video.isLocal && this.serverConfig.tracker.enabled === false
|
||||
}
|
||||
|
||||
private isP2PDisabled () {
|
||||
return getStoredP2PEnabled() === false
|
||||
private updateDisplay (user: User) {
|
||||
if (isP2PEnabled(this.video, this.serverConfig, user.p2pEnabled) && !this.alreadyAccepted()) {
|
||||
this.display = true
|
||||
}
|
||||
}
|
||||
|
||||
private alreadyAccepted () {
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
import { Component, EventEmitter, Input, Output } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
import {
|
||||
AuthService,
|
||||
ComponentPagination,
|
||||
HooksService,
|
||||
LocalStorageService,
|
||||
Notifier,
|
||||
SessionStorageService,
|
||||
UserService
|
||||
} from '@app/core'
|
||||
import { AuthService, ComponentPagination, HooksService, Notifier, SessionStorageService, UserService } from '@app/core'
|
||||
import { VideoPlaylist, VideoPlaylistElement, VideoPlaylistService } from '@app/shared/shared-video-playlist'
|
||||
import { peertubeLocalStorage, peertubeSessionStorage } from '@root-helpers/peertube-web-storage'
|
||||
import { peertubeSessionStorage } from '@root-helpers/peertube-web-storage'
|
||||
import { getBoolOrDefault } from '@root-helpers/local-storage-utils'
|
||||
import { VideoPlaylistPrivacy } from '@shared/models'
|
||||
|
||||
@Component({
|
||||
|
@ -19,8 +12,7 @@ import { VideoPlaylistPrivacy } from '@shared/models'
|
|||
styleUrls: [ './video-watch-playlist.component.scss' ]
|
||||
})
|
||||
export class VideoWatchPlaylistComponent {
|
||||
static LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST = 'auto_play_video_playlist'
|
||||
static SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST = 'loop_playlist'
|
||||
static SESSION_STORAGE_LOOP_PLAYLIST = 'loop_playlist'
|
||||
|
||||
@Input() playlist: VideoPlaylist
|
||||
|
||||
|
@ -47,19 +39,15 @@ export class VideoWatchPlaylistComponent {
|
|||
private auth: AuthService,
|
||||
private notifier: Notifier,
|
||||
private videoPlaylist: VideoPlaylistService,
|
||||
private localStorageService: LocalStorageService,
|
||||
private sessionStorage: SessionStorageService,
|
||||
private router: Router
|
||||
) {
|
||||
// defaults to true
|
||||
this.autoPlayNextVideoPlaylist = this.auth.isLoggedIn()
|
||||
? this.auth.getUser().autoPlayNextVideoPlaylist
|
||||
: this.localStorageService.getItem(VideoWatchPlaylistComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) !== 'false'
|
||||
this.userService.getAnonymousOrLoggedUser()
|
||||
.subscribe(user => this.autoPlayNextVideoPlaylist = user.autoPlayNextVideoPlaylist)
|
||||
|
||||
this.setAutoPlayNextVideoPlaylistSwitchText()
|
||||
|
||||
// defaults to false
|
||||
this.loopPlaylist = this.sessionStorage.getItem(VideoWatchPlaylistComponent.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) === 'true'
|
||||
this.loopPlaylist = getBoolOrDefault(this.sessionStorage.getItem(VideoWatchPlaylistComponent.SESSION_STORAGE_LOOP_PLAYLIST), false)
|
||||
this.setLoopPlaylistSwitchText()
|
||||
}
|
||||
|
||||
|
@ -201,16 +189,9 @@ export class VideoWatchPlaylistComponent {
|
|||
this.autoPlayNextVideoPlaylist = !this.autoPlayNextVideoPlaylist
|
||||
this.setAutoPlayNextVideoPlaylistSwitchText()
|
||||
|
||||
peertubeLocalStorage.setItem(
|
||||
VideoWatchPlaylistComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST,
|
||||
this.autoPlayNextVideoPlaylist.toString()
|
||||
)
|
||||
const details = { autoPlayNextVideoPlaylist: this.autoPlayNextVideoPlaylist }
|
||||
|
||||
if (this.auth.isLoggedIn()) {
|
||||
const details = {
|
||||
autoPlayNextVideoPlaylist: this.autoPlayNextVideoPlaylist
|
||||
}
|
||||
|
||||
this.userService.updateMyProfile(details)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
|
@ -219,6 +200,8 @@ export class VideoWatchPlaylistComponent {
|
|||
|
||||
error: err => this.notifier.error(err.message)
|
||||
})
|
||||
} else {
|
||||
this.userService.updateMyAnonymousProfile(details)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -227,7 +210,7 @@ export class VideoWatchPlaylistComponent {
|
|||
this.setLoopPlaylistSwitchText()
|
||||
|
||||
peertubeSessionStorage.setItem(
|
||||
VideoWatchPlaylistComponent.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST,
|
||||
VideoWatchPlaylistComponent.SESSION_STORAGE_LOOP_PLAYLIST,
|
||||
this.loopPlaylist.toString()
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { Observable } from 'rxjs'
|
||||
import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'
|
||||
import { AuthService, Notifier, SessionStorageService, User, UserService } from '@app/core'
|
||||
import { AuthService, Notifier, User, UserService } from '@app/core'
|
||||
import { Video } from '@app/shared/shared-main'
|
||||
import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature'
|
||||
import { VideoPlaylist } from '@app/shared/shared-video-playlist'
|
||||
import { UserLocalStorageKeys } from '@root-helpers/users'
|
||||
import { RecommendationInfo } from './recommendation-info.model'
|
||||
import { RecommendedVideosStore } from './recommended-videos.store'
|
||||
|
||||
|
@ -39,24 +38,14 @@ export class RecommendedVideosComponent implements OnInit, OnChanges {
|
|||
private userService: UserService,
|
||||
private authService: AuthService,
|
||||
private notifier: Notifier,
|
||||
private store: RecommendedVideosStore,
|
||||
private sessionStorageService: SessionStorageService
|
||||
private store: RecommendedVideosStore
|
||||
) {
|
||||
this.videos$ = this.store.recommendations$
|
||||
this.hasVideos$ = this.store.hasRecommendations$
|
||||
this.videos$.subscribe(videos => this.gotRecommendations.emit(videos))
|
||||
|
||||
if (this.authService.isLoggedIn()) {
|
||||
this.autoPlayNextVideo = this.authService.getUser().autoPlayNextVideo
|
||||
} else {
|
||||
this.autoPlayNextVideo = this.sessionStorageService.getItem(UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true'
|
||||
|
||||
this.sessionStorageService.watch([ UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO ]).subscribe(
|
||||
() => {
|
||||
this.autoPlayNextVideo = this.sessionStorageService.getItem(UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true'
|
||||
}
|
||||
)
|
||||
}
|
||||
this.userService.getAnonymousOrLoggedUser()
|
||||
.subscribe(user => this.autoPlayNextVideo = user.autoPlayNextVideo)
|
||||
|
||||
this.autoPlayNextVideoTooltip = $localize`When active, the next video is automatically played after the current one.`
|
||||
}
|
||||
|
@ -77,13 +66,9 @@ export class RecommendedVideosComponent implements OnInit, OnChanges {
|
|||
}
|
||||
|
||||
switchAutoPlayNextVideo () {
|
||||
this.sessionStorageService.setItem(UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO, this.autoPlayNextVideo.toString())
|
||||
const details = { autoPlayNextVideo: this.autoPlayNextVideo }
|
||||
|
||||
if (this.authService.isLoggedIn()) {
|
||||
const details = {
|
||||
autoPlayNextVideo: this.autoPlayNextVideo
|
||||
}
|
||||
|
||||
this.userService.updateMyProfile(details)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
|
@ -92,6 +77,8 @@ export class RecommendedVideosComponent implements OnInit, OnChanges {
|
|||
|
||||
error: err => this.notifier.error(err.message)
|
||||
})
|
||||
} else {
|
||||
this.userService.updateMyAnonymousProfile(details)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Hotkey, HotkeysService } from 'angular2-hotkeys'
|
||||
import { forkJoin, Subscription } from 'rxjs'
|
||||
import { isP2PEnabled } from 'src/assets/player/utils'
|
||||
import { PlatformLocation } from '@angular/common'
|
||||
import { Component, ElementRef, Inject, LOCALE_ID, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core'
|
||||
import { ActivatedRoute, Router } from '@angular/router'
|
||||
|
@ -14,6 +15,7 @@ import {
|
|||
RestExtractor,
|
||||
ScreenService,
|
||||
ServerService,
|
||||
User,
|
||||
UserService
|
||||
} from '@app/core'
|
||||
import { HooksService } from '@app/core/plugins/hooks.service'
|
||||
|
@ -237,31 +239,34 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
'filter:api.video-watch.video.get.result'
|
||||
)
|
||||
|
||||
forkJoin([ videoObs, this.videoCaptionService.listCaptions(videoId) ])
|
||||
.subscribe({
|
||||
next: ([ video, captionsResult ]) => {
|
||||
const queryParams = this.route.snapshot.queryParams
|
||||
forkJoin([
|
||||
videoObs,
|
||||
this.videoCaptionService.listCaptions(videoId),
|
||||
this.userService.getAnonymousOrLoggedUser()
|
||||
]).subscribe({
|
||||
next: ([ video, captionsResult, loggedInOrAnonymousUser ]) => {
|
||||
const queryParams = this.route.snapshot.queryParams
|
||||
|
||||
const urlOptions = {
|
||||
resume: queryParams.resume,
|
||||
const urlOptions = {
|
||||
resume: queryParams.resume,
|
||||
|
||||
startTime: queryParams.start,
|
||||
stopTime: queryParams.stop,
|
||||
startTime: queryParams.start,
|
||||
stopTime: queryParams.stop,
|
||||
|
||||
muted: queryParams.muted,
|
||||
loop: queryParams.loop,
|
||||
subtitle: queryParams.subtitle,
|
||||
muted: queryParams.muted,
|
||||
loop: queryParams.loop,
|
||||
subtitle: queryParams.subtitle,
|
||||
|
||||
playerMode: queryParams.mode,
|
||||
peertubeLink: false
|
||||
}
|
||||
playerMode: queryParams.mode,
|
||||
peertubeLink: false
|
||||
}
|
||||
|
||||
this.onVideoFetched(video, captionsResult.data, urlOptions)
|
||||
.catch(err => this.handleGlobalError(err))
|
||||
},
|
||||
this.onVideoFetched({ video, videoCaptions: captionsResult.data, loggedInOrAnonymousUser, urlOptions })
|
||||
.catch(err => this.handleGlobalError(err))
|
||||
},
|
||||
|
||||
error: err => this.handleRequestError(err)
|
||||
})
|
||||
error: err => this.handleRequestError(err)
|
||||
})
|
||||
}
|
||||
|
||||
private loadPlaylist (playlistId: string) {
|
||||
|
@ -323,11 +328,14 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
this.notifier.error(errorMessage)
|
||||
}
|
||||
|
||||
private async onVideoFetched (
|
||||
video: VideoDetails,
|
||||
videoCaptions: VideoCaption[],
|
||||
private async onVideoFetched (options: {
|
||||
video: VideoDetails
|
||||
videoCaptions: VideoCaption[]
|
||||
urlOptions: URLOptions
|
||||
) {
|
||||
loggedInOrAnonymousUser: User
|
||||
}) {
|
||||
const { video, videoCaptions, urlOptions, loggedInOrAnonymousUser } = options
|
||||
|
||||
this.subscribeToLiveEventsIfNeeded(this.video, video)
|
||||
|
||||
this.video = video
|
||||
|
@ -346,7 +354,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
if (res === false) return this.location.back()
|
||||
}
|
||||
|
||||
this.buildPlayer(urlOptions)
|
||||
this.buildPlayer(urlOptions, loggedInOrAnonymousUser)
|
||||
.catch(err => console.error('Cannot build the player', err))
|
||||
|
||||
this.setOpenGraphTags()
|
||||
|
@ -359,7 +367,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
this.hooks.runAction('action:video-watch.video.loaded', 'video-watch', hookOptions)
|
||||
}
|
||||
|
||||
private async buildPlayer (urlOptions: URLOptions) {
|
||||
private async buildPlayer (urlOptions: URLOptions, loggedInOrAnonymousUser: User) {
|
||||
// Flush old player if needed
|
||||
this.flushPlayer()
|
||||
|
||||
|
@ -380,6 +388,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
video: this.video,
|
||||
videoCaptions: this.videoCaptions,
|
||||
urlOptions,
|
||||
loggedInOrAnonymousUser,
|
||||
user: this.user
|
||||
}
|
||||
const { playerMode, playerOptions } = await this.hooks.wrapFun(
|
||||
|
@ -517,9 +526,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
video: VideoDetails
|
||||
videoCaptions: VideoCaption[]
|
||||
urlOptions: CustomizationOptions & { playerMode: PlayerMode }
|
||||
loggedInOrAnonymousUser: User
|
||||
user?: AuthUser
|
||||
}) {
|
||||
const { video, videoCaptions, urlOptions, user } = params
|
||||
const { video, videoCaptions, urlOptions, loggedInOrAnonymousUser, user } = params
|
||||
|
||||
const getStartTime = () => {
|
||||
const byUrl = urlOptions.startTime !== undefined
|
||||
|
@ -547,6 +557,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
|||
const options: PeertubePlayerManagerOptions = {
|
||||
common: {
|
||||
autoplay: this.isAutoplay(),
|
||||
p2pEnabled: isP2PEnabled(video, this.serverConfig, loggedInOrAnonymousUser.p2pEnabled),
|
||||
|
||||
nextVideo: () => this.playNextVideoInAngularZone(),
|
||||
|
||||
playerElement: this.playerElement,
|
||||
|
|
|
@ -14,7 +14,8 @@ import {
|
|||
ScrollService,
|
||||
ServerService,
|
||||
ThemeService,
|
||||
User
|
||||
User,
|
||||
UserLocalStorageService
|
||||
} from '@app/core'
|
||||
import { HooksService } from '@app/core/plugins/hooks.service'
|
||||
import { PluginService } from '@app/core/plugins/plugin.service'
|
||||
|
@ -70,6 +71,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||
private ngbConfig: NgbConfig,
|
||||
private loadingBar: LoadingBarService,
|
||||
private scrollService: ScrollService,
|
||||
private userLocalStorage: UserLocalStorageService,
|
||||
public menu: MenuService
|
||||
) {
|
||||
this.ngbConfig.animation = false
|
||||
|
@ -86,6 +88,8 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||
ngOnInit () {
|
||||
document.getElementById('incompatible-browser').className += ' browser-ok'
|
||||
|
||||
this.loadUser()
|
||||
|
||||
this.serverConfig = this.serverService.getHTMLConfig()
|
||||
|
||||
this.hooks.runAction('action:application.init', 'common')
|
||||
|
@ -300,4 +304,15 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||
}, undefined, $localize`Go to the videos upload page`)
|
||||
])
|
||||
}
|
||||
|
||||
private loadUser () {
|
||||
const tokens = this.userLocalStorage.getTokens()
|
||||
if (!tokens) return
|
||||
|
||||
const user = this.userLocalStorage.getLoggedInUser()
|
||||
if (!user) return
|
||||
|
||||
// Initialize user
|
||||
this.authService.buildAuthUser(user, tokens)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
import { Observable, of } from 'rxjs'
|
||||
import { map } from 'rxjs/operators'
|
||||
import { User } from '@app/core/users/user.model'
|
||||
import {
|
||||
flushUserInfoFromLocalStorage,
|
||||
getUserInfoFromLocalStorage,
|
||||
saveUserInfoIntoLocalStorage,
|
||||
TokenOptions,
|
||||
Tokens
|
||||
} from '@root-helpers/users'
|
||||
import { UserTokens } from '@root-helpers/users'
|
||||
import { hasUserRight } from '@shared/core-utils/users'
|
||||
import {
|
||||
MyUser as ServerMyUserModel,
|
||||
|
@ -19,31 +13,15 @@ import {
|
|||
} from '@shared/models'
|
||||
|
||||
export class AuthUser extends User implements ServerMyUserModel {
|
||||
tokens: Tokens
|
||||
tokens: UserTokens
|
||||
specialPlaylists: MyUserSpecialPlaylist[]
|
||||
|
||||
canSeeVideosLink = true
|
||||
|
||||
static load () {
|
||||
const tokens = Tokens.load()
|
||||
if (!tokens) return null
|
||||
|
||||
const userInfo = getUserInfoFromLocalStorage()
|
||||
if (!userInfo) return null
|
||||
|
||||
return new AuthUser(userInfo, tokens)
|
||||
}
|
||||
|
||||
static flush () {
|
||||
flushUserInfoFromLocalStorage()
|
||||
|
||||
Tokens.flush()
|
||||
}
|
||||
|
||||
constructor (userHash: Partial<ServerMyUserModel>, hashTokens: TokenOptions) {
|
||||
constructor (userHash: Partial<ServerMyUserModel>, hashTokens: Partial<UserTokens>) {
|
||||
super(userHash)
|
||||
|
||||
this.tokens = new Tokens(hashTokens)
|
||||
this.tokens = new UserTokens(hashTokens)
|
||||
this.specialPlaylists = userHash.specialPlaylists
|
||||
}
|
||||
|
||||
|
@ -77,20 +55,6 @@ export class AuthUser extends User implements ServerMyUserModel {
|
|||
return user.role === UserRole.USER
|
||||
}
|
||||
|
||||
save () {
|
||||
saveUserInfoIntoLocalStorage({
|
||||
id: this.id,
|
||||
username: this.username,
|
||||
email: this.email,
|
||||
role: this.role,
|
||||
nsfwPolicy: this.nsfwPolicy,
|
||||
webTorrentEnabled: this.webTorrentEnabled,
|
||||
autoPlayVideo: this.autoPlayVideo
|
||||
})
|
||||
|
||||
this.tokens.save()
|
||||
}
|
||||
|
||||
computeCanSeeVideosLink (quotaObservable: Observable<UserVideoQuota>): Observable<boolean> {
|
||||
if (!this.isUploadDisabled()) {
|
||||
this.canSeeVideosLink = true
|
||||
|
|
|
@ -5,7 +5,7 @@ import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'
|
|||
import { Injectable } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
import { Notifier } from '@app/core/notification/notifier.service'
|
||||
import { objectToUrlEncoded, peertubeLocalStorage } from '@root-helpers/index'
|
||||
import { objectToUrlEncoded, peertubeLocalStorage, UserTokens } from '@root-helpers/index'
|
||||
import { HttpStatusCode, MyUser as UserServerModel, OAuthClientLocal, User, UserLogin, UserRefreshToken } from '@shared/models'
|
||||
import { environment } from '../../../environments/environment'
|
||||
import { RestExtractor } from '../rest/rest-extractor.service'
|
||||
|
@ -34,6 +34,7 @@ export class AuthService {
|
|||
|
||||
loginChangedSource: Observable<AuthStatus>
|
||||
userInformationLoaded = new ReplaySubject<boolean>(1)
|
||||
tokensRefreshed = new ReplaySubject<void>(1)
|
||||
hotkeys: Hotkey[]
|
||||
|
||||
private clientId: string = peertubeLocalStorage.getItem(AuthService.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_ID)
|
||||
|
@ -52,9 +53,6 @@ export class AuthService {
|
|||
this.loginChanged = new Subject<AuthStatus>()
|
||||
this.loginChangedSource = this.loginChanged.asObservable()
|
||||
|
||||
// Return null if there is nothing to load
|
||||
this.user = AuthUser.load()
|
||||
|
||||
// Set HotKeys
|
||||
this.hotkeys = [
|
||||
new Hotkey('m s', (event: KeyboardEvent): boolean => {
|
||||
|
@ -76,6 +74,10 @@ export class AuthService {
|
|||
]
|
||||
}
|
||||
|
||||
buildAuthUser (userInfo: Partial<User>, tokens: UserTokens) {
|
||||
this.user = new AuthUser(userInfo, tokens)
|
||||
}
|
||||
|
||||
loadClientCredentials () {
|
||||
// Fetch the client_id/client_secret
|
||||
this.http.get<OAuthClientLocal>(AuthService.BASE_CLIENT_URL)
|
||||
|
@ -180,8 +182,6 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular
|
|||
|
||||
this.user = null
|
||||
|
||||
AuthUser.flush()
|
||||
|
||||
this.setStatus(AuthStatus.LoggedOut)
|
||||
|
||||
this.hotkeysService.remove(this.hotkeys)
|
||||
|
@ -239,7 +239,6 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular
|
|||
.subscribe({
|
||||
next: res => {
|
||||
this.user.patch(res)
|
||||
this.user.save()
|
||||
|
||||
this.userInformationLoaded.next(true)
|
||||
}
|
||||
|
@ -262,7 +261,6 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular
|
|||
}
|
||||
|
||||
this.user = new AuthUser(obj, hashTokens)
|
||||
this.user.save()
|
||||
|
||||
this.setStatus(AuthStatus.LoggedIn)
|
||||
this.userInformationLoaded.next(true)
|
||||
|
@ -272,7 +270,7 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular
|
|||
|
||||
private handleRefreshToken (obj: UserRefreshToken) {
|
||||
this.user.refreshTokens(obj.access_token, obj.refresh_token)
|
||||
this.user.save()
|
||||
this.tokensRefreshed.next()
|
||||
}
|
||||
|
||||
private setStatus (status: AuthStatus) {
|
||||
|
|
|
@ -30,7 +30,7 @@ import { ServerConfigResolver } from './routing/server-config-resolver.service'
|
|||
import { ScopedTokensService } from './scoped-tokens'
|
||||
import { ServerService } from './server'
|
||||
import { ThemeService } from './theme'
|
||||
import { UserService } from './users'
|
||||
import { UserLocalStorageService, UserService } from './users'
|
||||
import { LocalStorageService, ScreenService, SessionStorageService } from './wrappers'
|
||||
|
||||
@NgModule({
|
||||
|
@ -79,6 +79,7 @@ import { LocalStorageService, ScreenService, SessionStorageService } from './wra
|
|||
RestService,
|
||||
|
||||
UserService,
|
||||
UserLocalStorageService,
|
||||
|
||||
ScreenService,
|
||||
LocalStorageService,
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
export * from './user-local-storage.service'
|
||||
export * from './user.model'
|
||||
export * from './user.service'
|
||||
|
|
186
client/src/app/core/users/user-local-storage.service.ts
Normal file
186
client/src/app/core/users/user-local-storage.service.ts
Normal file
|
@ -0,0 +1,186 @@
|
|||
|
||||
import { filter, throttleTime } from 'rxjs'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { AuthService, AuthStatus } from '@app/core/auth'
|
||||
import { UserLocalStorageKeys, UserTokens } from '@root-helpers/users'
|
||||
import { getBoolOrDefault } from '@root-helpers/local-storage-utils'
|
||||
import { UserRole, UserUpdateMe } from '@shared/models'
|
||||
import { NSFWPolicyType } from '@shared/models/videos'
|
||||
import { ServerService } from '../server'
|
||||
import { LocalStorageService } from '../wrappers/storage.service'
|
||||
|
||||
@Injectable()
|
||||
export class UserLocalStorageService {
|
||||
|
||||
constructor (
|
||||
private authService: AuthService,
|
||||
private server: ServerService,
|
||||
private localStorageService: LocalStorageService
|
||||
) {
|
||||
this.authService.userInformationLoaded.subscribe({
|
||||
next: () => {
|
||||
const user = this.authService.getUser()
|
||||
|
||||
this.setLoggedInUser(user)
|
||||
this.setUserInfo(user)
|
||||
this.setTokens(user.tokens)
|
||||
}
|
||||
})
|
||||
|
||||
this.authService.loginChangedSource
|
||||
.pipe(filter(status => status === AuthStatus.LoggedOut))
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.flushLoggedInUser()
|
||||
this.flushUserInfo()
|
||||
this.flushTokens()
|
||||
}
|
||||
})
|
||||
|
||||
this.authService.tokensRefreshed
|
||||
.subscribe({
|
||||
next: () => {
|
||||
const user = this.authService.getUser()
|
||||
|
||||
this.setTokens(user.tokens)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
getLoggedInUser () {
|
||||
const usernameLocalStorage = this.localStorageService.getItem(UserLocalStorageKeys.USERNAME)
|
||||
|
||||
if (!usernameLocalStorage) return undefined
|
||||
|
||||
return {
|
||||
id: parseInt(this.localStorageService.getItem(UserLocalStorageKeys.ID), 10),
|
||||
username: this.localStorageService.getItem(UserLocalStorageKeys.USERNAME),
|
||||
email: this.localStorageService.getItem(UserLocalStorageKeys.EMAIL),
|
||||
role: parseInt(this.localStorageService.getItem(UserLocalStorageKeys.ROLE), 10) as UserRole,
|
||||
|
||||
...this.getUserInfo()
|
||||
}
|
||||
}
|
||||
|
||||
setLoggedInUser (user: {
|
||||
id: number
|
||||
username: string
|
||||
email: string
|
||||
role: UserRole
|
||||
}) {
|
||||
this.localStorageService.setItem(UserLocalStorageKeys.ID, user.id.toString())
|
||||
this.localStorageService.setItem(UserLocalStorageKeys.USERNAME, user.username)
|
||||
this.localStorageService.setItem(UserLocalStorageKeys.EMAIL, user.email)
|
||||
this.localStorageService.setItem(UserLocalStorageKeys.ROLE, user.role.toString())
|
||||
}
|
||||
|
||||
flushLoggedInUser () {
|
||||
this.localStorageService.removeItem(UserLocalStorageKeys.ID)
|
||||
this.localStorageService.removeItem(UserLocalStorageKeys.USERNAME)
|
||||
this.localStorageService.removeItem(UserLocalStorageKeys.EMAIL)
|
||||
this.localStorageService.removeItem(UserLocalStorageKeys.ROLE)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
getUserInfo () {
|
||||
let videoLanguages: string[]
|
||||
|
||||
try {
|
||||
const languagesString = this.localStorageService.getItem(UserLocalStorageKeys.VIDEO_LANGUAGES)
|
||||
videoLanguages = languagesString && languagesString !== 'undefined'
|
||||
? JSON.parse(languagesString)
|
||||
: null
|
||||
} catch (err) {
|
||||
videoLanguages = null
|
||||
console.error('Cannot parse desired video languages from localStorage.', err)
|
||||
}
|
||||
|
||||
const htmlConfig = this.server.getHTMLConfig()
|
||||
|
||||
const defaultNSFWPolicy = htmlConfig.instance.defaultNSFWPolicy
|
||||
const defaultP2PEnabled = htmlConfig.defaults.p2p.enabled
|
||||
|
||||
return {
|
||||
nsfwPolicy: this.localStorageService.getItem<NSFWPolicyType>(UserLocalStorageKeys.NSFW_POLICY) || defaultNSFWPolicy,
|
||||
p2pEnabled: getBoolOrDefault(this.localStorageService.getItem(UserLocalStorageKeys.P2P_ENABLED), defaultP2PEnabled),
|
||||
theme: this.localStorageService.getItem(UserLocalStorageKeys.THEME) || 'instance-default',
|
||||
videoLanguages,
|
||||
|
||||
autoPlayVideo: getBoolOrDefault(this.localStorageService.getItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO), true),
|
||||
autoPlayNextVideo: getBoolOrDefault(this.localStorageService.getItem(UserLocalStorageKeys.AUTO_PLAY_NEXT_VIDEO), false),
|
||||
autoPlayNextVideoPlaylist: getBoolOrDefault(this.localStorageService.getItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST), true)
|
||||
}
|
||||
}
|
||||
|
||||
setUserInfo (profile: UserUpdateMe) {
|
||||
const localStorageKeys: { [ id in keyof UserUpdateMe ]: string } = {
|
||||
nsfwPolicy: UserLocalStorageKeys.NSFW_POLICY,
|
||||
p2pEnabled: UserLocalStorageKeys.P2P_ENABLED,
|
||||
autoPlayNextVideo: UserLocalStorageKeys.AUTO_PLAY_VIDEO,
|
||||
autoPlayNextVideoPlaylist: UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST,
|
||||
theme: UserLocalStorageKeys.THEME,
|
||||
videoLanguages: UserLocalStorageKeys.VIDEO_LANGUAGES
|
||||
}
|
||||
|
||||
const obj = Object.keys(localStorageKeys)
|
||||
.filter(key => key in profile)
|
||||
.map(key => ([ localStorageKeys[key], profile[key] ]))
|
||||
|
||||
for (const [ key, value ] of obj) {
|
||||
try {
|
||||
if (value === undefined) {
|
||||
this.localStorageService.removeItem(key)
|
||||
continue
|
||||
}
|
||||
|
||||
const localStorageValue = typeof value === 'string'
|
||||
? value
|
||||
: JSON.stringify(value)
|
||||
|
||||
this.localStorageService.setItem(key, localStorageValue)
|
||||
} catch (err) {
|
||||
console.error(`Cannot set ${key}->${value} in localStorage. Likely due to a value impossible to stringify.`, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flushUserInfo () {
|
||||
this.localStorageService.removeItem(UserLocalStorageKeys.NSFW_POLICY)
|
||||
this.localStorageService.removeItem(UserLocalStorageKeys.P2P_ENABLED)
|
||||
this.localStorageService.removeItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO)
|
||||
this.localStorageService.removeItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST)
|
||||
this.localStorageService.removeItem(UserLocalStorageKeys.THEME)
|
||||
this.localStorageService.removeItem(UserLocalStorageKeys.VIDEO_LANGUAGES)
|
||||
}
|
||||
|
||||
listenUserInfoChange () {
|
||||
return this.localStorageService.watch([
|
||||
UserLocalStorageKeys.NSFW_POLICY,
|
||||
UserLocalStorageKeys.P2P_ENABLED,
|
||||
UserLocalStorageKeys.AUTO_PLAY_VIDEO,
|
||||
UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST,
|
||||
UserLocalStorageKeys.THEME,
|
||||
UserLocalStorageKeys.VIDEO_LANGUAGES
|
||||
]).pipe(
|
||||
throttleTime(200),
|
||||
filter(() => this.authService.isLoggedIn() !== true)
|
||||
)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
getTokens () {
|
||||
return UserTokens.getUserTokens(this.localStorageService)
|
||||
}
|
||||
|
||||
setTokens (tokens: UserTokens) {
|
||||
UserTokens.saveToLocalStorage(this.localStorageService, tokens)
|
||||
}
|
||||
|
||||
flushTokens () {
|
||||
UserTokens.flushLocalStorage(this.localStorageService)
|
||||
}
|
||||
}
|
|
@ -26,7 +26,11 @@ export class User implements UserServerModel {
|
|||
autoPlayVideo: boolean
|
||||
autoPlayNextVideo: boolean
|
||||
autoPlayNextVideoPlaylist: boolean
|
||||
webTorrentEnabled: boolean
|
||||
|
||||
p2pEnabled: boolean
|
||||
// FIXME: deprecated in 4.1
|
||||
webTorrentEnabled: never
|
||||
|
||||
videosHistoryEnabled: boolean
|
||||
videoLanguages: string[]
|
||||
|
||||
|
@ -84,7 +88,7 @@ export class User implements UserServerModel {
|
|||
this.videoCommentsCount = hash.videoCommentsCount
|
||||
|
||||
this.nsfwPolicy = hash.nsfwPolicy
|
||||
this.webTorrentEnabled = hash.webTorrentEnabled
|
||||
this.p2pEnabled = hash.p2pEnabled
|
||||
this.autoPlayVideo = hash.autoPlayVideo
|
||||
this.autoPlayNextVideo = hash.autoPlayNextVideo
|
||||
this.autoPlayNextVideoPlaylist = hash.autoPlayNextVideoPlaylist
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import { SortMeta } from 'primeng/api'
|
||||
import { from, Observable, of } from 'rxjs'
|
||||
import { catchError, concatMap, filter, first, map, shareReplay, tap, throttleTime, toArray } from 'rxjs/operators'
|
||||
import { catchError, concatMap, first, map, shareReplay, tap, toArray } from 'rxjs/operators'
|
||||
import { HttpClient, HttpParams } from '@angular/common/http'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { AuthService } from '@app/core/auth'
|
||||
import { getBytes } from '@root-helpers/bytes'
|
||||
import { UserLocalStorageKeys } from '@root-helpers/users'
|
||||
import {
|
||||
ActorImage,
|
||||
ResultList,
|
||||
|
@ -17,10 +16,9 @@ import {
|
|||
UserUpdateMe,
|
||||
UserVideoQuota
|
||||
} from '@shared/models'
|
||||
import { ServerService } from '../'
|
||||
import { environment } from '../../../environments/environment'
|
||||
import { RestExtractor, RestPagination, RestService } from '../rest'
|
||||
import { LocalStorageService, SessionStorageService } from '../wrappers/storage.service'
|
||||
import { UserLocalStorageService } from './'
|
||||
import { User } from './user.model'
|
||||
|
||||
@Injectable()
|
||||
|
@ -33,12 +31,10 @@ export class UserService {
|
|||
|
||||
constructor (
|
||||
private authHttp: HttpClient,
|
||||
private server: ServerService,
|
||||
private authService: AuthService,
|
||||
private restExtractor: RestExtractor,
|
||||
private restService: RestService,
|
||||
private localStorageService: LocalStorageService,
|
||||
private sessionStorageService: SessionStorageService
|
||||
private userLocalStorageService: UserLocalStorageService
|
||||
) { }
|
||||
|
||||
hasSignupInThisSession () {
|
||||
|
@ -73,6 +69,23 @@ export class UserService {
|
|||
)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
updateMyAnonymousProfile (profile: UserUpdateMe) {
|
||||
this.userLocalStorageService.setUserInfo(profile)
|
||||
}
|
||||
|
||||
listenAnonymousUpdate () {
|
||||
return this.userLocalStorageService.listenUserInfoChange()
|
||||
.pipe(map(() => this.getAnonymousUser()))
|
||||
}
|
||||
|
||||
getAnonymousUser () {
|
||||
return new User(this.userLocalStorageService.getUserInfo())
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
updateMyProfile (profile: UserUpdateMe) {
|
||||
const url = UserService.BASE_USERS_URL + 'me'
|
||||
|
||||
|
@ -83,53 +96,6 @@ export class UserService {
|
|||
)
|
||||
}
|
||||
|
||||
updateMyAnonymousProfile (profile: UserUpdateMe) {
|
||||
const localStorageKeys: { [ id in keyof UserUpdateMe ]: string } = {
|
||||
nsfwPolicy: UserLocalStorageKeys.NSFW_POLICY,
|
||||
webTorrentEnabled: UserLocalStorageKeys.WEBTORRENT_ENABLED,
|
||||
autoPlayNextVideo: UserLocalStorageKeys.AUTO_PLAY_VIDEO,
|
||||
autoPlayNextVideoPlaylist: UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST,
|
||||
theme: UserLocalStorageKeys.THEME,
|
||||
videoLanguages: UserLocalStorageKeys.VIDEO_LANGUAGES
|
||||
}
|
||||
|
||||
const obj = Object.keys(localStorageKeys)
|
||||
.filter(key => key in profile)
|
||||
.map(key => ([ localStorageKeys[key], profile[key] ]))
|
||||
|
||||
for (const [ key, value ] of obj) {
|
||||
try {
|
||||
if (value === undefined) {
|
||||
this.localStorageService.removeItem(key)
|
||||
continue
|
||||
}
|
||||
|
||||
const localStorageValue = typeof value === 'string'
|
||||
? value
|
||||
: JSON.stringify(value)
|
||||
|
||||
this.localStorageService.setItem(key, localStorageValue)
|
||||
} catch (err) {
|
||||
console.error(`Cannot set ${key}->${value} in localStorage. Likely due to a value impossible to stringify.`, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listenAnonymousUpdate () {
|
||||
return this.localStorageService.watch([
|
||||
UserLocalStorageKeys.NSFW_POLICY,
|
||||
UserLocalStorageKeys.WEBTORRENT_ENABLED,
|
||||
UserLocalStorageKeys.AUTO_PLAY_VIDEO,
|
||||
UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST,
|
||||
UserLocalStorageKeys.THEME,
|
||||
UserLocalStorageKeys.VIDEO_LANGUAGES
|
||||
]).pipe(
|
||||
throttleTime(200),
|
||||
filter(() => this.authService.isLoggedIn() !== true),
|
||||
map(() => this.getAnonymousUser())
|
||||
)
|
||||
}
|
||||
|
||||
deleteMe () {
|
||||
const url = UserService.BASE_USERS_URL + 'me'
|
||||
|
||||
|
@ -287,36 +253,6 @@ export class UserService {
|
|||
.pipe(catchError(err => this.restExtractor.handleError(err)))
|
||||
}
|
||||
|
||||
getAnonymousUser () {
|
||||
let videoLanguages: string[]
|
||||
|
||||
try {
|
||||
const languagesString = this.localStorageService.getItem(UserLocalStorageKeys.VIDEO_LANGUAGES)
|
||||
videoLanguages = languagesString && languagesString !== 'undefined'
|
||||
? JSON.parse(languagesString)
|
||||
: null
|
||||
} catch (err) {
|
||||
videoLanguages = null
|
||||
console.error('Cannot parse desired video languages from localStorage.', err)
|
||||
}
|
||||
|
||||
const defaultNSFWPolicy = this.server.getHTMLConfig().instance.defaultNSFWPolicy
|
||||
|
||||
return new User({
|
||||
// local storage keys
|
||||
nsfwPolicy: this.localStorageService.getItem(UserLocalStorageKeys.NSFW_POLICY) || defaultNSFWPolicy,
|
||||
webTorrentEnabled: this.localStorageService.getItem(UserLocalStorageKeys.WEBTORRENT_ENABLED) !== 'false',
|
||||
theme: this.localStorageService.getItem(UserLocalStorageKeys.THEME) || 'instance-default',
|
||||
videoLanguages,
|
||||
|
||||
autoPlayNextVideoPlaylist: this.localStorageService.getItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO_PLAYLIST) !== 'false',
|
||||
autoPlayVideo: this.localStorageService.getItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO) === 'true',
|
||||
|
||||
// session storage keys
|
||||
autoPlayNextVideo: this.sessionStorageService.getItem(UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true'
|
||||
})
|
||||
}
|
||||
|
||||
getUsers (parameters: {
|
||||
pagination: RestPagination
|
||||
sort: SortMeta
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<my-global-icon iconName="p2p" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>Help share videos</ng-container>
|
||||
|
||||
<my-input-switch class="ml-auto" [checked]="user.webTorrentEnabled"></my-input-switch>
|
||||
<my-input-switch class="ml-auto" [checked]="user.p2pEnabled"></my-input-switch>
|
||||
</a>
|
||||
|
||||
<div class="dropdown-divider"></div>
|
||||
|
|
|
@ -196,9 +196,9 @@ export class MenuComponent implements OnInit {
|
|||
|
||||
toggleUseP2P () {
|
||||
if (!this.user) return
|
||||
this.user.webTorrentEnabled = !this.user.webTorrentEnabled
|
||||
this.user.p2pEnabled = !this.user.p2pEnabled
|
||||
|
||||
this.userService.updateMyProfile({ webTorrentEnabled: this.user.webTorrentEnabled })
|
||||
this.userService.updateMyProfile({ p2pEnabled: this.user.p2pEnabled })
|
||||
.subscribe(() => this.authService.refreshUserInformation())
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import { HttpClient, HttpParams } from '@angular/common/http'
|
|||
import { Injectable } from '@angular/core'
|
||||
import { ComponentPaginationLight, RestExtractor, RestPagination, RestService } from '@app/core'
|
||||
import { Video, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main'
|
||||
import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
|
||||
import {
|
||||
ResultList,
|
||||
Video as VideoServerModel,
|
||||
|
@ -25,11 +24,7 @@ export class SearchService {
|
|||
private restService: RestService,
|
||||
private videoService: VideoService,
|
||||
private playlistService: VideoPlaylistService
|
||||
) {
|
||||
// Add ability to override search endpoint if the user updated this local storage key
|
||||
const searchUrl = peertubeLocalStorage.getItem('search-url')
|
||||
if (searchUrl) SearchService.BASE_SEARCH_URL = searchUrl
|
||||
}
|
||||
) { }
|
||||
|
||||
searchVideos (parameters: {
|
||||
search?: string
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
<div class="form-group">
|
||||
<my-peertube-checkbox
|
||||
inputName="webTorrentEnabled" formControlName="webTorrentEnabled" [recommended]="true"
|
||||
inputName="p2pEnabled" formControlName="p2pEnabled" [recommended]="true"
|
||||
i18n-labelText labelText="Help share videos being played"
|
||||
>
|
||||
<ng-container ngProjectAs="description">
|
||||
|
|
|
@ -34,7 +34,7 @@ export class UserVideoSettingsComponent extends FormReactive implements OnInit,
|
|||
ngOnInit () {
|
||||
this.buildForm({
|
||||
nsfwPolicy: null,
|
||||
webTorrentEnabled: null,
|
||||
p2pEnabled: null,
|
||||
autoPlayVideo: null,
|
||||
autoPlayNextVideo: null,
|
||||
videoLanguages: null
|
||||
|
@ -48,7 +48,7 @@ export class UserVideoSettingsComponent extends FormReactive implements OnInit,
|
|||
|
||||
this.form.patchValue({
|
||||
nsfwPolicy: this.user.nsfwPolicy || this.defaultNSFWPolicy,
|
||||
webTorrentEnabled: this.user.webTorrentEnabled,
|
||||
p2pEnabled: this.user.p2pEnabled,
|
||||
autoPlayVideo: this.user.autoPlayVideo === true,
|
||||
autoPlayNextVideo: this.user.autoPlayNextVideo,
|
||||
videoLanguages: this.user.videoLanguages
|
||||
|
@ -65,7 +65,7 @@ export class UserVideoSettingsComponent extends FormReactive implements OnInit,
|
|||
|
||||
updateDetails (onlyKeys?: string[]) {
|
||||
const nsfwPolicy = this.form.value['nsfwPolicy']
|
||||
const webTorrentEnabled = this.form.value['webTorrentEnabled']
|
||||
const p2pEnabled = this.form.value['p2pEnabled']
|
||||
const autoPlayVideo = this.form.value['autoPlayVideo']
|
||||
const autoPlayNextVideo = this.form.value['autoPlayNextVideo']
|
||||
|
||||
|
@ -80,7 +80,7 @@ export class UserVideoSettingsComponent extends FormReactive implements OnInit,
|
|||
|
||||
let details: UserUpdateMe = {
|
||||
nsfwPolicy,
|
||||
webTorrentEnabled,
|
||||
p2pEnabled,
|
||||
autoPlayVideo,
|
||||
autoPlayNextVideo,
|
||||
videoLanguages
|
||||
|
|
|
@ -10,14 +10,6 @@ function getStoredVolume () {
|
|||
return undefined
|
||||
}
|
||||
|
||||
function getStoredP2PEnabled (): boolean {
|
||||
const value = getLocalStorage('webtorrent_enabled')
|
||||
if (value !== null && value !== undefined) return value === 'true'
|
||||
|
||||
// By default webtorrent is enabled
|
||||
return true
|
||||
}
|
||||
|
||||
function getStoredMute () {
|
||||
const value = getLocalStorage('mute')
|
||||
if (value !== null && value !== undefined) return value === 'true'
|
||||
|
@ -123,7 +115,6 @@ function cleanupVideoWatch () {
|
|||
|
||||
export {
|
||||
getStoredVolume,
|
||||
getStoredP2PEnabled,
|
||||
getStoredMute,
|
||||
getStoredTheater,
|
||||
saveVolumeInStore,
|
||||
|
|
|
@ -31,7 +31,7 @@ import { copyToClipboard } from '../../root-helpers/utils'
|
|||
import { RedundancyUrlManager } from './p2p-media-loader/redundancy-url-manager'
|
||||
import { segmentUrlBuilderFactory } from './p2p-media-loader/segment-url-builder'
|
||||
import { segmentValidatorFactory } from './p2p-media-loader/segment-validator'
|
||||
import { getAverageBandwidthInStore, getStoredP2PEnabled, saveAverageBandwidth } from './peertube-player-local-storage'
|
||||
import { getAverageBandwidthInStore, saveAverageBandwidth } from './peertube-player-local-storage'
|
||||
import {
|
||||
NextPreviousVideoButtonOptions,
|
||||
P2PMediaLoaderPluginOptions,
|
||||
|
@ -86,6 +86,7 @@ export interface CommonOptions extends CustomizationOptions {
|
|||
onPlayerElementChange: (element: HTMLVideoElement) => void
|
||||
|
||||
autoplay: boolean
|
||||
p2pEnabled: boolean
|
||||
|
||||
nextVideo?: () => void
|
||||
hasNextVideo?: () => boolean
|
||||
|
@ -374,7 +375,7 @@ export class PeertubePlayerManager {
|
|||
requiredSegmentsPriority: 1,
|
||||
simultaneousHttpDownloads: 1,
|
||||
segmentUrlBuilder: segmentUrlBuilderFactory(redundancyUrlManager, 1),
|
||||
useP2P: getStoredP2PEnabled(),
|
||||
useP2P: commonOptions.p2pEnabled,
|
||||
consumeOnly
|
||||
},
|
||||
segments: {
|
||||
|
@ -437,6 +438,7 @@ export class PeertubePlayerManager {
|
|||
|
||||
const webtorrent = {
|
||||
autoplay,
|
||||
playerRefusedP2P: commonOptions.p2pEnabled === false,
|
||||
videoDuration: commonOptions.videoDuration,
|
||||
playerElement: commonOptions.playerElement,
|
||||
videoFiles: webtorrentOptions.videoFiles.length !== 0
|
||||
|
|
|
@ -137,6 +137,8 @@ type WebtorrentPluginOptions = {
|
|||
videoFiles: VideoFile[]
|
||||
|
||||
startTime: number | string
|
||||
|
||||
playerRefusedP2P: boolean
|
||||
}
|
||||
|
||||
type P2PMediaLoaderPluginOptions = {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { VideoFile } from '@shared/models'
|
||||
import { HTMLServerConfig, Video, VideoFile } from '@shared/models'
|
||||
|
||||
function toTitleCase (str: string) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||
|
@ -8,6 +8,13 @@ function isWebRTCDisabled () {
|
|||
return !!((window as any).RTCPeerConnection || (window as any).mozRTCPeerConnection || (window as any).webkitRTCPeerConnection) === false
|
||||
}
|
||||
|
||||
function isP2PEnabled (video: Video, config: HTMLServerConfig, userP2PEnabled: boolean) {
|
||||
if (video.isLocal && config.tracker.enabled === false) return false
|
||||
if (isWebRTCDisabled()) return false
|
||||
|
||||
return userP2PEnabled
|
||||
}
|
||||
|
||||
function isIOS () {
|
||||
if (/iPad|iPhone|iPod/.test(navigator.platform)) {
|
||||
return true
|
||||
|
@ -97,6 +104,7 @@ export {
|
|||
getRtcConfig,
|
||||
toTitleCase,
|
||||
isWebRTCDisabled,
|
||||
isP2PEnabled,
|
||||
|
||||
buildVideoOrPlaylistEmbed,
|
||||
videoFileMaxByResolution,
|
||||
|
|
|
@ -2,13 +2,7 @@ import videojs from 'video.js'
|
|||
import * as WebTorrent from 'webtorrent'
|
||||
import { timeToInt } from '@shared/core-utils'
|
||||
import { VideoFile } from '@shared/models'
|
||||
import {
|
||||
getAverageBandwidthInStore,
|
||||
getStoredMute,
|
||||
getStoredP2PEnabled,
|
||||
getStoredVolume,
|
||||
saveAverageBandwidth
|
||||
} from '../peertube-player-local-storage'
|
||||
import { getAverageBandwidthInStore, getStoredMute, getStoredVolume, saveAverageBandwidth } from '../peertube-player-local-storage'
|
||||
import { PeerTubeResolution, PlayerNetworkInfo, WebtorrentPluginOptions } from '../peertube-videojs-typings'
|
||||
import { getRtcConfig, isIOS, videoFileMaxByResolution, videoFileMinByResolution } from '../utils'
|
||||
import { PeertubeChunkStore } from './peertube-chunk-store'
|
||||
|
@ -74,9 +68,10 @@ class WebTorrentPlugin extends Plugin {
|
|||
|
||||
this.startTime = timeToInt(options.startTime)
|
||||
|
||||
// Disable auto play on iOS
|
||||
// Custom autoplay handled by webtorrent because we lazy play the video
|
||||
this.autoplay = options.autoplay
|
||||
this.playerRefusedP2P = !getStoredP2PEnabled()
|
||||
|
||||
this.playerRefusedP2P = options.playerRefusedP2P
|
||||
|
||||
this.videoFiles = options.videoFiles
|
||||
this.videoDuration = options.videoDuration
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
export * from './users'
|
||||
export * from './bytes'
|
||||
export * from './images'
|
||||
export * from './local-storage-utils'
|
||||
export * from './peertube-web-storage'
|
||||
export * from './utils'
|
||||
export * from './plugins-manager'
|
||||
|
|
10
client/src/root-helpers/local-storage-utils.ts
Normal file
10
client/src/root-helpers/local-storage-utils.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
function getBoolOrDefault (value: string, defaultValue: boolean) {
|
||||
if (value === 'true') return true
|
||||
if (value === 'false') return false
|
||||
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
export {
|
||||
getBoolOrDefault
|
||||
}
|
|
@ -1,3 +1,2 @@
|
|||
export * from './user-local-storage-keys'
|
||||
export * from './user-local-storage-manager'
|
||||
export * from './user-tokens'
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
export const UserLocalStorageKeys = {
|
||||
ID: 'id',
|
||||
USERNAME: 'username',
|
||||
ROLE: 'role',
|
||||
EMAIL: 'email',
|
||||
|
||||
VIDEOS_HISTORY_ENABLED: 'videos-history-enabled',
|
||||
USERNAME: 'username',
|
||||
NSFW_POLICY: 'nsfw_policy',
|
||||
WEBTORRENT_ENABLED: 'peertube-videojs-' + 'webtorrent_enabled',
|
||||
P2P_ENABLED: 'peertube-videojs-' + 'webtorrent_enabled',
|
||||
|
||||
AUTO_PLAY_VIDEO: 'auto_play_video',
|
||||
SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO: 'auto_play_next_video',
|
||||
AUTO_PLAY_NEXT_VIDEO: 'auto_play_next_video',
|
||||
AUTO_PLAY_VIDEO_PLAYLIST: 'auto_play_video_playlist',
|
||||
|
||||
THEME: 'theme',
|
||||
LAST_ACTIVE_THEME: 'last_active_theme',
|
||||
|
||||
VIDEO_LANGUAGES: 'video_languages'
|
||||
}
|
||||
|
||||
export const UserTokenLocalStorageKeys = {
|
||||
ACCESS_TOKEN: 'access_token',
|
||||
REFRESH_TOKEN: 'refresh_token',
|
||||
TOKEN_TYPE: 'token_type'
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
import { NSFWPolicyType, UserRole } from '@shared/models'
|
||||
import { peertubeLocalStorage } from '../peertube-web-storage'
|
||||
import { UserLocalStorageKeys } from './user-local-storage-keys'
|
||||
|
||||
function getUserInfoFromLocalStorage () {
|
||||
const usernameLocalStorage = peertubeLocalStorage.getItem(UserLocalStorageKeys.USERNAME)
|
||||
|
||||
if (!usernameLocalStorage) return undefined
|
||||
|
||||
return {
|
||||
id: parseInt(peertubeLocalStorage.getItem(UserLocalStorageKeys.ID), 10),
|
||||
username: peertubeLocalStorage.getItem(UserLocalStorageKeys.USERNAME),
|
||||
email: peertubeLocalStorage.getItem(UserLocalStorageKeys.EMAIL),
|
||||
role: parseInt(peertubeLocalStorage.getItem(UserLocalStorageKeys.ROLE), 10) as UserRole,
|
||||
nsfwPolicy: peertubeLocalStorage.getItem(UserLocalStorageKeys.NSFW_POLICY) as NSFWPolicyType,
|
||||
webTorrentEnabled: peertubeLocalStorage.getItem(UserLocalStorageKeys.WEBTORRENT_ENABLED) === 'true',
|
||||
autoPlayVideo: peertubeLocalStorage.getItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO) === 'true',
|
||||
videosHistoryEnabled: peertubeLocalStorage.getItem(UserLocalStorageKeys.VIDEOS_HISTORY_ENABLED) === 'true'
|
||||
}
|
||||
}
|
||||
|
||||
function flushUserInfoFromLocalStorage () {
|
||||
peertubeLocalStorage.removeItem(UserLocalStorageKeys.ID)
|
||||
peertubeLocalStorage.removeItem(UserLocalStorageKeys.USERNAME)
|
||||
peertubeLocalStorage.removeItem(UserLocalStorageKeys.EMAIL)
|
||||
peertubeLocalStorage.removeItem(UserLocalStorageKeys.ROLE)
|
||||
peertubeLocalStorage.removeItem(UserLocalStorageKeys.NSFW_POLICY)
|
||||
peertubeLocalStorage.removeItem(UserLocalStorageKeys.WEBTORRENT_ENABLED)
|
||||
peertubeLocalStorage.removeItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO)
|
||||
peertubeLocalStorage.removeItem(UserLocalStorageKeys.VIDEOS_HISTORY_ENABLED)
|
||||
}
|
||||
|
||||
function saveUserInfoIntoLocalStorage (info: {
|
||||
id: number
|
||||
username: string
|
||||
email: string
|
||||
role: UserRole
|
||||
nsfwPolicy: NSFWPolicyType
|
||||
webTorrentEnabled: boolean
|
||||
autoPlayVideo: boolean
|
||||
}) {
|
||||
peertubeLocalStorage.setItem(UserLocalStorageKeys.ID, info.id.toString())
|
||||
peertubeLocalStorage.setItem(UserLocalStorageKeys.USERNAME, info.username)
|
||||
peertubeLocalStorage.setItem(UserLocalStorageKeys.EMAIL, info.email)
|
||||
peertubeLocalStorage.setItem(UserLocalStorageKeys.ROLE, info.role.toString())
|
||||
peertubeLocalStorage.setItem(UserLocalStorageKeys.NSFW_POLICY, info.nsfwPolicy.toString())
|
||||
peertubeLocalStorage.setItem(UserLocalStorageKeys.WEBTORRENT_ENABLED, JSON.stringify(info.webTorrentEnabled))
|
||||
peertubeLocalStorage.setItem(UserLocalStorageKeys.AUTO_PLAY_VIDEO, JSON.stringify(info.autoPlayVideo))
|
||||
}
|
||||
|
||||
export {
|
||||
getUserInfoFromLocalStorage,
|
||||
saveUserInfoIntoLocalStorage,
|
||||
flushUserInfoFromLocalStorage
|
||||
}
|
|
@ -1,46 +1,11 @@
|
|||
import { peertubeLocalStorage } from '../peertube-web-storage'
|
||||
|
||||
export type TokenOptions = {
|
||||
accessToken: string
|
||||
refreshToken: string
|
||||
tokenType: string
|
||||
}
|
||||
|
||||
// Private class only used by User
|
||||
export class Tokens {
|
||||
private static KEYS = {
|
||||
ACCESS_TOKEN: 'access_token',
|
||||
REFRESH_TOKEN: 'refresh_token',
|
||||
TOKEN_TYPE: 'token_type'
|
||||
}
|
||||
import { UserTokenLocalStorageKeys } from './user-local-storage-keys'
|
||||
|
||||
export class UserTokens {
|
||||
accessToken: string
|
||||
refreshToken: string
|
||||
tokenType: string
|
||||
|
||||
static load () {
|
||||
const accessTokenLocalStorage = peertubeLocalStorage.getItem(this.KEYS.ACCESS_TOKEN)
|
||||
const refreshTokenLocalStorage = peertubeLocalStorage.getItem(this.KEYS.REFRESH_TOKEN)
|
||||
const tokenTypeLocalStorage = peertubeLocalStorage.getItem(this.KEYS.TOKEN_TYPE)
|
||||
|
||||
if (accessTokenLocalStorage && refreshTokenLocalStorage && tokenTypeLocalStorage) {
|
||||
return new Tokens({
|
||||
accessToken: accessTokenLocalStorage,
|
||||
refreshToken: refreshTokenLocalStorage,
|
||||
tokenType: tokenTypeLocalStorage
|
||||
})
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
static flush () {
|
||||
peertubeLocalStorage.removeItem(this.KEYS.ACCESS_TOKEN)
|
||||
peertubeLocalStorage.removeItem(this.KEYS.REFRESH_TOKEN)
|
||||
peertubeLocalStorage.removeItem(this.KEYS.TOKEN_TYPE)
|
||||
}
|
||||
|
||||
constructor (hash?: TokenOptions) {
|
||||
constructor (hash?: Partial<UserTokens>) {
|
||||
if (hash) {
|
||||
this.accessToken = hash.accessToken
|
||||
this.refreshToken = hash.refreshToken
|
||||
|
@ -53,9 +18,29 @@ export class Tokens {
|
|||
}
|
||||
}
|
||||
|
||||
save () {
|
||||
peertubeLocalStorage.setItem(Tokens.KEYS.ACCESS_TOKEN, this.accessToken)
|
||||
peertubeLocalStorage.setItem(Tokens.KEYS.REFRESH_TOKEN, this.refreshToken)
|
||||
peertubeLocalStorage.setItem(Tokens.KEYS.TOKEN_TYPE, this.tokenType)
|
||||
static getUserTokens (localStorage: Pick<Storage, 'getItem'>) {
|
||||
const accessTokenLocalStorage = localStorage.getItem(UserTokenLocalStorageKeys.ACCESS_TOKEN)
|
||||
const refreshTokenLocalStorage = localStorage.getItem(UserTokenLocalStorageKeys.REFRESH_TOKEN)
|
||||
const tokenTypeLocalStorage = localStorage.getItem(UserTokenLocalStorageKeys.TOKEN_TYPE)
|
||||
|
||||
if (!accessTokenLocalStorage || !refreshTokenLocalStorage || !tokenTypeLocalStorage) return null
|
||||
|
||||
return new UserTokens({
|
||||
accessToken: accessTokenLocalStorage,
|
||||
refreshToken: refreshTokenLocalStorage,
|
||||
tokenType: tokenTypeLocalStorage
|
||||
})
|
||||
}
|
||||
|
||||
static saveToLocalStorage (localStorage: Pick<Storage, 'setItem'>, tokens: UserTokens) {
|
||||
localStorage.setItem(UserTokenLocalStorageKeys.ACCESS_TOKEN, tokens.accessToken)
|
||||
localStorage.setItem(UserTokenLocalStorageKeys.REFRESH_TOKEN, tokens.refreshToken)
|
||||
localStorage.setItem(UserTokenLocalStorageKeys.TOKEN_TYPE, tokens.tokenType)
|
||||
}
|
||||
|
||||
static flushLocalStorage (localStorage: Pick<Storage, 'removeItem'>) {
|
||||
localStorage.removeItem(UserTokenLocalStorageKeys.ACCESS_TOKEN)
|
||||
localStorage.removeItem(UserTokenLocalStorageKeys.REFRESH_TOKEN)
|
||||
localStorage.removeItem(UserTokenLocalStorageKeys.TOKEN_TYPE)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
OAuth2ErrorCode,
|
||||
ResultList,
|
||||
UserRefreshToken,
|
||||
Video,
|
||||
VideoCaption,
|
||||
VideoDetails,
|
||||
VideoPlaylist,
|
||||
|
@ -16,9 +17,11 @@ import {
|
|||
import { P2PMediaLoaderOptions, PeertubePlayerManagerOptions, PlayerMode } from '../../assets/player/peertube-player-manager'
|
||||
import { VideoJSCaption } from '../../assets/player/peertube-videojs-typings'
|
||||
import { TranslationsManager } from '../../assets/player/translations-manager'
|
||||
import { isP2PEnabled } from '../../assets/player/utils'
|
||||
import { getBoolOrDefault } from '../../root-helpers/local-storage-utils'
|
||||
import { peertubeLocalStorage } from '../../root-helpers/peertube-web-storage'
|
||||
import { PluginsManager } from '../../root-helpers/plugins-manager'
|
||||
import { Tokens } from '../../root-helpers/users'
|
||||
import { UserLocalStorageKeys, UserTokens } from '../../root-helpers/users'
|
||||
import { objectToUrlEncoded } from '../../root-helpers/utils'
|
||||
import { RegisterClientHelpers } from '../../types/register-client-option.model'
|
||||
import { PeerTubeEmbedApi } from './embed-api'
|
||||
|
@ -48,7 +51,7 @@ export class PeerTubeEmbed {
|
|||
mode: PlayerMode
|
||||
scope = 'peertube'
|
||||
|
||||
userTokens: Tokens
|
||||
userTokens: UserTokens
|
||||
headers = new Headers()
|
||||
LOCAL_STORAGE_OAUTH_CLIENT_KEYS = {
|
||||
CLIENT_ID: 'client_id',
|
||||
|
@ -118,7 +121,7 @@ export class PeerTubeEmbed {
|
|||
return res.json()
|
||||
}).then((obj: UserRefreshToken & { code?: OAuth2ErrorCode }) => {
|
||||
if (!obj || obj.code === OAuth2ErrorCode.INVALID_GRANT) {
|
||||
Tokens.flush()
|
||||
UserTokens.flushLocalStorage(peertubeLocalStorage)
|
||||
this.removeTokensFromHeaders()
|
||||
|
||||
return resolve()
|
||||
|
@ -126,7 +129,7 @@ export class PeerTubeEmbed {
|
|||
|
||||
this.userTokens.accessToken = obj.access_token
|
||||
this.userTokens.refreshToken = obj.refresh_token
|
||||
this.userTokens.save()
|
||||
UserTokens.saveToLocalStorage(peertubeLocalStorage, this.userTokens)
|
||||
|
||||
this.setHeadersFromTokens()
|
||||
|
||||
|
@ -138,7 +141,7 @@ export class PeerTubeEmbed {
|
|||
|
||||
return refreshingTokenPromise
|
||||
.catch(() => {
|
||||
Tokens.flush()
|
||||
UserTokens.flushLocalStorage(peertubeLocalStorage)
|
||||
|
||||
this.removeTokensFromHeaders()
|
||||
}).then(() => fetch(url, {
|
||||
|
@ -258,7 +261,7 @@ export class PeerTubeEmbed {
|
|||
}
|
||||
|
||||
async init () {
|
||||
this.userTokens = Tokens.load()
|
||||
this.userTokens = UserTokens.getUserTokens(peertubeLocalStorage)
|
||||
await this.initCore()
|
||||
}
|
||||
|
||||
|
@ -515,6 +518,8 @@ export class PeerTubeEmbed {
|
|||
muted: this.muted,
|
||||
loop: this.loop,
|
||||
|
||||
p2pEnabled: this.isP2PEnabled(videoInfo),
|
||||
|
||||
captions: videoCaptions.length !== 0,
|
||||
subtitle: this.subtitle,
|
||||
|
||||
|
@ -669,7 +674,7 @@ export class PeerTubeEmbed {
|
|||
|
||||
const title = this.title ? videoInfo.name : undefined
|
||||
|
||||
const description = this.warningTitle && (!videoInfo.isLocal || this.config.tracker.enabled)
|
||||
const description = this.warningTitle && this.isP2PEnabled(videoInfo)
|
||||
? '<span class="text">' + peertubeTranslate('Watching this video may reveal your IP address to others.') + '</span>'
|
||||
: undefined
|
||||
|
||||
|
@ -784,6 +789,15 @@ export class PeerTubeEmbed {
|
|||
translate: (value: string) => Promise.resolve(peertubeTranslate(value, translations))
|
||||
}
|
||||
}
|
||||
|
||||
private isP2PEnabled (video: Video) {
|
||||
const userP2PEnabled = getBoolOrDefault(
|
||||
peertubeLocalStorage.getItem(UserLocalStorageKeys.P2P_ENABLED),
|
||||
this.config.defaults.p2p.enabled
|
||||
)
|
||||
|
||||
return isP2PEnabled(video, this.config, userP2PEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
PeerTubeEmbed.main()
|
||||
|
|
|
@ -92,6 +92,11 @@ defaults:
|
|||
# No licence by default
|
||||
licence: null
|
||||
|
||||
p2p:
|
||||
# Enable P2P by default
|
||||
# Can be enabled/disabled by anonymous users and logged in users
|
||||
enabled: true
|
||||
|
||||
# From the project root directory
|
||||
storage:
|
||||
tmp: 'storage/tmp/' # Use to download data (imports etc), store uploaded files before and during processing...
|
||||
|
@ -216,7 +221,7 @@ security:
|
|||
enabled: true
|
||||
|
||||
tracker:
|
||||
# If you disable the tracker, you disable the P2P aspect of PeerTube
|
||||
# If you disable the tracker, you disable the P2P on your PeerTube instance
|
||||
enabled: true
|
||||
# Only handle requests on your videos
|
||||
# If you set this to false it means you have a public tracker
|
||||
|
|
|
@ -90,6 +90,11 @@ defaults:
|
|||
# No licence by default
|
||||
licence: null
|
||||
|
||||
p2p:
|
||||
# Enable P2P by default
|
||||
# Can be enabled/disabled by anonymous users and logged in users
|
||||
enabled: true
|
||||
|
||||
# From the project root directory
|
||||
storage:
|
||||
tmp: '/var/www/peertube/storage/tmp/' # Use to download data (imports etc), store uploaded files before and during processing...
|
||||
|
|
|
@ -183,6 +183,7 @@ async function createUser (req: express.Request, res: express.Response) {
|
|||
password: body.password,
|
||||
email: body.email,
|
||||
nsfwPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
|
||||
p2pEnabled: CONFIG.DEFAULTS.P2P.ENABLED,
|
||||
autoPlayVideo: true,
|
||||
role: body.role,
|
||||
videoQuota: body.videoQuota,
|
||||
|
@ -232,6 +233,7 @@ async function registerUser (req: express.Request, res: express.Response) {
|
|||
password: body.password,
|
||||
email: body.email,
|
||||
nsfwPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
|
||||
p2pEnabled: CONFIG.DEFAULTS.P2P.ENABLED,
|
||||
autoPlayVideo: true,
|
||||
role: UserRole.USER,
|
||||
videoQuota: CONFIG.USER.VIDEO_QUOTA,
|
||||
|
|
|
@ -197,7 +197,7 @@ async function updateMe (req: express.Request, res: express.Response) {
|
|||
const keysToUpdate: (keyof UserUpdateMe & keyof AttributesOnly<UserModel>)[] = [
|
||||
'password',
|
||||
'nsfwPolicy',
|
||||
'webTorrentEnabled',
|
||||
'p2pEnabled',
|
||||
'autoPlayVideo',
|
||||
'autoPlayNextVideo',
|
||||
'autoPlayNextVideoPlaylist',
|
||||
|
@ -213,6 +213,12 @@ async function updateMe (req: express.Request, res: express.Response) {
|
|||
if (body[key] !== undefined) user.set(key, body[key])
|
||||
}
|
||||
|
||||
if (body.p2pEnabled !== undefined) {
|
||||
user.set('p2pEnabled', body.p2pEnabled)
|
||||
} else if (body.webTorrentEnabled !== undefined) { // FIXME: deprecated in 4.1
|
||||
user.set('p2pEnabled', body.webTorrentEnabled)
|
||||
}
|
||||
|
||||
if (body.email !== undefined) {
|
||||
if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION) {
|
||||
user.pendingEmail = body.email
|
||||
|
|
|
@ -49,7 +49,7 @@ function isUserNSFWPolicyValid (value: any) {
|
|||
return exists(value) && nsfwPolicies.includes(value)
|
||||
}
|
||||
|
||||
function isUserWebTorrentEnabledValid (value: any) {
|
||||
function isUserP2PEnabledValid (value: any) {
|
||||
return isBooleanValid(value)
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ export {
|
|||
isUserAdminFlagsValid,
|
||||
isUserEmailVerifiedValid,
|
||||
isUserNSFWPolicyValid,
|
||||
isUserWebTorrentEnabledValid,
|
||||
isUserP2PEnabledValid,
|
||||
isUserAutoPlayVideoValid,
|
||||
isUserAutoPlayNextVideoValid,
|
||||
isUserAutoPlayNextVideoPlaylistValid,
|
||||
|
|
|
@ -78,6 +78,9 @@ const CONFIG = {
|
|||
COMMENTS_ENABLED: config.get<boolean>('defaults.publish.comments_enabled'),
|
||||
PRIVACY: config.get<VideoPrivacy>('defaults.publish.privacy'),
|
||||
LICENCE: config.get<number>('defaults.publish.licence')
|
||||
},
|
||||
P2P: {
|
||||
ENABLED: config.get<boolean>('defaults.p2p.enabled')
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import { CONFIG, registerConfigChangedHandler } from './config'
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const LAST_MIGRATION_VERSION = 670
|
||||
const LAST_MIGRATION_VERSION = 675
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -144,6 +144,7 @@ async function createOAuthAdminIfNotExist () {
|
|||
role,
|
||||
verified: true,
|
||||
nsfwPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
|
||||
p2pEnabled: CONFIG.DEFAULTS.P2P.ENABLED,
|
||||
videoQuota: -1,
|
||||
videoQuotaDaily: -1
|
||||
}
|
||||
|
|
21
server/initializers/migrations/0675-p2p-enabled.ts
Normal file
21
server/initializers/migrations/0675-p2p-enabled.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
db: any
|
||||
}): Promise<void> {
|
||||
await utils.queryInterface.renameColumn('user', 'webTorrentEnabled', 'p2pEnabled')
|
||||
|
||||
await utils.sequelize.query('ALTER TABLE "user" ALTER COLUMN "p2pEnabled" DROP DEFAULT')
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
|
@ -226,6 +226,7 @@ async function createUserFromExternal (pluginAuth: string, options: {
|
|||
password: null,
|
||||
email: options.email,
|
||||
nsfwPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
|
||||
p2pEnabled: CONFIG.DEFAULTS.P2P.ENABLED,
|
||||
autoPlayVideo: true,
|
||||
role: options.role,
|
||||
videoQuota: CONFIG.USER.VIDEO_QUOTA,
|
||||
|
|
|
@ -61,6 +61,9 @@ class ServerConfigManager {
|
|||
commentsEnabled: CONFIG.DEFAULTS.PUBLISH.COMMENTS_ENABLED,
|
||||
privacy: CONFIG.DEFAULTS.PUBLISH.PRIVACY,
|
||||
licence: CONFIG.DEFAULTS.PUBLISH.LICENCE
|
||||
},
|
||||
p2p: {
|
||||
enabled: CONFIG.DEFAULTS.P2P.ENABLED
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
isUserDisplayNameValid,
|
||||
isUserNoModal,
|
||||
isUserNSFWPolicyValid,
|
||||
isUserP2PEnabledValid,
|
||||
isUserPasswordValid,
|
||||
isUserPasswordValidOrEmpty,
|
||||
isUserRoleValid,
|
||||
|
@ -239,6 +240,9 @@ const usersUpdateMeValidator = [
|
|||
body('autoPlayVideo')
|
||||
.optional()
|
||||
.custom(isUserAutoPlayVideoValid).withMessage('Should have a valid automatically plays video attribute'),
|
||||
body('p2pEnabled')
|
||||
.optional()
|
||||
.custom(isUserP2PEnabledValid).withMessage('Should have a valid p2p enabled boolean'),
|
||||
body('videoLanguages')
|
||||
.optional()
|
||||
.custom(isUserVideoLanguages).withMessage('Should have a valid video languages attribute'),
|
||||
|
|
|
@ -55,7 +55,7 @@ import {
|
|||
isUserVideoQuotaDailyValid,
|
||||
isUserVideoQuotaValid,
|
||||
isUserVideosHistoryEnabledValid,
|
||||
isUserWebTorrentEnabledValid
|
||||
isUserP2PEnabledValid
|
||||
} from '../../helpers/custom-validators/users'
|
||||
import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto'
|
||||
import { DEFAULT_USER_THEME_NAME, NSFW_POLICY_TYPES } from '../../initializers/constants'
|
||||
|
@ -267,10 +267,9 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
|
|||
nsfwPolicy: NSFWPolicyType
|
||||
|
||||
@AllowNull(false)
|
||||
@Default(true)
|
||||
@Is('UserWebTorrentEnabled', value => throwIfNotValid(value, isUserWebTorrentEnabledValid, 'WebTorrent enabled'))
|
||||
@Is('p2pEnabled', value => throwIfNotValid(value, isUserP2PEnabledValid, 'P2P enabled'))
|
||||
@Column
|
||||
webTorrentEnabled: boolean
|
||||
p2pEnabled: boolean
|
||||
|
||||
@AllowNull(false)
|
||||
@Default(true)
|
||||
|
@ -892,7 +891,11 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
|
|||
emailVerified: this.emailVerified,
|
||||
|
||||
nsfwPolicy: this.nsfwPolicy,
|
||||
webTorrentEnabled: this.webTorrentEnabled,
|
||||
|
||||
// FIXME: deprecated in 4.1
|
||||
webTorrentEnabled: this.p2pEnabled,
|
||||
p2pEnabled: this.p2pEnabled,
|
||||
|
||||
videosHistoryEnabled: this.videosHistoryEnabled,
|
||||
autoPlayVideo: this.autoPlayVideo,
|
||||
autoPlayNextVideo: this.autoPlayNextVideo,
|
||||
|
|
|
@ -21,18 +21,7 @@ describe('Test config defaults', function () {
|
|||
before(async function () {
|
||||
this.timeout(30000)
|
||||
|
||||
const overrideConfig = {
|
||||
defaults: {
|
||||
publish: {
|
||||
comments_enabled: false,
|
||||
download_enabled: false,
|
||||
privacy: VideoPrivacy.INTERNAL,
|
||||
licence: 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
server = await createSingleServer(1, overrideConfig)
|
||||
server = await createSingleServer(1)
|
||||
await setAccessTokensToServers([ server ])
|
||||
await setDefaultVideoChannel([ server ])
|
||||
|
||||
|
@ -40,6 +29,23 @@ describe('Test config defaults', function () {
|
|||
})
|
||||
|
||||
describe('Default publish values', function () {
|
||||
|
||||
before(async function () {
|
||||
const overrideConfig = {
|
||||
defaults: {
|
||||
publish: {
|
||||
comments_enabled: false,
|
||||
download_enabled: false,
|
||||
privacy: VideoPrivacy.INTERNAL,
|
||||
licence: 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await server.kill()
|
||||
await server.run(overrideConfig)
|
||||
})
|
||||
|
||||
const attributes = {
|
||||
name: 'video',
|
||||
downloadEnabled: undefined,
|
||||
|
@ -117,6 +123,45 @@ describe('Test config defaults', function () {
|
|||
})
|
||||
})
|
||||
|
||||
describe('Default P2P values', function () {
|
||||
|
||||
before(async function () {
|
||||
const overrideConfig = {
|
||||
defaults: {
|
||||
p2p: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await server.kill()
|
||||
await server.run(overrideConfig)
|
||||
})
|
||||
|
||||
it('Should not have P2P enabled', async function () {
|
||||
const config = await server.config.getConfig()
|
||||
|
||||
expect(config.defaults.p2p.enabled).to.be.false
|
||||
})
|
||||
|
||||
it('Should create a user with this default setting', async function () {
|
||||
await server.users.create({ username: 'user_p2p_1' })
|
||||
const userToken = await server.login.getAccessToken('user_p2p_1')
|
||||
|
||||
const { p2pEnabled } = await server.users.getMyInfo({ token: userToken })
|
||||
expect(p2pEnabled).to.be.false
|
||||
})
|
||||
|
||||
it('Should register a user with this default setting', async function () {
|
||||
await server.users.register({ username: 'user_p2p_2' })
|
||||
|
||||
const userToken = await server.login.getAccessToken('user_p2p_2')
|
||||
|
||||
const { p2pEnabled } = await server.users.getMyInfo({ token: userToken })
|
||||
expect(p2pEnabled).to.be.false
|
||||
})
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await cleanupTests([ server ])
|
||||
})
|
||||
|
|
|
@ -292,7 +292,7 @@ describe('Test follows', function () {
|
|||
})
|
||||
|
||||
it('Should upload a video on server 2 and 3 and propagate only the video of server 2', async function () {
|
||||
this.timeout(60000)
|
||||
this.timeout(120000)
|
||||
|
||||
await servers[1].videos.upload({ attributes: { name: 'server2' } })
|
||||
await servers[2].videos.upload({ attributes: { name: 'server3' } })
|
||||
|
|
|
@ -559,6 +559,28 @@ describe('Test users', function () {
|
|||
expect(user.autoPlayNextVideo).to.be.true
|
||||
})
|
||||
|
||||
it('Should be able to change the p2p attribute', async function () {
|
||||
{
|
||||
await server.users.updateMe({
|
||||
token: userToken,
|
||||
webTorrentEnabled: false
|
||||
})
|
||||
|
||||
const user = await server.users.getMyInfo({ token: userToken })
|
||||
expect(user.p2pEnabled).to.be.false
|
||||
}
|
||||
|
||||
{
|
||||
await server.users.updateMe({
|
||||
token: userToken,
|
||||
p2pEnabled: true
|
||||
})
|
||||
|
||||
const user = await server.users.getMyInfo({ token: userToken })
|
||||
expect(user.p2pEnabled).to.be.true
|
||||
}
|
||||
})
|
||||
|
||||
it('Should be able to change the email attribute', async function () {
|
||||
await server.users.updateMe({
|
||||
token: userToken,
|
||||
|
|
|
@ -55,6 +55,10 @@ export interface ServerConfig {
|
|||
privacy: VideoPrivacy
|
||||
licence: number
|
||||
}
|
||||
|
||||
p2p: {
|
||||
enabled: boolean
|
||||
}
|
||||
}
|
||||
|
||||
webadmin: {
|
||||
|
|
|
@ -5,7 +5,10 @@ export interface UserUpdateMe {
|
|||
description?: string
|
||||
nsfwPolicy?: NSFWPolicyType
|
||||
|
||||
// FIXME: deprecated in favour of p2pEnabled in 4.1
|
||||
webTorrentEnabled?: boolean
|
||||
p2pEnabled?: boolean
|
||||
|
||||
autoPlayVideo?: boolean
|
||||
autoPlayNextVideo?: boolean
|
||||
autoPlayNextVideoPlaylist?: boolean
|
||||
|
|
|
@ -20,7 +20,11 @@ export interface User {
|
|||
autoPlayVideo: boolean
|
||||
autoPlayNextVideo: boolean
|
||||
autoPlayNextVideoPlaylist: boolean
|
||||
|
||||
// @deprecated in favour of p2pEnabled
|
||||
webTorrentEnabled: boolean
|
||||
p2pEnabled: boolean
|
||||
|
||||
videosHistoryEnabled: boolean
|
||||
videoLanguages: string[]
|
||||
|
||||
|
|
|
@ -6679,7 +6679,7 @@ components:
|
|||
type: integer
|
||||
description: The user daily video quota in bytes
|
||||
example: -1
|
||||
webtorrentEnabled:
|
||||
p2pEnabled:
|
||||
type: boolean
|
||||
description: Enable P2P in the player
|
||||
UserWithStats:
|
||||
|
@ -6780,7 +6780,7 @@ components:
|
|||
- 'true'
|
||||
- 'false'
|
||||
- both
|
||||
webTorrentEnabled:
|
||||
p2pEnabled:
|
||||
type: boolean
|
||||
description: whether to enable P2P in the player or not
|
||||
autoPlayVideo:
|
||||
|
|
Loading…
Reference in a new issue