1
0
Fork 0

Merge branch 'next' into develop

This commit is contained in:
Chocobozzz 2021-07-21 15:51:30 +02:00
commit a24bd1ed41
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
420 changed files with 14672 additions and 16642 deletions

View File

@ -2,11 +2,6 @@ name: Test Suite
on: on:
push: push:
branches:
- develop
- master
- ci
- next
pull_request: pull_request:
types: [synchronize, opened] types: [synchronize, opened]
schedule: schedule:

View File

@ -11,8 +11,7 @@ import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
import { InstanceService } from '@app/shared/shared-instance' import { InstanceService } from '@app/shared/shared-instance'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HTMLServerConfig, HttpStatusCode } from '@shared/models'
import { HTMLServerConfig } from '@shared/models'
type Prefill = { type Prefill = {
subject?: string subject?: string

View File

@ -13,8 +13,7 @@ import {
VideoService VideoService
} from '@app/shared/shared-main' } from '@app/shared/shared-main'
import { AccountReportComponent } from '@app/shared/shared-moderation' import { AccountReportComponent } from '@app/shared/shared-moderation'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode, User, UserRight } from '@shared/models'
import { User, UserRight } from '@shared/models'
import { AccountSearchComponent } from './account-search/account-search.component' import { AccountSearchComponent } from './account-search/account-search.component'
@Component({ @Component({

View File

@ -26,12 +26,12 @@ export class AdminComponent implements OnInit {
label: $localize`Federation`, label: $localize`Federation`,
children: [ children: [
{ {
label: $localize`Instances you follow`, label: $localize`Following`,
routerLink: '/admin/follows/following-list', routerLink: '/admin/follows/following-list',
iconName: 'following' iconName: 'following'
}, },
{ {
label: $localize`Instances following you`, label: $localize`Followers`,
routerLink: '/admin/follows/followers-list', routerLink: '/admin/follows/followers-list',
iconName: 'follower' iconName: 'follower'
}, },

View File

@ -25,7 +25,7 @@ import {
EditVODTranscodingComponent EditVODTranscodingComponent
} from './config' } from './config'
import { ConfigService } from './config/shared/config.service' import { ConfigService } from './config/shared/config.service'
import { FollowersListComponent, FollowsComponent, VideoRedundanciesListComponent } from './follows' import { FollowersListComponent, FollowModalComponent, FollowsComponent, VideoRedundanciesListComponent } from './follows'
import { FollowingListComponent } from './follows/following-list/following-list.component' import { FollowingListComponent } from './follows/following-list/following-list.component'
import { RedundancyCheckboxComponent } from './follows/shared/redundancy-checkbox.component' import { RedundancyCheckboxComponent } from './follows/shared/redundancy-checkbox.component'
import { VideoRedundancyInformationComponent } from './follows/video-redundancies-list/video-redundancy-information.component' import { VideoRedundancyInformationComponent } from './follows/video-redundancies-list/video-redundancy-information.component'
@ -68,6 +68,7 @@ import { UserCreateComponent, UserListComponent, UserPasswordComponent, UsersCom
FollowsComponent, FollowsComponent,
FollowersListComponent, FollowersListComponent,
FollowingListComponent, FollowingListComponent,
FollowModalComponent,
RedundancyCheckboxComponent, RedundancyCheckboxComponent,
VideoRedundanciesListComponent, VideoRedundanciesListComponent,
VideoRedundancyInformationComponent, VideoRedundancyInformationComponent,

View File

@ -1,6 +1,6 @@
<h1> <h1>
<my-global-icon iconName="follower" aria-hidden="true"></my-global-icon> <my-global-icon iconName="follower" aria-hidden="true"></my-global-icon>
<ng-container i18n>Instances following you</ng-container> <ng-container i18n>Followers of your instance</ng-container>
</h1> </h1>
<p-table <p-table
@ -21,7 +21,7 @@
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th style="width: 150px;" i18n>Actions</th> <th style="width: 150px;" i18n>Actions</th>
<th i18n>Follower handle</th> <th i18n>Follower</th>
<th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th> <th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th>
<th style="width: 100px;" i18n pSortableColumn="score">Score <p-sortIcon field="score"></p-sortIcon></th> <th style="width: 100px;" i18n pSortableColumn="score">Score <p-sortIcon field="score"></p-sortIcon></th>
<th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th> <th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>

View File

@ -0,0 +1,42 @@
<ng-template #modal>
<div class="modal-header">
<h4 i18n class="modal-title">Follow</h4>
<my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
</div>
<div class="modal-body">
<form novalidate [formGroup]="form" (ngSubmit)="submit()">
<div class="form-group">
<label i18n for="hostsOrHandles">1 host (without "http://"), account handle or channel handle per line</label>
<textarea
[placeholder]="placeholder" formControlName="hostsOrHandles" type="text" id="hostsOrHandles" name="hostsOrHandles"
class="form-control" [ngClass]="{ 'input-error': formErrors['hostsOrHandles'] }" ngbAutofocus
></textarea>
<div *ngIf="formErrors.hostsOrHandles" class="form-error">
{{ formErrors.hostsOrHandles }}
<div *ngIf="form.controls['hostsOrHandles'].errors.validHostsOrHandles">
{{ form.controls['hostsOrHandles'].errors.validHostsOrHandles.value }}
</div>
</div>
</div>
<div i18n *ngIf="httpEnabled() === false" class="alert alert-warning">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</div>
<div class="form-group inputs">
<input
type="button" role="button" i18n-value value="Cancel" class="peertube-button grey-button"
(click)="hide()" (key.enter)="hide()"
>
<input type="submit" i18n-value value="Follow" class="peertube-button orange-button" [disabled]="!form.valid" />
</div>
</form>
</div>
</ng-template>

View File

@ -0,0 +1,3 @@
textarea {
height: 200px;
}

View File

@ -0,0 +1,69 @@
import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/core'
import { Notifier } from '@app/core'
import { splitAndGetNotEmpty, UNIQUE_HOSTS_OR_HANDLE_VALIDATOR } from '@app/shared/form-validators/host-validators'
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
import { InstanceFollowService } from '@app/shared/shared-instance'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
@Component({
selector: 'my-follow-modal',
templateUrl: './follow-modal.component.html',
styleUrls: [ './follow-modal.component.scss' ]
})
export class FollowModalComponent extends FormReactive implements OnInit {
@ViewChild('modal', { static: true }) modal: NgbModal
@Output() newFollow = new EventEmitter<void>()
placeholder = 'example.com\nchocobozzz@example.com\nchocobozzz_channel@example.com'
private openedModal: NgbModalRef
constructor (
protected formValidatorService: FormValidatorService,
private modalService: NgbModal,
private followService: InstanceFollowService,
private notifier: Notifier
) {
super()
}
ngOnInit () {
this.buildForm({
hostsOrHandles: UNIQUE_HOSTS_OR_HANDLE_VALIDATOR
})
}
openModal () {
this.openedModal = this.modalService.open(this.modal, { centered: true })
}
hide () {
this.openedModal.close()
}
submit () {
this.addFollowing()
this.form.reset()
this.hide()
}
httpEnabled () {
return window.location.protocol === 'https:'
}
private async addFollowing () {
const hostsOrHandles = splitAndGetNotEmpty(this.form.value['hostsOrHandles'])
this.followService.follow(hostsOrHandles).subscribe(
() => {
this.notifier.success($localize`Follow request(s) sent!`)
this.newFollow.emit()
},
err => this.notifier.error(err.message)
)
}
}

View File

@ -1,6 +1,6 @@
<h1> <h1>
<my-global-icon iconName="following" aria-hidden="true"></my-global-icon> <my-global-icon iconName="following" aria-hidden="true"></my-global-icon>
<ng-container i18n>Instances you follow</ng-container> <ng-container i18n>Your instance subscriptions</ng-container>
</h1> </h1>
<p-table <p-table
@ -13,9 +13,9 @@
<ng-template pTemplate="caption"> <ng-template pTemplate="caption">
<div class="caption"> <div class="caption">
<div class="left-buttons"> <div class="left-buttons">
<a class="follow-button" (click)="addDomainsToFollow()" (key.enter)="addDomainsToFollow()"> <a class="follow-button" (click)="openFollowModal()" (key.enter)="openFollowModal()">
<my-global-icon iconName="following" aria-hidden="true"></my-global-icon> <my-global-icon iconName="following" aria-hidden="true"></my-global-icon>
<ng-container i18n>Follow instances</ng-container> <ng-container i18n>Follow</ng-container>
</a> </a>
</div> </div>
@ -28,7 +28,7 @@
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th style="width: 150px;" i18n>Action</th> <th style="width: 150px;" i18n>Action</th>
<th i18n>Host</th> <th i18n>Following</th>
<th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th> <th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th>
<th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th> <th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 160px;" i18n pSortableColumn="redundancyAllowed">Redundancy allowed <p-sortIcon field="redundancyAllowed"></p-sortIcon></th> <th style="width: 160px;" i18n pSortableColumn="redundancyAllowed">Redundancy allowed <p-sortIcon field="redundancyAllowed"></p-sortIcon></th>
@ -41,8 +41,8 @@
<my-delete-button label="Unfollow" i18n-label (click)="removeFollowing(follow)"></my-delete-button> <my-delete-button label="Unfollow" i18n-label (click)="removeFollowing(follow)"></my-delete-button>
</td> </td>
<td> <td>
<a [href]="'https://' + follow.following.host" i18n-title title="Open instance in a new tab" target="_blank" rel="noopener noreferrer"> <a [href]="follow.following.url" i18n-title title="Open instance in a new tab" target="_blank" rel="noopener noreferrer">
{{ follow.following.host }} {{ follow.following.name + '@' + follow.following.host }}
<span class="glyphicon glyphicon-new-window"></span> <span class="glyphicon glyphicon-new-window"></span>
</a> </a>
</td> </td>
@ -57,6 +57,7 @@
<td>{{ follow.createdAt | date: 'short' }}</td> <td>{{ follow.createdAt | date: 'short' }}</td>
<td> <td>
<my-redundancy-checkbox <my-redundancy-checkbox
*ngIf="isInstanceFollowing(follow)"
[host]="follow.following.host" [redundancyAllowed]="follow.following.hostRedundancyAllowed" [host]="follow.following.host" [redundancyAllowed]="follow.following.hostRedundancyAllowed"
></my-redundancy-checkbox> ></my-redundancy-checkbox>
</td> </td>
@ -75,10 +76,4 @@
</ng-template> </ng-template>
</p-table> </p-table>
<my-batch-domains-modal #batchDomainsModal i18n-action action="Follow domains" (domains)="addFollowing($event)"> <my-follow-modal #followModal></my-follow-modal>
<ng-container ngProjectAs="warning">
<div i18n *ngIf="httpEnabled() === false" class="alert alert-warning">
It seems that you are not on a HTTPS server. Your webserver needs to have TLS activated in order to follow servers.
</div>
</ng-container>
</my-batch-domains-modal>

View File

@ -4,13 +4,14 @@ import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
import { InstanceFollowService } from '@app/shared/shared-instance' import { InstanceFollowService } from '@app/shared/shared-instance'
import { BatchDomainsModalComponent } from '@app/shared/shared-moderation' import { BatchDomainsModalComponent } from '@app/shared/shared-moderation'
import { ActorFollow } from '@shared/models' import { ActorFollow } from '@shared/models'
import { FollowModalComponent } from './follow-modal.component'
@Component({ @Component({
templateUrl: './following-list.component.html', templateUrl: './following-list.component.html',
styleUrls: [ '../follows.component.scss', './following-list.component.scss' ] styleUrls: [ '../follows.component.scss', './following-list.component.scss' ]
}) })
export class FollowingListComponent extends RestTable implements OnInit { export class FollowingListComponent extends RestTable implements OnInit {
@ViewChild('batchDomainsModal') batchDomainsModal: BatchDomainsModalComponent @ViewChild('followModal') followModal: FollowModalComponent
following: ActorFollow[] = [] following: ActorFollow[] = []
totalRecords = 0 totalRecords = 0
@ -33,23 +34,12 @@ export class FollowingListComponent extends RestTable implements OnInit {
return 'FollowingListComponent' return 'FollowingListComponent'
} }
addDomainsToFollow () { openFollowModal () {
this.batchDomainsModal.openModal() this.followModal.openModal()
} }
httpEnabled () { isInstanceFollowing (follow: ActorFollow) {
return window.location.protocol === 'https:' return follow.following.name === 'peertube'
}
async addFollowing (hosts: string[]) {
this.followService.follow(hosts).subscribe(
() => {
this.notifier.success($localize`Follow request(s) sent!`)
this.reloadData()
},
err => this.notifier.error(err.message)
)
} }
async removeFollowing (follow: ActorFollow) { async removeFollowing (follow: ActorFollow) {

View File

@ -1 +1,2 @@
export * from './follow-modal.component'
export * from './following-list.component' export * from './following-list.component'

View File

@ -25,7 +25,7 @@ export const FollowsRoutes: Routes = [
component: FollowingListComponent, component: FollowingListComponent,
data: { data: {
meta: { meta: {
title: $localize`Following list` title: $localize`Following`
} }
} }
}, },
@ -34,7 +34,7 @@ export const FollowsRoutes: Routes = [
component: FollowersListComponent, component: FollowersListComponent,
data: { data: {
meta: { meta: {
title: $localize`Followers list` title: $localize`Followers`
} }
} }
}, },

View File

@ -28,6 +28,10 @@
<div *ngIf="formErrors.username" class="form-error"> <div *ngIf="formErrors.username" class="form-error">
{{ formErrors.username }} {{ formErrors.username }}
</div> </div>
<div *ngIf="hasUsernameUppercase()" i18n class="form-warning">
⚠️ Most email addresses do not include capital letters.
</div>
</div> </div>
<div class="form-group"> <div class="form-group">

View File

@ -141,6 +141,10 @@ The link will expire within 1 hour.`
this.accordion = instanceAboutAccordion.accordion this.accordion = instanceAboutAccordion.accordion
} }
hasUsernameUppercase () {
return this.form.value['username'].match(/[A-Z]/)
}
private loadExternalAuthToken (username: string, token: string) { private loadExternalAuthToken (username: string, token: string) {
this.isAuthenticatedWithExternalAuth = true this.isAuthenticatedWithExternalAuth = true

View File

@ -1,3 +1,5 @@
import { of } from 'rxjs'
import { switchMap } from 'rxjs/operators'
import { Component, OnInit } from '@angular/core' import { Component, OnInit } from '@angular/core'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { AuthService, Notifier } from '@app/core' import { AuthService, Notifier } from '@app/core'
@ -9,11 +11,8 @@ import {
} from '@app/shared/form-validators/video-channel-validators' } from '@app/shared/form-validators/video-channel-validators'
import { FormValidatorService } from '@app/shared/shared-forms' import { FormValidatorService } from '@app/shared/shared-forms'
import { VideoChannel, VideoChannelService } from '@app/shared/shared-main' import { VideoChannel, VideoChannelService } from '@app/shared/shared-main'
import { VideoChannelCreate } from '@shared/models' import { HttpStatusCode, VideoChannelCreate } from '@shared/models'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
import { MyVideoChannelEdit } from './my-video-channel-edit' import { MyVideoChannelEdit } from './my-video-channel-edit'
import { switchMap } from 'rxjs/operators'
import { of } from 'rxjs'
@Component({ @Component({
templateUrl: './my-video-channel-edit.component.html', templateUrl: './my-video-channel-edit.component.html',

View File

@ -45,9 +45,9 @@ export class MyVideoChannelsComponent {
It will delete ${videoChannel.videosCount} videos uploaded in this channel, and you will not be able to create another It will delete ${videoChannel.videosCount} videos uploaded in this channel, and you will not be able to create another
channel with the same name (${videoChannel.name})!`, channel with the same name (${videoChannel.name})!`,
$localize`Please type the display name of the video channel (${videoChannel.displayName}) to confirm`, $localize`Please type the name of the video channel (${videoChannel.name}) to confirm`,
videoChannel.displayName, videoChannel.name,
$localize`Delete` $localize`Delete`
) )

View File

@ -1,7 +1,8 @@
import { Component, OnInit } from '@angular/core' import { Component, OnInit } from '@angular/core'
import { Title } from '@angular/platform-browser' import { Title } from '@angular/platform-browser'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '@shared/models'
@Component({ @Component({
selector: 'my-page-not-found', selector: 'my-page-not-found',
templateUrl: './page-not-found.component.html', templateUrl: './page-not-found.component.html',

View File

@ -7,7 +7,7 @@ import { AuthService, MarkdownService, Notifier, RestExtractor, ScreenService }
import { ListOverflowItem, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main' import { ListOverflowItem, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main'
import { SupportModalComponent } from '@app/shared/shared-support-modal' import { SupportModalComponent } from '@app/shared/shared-support-modal'
import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription' import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '@shared/models'
@Component({ @Component({
templateUrl: './video-channels.component.html', templateUrl: './video-channels.component.html',

View File

@ -7,8 +7,7 @@ import { genericUploadErrorHandler, scrollToTop } from '@app/helpers'
import { FormValidatorService } from '@app/shared/shared-forms' import { FormValidatorService } from '@app/shared/shared-forms'
import { BytesPipe, Video, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' import { BytesPipe, Video, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main'
import { LoadingBarService } from '@ngx-loading-bar/core' import { LoadingBarService } from '@ngx-loading-bar/core'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode, VideoPrivacy } from '@shared/models'
import { VideoPrivacy } from '@shared/models'
import { UploaderXFormData } from './uploaderx-form-data' import { UploaderXFormData } from './uploaderx-form-data'
import { VideoSend } from './video-send' import { VideoSend } from './video-send'

View File

@ -21,8 +21,15 @@ import { isXPercentInViewport, scrollToTop } from '@app/helpers'
import { Video, VideoCaptionService, VideoDetails, VideoService } from '@app/shared/shared-main' import { Video, VideoCaptionService, VideoDetails, VideoService } from '@app/shared/shared-main'
import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription' import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription'
import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist' import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import {
import { HTMLServerConfig, PeerTubeProblemDocument, ServerErrorCode, VideoCaption, VideoPrivacy, VideoState } from '@shared/models' HTMLServerConfig,
HttpStatusCode,
PeerTubeProblemDocument,
ServerErrorCode,
VideoCaption,
VideoPrivacy,
VideoState
} from '@shared/models'
import { cleanupVideoWatch, getStoredTheater, getStoredVideoWatchHistory } from '../../../assets/player/peertube-player-local-storage' import { cleanupVideoWatch, getStoredTheater, getStoredVideoWatchHistory } from '../../../assets/player/peertube-player-local-storage'
import { import {
CustomizationOptions, CustomizationOptions,

View File

@ -6,12 +6,11 @@ import { Injectable } from '@angular/core'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { Notifier } from '@app/core/notification/notifier.service' import { Notifier } from '@app/core/notification/notifier.service'
import { objectToUrlEncoded, peertubeLocalStorage } from '@root-helpers/index' import { objectToUrlEncoded, peertubeLocalStorage } from '@root-helpers/index'
import { MyUser as UserServerModel, OAuthClientLocal, User, UserLogin, UserRefreshToken } from '@shared/models' import { HttpStatusCode, MyUser as UserServerModel, OAuthClientLocal, User, UserLogin, UserRefreshToken } from '@shared/models'
import { environment } from '../../../environments/environment' import { environment } from '../../../environments/environment'
import { RestExtractor } from '../rest/rest-extractor.service' import { RestExtractor } from '../rest/rest-extractor.service'
import { AuthStatus } from './auth-status.model' import { AuthStatus } from './auth-status.model'
import { AuthUser } from './auth-user.model' import { AuthUser } from './auth-user.model'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
interface UserLoginWithUsername extends UserLogin { interface UserLoginWithUsername extends UserLogin {
access_token: string access_token: string

View File

@ -2,8 +2,7 @@ import { throwError as observableThrowError } from 'rxjs'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { dateToHuman } from '@app/helpers' import { dateToHuman } from '@app/helpers'
import { ResultList } from '@shared/models' import { HttpStatusCode, ResultList } from '@shared/models'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
@Injectable() @Injectable()
export class RestExtractor { export class RestExtractor {

View File

@ -3,7 +3,7 @@ import { SelectChannelItem } from 'src/types/select-options-item.model'
import { DatePipe } from '@angular/common' import { DatePipe } from '@angular/common'
import { HttpErrorResponse } from '@angular/common/http' import { HttpErrorResponse } from '@angular/common/http'
import { Notifier } from '@app/core' import { Notifier } from '@app/core'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '@shared/models'
import { environment } from '../../environments/environment' import { environment } from '../../environments/environment'
import { AuthService } from '../core/auth' import { AuthService } from '../core/auth'

View File

@ -1,60 +0,0 @@
import { AbstractControl, FormControl, ValidatorFn, Validators } from '@angular/forms'
import { BuildFormValidator } from './form-validator.model'
import { validateHost } from './host'
export function getNotEmptyHosts (hosts: string) {
return hosts
.split('\n')
.filter((host: string) => host && host.length !== 0) // Eject empty hosts
}
const validDomains: ValidatorFn = (control: FormControl) => {
if (!control.value) return null
const newHostsErrors = []
const hosts = getNotEmptyHosts(control.value)
for (const host of hosts) {
if (validateHost(host) === false) {
newHostsErrors.push($localize`${host} is not valid`)
}
}
/* Is not valid. */
if (newHostsErrors.length !== 0) {
return {
'validDomains': {
reason: 'invalid',
value: newHostsErrors.join('. ') + '.'
}
}
}
/* Is valid. */
return null
}
const isHostsUnique: ValidatorFn = (control: AbstractControl) => {
if (!control.value) return null
const hosts = getNotEmptyHosts(control.value)
if (hosts.every((host: string) => hosts.indexOf(host) === hosts.lastIndexOf(host))) {
return null
} else {
return {
'uniqueDomains': {
reason: 'invalid'
}
}
}
}
export const DOMAINS_VALIDATOR: BuildFormValidator = {
VALIDATORS: [Validators.required, validDomains, isHostsUnique],
MESSAGES: {
'required': $localize`Domain is required.`,
'validDomains': $localize`Domains entered are invalid.`,
'uniqueDomains': $localize`Domains entered contain duplicates.`
}
}

View File

@ -0,0 +1,105 @@
import { AbstractControl, ValidatorFn, Validators } from '@angular/forms'
import { BuildFormValidator } from './form-validator.model'
function validateHost (value: string) {
// Thanks to http://stackoverflow.com/a/106223
const HOST_REGEXP = new RegExp(
'^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$'
)
return HOST_REGEXP.test(value)
}
function validateHandle (value: string) {
if (!value) return false
return value.includes('@')
}
const validHosts: ValidatorFn = (control: AbstractControl) => {
if (!control.value) return null
const errors = []
const hosts = splitAndGetNotEmpty(control.value)
for (const host of hosts) {
if (validateHost(host) === false) {
errors.push($localize`${host} is not valid`)
}
}
// valid
if (errors.length === 0) return null
return {
'validHosts': {
reason: 'invalid',
value: errors.join('. ') + '.'
}
}
}
const validHostsOrHandles: ValidatorFn = (control: AbstractControl) => {
if (!control.value) return null
const errors = []
const lines = splitAndGetNotEmpty(control.value)
for (const line of lines) {
if (validateHost(line) === false && validateHandle(line) === false) {
errors.push($localize`${line} is not valid`)
}
}
// valid
if (errors.length === 0) return null
return {
'validHostsOrHandles': {
reason: 'invalid',
value: errors.join('. ') + '.'
}
}
}
// ---------------------------------------------------------------------------
export function splitAndGetNotEmpty (value: string) {
return value
.split('\n')
.filter(line => line && line.length !== 0) // Eject empty hosts
}
export const unique: ValidatorFn = (control: AbstractControl) => {
if (!control.value) return null
const hosts = splitAndGetNotEmpty(control.value)
if (hosts.every((host: string) => hosts.indexOf(host) === hosts.lastIndexOf(host))) {
return null
}
return {
'unique': {
reason: 'invalid'
}
}
}
export const UNIQUE_HOSTS_VALIDATOR: BuildFormValidator = {
VALIDATORS: [ Validators.required, validHosts, unique ],
MESSAGES: {
'required': $localize`Domain is required.`,
'validHosts': $localize`Hosts entered are invalid.`,
'unique': $localize`Hosts entered contain duplicates.`
}
}
export const UNIQUE_HOSTS_OR_HANDLE_VALIDATOR: BuildFormValidator = {
VALIDATORS: [ Validators.required, validHostsOrHandles, unique ],
MESSAGES: {
'required': $localize`Domain is required.`,
'validHostsOrHandles': $localize`Hosts or handles are invalid.`,
'unique': $localize`Hosts or handles contain duplicates.`
}
}

View File

@ -1,8 +0,0 @@
export function validateHost (value: string) {
// Thanks to http://stackoverflow.com/a/106223
const HOST_REGEXP = new RegExp(
'^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$'
)
return HOST_REGEXP.test(value)
}

View File

@ -1,7 +1,6 @@
export * from './form-validator.model' export * from './form-validator.model'
export * from './host'
// Don't re export const variables because webpack 4 cannot do tree shaking with them // Don't re export const variables because webpack cannot do tree shaking with them
// export * from './abuse-validators' // export * from './abuse-validators'
// export * from './batch-domains-validators' // export * from './batch-domains-validators'
// export * from './custom-config-validators' // export * from './custom-config-validators'

View File

@ -4,7 +4,7 @@ import { catchError, map } from 'rxjs/operators'
import { HttpClient, HttpParams } from '@angular/common/http' import { HttpClient, HttpParams } from '@angular/common/http'
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { RestExtractor, RestPagination, RestService } from '@app/core' import { RestExtractor, RestPagination, RestService } from '@app/core'
import { ActivityPubActorType, ActorFollow, FollowState, ResultList } from '@shared/models' import { ActivityPubActorType, ActorFollow, FollowState, ResultList, ServerFollowCreate } from '@shared/models'
import { environment } from '../../../environments/environment' import { environment } from '../../../environments/environment'
@Injectable() @Injectable()
@ -64,9 +64,10 @@ export class InstanceFollowService {
) )
} }
follow (notEmptyHosts: string[]) { follow (hostsOrHandles: string[]) {
const body = { const body: ServerFollowCreate = {
hosts: notEmptyHosts handles: hostsOrHandles.filter(v => v.includes('@')),
hosts: hostsOrHandles.filter(v => !v.includes('@'))
} }
return this.authHttp.post(InstanceFollowService.BASE_APPLICATION_URL + '/following', body) return this.authHttp.post(InstanceFollowService.BASE_APPLICATION_URL + '/following', body)
@ -77,7 +78,9 @@ export class InstanceFollowService {
} }
unfollow (follow: ActorFollow) { unfollow (follow: ActorFollow) {
return this.authHttp.delete(InstanceFollowService.BASE_APPLICATION_URL + '/following/' + follow.following.host) const handle = follow.following.name + '@' + follow.following.host
return this.authHttp.delete(InstanceFollowService.BASE_APPLICATION_URL + '/following/' + handle)
.pipe( .pipe(
map(this.restExtractor.extractDataBool), map(this.restExtractor.extractDataBool),
catchError(res => this.restExtractor.handleError(res)) catchError(res => this.restExtractor.handleError(res))

View File

@ -1,11 +1,11 @@
import { Observable, of, throwError as observableThrowError } from 'rxjs' import { Observable, of, throwError as observableThrowError } from 'rxjs'
import { catchError, switchMap } from 'rxjs/operators' import { catchError, switchMap } from 'rxjs/operators'
import { HTTP_INTERCEPTORS, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpErrorResponse } from '@angular/common/http' import { HTTP_INTERCEPTORS, HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'
import { Injectable, Injector } from '@angular/core' import { Injectable, Injector } from '@angular/core'
import { AuthService } from '@app/core/auth/auth.service'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { AuthService } from '@app/core/auth/auth.service'
import { OAuth2ErrorCode, PeerTubeProblemDocument, ServerErrorCode } from '@shared/models/server' import { HttpStatusCode } from '@shared/models'
import { OAuth2ErrorCode, PeerTubeProblemDocument } from '@shared/models/server'
@Injectable() @Injectable()
export class AuthInterceptor implements HttpInterceptor { export class AuthInterceptor implements HttpInterceptor {

View File

@ -1,6 +1,6 @@
<ng-template #modal> <ng-template #modal>
<div class="modal-header"> <div class="modal-header">
<h4 i18n class="modal-title">{{ action }}</h4> <h4 class="modal-title">{{ action }}</h4>
<my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon> <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
</div> </div>
@ -11,15 +11,15 @@
<label i18n for="hosts">1 host (without "http://") per line</label> <label i18n for="hosts">1 host (without "http://") per line</label>
<textarea <textarea
[placeholder]="placeholder" formControlName="domains" type="text" id="hosts" name="hosts" [placeholder]="placeholder" formControlName="hosts" type="text" id="hosts" name="hosts"
class="form-control" [ngClass]="{ 'input-error': formErrors['domains'] }" ngbAutofocus class="form-control" [ngClass]="{ 'input-error': formErrors['hosts'] }" ngbAutofocus
></textarea> ></textarea>
<div *ngIf="formErrors.domains" class="form-error"> <div *ngIf="formErrors.hosts" class="form-error">
{{ formErrors.domains }} {{ formErrors.hosts }}
<div *ngIf="form.controls['domains'].errors.validDomains"> <div *ngIf="form.controls['hosts'].errors.validHosts">
{{ form.controls['domains'].errors.validDomains.value }} {{ form.controls['hosts'].errors.validHosts.value }}
</div> </div>
</div> </div>
</div> </div>

View File

@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angu
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
import { DOMAINS_VALIDATOR, getNotEmptyHosts } from '../form-validators/batch-domains-validators' import { splitAndGetNotEmpty, UNIQUE_HOSTS_VALIDATOR } from '../form-validators/host-validators'
@Component({ @Component({
selector: 'my-batch-domains-modal', selector: 'my-batch-domains-modal',
@ -28,7 +28,7 @@ export class BatchDomainsModalComponent extends FormReactive implements OnInit {
if (!this.action) this.action = $localize`Process domains` if (!this.action) this.action = $localize`Process domains`
this.buildForm({ this.buildForm({
domains: DOMAINS_VALIDATOR hosts: UNIQUE_HOSTS_VALIDATOR
}) })
} }
@ -41,9 +41,7 @@ export class BatchDomainsModalComponent extends FormReactive implements OnInit {
} }
submit () { submit () {
this.domains.emit( this.domains.emit(splitAndGetNotEmpty(this.form.controls['hosts'].value))
getNotEmptyHosts(this.form.controls['domains'].value)
)
this.form.reset() this.form.reset()
this.hide() this.hide()
} }

View File

@ -123,12 +123,16 @@ code {
vertical-align: middle; vertical-align: middle;
} }
.form-error { .form-error,
.form-warning {
display: block; display: block;
color: $red;
margin-top: 5px; margin-top: 5px;
} }
.form-error {
color: $red;
}
.input-error, .input-error,
my-input-toggle-hidden ::ng-deep input { my-input-toggle-hidden ::ng-deep input {
border-color: $red !important; border-color: $red !important;

View File

@ -1,9 +1,9 @@
import './embed.scss' import './embed.scss'
import videojs from 'video.js' import videojs from 'video.js'
import { peertubeTranslate } from '../../../../shared/core-utils/i18n' import { peertubeTranslate } from '../../../../shared/core-utils/i18n'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import { import {
HTMLServerConfig, HTMLServerConfig,
HttpStatusCode,
OAuth2ErrorCode, OAuth2ErrorCode,
ResultList, ResultList,
UserRefreshToken, UserRefreshToken,

View File

@ -1,22 +1,12 @@
import * as autocannon from 'autocannon'
import { writeJson } from 'fs-extra'
import { createSingleServer, killallServers, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
import { Video, VideoPrivacy } from '@shared/models'
import { registerTSPaths } from '../server/helpers/register-ts-paths' import { registerTSPaths } from '../server/helpers/register-ts-paths'
registerTSPaths() registerTSPaths()
import * as autocannon from 'autocannon' let server: PeerTubeServer
import {
addVideoCommentReply,
addVideoCommentThread,
createVideoCaption,
flushAndRunServer,
getVideosList,
killallServers,
ServerInfo,
setAccessTokensToServers,
uploadVideo
} from '@shared/extra-utils'
import { Video, VideoPrivacy } from '@shared/models'
import { writeJson } from 'fs-extra'
let server: ServerInfo
let video: Video let video: Video
let threadId: number let threadId: number
@ -25,7 +15,7 @@ const outfile = process.argv[2]
run() run()
.catch(err => console.error(err)) .catch(err => console.error(err))
.finally(() => { .finally(() => {
if (server) killallServers([ server ]) if (server) return killallServers([ server ])
}) })
function buildAuthorizationHeader () { function buildAuthorizationHeader () {
@ -198,7 +188,7 @@ function runBenchmark (options: {
} }
async function prepare () { async function prepare () {
server = await flushAndRunServer(1, { server = await createSingleServer(1, {
rates_limit: { rates_limit: {
api: { api: {
max: 5_000_000 max: 5_000_000
@ -207,7 +197,7 @@ async function prepare () {
}) })
await setAccessTokensToServers([ server ]) await setAccessTokensToServers([ server ])
const videoAttributes = { const attributes = {
name: 'my super video', name: 'my super video',
category: 2, category: 2,
nsfw: true, nsfw: true,
@ -220,33 +210,29 @@ async function prepare () {
} }
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
Object.assign(videoAttributes, { name: 'my super video ' + i }) await server.videos.upload({ attributes: { ...attributes, name: 'my super video ' + i } })
await uploadVideo(server.url, server.accessToken, videoAttributes)
} }
const resVideos = await getVideosList(server.url) const { data } = await server.videos.list()
video = resVideos.body.data.find(v => v.name === 'my super video 1') video = data.find(v => v.name === 'my super video 1')
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
const text = 'my super first comment' const text = 'my super first comment'
const res = await addVideoCommentThread(server.url, server.accessToken, video.id, text) const created = await server.comments.createThread({ videoId: video.id, text })
threadId = res.body.comment.id threadId = created.id
const text1 = 'my super answer to thread 1' const text1 = 'my super answer to thread 1'
const childCommentRes = await addVideoCommentReply(server.url, server.accessToken, video.id, threadId, text1) const child = await server.comments.addReply({ videoId: video.id, toCommentId: threadId, text: text1 })
const childCommentId = childCommentRes.body.comment.id
const text2 = 'my super answer to answer of thread 1' const text2 = 'my super answer to answer of thread 1'
await addVideoCommentReply(server.url, server.accessToken, video.id, childCommentId, text2) await server.comments.addReply({ videoId: video.id, toCommentId: child.id, text: text2 })
const text3 = 'my second answer to thread 1' const text3 = 'my second answer to thread 1'
await addVideoCommentReply(server.url, server.accessToken, video.id, threadId, text3) await server.comments.addReply({ videoId: video.id, toCommentId: threadId, text: text3 })
} }
for (const caption of [ 'ar', 'fr', 'en', 'zh' ]) { for (const caption of [ 'ar', 'fr', 'en', 'zh' ]) {
await createVideoCaption({ await server.captions.add({
url: server.url,
accessToken: server.accessToken,
language: caption, language: caption,
videoId: video.id, videoId: video.id,
fixture: 'subtitle-good2.vtt' fixture: 'subtitle-good2.vtt'

View File

@ -1,7 +1,7 @@
import { registerTSPaths } from '../server/helpers/register-ts-paths' import { registerTSPaths } from '../server/helpers/register-ts-paths'
registerTSPaths() registerTSPaths()
import { execCLI } from '@shared/extra-utils' import { CLICommand } from '@shared/extra-utils'
run() run()
.then(() => process.exit(0)) .then(() => process.exit(0))
@ -59,7 +59,7 @@ async function run () {
} }
async function getGitContributors () { async function getGitContributors () {
const output = await execCLI(`git --no-pager shortlog -sn < /dev/tty | sed 's/^\\s\\+[0-9]\\+\\s\\+//g'`) const output = await CLICommand.exec(`git --no-pager shortlog -sn < /dev/tty | sed 's/^\\s\\+[0-9]\\+\\s\\+//g'`)
return output.split('\n') return output.split('\n')
.filter(l => !!l) .filter(l => !!l)

View File

@ -125,7 +125,7 @@ import { PeerTubeVersionCheckScheduler } from './server/lib/schedulers/peertube-
import { Hooks } from './server/lib/plugins/hooks' import { Hooks } from './server/lib/plugins/hooks'
import { PluginManager } from './server/lib/plugins/plugin-manager' import { PluginManager } from './server/lib/plugins/plugin-manager'
import { LiveManager } from './server/lib/live' import { LiveManager } from './server/lib/live'
import { HttpStatusCode } from './shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from './shared/models/http/http-error-codes'
import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache' import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache'
import { ServerConfigManager } from '@server/lib/server-config-manager' import { ServerConfigManager } from '@server/lib/server-config-manager'

View File

@ -1,7 +1,7 @@
import * as express from 'express' import * as express from 'express'
import { InboxManager } from '@server/lib/activitypub/inbox-manager' import { InboxManager } from '@server/lib/activitypub/inbox-manager'
import { Activity, ActivityPubCollection, ActivityPubOrderedCollection, RootActivity } from '../../../shared' import { Activity, ActivityPubCollection, ActivityPubOrderedCollection, RootActivity } from '../../../shared'
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isActivityValid } from '../../helpers/custom-validators/activitypub/activity' import { isActivityValid } from '../../helpers/custom-validators/activitypub/activity'
import { logger } from '../../helpers/logger' import { logger } from '../../helpers/logger'
import { asyncMiddleware, checkSignature, localAccountValidator, localVideoChannelValidator, signatureValidator } from '../../middlewares' import { asyncMiddleware, checkSignature, localAccountValidator, localVideoChannelValidator, signatureValidator } from '../../middlewares'

View File

@ -6,7 +6,7 @@ import { AbuseModel } from '@server/models/abuse/abuse'
import { AbuseMessageModel } from '@server/models/abuse/abuse-message' import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
import { getServerActor } from '@server/models/application/application' import { getServerActor } from '@server/models/application/application'
import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse' import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '@shared/models'
import { AbuseCreate, AbuseState, UserRight } from '../../../shared' import { AbuseCreate, AbuseState, UserRight } from '../../../shared'
import { getFormattedObjects } from '../../helpers/utils' import { getFormattedObjects } from '../../helpers/utils'
import { sequelizeTypescript } from '../../initializers/database' import { sequelizeTypescript } from '../../initializers/database'

View File

@ -1,10 +1,10 @@
import * as express from 'express' import * as express from 'express'
import { asyncMiddleware, authenticate } from '../../middlewares' import { removeComment } from '@server/lib/video-comment'
import { bulkRemoveCommentsOfValidator } from '@server/middlewares/validators/bulk' import { bulkRemoveCommentsOfValidator } from '@server/middlewares/validators/bulk'
import { VideoCommentModel } from '@server/models/video/video-comment' import { VideoCommentModel } from '@server/models/video/video-comment'
import { removeComment } from '@server/lib/video-comment' import { HttpStatusCode } from '@shared/models'
import { BulkRemoveCommentsOfBody } from '@shared/models/bulk/bulk-remove-comments-of-body.model' import { BulkRemoveCommentsOfBody } from '@shared/models/bulk/bulk-remove-comments-of-body.model'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { asyncMiddleware, authenticate } from '../../middlewares'
const bulkRouter = express.Router() const bulkRouter = express.Router()

View File

@ -1,8 +1,8 @@
import { ServerConfigManager } from '@server/lib/server-config-manager'
import * as express from 'express' import * as express from 'express'
import { remove, writeJSON } from 'fs-extra' import { remove, writeJSON } from 'fs-extra'
import { snakeCase } from 'lodash' import { snakeCase } from 'lodash'
import validator from 'validator' import validator from 'validator'
import { ServerConfigManager } from '@server/lib/server-config-manager'
import { UserRight } from '../../../shared' import { UserRight } from '../../../shared'
import { About } from '../../../shared/models/server/about.model' import { About } from '../../../shared/models/server/about.model'
import { CustomConfig } from '../../../shared/models/server/custom-config.model' import { CustomConfig } from '../../../shared/models/server/custom-config.model'

View File

@ -1,8 +1,7 @@
import * as express from 'express' import * as express from 'express'
import { ServerConfigManager } from '@server/lib/server-config-manager' import { ServerConfigManager } from '@server/lib/server-config-manager'
import { ActorCustomPageModel } from '@server/models/account/actor-custom-page' import { ActorCustomPageModel } from '@server/models/account/actor-custom-page'
import { HttpStatusCode } from '@shared/core-utils' import { HttpStatusCode, UserRight } from '@shared/models'
import { UserRight } from '@shared/models'
import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares' import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares'
const customPageRouter = express.Router() const customPageRouter = express.Router()

View File

@ -1,7 +1,7 @@
import * as cors from 'cors' import * as cors from 'cors'
import * as express from 'express' import * as express from 'express'
import * as RateLimit from 'express-rate-limit' import * as RateLimit from 'express-rate-limit'
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../shared/models'
import { badRequest } from '../../helpers/express-utils' import { badRequest } from '../../helpers/express-utils'
import { CONFIG } from '../../initializers/config' import { CONFIG } from '../../initializers/config'
import { abuseRouter } from './abuse' import { abuseRouter } from './abuse'

View File

@ -1,6 +1,6 @@
import * as express from 'express' import * as express from 'express'
import { OAuthClientLocal } from '../../../shared' import { OAuthClientLocal } from '../../../shared'
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { logger } from '../../helpers/logger' import { logger } from '../../helpers/logger'
import { CONFIG } from '../../initializers/config' import { CONFIG } from '../../initializers/config'
import { asyncMiddleware, openapiOperationDoc } from '../../middlewares' import { asyncMiddleware, openapiOperationDoc } from '../../middlewares'

View File

@ -1,12 +1,12 @@
import * as express from 'express' import * as express from 'express'
import { buildNSFWFilter } from '../../helpers/express-utils'
import { VideoModel } from '../../models/video/video'
import { asyncMiddleware, optionalAuthenticate, videosOverviewValidator } from '../../middlewares'
import { TagModel } from '../../models/video/tag'
import { CategoryOverview, ChannelOverview, TagOverview, VideosOverview } from '../../../shared/models/overviews'
import { MEMOIZE_TTL, OVERVIEWS } from '../../initializers/constants'
import * as memoizee from 'memoizee' import * as memoizee from 'memoizee'
import { logger } from '@server/helpers/logger' import { logger } from '@server/helpers/logger'
import { CategoryOverview, ChannelOverview, TagOverview, VideosOverview } from '../../../shared/models/overviews'
import { buildNSFWFilter } from '../../helpers/express-utils'
import { MEMOIZE_TTL, OVERVIEWS } from '../../initializers/constants'
import { asyncMiddleware, optionalAuthenticate, videosOverviewValidator } from '../../middlewares'
import { TagModel } from '../../models/video/tag'
import { VideoModel } from '../../models/video/video'
const overviewsRouter = express.Router() const overviewsRouter = express.Router()

View File

@ -23,8 +23,8 @@ import {
updatePluginSettingsValidator updatePluginSettingsValidator
} from '@server/middlewares/validators/plugins' } from '@server/middlewares/validators/plugins'
import { PluginModel } from '@server/models/server/plugin' import { PluginModel } from '@server/models/server/plugin'
import { HttpStatusCode } from '@shared/core-utils'
import { import {
HttpStatusCode,
InstallOrUpdatePlugin, InstallOrUpdatePlugin,
ManagePlugin, ManagePlugin,
PeertubePluginIndexList, PeertubePluginIndexList,

View File

@ -6,8 +6,7 @@ import { WEBSERVER } from '@server/initializers/constants'
import { Hooks } from '@server/lib/plugins/hooks' import { Hooks } from '@server/lib/plugins/hooks'
import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search' import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search'
import { getServerActor } from '@server/models/application/application' import { getServerActor } from '@server/models/application/application'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode, ResultList, VideoChannel } from '@shared/models'
import { ResultList, VideoChannel } from '@shared/models'
import { VideoChannelsSearchQuery } from '../../../../shared/models/search' import { VideoChannelsSearchQuery } from '../../../../shared/models/search'
import { isUserAbleToSearchRemoteURI } from '../../../helpers/express-utils' import { isUserAbleToSearchRemoteURI } from '../../../helpers/express-utils'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'

View File

@ -5,14 +5,14 @@ import { logger } from '@server/helpers/logger'
import { doJSONRequest } from '@server/helpers/requests' import { doJSONRequest } from '@server/helpers/requests'
import { getFormattedObjects } from '@server/helpers/utils' import { getFormattedObjects } from '@server/helpers/utils'
import { CONFIG } from '@server/initializers/config' import { CONFIG } from '@server/initializers/config'
import { WEBSERVER } from '@server/initializers/constants'
import { getOrCreateAPVideoPlaylist } from '@server/lib/activitypub/playlists/get' import { getOrCreateAPVideoPlaylist } from '@server/lib/activitypub/playlists/get'
import { Hooks } from '@server/lib/plugins/hooks' import { Hooks } from '@server/lib/plugins/hooks'
import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search' import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search'
import { getServerActor } from '@server/models/application/application' import { getServerActor } from '@server/models/application/application'
import { VideoPlaylistModel } from '@server/models/video/video-playlist' import { VideoPlaylistModel } from '@server/models/video/video-playlist'
import { MVideoPlaylistFullSummary } from '@server/types/models' import { MVideoPlaylistFullSummary } from '@server/types/models'
import { HttpStatusCode } from '@shared/core-utils' import { HttpStatusCode, ResultList, VideoPlaylist, VideoPlaylistsSearchQuery } from '@shared/models'
import { ResultList, VideoPlaylist, VideoPlaylistsSearchQuery } from '@shared/models'
import { import {
asyncMiddleware, asyncMiddleware,
openapiOperationDoc, openapiOperationDoc,
@ -23,7 +23,6 @@ import {
videoPlaylistsListSearchValidator, videoPlaylistsListSearchValidator,
videoPlaylistsSearchSortValidator videoPlaylistsSearchSortValidator
} from '../../../middlewares' } from '../../../middlewares'
import { WEBSERVER } from '@server/initializers/constants'
const searchPlaylistsRouter = express.Router() const searchPlaylistsRouter = express.Router()

View File

@ -6,8 +6,7 @@ import { WEBSERVER } from '@server/initializers/constants'
import { getOrCreateAPVideo } from '@server/lib/activitypub/videos' import { getOrCreateAPVideo } from '@server/lib/activitypub/videos'
import { Hooks } from '@server/lib/plugins/hooks' import { Hooks } from '@server/lib/plugins/hooks'
import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search' import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode, ResultList, Video } from '@shared/models'
import { ResultList, Video } from '@shared/models'
import { VideosSearchQuery } from '../../../../shared/models/search' import { VideosSearchQuery } from '../../../../shared/models/search'
import { buildNSFWFilter, isUserAbleToSearchRemoteURI } from '../../../helpers/express-utils' import { buildNSFWFilter, isUserAbleToSearchRemoteURI } from '../../../helpers/express-utils'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'

View File

@ -1,9 +1,9 @@
import * as express from 'express' import * as express from 'express'
import { asyncMiddleware, contactAdministratorValidator } from '../../../middlewares' import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { Redis } from '../../../lib/redis'
import { Emailer } from '../../../lib/emailer'
import { ContactForm } from '../../../../shared/models/server' import { ContactForm } from '../../../../shared/models/server'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { Emailer } from '../../../lib/emailer'
import { Redis } from '../../../lib/redis'
import { asyncMiddleware, contactAdministratorValidator } from '../../../middlewares'
const contactRouter = express.Router() const contactRouter = express.Router()
@ -15,7 +15,7 @@ contactRouter.post('/contact',
async function contactAdministrator (req: express.Request, res: express.Response) { async function contactAdministrator (req: express.Request, res: express.Response) {
const data = req.body as ContactForm const data = req.body as ContactForm
await Emailer.Instance.addContactFormJob(data.fromEmail, data.fromName, data.subject, data.body) Emailer.Instance.addContactFormJob(data.fromEmail, data.fromName, data.subject, data.body)
await Redis.Instance.setContactFormIp(req.ip) await Redis.Instance.setContactFormIp(req.ip)

View File

@ -1,8 +1,8 @@
import * as express from 'express'
import { InboxManager } from '@server/lib/activitypub/inbox-manager' import { InboxManager } from '@server/lib/activitypub/inbox-manager'
import { RemoveDanglingResumableUploadsScheduler } from '@server/lib/schedulers/remove-dangling-resumable-uploads-scheduler' import { RemoveDanglingResumableUploadsScheduler } from '@server/lib/schedulers/remove-dangling-resumable-uploads-scheduler'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { Debug, SendDebugCommand } from '@shared/models'
import { SendDebugCommand } from '@shared/models' import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import * as express from 'express'
import { UserRight } from '../../../../shared/models/users' import { UserRight } from '../../../../shared/models/users'
import { authenticate, ensureUserHasRight } from '../../../middlewares' import { authenticate, ensureUserHasRight } from '../../../middlewares'
@ -32,7 +32,7 @@ function getDebug (req: express.Request, res: express.Response) {
return res.json({ return res.json({
ip: req.ip, ip: req.ip,
activityPubMessagesWaiting: InboxManager.Instance.getActivityPubMessagesWaiting() activityPubMessagesWaiting: InboxManager.Instance.getActivityPubMessagesWaiting()
}) } as Debug)
} }
async function runCommand (req: express.Request, res: express.Response) { async function runCommand (req: express.Request, res: express.Response) {

View File

@ -1,6 +1,6 @@
import * as express from 'express' import * as express from 'express'
import { getServerActor } from '@server/models/application/application' import { getServerActor } from '@server/models/application/application'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserRight } from '../../../../shared/models/users' import { UserRight } from '../../../../shared/models/users'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'
import { getFormattedObjects } from '../../../helpers/utils' import { getFormattedObjects } from '../../../helpers/utils'
@ -29,6 +29,7 @@ import {
removeFollowingValidator removeFollowingValidator
} from '../../../middlewares/validators' } from '../../../middlewares/validators'
import { ActorFollowModel } from '../../../models/actor/actor-follow' import { ActorFollowModel } from '../../../models/actor/actor-follow'
import { ServerFollowCreate } from '@shared/models'
const serverFollowsRouter = express.Router() const serverFollowsRouter = express.Router()
serverFollowsRouter.get('/following', serverFollowsRouter.get('/following',
@ -45,10 +46,10 @@ serverFollowsRouter.post('/following',
ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW), ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW),
followValidator, followValidator,
setBodyHostsPort, setBodyHostsPort,
asyncMiddleware(followInstance) asyncMiddleware(addFollow)
) )
serverFollowsRouter.delete('/following/:host', serverFollowsRouter.delete('/following/:hostOrHandle',
authenticate, authenticate,
ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW), ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW),
asyncMiddleware(removeFollowingValidator), asyncMiddleware(removeFollowingValidator),
@ -125,8 +126,8 @@ async function listFollowers (req: express.Request, res: express.Response) {
return res.json(getFormattedObjects(resultList.data, resultList.total)) return res.json(getFormattedObjects(resultList.data, resultList.total))
} }
async function followInstance (req: express.Request, res: express.Response) { async function addFollow (req: express.Request, res: express.Response) {
const hosts = req.body.hosts as string[] const { hosts, handles } = req.body as ServerFollowCreate
const follower = await getServerActor() const follower = await getServerActor()
for (const host of hosts) { for (const host of hosts) {
@ -139,6 +140,18 @@ async function followInstance (req: express.Request, res: express.Response) {
JobQueue.Instance.createJob({ type: 'activitypub-follow', payload }) JobQueue.Instance.createJob({ type: 'activitypub-follow', payload })
} }
for (const handle of handles) {
const [ name, host ] = handle.split('@')
const payload = {
host,
name,
followerActorId: follower.id
}
JobQueue.Instance.createJob({ type: 'activitypub-follow', payload })
}
return res.status(HttpStatusCode.NO_CONTENT_204).end() return res.status(HttpStatusCode.NO_CONTENT_204).end()
} }

View File

@ -1,11 +1,11 @@
import * as express from 'express' import * as express from 'express'
import { contactRouter } from './contact'
import { debugRouter } from './debug'
import { serverFollowsRouter } from './follows' import { serverFollowsRouter } from './follows'
import { statsRouter } from './stats' import { logsRouter } from './logs'
import { serverRedundancyRouter } from './redundancy' import { serverRedundancyRouter } from './redundancy'
import { serverBlocklistRouter } from './server-blocklist' import { serverBlocklistRouter } from './server-blocklist'
import { contactRouter } from './contact' import { statsRouter } from './stats'
import { logsRouter } from './logs'
import { debugRouter } from './debug'
const serverRouter = express.Router() const serverRouter = express.Router()

View File

@ -1,14 +1,14 @@
import * as express from 'express' import * as express from 'express'
import { UserRight } from '../../../../shared/models/users'
import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares'
import { mtimeSortFilesDesc } from '../../../../shared/core-utils/logs/logs'
import { readdir, readFile } from 'fs-extra' import { readdir, readFile } from 'fs-extra'
import { AUDIT_LOG_FILENAME, MAX_LOGS_OUTPUT_CHARACTERS, LOG_FILENAME } from '../../../initializers/constants'
import { join } from 'path' import { join } from 'path'
import { getAuditLogsValidator, getLogsValidator } from '../../../middlewares/validators/logs'
import { LogLevel } from '../../../../shared/models/server/log-level.type'
import { CONFIG } from '../../../initializers/config'
import { logger } from '@server/helpers/logger' import { logger } from '@server/helpers/logger'
import { mtimeSortFilesDesc } from '../../../../shared/core-utils/logs/logs'
import { LogLevel } from '../../../../shared/models/server/log-level.type'
import { UserRight } from '../../../../shared/models/users'
import { CONFIG } from '../../../initializers/config'
import { AUDIT_LOG_FILENAME, LOG_FILENAME, MAX_LOGS_OUTPUT_CHARACTERS } from '../../../initializers/constants'
import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares'
import { getAuditLogsValidator, getLogsValidator } from '../../../middlewares/validators/logs'
const logsRouter = express.Router() const logsRouter = express.Router()

View File

@ -1,5 +1,10 @@
import * as express from 'express' import * as express from 'express'
import { JobQueue } from '@server/lib/job-queue'
import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserRight } from '../../../../shared/models/users' import { UserRight } from '../../../../shared/models/users'
import { logger } from '../../../helpers/logger'
import { removeRedundanciesOfServer, removeVideoRedundancy } from '../../../lib/redundancy'
import { import {
asyncMiddleware, asyncMiddleware,
authenticate, authenticate,
@ -10,16 +15,11 @@ import {
videoRedundanciesSortValidator videoRedundanciesSortValidator
} from '../../../middlewares' } from '../../../middlewares'
import { import {
listVideoRedundanciesValidator,
updateServerRedundancyValidator,
addVideoRedundancyValidator, addVideoRedundancyValidator,
removeVideoRedundancyValidator listVideoRedundanciesValidator,
removeVideoRedundancyValidator,
updateServerRedundancyValidator
} from '../../../middlewares/validators/redundancy' } from '../../../middlewares/validators/redundancy'
import { removeRedundanciesOfServer, removeVideoRedundancy } from '../../../lib/redundancy'
import { logger } from '../../../helpers/logger'
import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy'
import { JobQueue } from '@server/lib/job-queue'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const serverRedundancyRouter = express.Router() const serverRedundancyRouter = express.Router()

View File

@ -1,8 +1,9 @@
import 'multer' import 'multer'
import * as express from 'express' import * as express from 'express'
import { logger } from '@server/helpers/logger' import { logger } from '@server/helpers/logger'
import { UserNotificationModel } from '@server/models/user/user-notification'
import { getServerActor } from '@server/models/application/application' import { getServerActor } from '@server/models/application/application'
import { UserNotificationModel } from '@server/models/user/user-notification'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserRight } from '../../../../shared/models/users' import { UserRight } from '../../../../shared/models/users'
import { getFormattedObjects } from '../../../helpers/utils' import { getFormattedObjects } from '../../../helpers/utils'
import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../../../lib/blocklist' import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../../../lib/blocklist'
@ -25,7 +26,6 @@ import {
} from '../../../middlewares/validators' } from '../../../middlewares/validators'
import { AccountBlocklistModel } from '../../../models/account/account-blocklist' import { AccountBlocklistModel } from '../../../models/account/account-blocklist'
import { ServerBlocklistModel } from '../../../models/server/server-blocklist' import { ServerBlocklistModel } from '../../../models/server/server-blocklist'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const serverBlocklistRouter = express.Router() const serverBlocklistRouter = express.Router()

View File

@ -4,8 +4,8 @@ import { tokensRouter } from '@server/controllers/api/users/token'
import { Hooks } from '@server/lib/plugins/hooks' import { Hooks } from '@server/lib/plugins/hooks'
import { OAuthTokenModel } from '@server/models/oauth/oauth-token' import { OAuthTokenModel } from '@server/models/oauth/oauth-token'
import { MUser, MUserAccountDefault } from '@server/types/models' import { MUser, MUserAccountDefault } from '@server/types/models'
import { UserCreate, UserRight, UserRole, UserUpdate } from '../../../../shared' import { UserCreate, UserCreateResult, UserRight, UserRole, UserUpdate } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model' import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
import { UserRegister } from '../../../../shared/models/users/user-register.model' import { UserRegister } from '../../../../shared/models/users/user-register.model'
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger' import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger'
@ -220,7 +220,7 @@ async function createUser (req: express.Request, res: express.Response) {
account: { account: {
id: account.id id: account.id
} }
} } as UserCreateResult
}) })
} }

View File

@ -2,8 +2,9 @@ import 'multer'
import * as express from 'express' import * as express from 'express'
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '@server/helpers/audit-logger' import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '@server/helpers/audit-logger'
import { Hooks } from '@server/lib/plugins/hooks' import { Hooks } from '@server/lib/plugins/hooks'
import { AttributesOnly } from '@shared/core-utils'
import { ActorImageType, UserUpdateMe, UserVideoRate as FormattedUserVideoRate } from '../../../../shared' import { ActorImageType, UserUpdateMe, UserVideoRate as FormattedUserVideoRate } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserVideoQuota } from '../../../../shared/models/users/user-video-quota.model' import { UserVideoQuota } from '../../../../shared/models/users/user-video-quota.model'
import { createReqFiles } from '../../../helpers/express-utils' import { createReqFiles } from '../../../helpers/express-utils'
import { getFormattedObjects } from '../../../helpers/utils' import { getFormattedObjects } from '../../../helpers/utils'
@ -31,7 +32,6 @@ import { AccountVideoRateModel } from '../../../models/account/account-video-rat
import { UserModel } from '../../../models/user/user' import { UserModel } from '../../../models/user/user'
import { VideoModel } from '../../../models/video/video' import { VideoModel } from '../../../models/video/video'
import { VideoImportModel } from '../../../models/video/video-import' import { VideoImportModel } from '../../../models/video/video-import'
import { AttributesOnly } from '@shared/core-utils'
const auditLogger = auditLoggerFactory('users') const auditLogger = auditLoggerFactory('users')

View File

@ -1,6 +1,10 @@
import * as express from 'express'
import 'multer' import 'multer'
import * as express from 'express'
import { logger } from '@server/helpers/logger'
import { UserNotificationModel } from '@server/models/user/user-notification'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { getFormattedObjects } from '../../../helpers/utils' import { getFormattedObjects } from '../../../helpers/utils'
import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../../../lib/blocklist'
import { import {
asyncMiddleware, asyncMiddleware,
asyncRetryTransactionMiddleware, asyncRetryTransactionMiddleware,
@ -18,11 +22,7 @@ import {
unblockServerByAccountValidator unblockServerByAccountValidator
} from '../../../middlewares/validators' } from '../../../middlewares/validators'
import { AccountBlocklistModel } from '../../../models/account/account-blocklist' import { AccountBlocklistModel } from '../../../models/account/account-blocklist'
import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../../../lib/blocklist'
import { ServerBlocklistModel } from '../../../models/server/server-blocklist' import { ServerBlocklistModel } from '../../../models/server/server-blocklist'
import { UserNotificationModel } from '@server/models/user/user-notification'
import { logger } from '@server/helpers/logger'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const myBlocklistRouter = express.Router() const myBlocklistRouter = express.Router()

View File

@ -1,4 +1,7 @@
import * as express from 'express' import * as express from 'express'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { getFormattedObjects } from '../../../helpers/utils'
import { sequelizeTypescript } from '../../../initializers/database'
import { import {
asyncMiddleware, asyncMiddleware,
asyncRetryTransactionMiddleware, asyncRetryTransactionMiddleware,
@ -8,10 +11,7 @@ import {
userHistoryListValidator, userHistoryListValidator,
userHistoryRemoveValidator userHistoryRemoveValidator
} from '../../../middlewares' } from '../../../middlewares'
import { getFormattedObjects } from '../../../helpers/utils'
import { UserVideoHistoryModel } from '../../../models/user/user-video-history' import { UserVideoHistoryModel } from '../../../models/user/user-video-history'
import { sequelizeTypescript } from '../../../initializers/database'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const myVideosHistoryRouter = express.Router() const myVideosHistoryRouter = express.Router()

View File

@ -1,7 +1,7 @@
import 'multer' import 'multer'
import * as express from 'express' import * as express from 'express'
import { UserNotificationModel } from '@server/models/user/user-notification' import { UserNotificationModel } from '@server/models/user/user-notification'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserNotificationSetting } from '../../../../shared/models/users' import { UserNotificationSetting } from '../../../../shared/models/users'
import { getFormattedObjects } from '../../../helpers/utils' import { getFormattedObjects } from '../../../helpers/utils'
import { import {

View File

@ -3,7 +3,7 @@ import * as express from 'express'
import { sendUndoFollow } from '@server/lib/activitypub/send' import { sendUndoFollow } from '@server/lib/activitypub/send'
import { VideoChannelModel } from '@server/models/video/video-channel' import { VideoChannelModel } from '@server/models/video/video-channel'
import { VideosCommonQuery } from '@shared/models' import { VideosCommonQuery } from '@shared/models'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils' import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils'
import { getFormattedObjects } from '../../../helpers/utils' import { getFormattedObjects } from '../../../helpers/utils'
import { WEBSERVER } from '../../../initializers/constants' import { WEBSERVER } from '../../../initializers/constants'

View File

@ -1,8 +1,8 @@
import * as express from 'express' import * as express from 'express'
import { VideosExistInPlaylists } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model'
import { asyncMiddleware, authenticate } from '../../../middlewares' import { asyncMiddleware, authenticate } from '../../../middlewares'
import { doVideosInPlaylistExistValidator } from '../../../middlewares/validators/videos/video-playlists' import { doVideosInPlaylistExistValidator } from '../../../middlewares/validators/videos/video-playlists'
import { VideoPlaylistModel } from '../../../models/video/video-playlist' import { VideoPlaylistModel } from '../../../models/video/video-playlist'
import { VideosExistInPlaylists } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model'
const myVideoPlaylistsRouter = express.Router() const myVideoPlaylistsRouter = express.Router()

View File

@ -3,7 +3,7 @@ import { Hooks } from '@server/lib/plugins/hooks'
import { getServerActor } from '@server/models/application/application' import { getServerActor } from '@server/models/application/application'
import { MChannelBannerAccountDefault } from '@server/types/models' import { MChannelBannerAccountDefault } from '@server/types/models'
import { ActorImageType, VideoChannelCreate, VideoChannelUpdate, VideosCommonQuery } from '../../../shared' import { ActorImageType, VideoChannelCreate, VideoChannelUpdate, VideosCommonQuery } from '../../../shared'
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { auditLoggerFactory, getAuditIdFromRes, VideoChannelAuditView } from '../../helpers/audit-logger' import { auditLoggerFactory, getAuditIdFromRes, VideoChannelAuditView } from '../../helpers/audit-logger'
import { resetSequelizeInstance } from '../../helpers/database-utils' import { resetSequelizeInstance } from '../../helpers/database-utils'
import { buildNSFWFilter, createReqFiles, getCountVideos, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils' import { buildNSFWFilter, createReqFiles, getCountVideos, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'

View File

@ -5,7 +5,8 @@ import { scheduleRefreshIfNeeded } from '@server/lib/activitypub/playlists'
import { Hooks } from '@server/lib/plugins/hooks' import { Hooks } from '@server/lib/plugins/hooks'
import { getServerActor } from '@server/models/application/application' import { getServerActor } from '@server/models/application/application'
import { MVideoPlaylistFull, MVideoPlaylistThumbnail, MVideoThumbnail } from '@server/types/models' import { MVideoPlaylistFull, MVideoPlaylistThumbnail, MVideoThumbnail } from '@server/types/models'
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' import { VideoPlaylistCreateResult, VideoPlaylistElementCreateResult } from '@shared/models'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { VideoPlaylistCreate } from '../../../shared/models/videos/playlist/video-playlist-create.model' import { VideoPlaylistCreate } from '../../../shared/models/videos/playlist/video-playlist-create.model'
import { VideoPlaylistElementCreate } from '../../../shared/models/videos/playlist/video-playlist-element-create.model' import { VideoPlaylistElementCreate } from '../../../shared/models/videos/playlist/video-playlist-element-create.model'
import { VideoPlaylistElementUpdate } from '../../../shared/models/videos/playlist/video-playlist-element-update.model' import { VideoPlaylistElementUpdate } from '../../../shared/models/videos/playlist/video-playlist-element-update.model'
@ -202,7 +203,7 @@ async function addVideoPlaylist (req: express.Request, res: express.Response) {
id: videoPlaylistCreated.id, id: videoPlaylistCreated.id,
shortUUID: uuidToShort(videoPlaylistCreated.uuid), shortUUID: uuidToShort(videoPlaylistCreated.uuid),
uuid: videoPlaylistCreated.uuid uuid: videoPlaylistCreated.uuid
} } as VideoPlaylistCreateResult
}) })
} }
@ -338,8 +339,8 @@ async function addVideoInPlaylist (req: express.Request, res: express.Response)
return res.json({ return res.json({
videoPlaylistElement: { videoPlaylistElement: {
id: playlistElement.id id: playlistElement.id
} } as VideoPlaylistElementCreateResult
}).end() })
} }
async function updateVideoPlaylistElement (req: express.Request, res: express.Response) { async function updateVideoPlaylistElement (req: express.Request, res: express.Response) {

View File

@ -1,6 +1,7 @@
import * as express from 'express' import * as express from 'express'
import { blacklistVideo, unblacklistVideo } from '@server/lib/video-blacklist' import { blacklistVideo, unblacklistVideo } from '@server/lib/video-blacklist'
import { UserRight, VideoBlacklistCreate } from '../../../../shared' import { UserRight, VideoBlacklistCreate } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'
import { getFormattedObjects } from '../../../helpers/utils' import { getFormattedObjects } from '../../../helpers/utils'
import { sequelizeTypescript } from '../../../initializers/database' import { sequelizeTypescript } from '../../../initializers/database'
@ -19,7 +20,6 @@ import {
videosBlacklistUpdateValidator videosBlacklistUpdateValidator
} from '../../../middlewares' } from '../../../middlewares'
import { VideoBlacklistModel } from '../../../models/video/video-blacklist' import { VideoBlacklistModel } from '../../../models/video/video-blacklist'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const blacklistRouter = express.Router() const blacklistRouter = express.Router()

View File

@ -1,6 +1,6 @@
import * as express from 'express' import * as express from 'express'
import { MVideoCaption } from '@server/types/models' import { MVideoCaption } from '@server/types/models'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { moveAndProcessCaptionFile } from '../../../helpers/captions-utils' import { moveAndProcessCaptionFile } from '../../../helpers/captions-utils'
import { createReqFiles } from '../../../helpers/express-utils' import { createReqFiles } from '../../../helpers/express-utils'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'

View File

@ -1,7 +1,7 @@
import * as express from 'express' import * as express from 'express'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { ResultList, ThreadsResultList, UserRight, VideoCommentCreate } from '../../../../shared/models'
import { ResultList, ThreadsResultList, UserRight } from '../../../../shared/models' import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { VideoCommentCreate } from '../../../../shared/models/videos/comment/video-comment.model' import { VideoCommentThreads } from '../../../../shared/models/videos/comment/video-comment.model'
import { auditLoggerFactory, CommentAuditView, getAuditIdFromRes } from '../../../helpers/audit-logger' import { auditLoggerFactory, CommentAuditView, getAuditIdFromRes } from '../../../helpers/audit-logger'
import { getFormattedObjects } from '../../../helpers/utils' import { getFormattedObjects } from '../../../helpers/utils'
import { sequelizeTypescript } from '../../../initializers/database' import { sequelizeTypescript } from '../../../initializers/database'
@ -136,7 +136,7 @@ async function listVideoThreads (req: express.Request, res: express.Response) {
return res.json({ return res.json({
...getFormattedObjects(resultList.data, resultList.total), ...getFormattedObjects(resultList.data, resultList.total),
totalNotDeletedComments: resultList.totalNotDeletedComments totalNotDeletedComments: resultList.totalNotDeletedComments
}) } as VideoCommentThreads)
} }
async function listVideoThreadComments (req: express.Request, res: express.Response) { async function listVideoThreadComments (req: express.Request, res: express.Response) {

View File

@ -6,7 +6,7 @@ import { openapiOperationDoc } from '@server/middlewares/doc'
import { getServerActor } from '@server/models/application/application' import { getServerActor } from '@server/models/application/application'
import { MVideoAccountLight } from '@server/types/models' import { MVideoAccountLight } from '@server/types/models'
import { VideosCommonQuery } from '../../../../shared' import { VideosCommonQuery } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs' import { HttpStatusCode } from '../../../../shared/models'
import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger' import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger'
import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils' import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'

View File

@ -11,7 +11,7 @@ import { videoLiveAddValidator, videoLiveGetValidator, videoLiveUpdateValidator
import { VideoLiveModel } from '@server/models/video/video-live' import { VideoLiveModel } from '@server/models/video/video-live'
import { MVideoDetails, MVideoFullLight } from '@server/types/models' import { MVideoDetails, MVideoFullLight } from '@server/types/models'
import { LiveVideoCreate, LiveVideoUpdate, VideoState } from '../../../../shared' import { LiveVideoCreate, LiveVideoUpdate, VideoState } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'
import { sequelizeTypescript } from '../../../initializers/database' import { sequelizeTypescript } from '../../../initializers/database'
import { updateVideoMiniatureFromExisting } from '../../../lib/thumbnail' import { updateVideoMiniatureFromExisting } from '../../../lib/thumbnail'

View File

@ -1,6 +1,12 @@
import * as express from 'express' import * as express from 'express'
import { MVideoFullLight } from '@server/types/models'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { VideoChangeOwnershipStatus, VideoState } from '../../../../shared/models/videos'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'
import { getFormattedObjects } from '../../../helpers/utils'
import { sequelizeTypescript } from '../../../initializers/database' import { sequelizeTypescript } from '../../../initializers/database'
import { sendUpdateVideo } from '../../../lib/activitypub/send'
import { changeVideoChannelShare } from '../../../lib/activitypub/share'
import { import {
asyncMiddleware, asyncMiddleware,
asyncRetryTransactionMiddleware, asyncRetryTransactionMiddleware,
@ -11,15 +17,9 @@ import {
videosChangeOwnershipValidator, videosChangeOwnershipValidator,
videosTerminateChangeOwnershipValidator videosTerminateChangeOwnershipValidator
} from '../../../middlewares' } from '../../../middlewares'
import { VideoChangeOwnershipModel } from '../../../models/video/video-change-ownership'
import { VideoChangeOwnershipStatus, VideoState } from '../../../../shared/models/videos'
import { VideoChannelModel } from '../../../models/video/video-channel'
import { getFormattedObjects } from '../../../helpers/utils'
import { changeVideoChannelShare } from '../../../lib/activitypub/share'
import { sendUpdateVideo } from '../../../lib/activitypub/send'
import { VideoModel } from '../../../models/video/video' import { VideoModel } from '../../../models/video/video'
import { MVideoFullLight } from '@server/types/models' import { VideoChangeOwnershipModel } from '../../../models/video/video-change-ownership'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { VideoChannelModel } from '../../../models/video/video-channel'
const ownershipVideoRouter = express.Router() const ownershipVideoRouter = express.Router()

View File

@ -1,13 +1,13 @@
import * as express from 'express' import * as express from 'express'
import { UserVideoRateUpdate } from '../../../../shared' import { UserVideoRateUpdate } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'
import { VIDEO_RATE_TYPES } from '../../../initializers/constants' import { VIDEO_RATE_TYPES } from '../../../initializers/constants'
import { sequelizeTypescript } from '../../../initializers/database'
import { getLocalRateUrl, sendVideoRateChange } from '../../../lib/activitypub/video-rates' import { getLocalRateUrl, sendVideoRateChange } from '../../../lib/activitypub/video-rates'
import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videoUpdateRateValidator } from '../../../middlewares' import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videoUpdateRateValidator } from '../../../middlewares'
import { AccountModel } from '../../../models/account/account' import { AccountModel } from '../../../models/account/account'
import { AccountVideoRateModel } from '../../../models/account/account-video-rate' import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
import { sequelizeTypescript } from '../../../initializers/database'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const rateVideoRouter = express.Router() const rateVideoRouter = express.Router()

View File

@ -2,10 +2,11 @@ import * as express from 'express'
import { Transaction } from 'sequelize/types' import { Transaction } from 'sequelize/types'
import { changeVideoChannelShare } from '@server/lib/activitypub/share' import { changeVideoChannelShare } from '@server/lib/activitypub/share'
import { buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video' import { buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video'
import { openapiOperationDoc } from '@server/middlewares/doc'
import { FilteredModelAttributes } from '@server/types' import { FilteredModelAttributes } from '@server/types'
import { MVideoFullLight } from '@server/types/models' import { MVideoFullLight } from '@server/types/models'
import { VideoUpdate } from '../../../../shared' import { VideoUpdate } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs' import { HttpStatusCode } from '../../../../shared/models'
import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger' import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger'
import { resetSequelizeInstance } from '../../../helpers/database-utils' import { resetSequelizeInstance } from '../../../helpers/database-utils'
import { createReqFiles } from '../../../helpers/express-utils' import { createReqFiles } from '../../../helpers/express-utils'
@ -20,7 +21,6 @@ import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist'
import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videosUpdateValidator } from '../../../middlewares' import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videosUpdateValidator } from '../../../middlewares'
import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update'
import { VideoModel } from '../../../models/video/video' import { VideoModel } from '../../../models/video/video'
import { openapiOperationDoc } from '@server/middlewares/doc'
const lTags = loggerTagsFactory('api', 'video') const lTags = loggerTagsFactory('api', 'video')
const auditLogger = auditLoggerFactory('videos') const auditLogger = auditLoggerFactory('videos')

View File

@ -11,7 +11,7 @@ import { openapiOperationDoc } from '@server/middlewares/doc'
import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
import { uploadx } from '@uploadx/core' import { uploadx } from '@uploadx/core'
import { VideoCreate, VideoState } from '../../../../shared' import { VideoCreate, VideoState } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs' import { HttpStatusCode } from '../../../../shared/models'
import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger' import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger'
import { retryTransactionWrapper } from '../../../helpers/database-utils' import { retryTransactionWrapper } from '../../../helpers/database-utils'
import { createReqFiles } from '../../../helpers/express-utils' import { createReqFiles } from '../../../helpers/express-utils'

View File

@ -1,5 +1,6 @@
import * as express from 'express' import * as express from 'express'
import { UserWatchingVideo } from '../../../../shared' import { UserWatchingVideo } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { import {
asyncMiddleware, asyncMiddleware,
asyncRetryTransactionMiddleware, asyncRetryTransactionMiddleware,
@ -8,7 +9,6 @@ import {
videoWatchingValidator videoWatchingValidator
} from '../../../middlewares' } from '../../../middlewares'
import { UserVideoHistoryModel } from '../../../models/user/user-video-history' import { UserVideoHistoryModel } from '../../../models/user/user-video-history'
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
const watchingRouter = express.Router() const watchingRouter = express.Router()

View File

@ -5,7 +5,7 @@ import { join } from 'path'
import { logger } from '@server/helpers/logger' import { logger } from '@server/helpers/logger'
import { CONFIG } from '@server/initializers/config' import { CONFIG } from '@server/initializers/config'
import { Hooks } from '@server/lib/plugins/hooks' import { Hooks } from '@server/lib/plugins/hooks'
import { HttpStatusCode } from '@shared/core-utils' import { HttpStatusCode } from '@shared/models'
import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@shared/core-utils/i18n' import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@shared/core-utils/i18n'
import { root } from '../helpers/core-utils' import { root } from '../helpers/core-utils'
import { STATIC_MAX_AGE } from '../initializers/constants' import { STATIC_MAX_AGE } from '../initializers/constants'

View File

@ -5,8 +5,7 @@ import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache
import { Hooks } from '@server/lib/plugins/hooks' import { Hooks } from '@server/lib/plugins/hooks'
import { getVideoFilePath } from '@server/lib/video-paths' import { getVideoFilePath } from '@server/lib/video-paths'
import { MStreamingPlaylist, MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' import { MStreamingPlaylist, MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode, VideoStreamingPlaylistType } from '@shared/models'
import { VideoStreamingPlaylistType } from '@shared/models'
import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants' import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants'
import { asyncMiddleware, videosDownloadValidator } from '../middlewares' import { asyncMiddleware, videosDownloadValidator } from '../middlewares'

View File

@ -1,7 +1,7 @@
import * as cors from 'cors' import * as cors from 'cors'
import * as express from 'express' import * as express from 'express'
import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache' import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache'
import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { logger } from '../helpers/logger' import { logger } from '../helpers/logger'
import { LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants' import { LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants'
import { VideosCaptionCache, VideosPreviewCache } from '../lib/files-cache' import { VideosCaptionCache, VideosPreviewCache } from '../lib/files-cache'

View File

@ -2,7 +2,7 @@ import * as cors from 'cors'
import * as express from 'express' import * as express from 'express'
import { mapToJSON } from '@server/helpers/core-utils' import { mapToJSON } from '@server/helpers/core-utils'
import { LiveSegmentShaStore } from '@server/lib/live' import { LiveSegmentShaStore } from '@server/lib/live'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '@shared/models'
const liveRouter = express.Router() const liveRouter = express.Router()

View File

@ -3,7 +3,7 @@ import { join } from 'path'
import { logger } from '@server/helpers/logger' import { logger } from '@server/helpers/logger'
import { optionalAuthenticate } from '@server/middlewares/auth' import { optionalAuthenticate } from '@server/middlewares/auth'
import { getCompleteLocale, is18nLocale } from '../../shared/core-utils/i18n' import { getCompleteLocale, is18nLocale } from '../../shared/core-utils/i18n'
import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { PluginType } from '../../shared/models/plugins/plugin.type' import { PluginType } from '../../shared/models/plugins/plugin.type'
import { isTestInstance } from '../helpers/core-utils' import { isTestInstance } from '../helpers/core-utils'
import { PLUGIN_GLOBAL_CSS_PATH } from '../initializers/constants' import { PLUGIN_GLOBAL_CSS_PATH } from '../initializers/constants'

View File

@ -3,7 +3,7 @@ import * as express from 'express'
import { join } from 'path' import { join } from 'path'
import { serveIndexHTML } from '@server/lib/client-html' import { serveIndexHTML } from '@server/lib/client-html'
import { ServerConfigManager } from '@server/lib/server-config-manager' import { ServerConfigManager } from '@server/lib/server-config-manager'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '@shared/models'
import { HttpNodeinfoDiasporaSoftwareNsSchema20 } from '../../shared/models/nodeinfo/nodeinfo.model' import { HttpNodeinfoDiasporaSoftwareNsSchema20 } from '../../shared/models/nodeinfo/nodeinfo.model'
import { root } from '../helpers/core-utils' import { root } from '../helpers/core-utils'
import { CONFIG, isEmailEnabled } from '../initializers/config' import { CONFIG, isEmailEnabled } from '../initializers/config'

View File

@ -1,4 +1,4 @@
import { exists } from './misc' import { exists, isArray } from './misc'
import { FollowState } from '@shared/models' import { FollowState } from '@shared/models'
function isFollowStateValid (value: FollowState) { function isFollowStateValid (value: FollowState) {
@ -7,8 +7,24 @@ function isFollowStateValid (value: FollowState) {
return value === 'pending' || value === 'accepted' return value === 'pending' || value === 'accepted'
} }
function isRemoteHandleValid (value: string) {
if (!exists(value)) return false
if (typeof value !== 'string') return false
return value.includes('@')
}
function isEachUniqueHandleValid (handles: string[]) {
return isArray(handles) &&
handles.every(handle => {
return isRemoteHandleValid(handle) && handles.indexOf(handle) === handles.lastIndexOf(handle)
})
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
export { export {
isFollowStateValid isFollowStateValid,
isRemoteHandleValid,
isEachUniqueHandleValid
} }

View File

@ -19,7 +19,6 @@ function isHostValid (host: string) {
function isEachUniqueHostValid (hosts: string[]) { function isEachUniqueHostValid (hosts: string[]) {
return isArray(hosts) && return isArray(hosts) &&
hosts.length !== 0 &&
hosts.every(host => { hosts.every(host => {
return isHostValid(host) && hosts.indexOf(host) === hosts.lastIndexOf(host) return isHostValid(host) && hosts.indexOf(host) === hosts.lastIndexOf(host)
}) })

View File

@ -1,7 +1,7 @@
import { Response } from 'express' import { Response } from 'express'
import { MUserId } from '@server/types/models' import { MUserId } from '@server/types/models'
import { MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' import { MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership'
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
function checkUserCanTerminateOwnershipChange (user: MUserId, videoChangeOwnership: MVideoChangeOwnershipFull, res: Response) { function checkUserCanTerminateOwnershipChange (user: MUserId, videoChangeOwnership: MVideoChangeOwnershipFull, res: Response) {
if (videoChangeOwnership.NextOwner.userId === user.id) { if (videoChangeOwnership.NextOwner.userId === user.id) {

View File

@ -6,7 +6,7 @@ import { sequelizeTypescript } from '@server/initializers/database'
import { logger } from './logger' import { logger } from './logger'
function retryTransactionWrapper <T, A, B, C, D> ( function retryTransactionWrapper <T, A, B, C, D> (
functionToRetry: (arg1: A, arg2: B, arg3: C, arg4: D) => Promise<T> | Bluebird<T>, functionToRetry: (arg1: A, arg2: B, arg3: C, arg4: D) => Promise<T>,
arg1: A, arg1: A,
arg2: B, arg2: B,
arg3: C, arg3: C,
@ -14,20 +14,20 @@ function retryTransactionWrapper <T, A, B, C, D> (
): Promise<T> ): Promise<T>
function retryTransactionWrapper <T, A, B, C> ( function retryTransactionWrapper <T, A, B, C> (
functionToRetry: (arg1: A, arg2: B, arg3: C) => Promise<T> | Bluebird<T>, functionToRetry: (arg1: A, arg2: B, arg3: C) => Promise<T>,
arg1: A, arg1: A,
arg2: B, arg2: B,
arg3: C arg3: C
): Promise<T> ): Promise<T>
function retryTransactionWrapper <T, A, B> ( function retryTransactionWrapper <T, A, B> (
functionToRetry: (arg1: A, arg2: B) => Promise<T> | Bluebird<T>, functionToRetry: (arg1: A, arg2: B) => Promise<T>,
arg1: A, arg1: A,
arg2: B arg2: B
): Promise<T> ): Promise<T>
function retryTransactionWrapper <T, A> ( function retryTransactionWrapper <T, A> (
functionToRetry: (arg1: A) => Promise<T> | Bluebird<T>, functionToRetry: (arg1: A) => Promise<T>,
arg1: A arg1: A
): Promise<T> ): Promise<T>
@ -36,7 +36,7 @@ function retryTransactionWrapper <T> (
): Promise<T> ): Promise<T>
function retryTransactionWrapper <T> ( function retryTransactionWrapper <T> (
functionToRetry: (...args: any[]) => Promise<T> | Bluebird<T>, functionToRetry: (...args: any[]) => Promise<T>,
...args: any[] ...args: any[]
): Promise<T> { ): Promise<T> {
return transactionRetryer<T>(callback => { return transactionRetryer<T>(callback => {

View File

@ -1,6 +1,6 @@
import * as express from 'express' import * as express from 'express'
import * as multer from 'multer' import * as multer from 'multer'
import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { CONFIG } from '../initializers/config' import { CONFIG } from '../initializers/config'
import { REMOTE_SCHEME } from '../initializers/constants' import { REMOTE_SCHEME } from '../initializers/constants'
import { getLowercaseExtension } from './core-utils' import { getLowercaseExtension } from './core-utils'

View File

@ -3,7 +3,7 @@ import { ensureDir, move, pathExists, remove, writeFile } from 'fs-extra'
import got from 'got' import got from 'got'
import { join } from 'path' import { join } from 'path'
import { CONFIG } from '@server/initializers/config' import { CONFIG } from '@server/initializers/config'
import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { VideoResolution } from '../../shared/models/videos' import { VideoResolution } from '../../shared/models/videos'
import { CONSTRAINTS_FIELDS, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES } from '../initializers/constants' import { CONSTRAINTS_FIELDS, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES } from '../initializers/constants'
import { peertubeTruncate, pipelinePromise, root } from './core-utils' import { peertubeTruncate, pipelinePromise, root } from './core-utils'

View File

@ -4,7 +4,7 @@ import { PeerTubeRequestError } from '@server/helpers/requests'
import { ActorLoadByUrlType } from '@server/lib/model-loaders' import { ActorLoadByUrlType } from '@server/lib/model-loaders'
import { ActorModel } from '@server/models/actor/actor' import { ActorModel } from '@server/models/actor/actor'
import { MActorAccountChannelId, MActorFull } from '@server/types/models' import { MActorAccountChannelId, MActorFull } from '@server/types/models'
import { HttpStatusCode } from '@shared/core-utils' import { HttpStatusCode } from '@shared/models'
import { fetchRemoteActor } from './shared' import { fetchRemoteActor } from './shared'
import { APActorUpdater } from './updater' import { APActorUpdater } from './updater'
import { getUrlFromWebfinger } from './webfinger' import { getUrlFromWebfinger } from './webfinger'

View File

@ -1,3 +1,4 @@
import { retryTransactionWrapper } from '@server/helpers/database-utils'
import * as Bluebird from 'bluebird' import * as Bluebird from 'bluebird'
import { URL } from 'url' import { URL } from 'url'
import { ActivityPubOrderedCollection } from '../../../shared/models/activitypub' import { ActivityPubOrderedCollection } from '../../../shared/models/activitypub'
@ -51,7 +52,7 @@ async function crawlCollectionPage <T> (argUrl: string, handler: HandlerFunction
} }
} }
if (cleaner) await cleaner(startDate) if (cleaner) await retryTransactionWrapper(cleaner, startDate)
} }
export { export {

View File

@ -31,6 +31,21 @@ async function autoFollowBackIfNeeded (actorFollow: MActorFollowActors, transact
} }
} }
export { // If we only have an host, use a default account handle
autoFollowBackIfNeeded function getRemoteNameAndHost (handleOrHost: string) {
let name = SERVER_ACTOR_NAME
let host = handleOrHost
const splitted = handleOrHost.split('@')
if (splitted.length === 2) {
name = splitted[0]
host = splitted[1]
}
return { name, host }
}
export {
autoFollowBackIfNeeded,
getRemoteNameAndHost
} }

View File

@ -2,7 +2,7 @@ import { logger, loggerTagsFactory } from '@server/helpers/logger'
import { PeerTubeRequestError } from '@server/helpers/requests' import { PeerTubeRequestError } from '@server/helpers/requests'
import { JobQueue } from '@server/lib/job-queue' import { JobQueue } from '@server/lib/job-queue'
import { MVideoPlaylist, MVideoPlaylistOwner } from '@server/types/models' import { MVideoPlaylist, MVideoPlaylistOwner } from '@server/types/models'
import { HttpStatusCode } from '@shared/core-utils' import { HttpStatusCode } from '@shared/models'
import { createOrUpdateVideoPlaylist } from './create-update' import { createOrUpdateVideoPlaylist } from './create-update'
import { fetchRemoteVideoPlaylist } from './shared' import { fetchRemoteVideoPlaylist } from './shared'

View File

@ -4,7 +4,7 @@ import { ActorFollowScoreCache } from '@server/lib/files-cache'
import { VideoLoadByUrlType } from '@server/lib/model-loaders' import { VideoLoadByUrlType } from '@server/lib/model-loaders'
import { VideoModel } from '@server/models/video/video' import { VideoModel } from '@server/models/video/video'
import { MVideoAccountLightBlacklistAllFiles, MVideoThumbnail } from '@server/types/models' import { MVideoAccountLightBlacklistAllFiles, MVideoThumbnail } from '@server/types/models'
import { HttpStatusCode } from '@shared/core-utils' import { HttpStatusCode } from '@shared/models'
import { fetchRemoteVideo, SyncParam, syncVideoExternalAttributes } from './shared' import { fetchRemoteVideo, SyncParam, syncVideoExternalAttributes } from './shared'
import { APVideoUpdater } from './updater' import { APVideoUpdater } from './updater'

View File

@ -5,7 +5,7 @@ import validator from 'validator'
import { escapeHTML } from '@shared/core-utils/renderer' import { escapeHTML } from '@shared/core-utils/renderer'
import { HTMLServerConfig } from '@shared/models' import { HTMLServerConfig } from '@shared/models'
import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n' import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos' import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos'
import { isTestInstance, sha256 } from '../helpers/core-utils' import { isTestInstance, sha256 } from '../helpers/core-utils'
import { logger } from '../helpers/logger' import { logger } from '../helpers/logger'

View File

@ -12,7 +12,7 @@ import { AP_CLEANER_CONCURRENCY } from '@server/initializers/constants'
import { VideoModel } from '@server/models/video/video' import { VideoModel } from '@server/models/video/video'
import { VideoCommentModel } from '@server/models/video/video-comment' import { VideoCommentModel } from '@server/models/video/video-comment'
import { VideoShareModel } from '@server/models/video/video-share' import { VideoShareModel } from '@server/models/video/video-share'
import { HttpStatusCode } from '@shared/core-utils' import { HttpStatusCode } from '@shared/models'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'
import { AccountVideoRateModel } from '../../../models/account/account-video-rate' import { AccountVideoRateModel } from '../../../models/account/account-video-rate'

View File

@ -23,7 +23,7 @@ import { ActivityCreate } from '../../shared/models/activitypub'
import { VideoObject } from '../../shared/models/activitypub/objects' import { VideoObject } from '../../shared/models/activitypub/objects'
import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object' import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object'
import { LiveVideoCreate, VideoCreate, VideoImportCreate } from '../../shared/models/videos' import { LiveVideoCreate, VideoCreate, VideoImportCreate } from '../../shared/models/videos'
import { VideoCommentCreate } from '../../shared/models/videos/comment/video-comment.model' import { VideoCommentCreate } from '../../shared/models/videos/comment'
import { ActorModel } from '../models/actor/actor' import { ActorModel } from '../models/actor/actor'
import { UserModel } from '../models/user/user' import { UserModel } from '../models/user/user'
import { VideoModel } from '../models/video/video' import { VideoModel } from '../models/video/video'

View File

@ -2,7 +2,7 @@ import { NextFunction, Request, Response } from 'express'
import { getAPId } from '@server/helpers/activitypub' import { getAPId } from '@server/helpers/activitypub'
import { isActorDeleteActivityValid } from '@server/helpers/custom-validators/activitypub/actor' import { isActorDeleteActivityValid } from '@server/helpers/custom-validators/activitypub/actor'
import { ActivityDelete, ActivityPubSignature } from '../../shared' import { ActivityDelete, ActivityPubSignature } from '../../shared'
import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { logger } from '../helpers/logger' import { logger } from '../helpers/logger'
import { isHTTPSignatureVerified, isJsonLDSignatureVerified, parseHTTPSignature } from '../helpers/peertube-crypto' import { isHTTPSignatureVerified, isJsonLDSignatureVerified, parseHTTPSignature } from '../helpers/peertube-crypto'
import { ACCEPT_HEADERS, ACTIVITY_PUB, HTTP_SIGNATURE } from '../initializers/constants' import { ACCEPT_HEADERS, ACTIVITY_PUB, HTTP_SIGNATURE } from '../initializers/constants'

View File

@ -1,7 +1,7 @@
import * as express from 'express' import * as express from 'express'
import { Socket } from 'socket.io' import { Socket } from 'socket.io'
import { getAccessToken } from '@server/lib/auth/oauth-model' import { getAccessToken } from '@server/lib/auth/oauth-model'
import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { logger } from '../helpers/logger' import { logger } from '../helpers/logger'
import { handleOAuthAuthenticate } from '../lib/auth/oauth' import { handleOAuthAuthenticate } from '../lib/auth/oauth'

View File

@ -1,6 +1,6 @@
import { Redis } from '../lib/redis'
import * as apicache from 'apicache' import * as apicache from 'apicache'
import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { Redis } from '../lib/redis'
// Ensure Redis is initialized // Ensure Redis is initialized
Redis.Instance.init() Redis.Instance.init()

View File

@ -1,6 +1,6 @@
import * as express from 'express' import * as express from 'express'
import { ProblemDocument, ProblemDocumentExtension } from 'http-problem-details' import { ProblemDocument, ProblemDocumentExtension } from 'http-problem-details'
import { HttpStatusCode } from '@shared/core-utils' import { HttpStatusCode } from '@shared/models'
function apiFailMiddleware (req: express.Request, res: express.Response, next: express.NextFunction) { function apiFailMiddleware (req: express.Request, res: express.Response, next: express.NextFunction) {
res.fail = options => { res.fail = options => {

View File

@ -1,6 +1,6 @@
import * as express from 'express' import * as express from 'express'
import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { getHostWithPort } from '../helpers/express-utils' import { getHostWithPort } from '../helpers/express-utils'
import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
function setBodyHostsPort (req: express.Request, res: express.Response, next: express.NextFunction) { function setBodyHostsPort (req: express.Request, res: express.Response, next: express.NextFunction) {
if (!req.body.hosts) return next() if (!req.body.hosts) return next()

Some files were not shown because too many files have changed in this diff Show More