diff options
author | Chocobozzz <me@florianbigard.com> | 2018-08-17 15:45:42 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-08-27 09:41:54 +0200 |
commit | 8a19bee1a1ee39f973bb37429e4f73c3f2873cdb (patch) | |
tree | 33c93ef19451d7e46d4be74ce0681359d2dcc70e | |
parent | 965c4b22d0e4d2f853501e844e6ebbb861bd389d (diff) | |
download | PeerTube-8a19bee1a1ee39f973bb37429e4f73c3f2873cdb.tar.gz PeerTube-8a19bee1a1ee39f973bb37429e4f73c3f2873cdb.tar.zst PeerTube-8a19bee1a1ee39f973bb37429e4f73c3f2873cdb.zip |
Add ability to set a name to a channel
45 files changed, 317 insertions, 180 deletions
diff --git a/client/src/app/+accounts/account-video-channels/account-video-channels.component.html b/client/src/app/+accounts/account-video-channels/account-video-channels.component.html index bcd3beaf0..114a9e517 100644 --- a/client/src/app/+accounts/account-video-channels/account-video-channels.component.html +++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.html | |||
@@ -1,6 +1,6 @@ | |||
1 | <div *ngIf="account" class="row"> | 1 | <div *ngIf="account" class="row"> |
2 | <a | 2 | <a |
3 | *ngFor="let videoChannel of videoChannels" [routerLink]="[ '/video-channels', videoChannel.uuid ]" | 3 | *ngFor="let videoChannel of videoChannels" [routerLink]="[ '/video-channels', videoChannel.name ]" |
4 | class="video-channel" i18n-title title="See this video channel" | 4 | class="video-channel" i18n-title title="See this video channel" |
5 | > | 5 | > |
6 | <img [src]="videoChannel.avatarUrl" alt="Avatar" /> | 6 | <img [src]="videoChannel.avatarUrl" alt="Avatar" /> |
diff --git a/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts b/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts index ebc671113..44f5626bb 100644 --- a/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts +++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts | |||
@@ -2,10 +2,10 @@ import { Component, OnDestroy, OnInit } from '@angular/core' | |||
2 | import { ActivatedRoute } from '@angular/router' | 2 | import { ActivatedRoute } from '@angular/router' |
3 | import { Account } from '@app/shared/account/account.model' | 3 | import { Account } from '@app/shared/account/account.model' |
4 | import { AccountService } from '@app/shared/account/account.service' | 4 | import { AccountService } from '@app/shared/account/account.service' |
5 | import { VideoChannel } from '../../../../../shared/models/videos' | ||
6 | import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' | 5 | import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' |
7 | import { flatMap, map, tap } from 'rxjs/operators' | 6 | import { flatMap, map, tap } from 'rxjs/operators' |
8 | import { Subscription } from 'rxjs' | 7 | import { Subscription } from 'rxjs' |
8 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' | ||
9 | 9 | ||
10 | @Component({ | 10 | @Component({ |
11 | selector: 'my-account-video-channels', | 11 | selector: 'my-account-video-channels', |
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts index c0eaa4763..79ac07c93 100644 --- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts +++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts | |||
@@ -29,8 +29,13 @@ export class MyAccountVideoChannelCreateComponent extends MyAccountVideoChannelE | |||
29 | super() | 29 | super() |
30 | } | 30 | } |
31 | 31 | ||
32 | get instanceHost () { | ||
33 | return window.location.host | ||
34 | } | ||
35 | |||
32 | ngOnInit () { | 36 | ngOnInit () { |
33 | this.buildForm({ | 37 | this.buildForm({ |
38 | name: this.videoChannelValidatorsService.VIDEO_CHANNEL_NAME, | ||
34 | 'display-name': this.videoChannelValidatorsService.VIDEO_CHANNEL_DISPLAY_NAME, | 39 | 'display-name': this.videoChannelValidatorsService.VIDEO_CHANNEL_DISPLAY_NAME, |
35 | description: this.videoChannelValidatorsService.VIDEO_CHANNEL_DESCRIPTION, | 40 | description: this.videoChannelValidatorsService.VIDEO_CHANNEL_DESCRIPTION, |
36 | support: this.videoChannelValidatorsService.VIDEO_CHANNEL_SUPPORT | 41 | support: this.videoChannelValidatorsService.VIDEO_CHANNEL_SUPPORT |
@@ -42,6 +47,7 @@ export class MyAccountVideoChannelCreateComponent extends MyAccountVideoChannelE | |||
42 | 47 | ||
43 | const body = this.form.value | 48 | const body = this.form.value |
44 | const videoChannelCreate: VideoChannelCreate = { | 49 | const videoChannelCreate: VideoChannelCreate = { |
50 | name: body.name, | ||
45 | displayName: body['display-name'], | 51 | displayName: body['display-name'], |
46 | description: body.description || null, | 52 | description: body.description || null, |
47 | support: body.support || null | 53 | support: body.support || null |
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.html b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.html index f7ca2ec43..81fb11f45 100644 --- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.html +++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.html | |||
@@ -8,6 +8,22 @@ | |||
8 | <div *ngIf="error" class="alert alert-danger">{{ error }}</div> | 8 | <div *ngIf="error" class="alert alert-danger">{{ error }}</div> |
9 | 9 | ||
10 | <form role="form" (ngSubmit)="formValidated()" [formGroup]="form"> | 10 | <form role="form" (ngSubmit)="formValidated()" [formGroup]="form"> |
11 | <div class="form-group" *ngIf="isCreation() === true"> | ||
12 | <label i18n for="name">Name</label> | ||
13 | <div class="input-group"> | ||
14 | <input | ||
15 | type="text" id="name" i18n-placeholder placeholder="Example: my_channel" | ||
16 | formControlName="name" [ngClass]="{ 'input-error': formErrors['name'] }" | ||
17 | > | ||
18 | <div class="input-group-append"> | ||
19 | <span class="input-group-text">@{{ instanceHost }}</span> | ||
20 | </div> | ||
21 | </div> | ||
22 | <div *ngIf="formErrors['name']" class="form-error"> | ||
23 | {{ formErrors['name'] }} | ||
24 | </div> | ||
25 | </div> | ||
26 | |||
11 | <div class="form-group"> | 27 | <div class="form-group"> |
12 | <label i18n for="display-name">Display name</label> | 28 | <label i18n for="display-name">Display name</label> |
13 | <input | 29 | <input |
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.scss b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.scss index 86c2598b7..833fda450 100644 --- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.scss +++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.scss | |||
@@ -10,10 +10,19 @@ my-actor-avatar-info { | |||
10 | margin-bottom: 20px; | 10 | margin-bottom: 20px; |
11 | } | 11 | } |
12 | 12 | ||
13 | .input-group { | ||
14 | @include peertube-input-group(340px); | ||
15 | } | ||
16 | |||
13 | input[type=text] { | 17 | input[type=text] { |
14 | @include peertube-input-text(340px); | 18 | @include peertube-input-text(340px); |
15 | 19 | ||
16 | display: block; | 20 | display: block; |
21 | |||
22 | &#name { | ||
23 | width: auto; | ||
24 | flex-grow: 1; | ||
25 | } | ||
17 | } | 26 | } |
18 | 27 | ||
19 | textarea { | 28 | textarea { |
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html index d27c3b4ec..548645a76 100644 --- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html +++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html | |||
@@ -7,15 +7,14 @@ | |||
7 | 7 | ||
8 | <div class="video-channels"> | 8 | <div class="video-channels"> |
9 | <div *ngFor="let videoChannel of videoChannels" class="video-channel"> | 9 | <div *ngFor="let videoChannel of videoChannels" class="video-channel"> |
10 | <a [routerLink]="[ '/video-channels', videoChannel.uuid ]"> | 10 | <a [routerLink]="[ '/video-channels', videoChannel.name ]"> |
11 | <img [src]="videoChannel.avatarUrl" alt="Avatar" /> | 11 | <img [src]="videoChannel.avatarUrl" alt="Avatar" /> |
12 | </a> | 12 | </a> |
13 | 13 | ||
14 | <div class="video-channel-info"> | 14 | <div class="video-channel-info"> |
15 | <a [routerLink]="[ '/video-channels', videoChannel.uuid ]" class="video-channel-names" i18n-title title="Go to the channel"> | 15 | <a [routerLink]="[ '/video-channels', videoChannel.name ]" class="video-channel-names" i18n-title title="Go to the channel"> |
16 | <div class="video-channel-display-name">{{ videoChannel.displayName }}</div> | 16 | <div class="video-channel-display-name">{{ videoChannel.displayName }}</div> |
17 | <!-- Hide the name for now, because it's an UUID not very friendly --> | 17 | <div class="video-channel-name">{{ videoChannel.name }}</div> |
18 | <!--<div class="video-channel-name">{{ videoChannel.name }}</div>--> | ||
19 | </a> | 18 | </a> |
20 | 19 | ||
21 | <div i18n class="video-channel-followers">{{ videoChannel.followersCount }} subscribers</div> | 20 | <div i18n class="video-channel-followers">{{ videoChannel.followersCount }} subscribers</div> |
@@ -24,7 +23,7 @@ | |||
24 | <div class="video-channel-buttons"> | 23 | <div class="video-channel-buttons"> |
25 | <my-delete-button (click)="deleteVideoChannel(videoChannel)"></my-delete-button> | 24 | <my-delete-button (click)="deleteVideoChannel(videoChannel)"></my-delete-button> |
26 | 25 | ||
27 | <my-edit-button [routerLink]="[ 'update', videoChannel.uuid ]"></my-edit-button> | 26 | <my-edit-button [routerLink]="[ 'update', videoChannel.name ]"></my-edit-button> |
28 | </div> | 27 | </div> |
29 | </div> | 28 | </div> |
30 | </div> | 29 | </div> |
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss index f047bb411..f8fd2684e 100644 --- a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss +++ b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss | |||
@@ -30,7 +30,9 @@ | |||
30 | a.video-channel-names { | 30 | a.video-channel-names { |
31 | @include disable-default-a-behaviour; | 31 | @include disable-default-a-behaviour; |
32 | 32 | ||
33 | width: fit-content; | ||
33 | display: flex; | 34 | display: flex; |
35 | align-items: baseline; | ||
34 | color: #000; | 36 | color: #000; |
35 | 37 | ||
36 | .video-channel-display-name { | 38 | .video-channel-display-name { |
@@ -41,6 +43,7 @@ | |||
41 | .video-channel-name { | 43 | .video-channel-name { |
42 | font-size: 14px; | 44 | font-size: 14px; |
43 | color: #777272; | 45 | color: #777272; |
46 | margin-left: 5px; | ||
44 | } | 47 | } |
45 | } | 48 | } |
46 | } | 49 | } |
diff --git a/client/src/app/+video-channels/video-channels.component.html b/client/src/app/+video-channels/video-channels.component.html index a52894cac..5a69a82a0 100644 --- a/client/src/app/+video-channels/video-channels.component.html +++ b/client/src/app/+video-channels/video-channels.component.html | |||
@@ -7,6 +7,7 @@ | |||
7 | <div class="actor-info"> | 7 | <div class="actor-info"> |
8 | <div class="actor-names"> | 8 | <div class="actor-names"> |
9 | <div class="actor-display-name">{{ videoChannel.displayName }}</div> | 9 | <div class="actor-display-name">{{ videoChannel.displayName }}</div> |
10 | <div class="actor-name">{{ videoChannel.nameWithHost }}</div> | ||
10 | </div> | 11 | </div> |
11 | <div i18n class="actor-followers">{{ videoChannel.followersCount }} subscribers</div> | 12 | <div i18n class="actor-followers">{{ videoChannel.followersCount }} subscribers</div> |
12 | 13 | ||
diff --git a/client/src/app/shared/forms/form-validators/video-channel-validators.service.ts b/client/src/app/shared/forms/form-validators/video-channel-validators.service.ts index 28b063f89..1ce3a0dca 100644 --- a/client/src/app/shared/forms/form-validators/video-channel-validators.service.ts +++ b/client/src/app/shared/forms/form-validators/video-channel-validators.service.ts | |||
@@ -5,11 +5,27 @@ import { BuildFormValidator } from '@app/shared' | |||
5 | 5 | ||
6 | @Injectable() | 6 | @Injectable() |
7 | export class VideoChannelValidatorsService { | 7 | export class VideoChannelValidatorsService { |
8 | readonly VIDEO_CHANNEL_NAME: BuildFormValidator | ||
8 | readonly VIDEO_CHANNEL_DISPLAY_NAME: BuildFormValidator | 9 | readonly VIDEO_CHANNEL_DISPLAY_NAME: BuildFormValidator |
9 | readonly VIDEO_CHANNEL_DESCRIPTION: BuildFormValidator | 10 | readonly VIDEO_CHANNEL_DESCRIPTION: BuildFormValidator |
10 | readonly VIDEO_CHANNEL_SUPPORT: BuildFormValidator | 11 | readonly VIDEO_CHANNEL_SUPPORT: BuildFormValidator |
11 | 12 | ||
12 | constructor (private i18n: I18n) { | 13 | constructor (private i18n: I18n) { |
14 | this.VIDEO_CHANNEL_NAME = { | ||
15 | VALIDATORS: [ | ||
16 | Validators.required, | ||
17 | Validators.minLength(3), | ||
18 | Validators.maxLength(20), | ||
19 | Validators.pattern(/^[a-z0-9._]+$/) | ||
20 | ], | ||
21 | MESSAGES: { | ||
22 | 'required': this.i18n('Name is required.'), | ||
23 | 'minlength': this.i18n('Name must be at least 3 characters long.'), | ||
24 | 'maxlength': this.i18n('Name cannot be more than 20 characters long.'), | ||
25 | 'pattern': this.i18n('Name should be only lowercase alphanumeric characters.') | ||
26 | } | ||
27 | } | ||
28 | |||
13 | this.VIDEO_CHANNEL_DISPLAY_NAME = { | 29 | this.VIDEO_CHANNEL_DISPLAY_NAME = { |
14 | VALIDATORS: [ | 30 | VALIDATORS: [ |
15 | Validators.required, | 31 | Validators.required, |
diff --git a/client/src/app/shared/video-channel/video-channel.model.ts b/client/src/app/shared/video-channel/video-channel.model.ts index b6862b681..309b614ae 100644 --- a/client/src/app/shared/video-channel/video-channel.model.ts +++ b/client/src/app/shared/video-channel/video-channel.model.ts | |||
@@ -7,6 +7,7 @@ export class VideoChannel extends Actor implements ServerVideoChannel { | |||
7 | description: string | 7 | description: string |
8 | support: string | 8 | support: string |
9 | isLocal: boolean | 9 | isLocal: boolean |
10 | nameWithHost: string | ||
10 | ownerAccount?: Account | 11 | ownerAccount?: Account |
11 | ownerBy?: string | 12 | ownerBy?: string |
12 | ownerAvatarUrl?: string | 13 | ownerAvatarUrl?: string |
@@ -18,6 +19,7 @@ export class VideoChannel extends Actor implements ServerVideoChannel { | |||
18 | this.description = hash.description | 19 | this.description = hash.description |
19 | this.support = hash.support | 20 | this.support = hash.support |
20 | this.isLocal = hash.isLocal | 21 | this.isLocal = hash.isLocal |
22 | this.nameWithHost = Actor.CREATE_BY_STRING(this.name, this.host) | ||
21 | 23 | ||
22 | if (hash.ownerAccount) { | 24 | if (hash.ownerAccount) { |
23 | this.ownerAccount = hash.ownerAccount | 25 | this.ownerAccount = hash.ownerAccount |
diff --git a/client/src/app/shared/video-channel/video-channel.service.ts b/client/src/app/shared/video-channel/video-channel.service.ts index 8c000665f..510dc9c3d 100644 --- a/client/src/app/shared/video-channel/video-channel.service.ts +++ b/client/src/app/shared/video-channel/video-channel.service.ts | |||
@@ -22,8 +22,8 @@ export class VideoChannelService { | |||
22 | private restExtractor: RestExtractor | 22 | private restExtractor: RestExtractor |
23 | ) {} | 23 | ) {} |
24 | 24 | ||
25 | getVideoChannel (videoChannelUUID: string) { | 25 | getVideoChannel (videoChannelName: string) { |
26 | return this.authHttp.get<VideoChannel>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannelUUID) | 26 | return this.authHttp.get<VideoChannel>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannelName) |
27 | .pipe( | 27 | .pipe( |
28 | map(videoChannelHash => new VideoChannel(videoChannelHash)), | 28 | map(videoChannelHash => new VideoChannel(videoChannelHash)), |
29 | tap(videoChannel => this.videoChannelLoaded.next(videoChannel)), | 29 | tap(videoChannel => this.videoChannelLoaded.next(videoChannel)), |
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts index e2a62c701..e44f1ee65 100644 --- a/client/src/app/shared/video/video.service.ts +++ b/client/src/app/shared/video/video.service.ts | |||
@@ -150,7 +150,7 @@ export class VideoService { | |||
150 | params = this.restService.addRestGetParams(params, pagination, sort) | 150 | params = this.restService.addRestGetParams(params, pagination, sort) |
151 | 151 | ||
152 | return this.authHttp | 152 | return this.authHttp |
153 | .get<ResultList<Video>>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.uuid + '/videos', { params }) | 153 | .get<ResultList<Video>>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.name + '/videos', { params }) |
154 | .pipe( | 154 | .pipe( |
155 | switchMap(res => this.extractVideos(res)), | 155 | switchMap(res => this.extractVideos(res)), |
156 | catchError(err => this.restExtractor.handleError(err)) | 156 | catchError(err => this.restExtractor.handleError(err)) |
diff --git a/client/src/app/signup/signup.component.html b/client/src/app/signup/signup.component.html index 565b695d9..5fd630b09 100644 --- a/client/src/app/signup/signup.component.html +++ b/client/src/app/signup/signup.component.html | |||
@@ -23,10 +23,17 @@ | |||
23 | <form role="form" (ngSubmit)="signup()" [formGroup]="form"> | 23 | <form role="form" (ngSubmit)="signup()" [formGroup]="form"> |
24 | <div class="form-group"> | 24 | <div class="form-group"> |
25 | <label for="username" i18n>Username</label> | 25 | <label for="username" i18n>Username</label> |
26 | <input | 26 | |
27 | type="text" id="username" i18n-placeholder placeholder="Username" | 27 | <div class="input-group"> |
28 | formControlName="username" [ngClass]="{ 'input-error': formErrors['username'] }" | 28 | <input |
29 | > | 29 | type="text" id="username" i18n-placeholder placeholder="Example: neil_amstrong" |
30 | formControlName="username" [ngClass]="{ 'input-error': formErrors['username'] }" | ||
31 | > | ||
32 | <div class="input-group-append"> | ||
33 | <span class="input-group-text">@{{ instanceHost }}</span> | ||
34 | </div> | ||
35 | </div> | ||
36 | |||
30 | <div *ngIf="formErrors.username" class="form-error"> | 37 | <div *ngIf="formErrors.username" class="form-error"> |
31 | {{ formErrors.username }} | 38 | {{ formErrors.username }} |
32 | </div> | 39 | </div> |
diff --git a/client/src/app/signup/signup.component.scss b/client/src/app/signup/signup.component.scss index e6d484297..1c992faf5 100644 --- a/client/src/app/signup/signup.component.scss +++ b/client/src/app/signup/signup.component.scss | |||
@@ -14,9 +14,18 @@ | |||
14 | margin: 30px 0; | 14 | margin: 30px 0; |
15 | } | 15 | } |
16 | 16 | ||
17 | .input-group { | ||
18 | @include peertube-input-group(340px); | ||
19 | } | ||
20 | |||
17 | input:not([type=submit]) { | 21 | input:not([type=submit]) { |
18 | @include peertube-input-text(340px); | 22 | @include peertube-input-text(340px); |
19 | display: block; | 23 | display: block; |
24 | |||
25 | &#username { | ||
26 | width: auto; | ||
27 | flex-grow: 1; | ||
28 | } | ||
20 | } | 29 | } |
21 | 30 | ||
22 | input[type=submit] { | 31 | input[type=submit] { |
diff --git a/client/src/app/signup/signup.component.ts b/client/src/app/signup/signup.component.ts index 076dac454..ed68487ae 100644 --- a/client/src/app/signup/signup.component.ts +++ b/client/src/app/signup/signup.component.ts | |||
@@ -34,6 +34,10 @@ export class SignupComponent extends FormReactive implements OnInit { | |||
34 | return this.serverService.getConfig().user.videoQuota | 34 | return this.serverService.getConfig().user.videoQuota |
35 | } | 35 | } |
36 | 36 | ||
37 | get instanceHost () { | ||
38 | return window.location.host | ||
39 | } | ||
40 | |||
37 | ngOnInit () { | 41 | ngOnInit () { |
38 | this.buildForm({ | 42 | this.buildForm({ |
39 | username: this.userValidatorsService.USER_USERNAME, | 43 | username: this.userValidatorsService.USER_USERNAME, |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html index 8d4a4a5ca..c275258ef 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html | |||
@@ -37,7 +37,7 @@ | |||
37 | </div> | 37 | </div> |
38 | 38 | ||
39 | <div class="video-info-channel"> | 39 | <div class="video-info-channel"> |
40 | <a [routerLink]="[ '/video-channels', video.channel.uuid ]" i18n-title title="Go the channel page"> | 40 | <a [routerLink]="[ '/video-channels', video.channel.name ]" i18n-title title="Go the channel page"> |
41 | {{ video.channel.displayName }} | 41 | {{ video.channel.displayName }} |
42 | 42 | ||
43 | <img [src]="video.videoChannelAvatarUrl" alt="Video channel avatar" /> | 43 | <img [src]="video.videoChannelAvatarUrl" alt="Video channel avatar" /> |
diff --git a/client/src/sass/include/_mixins.scss b/client/src/sass/include/_mixins.scss index 3d518394a..b0b0f544c 100644 --- a/client/src/sass/include/_mixins.scss +++ b/client/src/sass/include/_mixins.scss | |||
@@ -36,9 +36,16 @@ | |||
36 | border-radius: 3px; | 36 | border-radius: 3px; |
37 | padding-left: 15px; | 37 | padding-left: 15px; |
38 | padding-right: 15px; | 38 | padding-right: 15px; |
39 | } | ||
39 | 40 | ||
40 | &::placeholder { | 41 | @mixin peertube-input-group($width) { |
41 | color: #585858; | 42 | width: $width; |
43 | height: $button-height; | ||
44 | padding-top: 0; | ||
45 | padding-bottom: 0; | ||
46 | |||
47 | .input-group-text{ | ||
48 | font-size: 14px; | ||
42 | } | 49 | } |
43 | } | 50 | } |
44 | 51 | ||
diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts index c90c3f931..54cf44419 100644 --- a/server/controllers/activitypub/client.ts +++ b/server/controllers/activitypub/client.ts | |||
@@ -6,8 +6,8 @@ import { CONFIG, ROUTE_CACHE_LIFETIME } from '../../initializers' | |||
6 | import { buildVideoAnnounce } from '../../lib/activitypub/send' | 6 | import { buildVideoAnnounce } from '../../lib/activitypub/send' |
7 | import { audiencify, getAudience } from '../../lib/activitypub/audience' | 7 | import { audiencify, getAudience } from '../../lib/activitypub/audience' |
8 | import { createActivityData } from '../../lib/activitypub/send/send-create' | 8 | import { createActivityData } from '../../lib/activitypub/send/send-create' |
9 | import { asyncMiddleware, executeIfActivityPub, localAccountValidator } from '../../middlewares' | 9 | import { asyncMiddleware, executeIfActivityPub, localAccountValidator, localVideoChannelValidator } from '../../middlewares' |
10 | import { videoChannelsGetValidator, videosGetValidator, videosShareValidator } from '../../middlewares/validators' | 10 | import { videosGetValidator, videosShareValidator } from '../../middlewares/validators' |
11 | import { videoCommentGetValidator } from '../../middlewares/validators/video-comments' | 11 | import { videoCommentGetValidator } from '../../middlewares/validators/video-comments' |
12 | import { AccountModel } from '../../models/account/account' | 12 | import { AccountModel } from '../../models/account/account' |
13 | import { ActorModel } from '../../models/activitypub/actor' | 13 | import { ActorModel } from '../../models/activitypub/actor' |
@@ -80,16 +80,16 @@ activityPubClientRouter.get('/videos/watch/:videoId/comments/:commentId/activity | |||
80 | executeIfActivityPub(asyncMiddleware(videoCommentController)) | 80 | executeIfActivityPub(asyncMiddleware(videoCommentController)) |
81 | ) | 81 | ) |
82 | 82 | ||
83 | activityPubClientRouter.get('/video-channels/:id', | 83 | activityPubClientRouter.get('/video-channels/:name', |
84 | executeIfActivityPub(asyncMiddleware(videoChannelsGetValidator)), | 84 | executeIfActivityPub(asyncMiddleware(localVideoChannelValidator)), |
85 | executeIfActivityPub(asyncMiddleware(videoChannelController)) | 85 | executeIfActivityPub(asyncMiddleware(videoChannelController)) |
86 | ) | 86 | ) |
87 | activityPubClientRouter.get('/video-channels/:id/followers', | 87 | activityPubClientRouter.get('/video-channels/:name/followers', |
88 | executeIfActivityPub(asyncMiddleware(videoChannelsGetValidator)), | 88 | executeIfActivityPub(asyncMiddleware(localVideoChannelValidator)), |
89 | executeIfActivityPub(asyncMiddleware(videoChannelFollowersController)) | 89 | executeIfActivityPub(asyncMiddleware(videoChannelFollowersController)) |
90 | ) | 90 | ) |
91 | activityPubClientRouter.get('/video-channels/:id/following', | 91 | activityPubClientRouter.get('/video-channels/:name/following', |
92 | executeIfActivityPub(asyncMiddleware(videoChannelsGetValidator)), | 92 | executeIfActivityPub(asyncMiddleware(localVideoChannelValidator)), |
93 | executeIfActivityPub(asyncMiddleware(videoChannelFollowingController)) | 93 | executeIfActivityPub(asyncMiddleware(videoChannelFollowingController)) |
94 | ) | 94 | ) |
95 | 95 | ||
diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index 308970abc..7b7e5e740 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts | |||
@@ -78,7 +78,7 @@ async function listAccountVideos (req: express.Request, res: express.Response, n | |||
78 | start: req.query.start, | 78 | start: req.query.start, |
79 | count: req.query.count, | 79 | count: req.query.count, |
80 | sort: req.query.sort, | 80 | sort: req.query.sort, |
81 | includeLocalVideos: false, | 81 | includeLocalVideos: true, |
82 | categoryOneOf: req.query.categoryOneOf, | 82 | categoryOneOf: req.query.categoryOneOf, |
83 | licenceOneOf: req.query.licenceOneOf, | 83 | licenceOneOf: req.query.licenceOneOf, |
84 | languageOneOf: req.query.languageOneOf, | 84 | languageOneOf: req.query.languageOneOf, |
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts index 6ffc09f87..3f51f03f4 100644 --- a/server/controllers/api/video-channel.ts +++ b/server/controllers/api/video-channel.ts | |||
@@ -10,13 +10,12 @@ import { | |||
10 | setDefaultPagination, | 10 | setDefaultPagination, |
11 | setDefaultSort, | 11 | setDefaultSort, |
12 | videoChannelsAddValidator, | 12 | videoChannelsAddValidator, |
13 | videoChannelsGetValidator, | ||
14 | videoChannelsRemoveValidator, | 13 | videoChannelsRemoveValidator, |
15 | videoChannelsSortValidator, | 14 | videoChannelsSortValidator, |
16 | videoChannelsUpdateValidator | 15 | videoChannelsUpdateValidator |
17 | } from '../../middlewares' | 16 | } from '../../middlewares' |
18 | import { VideoChannelModel } from '../../models/video/video-channel' | 17 | import { VideoChannelModel } from '../../models/video/video-channel' |
19 | import { videosSortValidator } from '../../middlewares/validators' | 18 | import { videoChannelsNameWithHostValidator, videosSortValidator } from '../../middlewares/validators' |
20 | import { sendUpdateActor } from '../../lib/activitypub/send' | 19 | import { sendUpdateActor } from '../../lib/activitypub/send' |
21 | import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared' | 20 | import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared' |
22 | import { createVideoChannel } from '../../lib/video-channel' | 21 | import { createVideoChannel } from '../../lib/video-channel' |
@@ -50,7 +49,7 @@ videoChannelRouter.post('/', | |||
50 | asyncRetryTransactionMiddleware(addVideoChannel) | 49 | asyncRetryTransactionMiddleware(addVideoChannel) |
51 | ) | 50 | ) |
52 | 51 | ||
53 | videoChannelRouter.post('/:id/avatar/pick', | 52 | videoChannelRouter.post('/:nameWithHost/avatar/pick', |
54 | authenticate, | 53 | authenticate, |
55 | reqAvatarFile, | 54 | reqAvatarFile, |
56 | // Check the rights | 55 | // Check the rights |
@@ -59,25 +58,25 @@ videoChannelRouter.post('/:id/avatar/pick', | |||
59 | asyncMiddleware(updateVideoChannelAvatar) | 58 | asyncMiddleware(updateVideoChannelAvatar) |
60 | ) | 59 | ) |
61 | 60 | ||
62 | videoChannelRouter.put('/:id', | 61 | videoChannelRouter.put('/:nameWithHost', |
63 | authenticate, | 62 | authenticate, |
64 | asyncMiddleware(videoChannelsUpdateValidator), | 63 | asyncMiddleware(videoChannelsUpdateValidator), |
65 | asyncRetryTransactionMiddleware(updateVideoChannel) | 64 | asyncRetryTransactionMiddleware(updateVideoChannel) |
66 | ) | 65 | ) |
67 | 66 | ||
68 | videoChannelRouter.delete('/:id', | 67 | videoChannelRouter.delete('/:nameWithHost', |
69 | authenticate, | 68 | authenticate, |
70 | asyncMiddleware(videoChannelsRemoveValidator), | 69 | asyncMiddleware(videoChannelsRemoveValidator), |
71 | asyncRetryTransactionMiddleware(removeVideoChannel) | 70 | asyncRetryTransactionMiddleware(removeVideoChannel) |
72 | ) | 71 | ) |
73 | 72 | ||
74 | videoChannelRouter.get('/:id', | 73 | videoChannelRouter.get('/:nameWithHost', |
75 | asyncMiddleware(videoChannelsGetValidator), | 74 | asyncMiddleware(videoChannelsNameWithHostValidator), |
76 | asyncMiddleware(getVideoChannel) | 75 | asyncMiddleware(getVideoChannel) |
77 | ) | 76 | ) |
78 | 77 | ||
79 | videoChannelRouter.get('/:id/videos', | 78 | videoChannelRouter.get('/:nameWithHost/videos', |
80 | asyncMiddleware(videoChannelsGetValidator), | 79 | asyncMiddleware(videoChannelsNameWithHostValidator), |
81 | paginationValidator, | 80 | paginationValidator, |
82 | videosSortValidator, | 81 | videosSortValidator, |
83 | setDefaultSort, | 82 | setDefaultSort, |
@@ -215,7 +214,7 @@ async function listVideoChannelVideos (req: express.Request, res: express.Respon | |||
215 | start: req.query.start, | 214 | start: req.query.start, |
216 | count: req.query.count, | 215 | count: req.query.count, |
217 | sort: req.query.sort, | 216 | sort: req.query.sort, |
218 | includeLocalVideos: false, | 217 | includeLocalVideos: true, |
219 | categoryOneOf: req.query.categoryOneOf, | 218 | categoryOneOf: req.query.categoryOneOf, |
220 | licenceOneOf: req.query.licenceOneOf, | 219 | licenceOneOf: req.query.licenceOneOf, |
221 | languageOneOf: req.query.languageOneOf, | 220 | languageOneOf: req.query.languageOneOf, |
diff --git a/server/helpers/custom-validators/accounts.ts b/server/helpers/custom-validators/accounts.ts index 0607d661c..191de1496 100644 --- a/server/helpers/custom-validators/accounts.ts +++ b/server/helpers/custom-validators/accounts.ts | |||
@@ -42,7 +42,7 @@ function isAccountNameWithHostExist (nameWithDomain: string, res: Response, send | |||
42 | 42 | ||
43 | let promise: Bluebird<AccountModel> | 43 | let promise: Bluebird<AccountModel> |
44 | if (!host || host === CONFIG.WEBSERVER.HOST) promise = AccountModel.loadLocalByName(accountName) | 44 | if (!host || host === CONFIG.WEBSERVER.HOST) promise = AccountModel.loadLocalByName(accountName) |
45 | else promise = AccountModel.loadLocalByNameAndHost(accountName, host) | 45 | else promise = AccountModel.loadByNameAndHost(accountName, host) |
46 | 46 | ||
47 | return isAccountExist(promise, res, sendNotFound) | 47 | return isAccountExist(promise, res, sendNotFound) |
48 | } | 48 | } |
diff --git a/server/helpers/custom-validators/activitypub/actor.ts b/server/helpers/custom-validators/activitypub/actor.ts index ae5014f8f..c3a62c12d 100644 --- a/server/helpers/custom-validators/activitypub/actor.ts +++ b/server/helpers/custom-validators/activitypub/actor.ts | |||
@@ -27,7 +27,7 @@ function isActorPublicKeyValid (publicKey: string) { | |||
27 | validator.isLength(publicKey, CONSTRAINTS_FIELDS.ACTORS.PUBLIC_KEY) | 27 | validator.isLength(publicKey, CONSTRAINTS_FIELDS.ACTORS.PUBLIC_KEY) |
28 | } | 28 | } |
29 | 29 | ||
30 | const actorNameRegExp = new RegExp('[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_]+') | 30 | const actorNameRegExp = new RegExp('^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\\-_]+$') |
31 | function isActorPreferredUsernameValid (preferredUsername: string) { | 31 | function isActorPreferredUsernameValid (preferredUsername: string) { |
32 | return exists(preferredUsername) && validator.matches(preferredUsername, actorNameRegExp) | 32 | return exists(preferredUsername) && validator.matches(preferredUsername, actorNameRegExp) |
33 | } | 33 | } |
diff --git a/server/helpers/custom-validators/video-channels.ts b/server/helpers/custom-validators/video-channels.ts index 32faf36f7..f13519c1d 100644 --- a/server/helpers/custom-validators/video-channels.ts +++ b/server/helpers/custom-validators/video-channels.ts | |||
@@ -2,10 +2,9 @@ import * as express from 'express' | |||
2 | import 'express-validator' | 2 | import 'express-validator' |
3 | import 'multer' | 3 | import 'multer' |
4 | import * as validator from 'validator' | 4 | import * as validator from 'validator' |
5 | import { CONSTRAINTS_FIELDS } from '../../initializers' | 5 | import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers' |
6 | import { VideoChannelModel } from '../../models/video/video-channel' | 6 | import { VideoChannelModel } from '../../models/video/video-channel' |
7 | import { exists } from './misc' | 7 | import { exists } from './misc' |
8 | import { Response } from 'express' | ||
9 | 8 | ||
10 | const VIDEO_CHANNELS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_CHANNELS | 9 | const VIDEO_CHANNELS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_CHANNELS |
11 | 10 | ||
@@ -21,13 +20,13 @@ function isVideoChannelSupportValid (value: string) { | |||
21 | return value === null || (exists(value) && validator.isLength(value, VIDEO_CHANNELS_CONSTRAINTS_FIELDS.SUPPORT)) | 20 | return value === null || (exists(value) && validator.isLength(value, VIDEO_CHANNELS_CONSTRAINTS_FIELDS.SUPPORT)) |
22 | } | 21 | } |
23 | 22 | ||
24 | async function isLocalVideoChannelNameExist (name: string, res: Response) { | 23 | async function isLocalVideoChannelNameExist (name: string, res: express.Response) { |
25 | const videoChannel = await VideoChannelModel.loadLocalByName(name) | 24 | const videoChannel = await VideoChannelModel.loadLocalByNameAndPopulateAccount(name) |
26 | 25 | ||
27 | return processVideoChannelExist(videoChannel, res) | 26 | return processVideoChannelExist(videoChannel, res) |
28 | } | 27 | } |
29 | 28 | ||
30 | async function isVideoChannelExist (id: string, res: express.Response) { | 29 | async function isVideoChannelIdExist (id: string, res: express.Response) { |
31 | let videoChannel: VideoChannelModel | 30 | let videoChannel: VideoChannelModel |
32 | if (validator.isInt(id)) { | 31 | if (validator.isInt(id)) { |
33 | videoChannel = await VideoChannelModel.loadAndPopulateAccount(+id) | 32 | videoChannel = await VideoChannelModel.loadAndPopulateAccount(+id) |
@@ -38,14 +37,25 @@ async function isVideoChannelExist (id: string, res: express.Response) { | |||
38 | return processVideoChannelExist(videoChannel, res) | 37 | return processVideoChannelExist(videoChannel, res) |
39 | } | 38 | } |
40 | 39 | ||
40 | async function isVideoChannelNameWithHostExist (nameWithDomain: string, res: express.Response) { | ||
41 | const [ name, host ] = nameWithDomain.split('@') | ||
42 | let videoChannel: VideoChannelModel | ||
43 | |||
44 | if (!host || host === CONFIG.WEBSERVER.HOST) videoChannel = await VideoChannelModel.loadLocalByNameAndPopulateAccount(name) | ||
45 | else videoChannel = await VideoChannelModel.loadByNameAndHostAndPopulateAccount(name, host) | ||
46 | |||
47 | return processVideoChannelExist(videoChannel, res) | ||
48 | } | ||
49 | |||
41 | // --------------------------------------------------------------------------- | 50 | // --------------------------------------------------------------------------- |
42 | 51 | ||
43 | export { | 52 | export { |
53 | isVideoChannelNameWithHostExist, | ||
44 | isLocalVideoChannelNameExist, | 54 | isLocalVideoChannelNameExist, |
45 | isVideoChannelDescriptionValid, | 55 | isVideoChannelDescriptionValid, |
46 | isVideoChannelNameValid, | 56 | isVideoChannelNameValid, |
47 | isVideoChannelSupportValid, | 57 | isVideoChannelSupportValid, |
48 | isVideoChannelExist | 58 | isVideoChannelIdExist |
49 | } | 59 | } |
50 | 60 | ||
51 | function processVideoChannelExist (videoChannel: VideoChannelModel, res: express.Response) { | 61 | function processVideoChannelExist (videoChannel: VideoChannelModel, res: express.Response) { |
diff --git a/server/lib/activitypub/url.ts b/server/lib/activitypub/url.ts index ba3bf688d..262463310 100644 --- a/server/lib/activitypub/url.ts +++ b/server/lib/activitypub/url.ts | |||
@@ -13,8 +13,8 @@ function getVideoCommentActivityPubUrl (video: VideoModel, videoComment: VideoCo | |||
13 | return CONFIG.WEBSERVER.URL + '/videos/watch/' + video.uuid + '/comments/' + videoComment.id | 13 | return CONFIG.WEBSERVER.URL + '/videos/watch/' + video.uuid + '/comments/' + videoComment.id |
14 | } | 14 | } |
15 | 15 | ||
16 | function getVideoChannelActivityPubUrl (videoChannelUUID: string) { | 16 | function getVideoChannelActivityPubUrl (videoChannelName: string) { |
17 | return CONFIG.WEBSERVER.URL + '/video-channels/' + videoChannelUUID | 17 | return CONFIG.WEBSERVER.URL + '/video-channels/' + videoChannelName |
18 | } | 18 | } |
19 | 19 | ||
20 | function getAccountActivityPubUrl (accountName: string) { | 20 | function getAccountActivityPubUrl (accountName: string) { |
diff --git a/server/lib/user.ts b/server/lib/user.ts index e7a45f5aa..db29469eb 100644 --- a/server/lib/user.ts +++ b/server/lib/user.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import * as Sequelize from 'sequelize' | 1 | import * as Sequelize from 'sequelize' |
2 | import * as uuidv4 from 'uuid/v4' | ||
2 | import { ActivityPubActorType } from '../../shared/models/activitypub' | 3 | import { ActivityPubActorType } from '../../shared/models/activitypub' |
3 | import { sequelizeTypescript, SERVER_ACTOR_NAME } from '../initializers' | 4 | import { sequelizeTypescript, SERVER_ACTOR_NAME } from '../initializers' |
4 | import { AccountModel } from '../models/account/account' | 5 | import { AccountModel } from '../models/account/account' |
@@ -7,6 +8,7 @@ import { buildActorInstance, getAccountActivityPubUrl, setAsyncActorKeys } from | |||
7 | import { createVideoChannel } from './video-channel' | 8 | import { createVideoChannel } from './video-channel' |
8 | import { VideoChannelModel } from '../models/video/video-channel' | 9 | import { VideoChannelModel } from '../models/video/video-channel' |
9 | import { FilteredModelAttributes } from 'sequelize-typescript/lib/models/Model' | 10 | import { FilteredModelAttributes } from 'sequelize-typescript/lib/models/Model' |
11 | import { ActorModel } from '../models/activitypub/actor' | ||
10 | 12 | ||
11 | async function createUserAccountAndChannel (userToCreate: UserModel, validateUser = true) { | 13 | async function createUserAccountAndChannel (userToCreate: UserModel, validateUser = true) { |
12 | const { user, account, videoChannel } = await sequelizeTypescript.transaction(async t => { | 14 | const { user, account, videoChannel } = await sequelizeTypescript.transaction(async t => { |
@@ -19,8 +21,15 @@ async function createUserAccountAndChannel (userToCreate: UserModel, validateUse | |||
19 | const accountCreated = await createLocalAccountWithoutKeys(userToCreate.username, userToCreate.id, null, t) | 21 | const accountCreated = await createLocalAccountWithoutKeys(userToCreate.username, userToCreate.id, null, t) |
20 | userCreated.Account = accountCreated | 22 | userCreated.Account = accountCreated |
21 | 23 | ||
22 | const videoChannelDisplayName = `Default ${userCreated.username} channel` | 24 | let channelName = userCreated.username + '_channel' |
25 | |||
26 | // Conflict, generate uuid instead | ||
27 | const actor = await ActorModel.loadLocalByName(channelName) | ||
28 | if (actor) channelName = uuidv4() | ||
29 | |||
30 | const videoChannelDisplayName = `Main ${userCreated.username} channel` | ||
23 | const videoChannelInfo = { | 31 | const videoChannelInfo = { |
32 | name: channelName, | ||
24 | displayName: videoChannelDisplayName | 33 | displayName: videoChannelDisplayName |
25 | } | 34 | } |
26 | const videoChannel = await createVideoChannel(videoChannelInfo, accountCreated, t) | 35 | const videoChannel = await createVideoChannel(videoChannelInfo, accountCreated, t) |
diff --git a/server/lib/video-channel.ts b/server/lib/video-channel.ts index 600316cda..0fe95ca09 100644 --- a/server/lib/video-channel.ts +++ b/server/lib/video-channel.ts | |||
@@ -7,9 +7,8 @@ import { buildActorInstance, getVideoChannelActivityPubUrl } from './activitypub | |||
7 | 7 | ||
8 | async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account: AccountModel, t: Sequelize.Transaction) { | 8 | async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account: AccountModel, t: Sequelize.Transaction) { |
9 | const uuid = uuidv4() | 9 | const uuid = uuidv4() |
10 | const url = getVideoChannelActivityPubUrl(uuid) | 10 | const url = getVideoChannelActivityPubUrl(videoChannelInfo.name) |
11 | // We use the name as uuid | 11 | const actorInstance = buildActorInstance('Group', url, videoChannelInfo.name, uuid) |
12 | const actorInstance = buildActorInstance('Group', url, uuid, uuid) | ||
13 | 12 | ||
14 | const actorInstanceCreated = await actorInstance.save({ transaction: t }) | 13 | const actorInstanceCreated = await actorInstance.save({ transaction: t }) |
15 | 14 | ||
diff --git a/server/middlewares/validators/feeds.ts b/server/middlewares/validators/feeds.ts index 3c8532bd9..c1054ad9b 100644 --- a/server/middlewares/validators/feeds.ts +++ b/server/middlewares/validators/feeds.ts | |||
@@ -1,13 +1,13 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { param, query } from 'express-validator/check' | 2 | import { param, query } from 'express-validator/check' |
3 | import { isAccountIdExist, isAccountNameValid } from '../../helpers/custom-validators/accounts' | 3 | import { isAccountIdExist, isAccountNameValid, isAccountNameWithHostExist } from '../../helpers/custom-validators/accounts' |
4 | import { join } from 'path' | ||
5 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' | 4 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' |
6 | import { logger } from '../../helpers/logger' | 5 | import { logger } from '../../helpers/logger' |
7 | import { areValidationErrors } from './utils' | 6 | import { areValidationErrors } from './utils' |
8 | import { isValidRSSFeed } from '../../helpers/custom-validators/feeds' | 7 | import { isValidRSSFeed } from '../../helpers/custom-validators/feeds' |
9 | import { isVideoChannelExist } from '../../helpers/custom-validators/video-channels' | 8 | import { isVideoChannelIdExist, isVideoChannelNameWithHostExist } from '../../helpers/custom-validators/video-channels' |
10 | import { isVideoExist } from '../../helpers/custom-validators/videos' | 9 | import { isVideoExist } from '../../helpers/custom-validators/videos' |
10 | import { isActorPreferredUsernameValid } from '../../helpers/custom-validators/activitypub/actor' | ||
11 | 11 | ||
12 | const videoFeedsValidator = [ | 12 | const videoFeedsValidator = [ |
13 | param('format').optional().custom(isValidRSSFeed).withMessage('Should have a valid format (rss, atom, json)'), | 13 | param('format').optional().custom(isValidRSSFeed).withMessage('Should have a valid format (rss, atom, json)'), |
@@ -15,6 +15,7 @@ const videoFeedsValidator = [ | |||
15 | query('accountId').optional().custom(isIdOrUUIDValid), | 15 | query('accountId').optional().custom(isIdOrUUIDValid), |
16 | query('accountName').optional().custom(isAccountNameValid), | 16 | query('accountName').optional().custom(isAccountNameValid), |
17 | query('videoChannelId').optional().custom(isIdOrUUIDValid), | 17 | query('videoChannelId').optional().custom(isIdOrUUIDValid), |
18 | query('videoChannelName').optional().custom(isActorPreferredUsernameValid), | ||
18 | 19 | ||
19 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 20 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
20 | logger.debug('Checking feeds parameters', { parameters: req.query }) | 21 | logger.debug('Checking feeds parameters', { parameters: req.query }) |
@@ -22,7 +23,9 @@ const videoFeedsValidator = [ | |||
22 | if (areValidationErrors(req, res)) return | 23 | if (areValidationErrors(req, res)) return |
23 | 24 | ||
24 | if (req.query.accountId && !await isAccountIdExist(req.query.accountId, res)) return | 25 | if (req.query.accountId && !await isAccountIdExist(req.query.accountId, res)) return |
25 | if (req.query.videoChannelId && !await isVideoChannelExist(req.query.videoChannelId, res)) return | 26 | if (req.query.videoChannelName && !await isVideoChannelIdExist(req.query.videoChannelName, res)) return |
27 | if (req.query.accountName && !await isAccountNameWithHostExist(req.query.accountName, res)) return | ||
28 | if (req.query.videoChannelName && !await isVideoChannelNameWithHostExist(req.query.videoChannelName, res)) return | ||
26 | 29 | ||
27 | return next() | 30 | return next() |
28 | } | 31 | } |
diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/video-channels.ts index d354c7e05..79587b028 100644 --- a/server/middlewares/validators/video-channels.ts +++ b/server/middlewares/validators/video-channels.ts | |||
@@ -2,18 +2,18 @@ import * as express from 'express' | |||
2 | import { body, param } from 'express-validator/check' | 2 | import { body, param } from 'express-validator/check' |
3 | import { UserRight } from '../../../shared' | 3 | import { UserRight } from '../../../shared' |
4 | import { isAccountNameWithHostExist } from '../../helpers/custom-validators/accounts' | 4 | import { isAccountNameWithHostExist } from '../../helpers/custom-validators/accounts' |
5 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' | ||
6 | import { | 5 | import { |
7 | isLocalVideoChannelNameExist, | 6 | isLocalVideoChannelNameExist, |
8 | isVideoChannelDescriptionValid, | 7 | isVideoChannelDescriptionValid, |
9 | isVideoChannelExist, | ||
10 | isVideoChannelNameValid, | 8 | isVideoChannelNameValid, |
9 | isVideoChannelNameWithHostExist, | ||
11 | isVideoChannelSupportValid | 10 | isVideoChannelSupportValid |
12 | } from '../../helpers/custom-validators/video-channels' | 11 | } from '../../helpers/custom-validators/video-channels' |
13 | import { logger } from '../../helpers/logger' | 12 | import { logger } from '../../helpers/logger' |
14 | import { UserModel } from '../../models/account/user' | 13 | import { UserModel } from '../../models/account/user' |
15 | import { VideoChannelModel } from '../../models/video/video-channel' | 14 | import { VideoChannelModel } from '../../models/video/video-channel' |
16 | import { areValidationErrors } from './utils' | 15 | import { areValidationErrors } from './utils' |
16 | import { isActorPreferredUsernameValid } from '../../helpers/custom-validators/activitypub/actor' | ||
17 | 17 | ||
18 | const listVideoAccountChannelsValidator = [ | 18 | const listVideoAccountChannelsValidator = [ |
19 | param('accountName').exists().withMessage('Should have a valid account name'), | 19 | param('accountName').exists().withMessage('Should have a valid account name'), |
@@ -29,6 +29,7 @@ const listVideoAccountChannelsValidator = [ | |||
29 | ] | 29 | ] |
30 | 30 | ||
31 | const videoChannelsAddValidator = [ | 31 | const videoChannelsAddValidator = [ |
32 | body('name').custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'), | ||
32 | body('displayName').custom(isVideoChannelNameValid).withMessage('Should have a valid display name'), | 33 | body('displayName').custom(isVideoChannelNameValid).withMessage('Should have a valid display name'), |
33 | body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), | 34 | body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), |
34 | body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'), | 35 | body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'), |
@@ -43,7 +44,7 @@ const videoChannelsAddValidator = [ | |||
43 | ] | 44 | ] |
44 | 45 | ||
45 | const videoChannelsUpdateValidator = [ | 46 | const videoChannelsUpdateValidator = [ |
46 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 47 | param('nameWithHost').exists().withMessage('Should have an video channel name with host'), |
47 | body('displayName').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid display name'), | 48 | body('displayName').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid display name'), |
48 | body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), | 49 | body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), |
49 | body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'), | 50 | body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'), |
@@ -52,7 +53,7 @@ const videoChannelsUpdateValidator = [ | |||
52 | logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body }) | 53 | logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body }) |
53 | 54 | ||
54 | if (areValidationErrors(req, res)) return | 55 | if (areValidationErrors(req, res)) return |
55 | if (!await isVideoChannelExist(req.params.id, res)) return | 56 | if (!await isVideoChannelNameWithHostExist(req.params.nameWithHost, res)) return |
56 | 57 | ||
57 | // We need to make additional checks | 58 | // We need to make additional checks |
58 | if (res.locals.videoChannel.Actor.isOwned() === false) { | 59 | if (res.locals.videoChannel.Actor.isOwned() === false) { |
@@ -72,13 +73,13 @@ const videoChannelsUpdateValidator = [ | |||
72 | ] | 73 | ] |
73 | 74 | ||
74 | const videoChannelsRemoveValidator = [ | 75 | const videoChannelsRemoveValidator = [ |
75 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 76 | param('nameWithHost').exists().withMessage('Should have an video channel name with host'), |
76 | 77 | ||
77 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 78 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
78 | logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params }) | 79 | logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params }) |
79 | 80 | ||
80 | if (areValidationErrors(req, res)) return | 81 | if (areValidationErrors(req, res)) return |
81 | if (!await isVideoChannelExist(req.params.id, res)) return | 82 | if (!await isVideoChannelNameWithHostExist(req.params.nameWithHost, res)) return |
82 | 83 | ||
83 | if (!checkUserCanDeleteVideoChannel(res.locals.oauth.token.User, res.locals.videoChannel, res)) return | 84 | if (!checkUserCanDeleteVideoChannel(res.locals.oauth.token.User, res.locals.videoChannel, res)) return |
84 | if (!await checkVideoChannelIsNotTheLastOne(res)) return | 85 | if (!await checkVideoChannelIsNotTheLastOne(res)) return |
@@ -87,15 +88,15 @@ const videoChannelsRemoveValidator = [ | |||
87 | } | 88 | } |
88 | ] | 89 | ] |
89 | 90 | ||
90 | const videoChannelsGetValidator = [ | 91 | const videoChannelsNameWithHostValidator = [ |
91 | param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), | 92 | param('nameWithHost').exists().withMessage('Should have an video channel name with host'), |
92 | 93 | ||
93 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 94 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
94 | logger.debug('Checking videoChannelsGet parameters', { parameters: req.params }) | 95 | logger.debug('Checking videoChannelsNameWithHostValidator parameters', { parameters: req.params }) |
95 | 96 | ||
96 | if (areValidationErrors(req, res)) return | 97 | if (areValidationErrors(req, res)) return |
97 | 98 | ||
98 | if (!await isVideoChannelExist(req.params.id, res)) return | 99 | if (!await isVideoChannelNameWithHostExist(req.params.nameWithHost, res)) return |
99 | 100 | ||
100 | return next() | 101 | return next() |
101 | } | 102 | } |
@@ -121,7 +122,7 @@ export { | |||
121 | videoChannelsAddValidator, | 122 | videoChannelsAddValidator, |
122 | videoChannelsUpdateValidator, | 123 | videoChannelsUpdateValidator, |
123 | videoChannelsRemoveValidator, | 124 | videoChannelsRemoveValidator, |
124 | videoChannelsGetValidator, | 125 | videoChannelsNameWithHostValidator, |
125 | localVideoChannelValidator | 126 | localVideoChannelValidator |
126 | } | 127 | } |
127 | 128 | ||
diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 66f5dcf2e..07539a04e 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts | |||
@@ -194,7 +194,7 @@ export class AccountModel extends Model<AccountModel> { | |||
194 | return AccountModel.findOne(query) | 194 | return AccountModel.findOne(query) |
195 | } | 195 | } |
196 | 196 | ||
197 | static loadLocalByNameAndHost (name: string, host: string) { | 197 | static loadByNameAndHost (name: string, host: string) { |
198 | const query = { | 198 | const query = { |
199 | include: [ | 199 | include: [ |
200 | { | 200 | { |
diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts index 35d7c35e8..2abf40713 100644 --- a/server/models/activitypub/actor.ts +++ b/server/models/activitypub/actor.ts | |||
@@ -260,12 +260,13 @@ export class ActorModel extends Model<ActorModel> { | |||
260 | return ActorModel.scope(ScopeNames.FULL).findAll(query) | 260 | return ActorModel.scope(ScopeNames.FULL).findAll(query) |
261 | } | 261 | } |
262 | 262 | ||
263 | static loadLocalByName (preferredUsername: string) { | 263 | static loadLocalByName (preferredUsername: string, transaction?: Sequelize.Transaction) { |
264 | const query = { | 264 | const query = { |
265 | where: { | 265 | where: { |
266 | preferredUsername, | 266 | preferredUsername, |
267 | serverId: null | 267 | serverId: null |
268 | } | 268 | }, |
269 | transaction | ||
269 | } | 270 | } |
270 | 271 | ||
271 | return ActorModel.scope(ScopeNames.FULL).findOne(query) | 272 | return ActorModel.scope(ScopeNames.FULL).findOne(query) |
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index 0273fab13..9f80e0b8d 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts | |||
@@ -29,6 +29,7 @@ import { getSort, throwIfNotValid } from '../utils' | |||
29 | import { VideoModel } from './video' | 29 | import { VideoModel } from './video' |
30 | import { CONSTRAINTS_FIELDS } from '../../initializers' | 30 | import { CONSTRAINTS_FIELDS } from '../../initializers' |
31 | import { AvatarModel } from '../avatar/avatar' | 31 | import { AvatarModel } from '../avatar/avatar' |
32 | import { ServerModel } from '../server/server' | ||
32 | 33 | ||
33 | enum ScopeNames { | 34 | enum ScopeNames { |
34 | WITH_ACCOUNT = 'WITH_ACCOUNT', | 35 | WITH_ACCOUNT = 'WITH_ACCOUNT', |
@@ -206,7 +207,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
206 | } | 207 | } |
207 | 208 | ||
208 | static loadByIdAndAccount (id: number, accountId: number) { | 209 | static loadByIdAndAccount (id: number, accountId: number) { |
209 | const options = { | 210 | const query = { |
210 | where: { | 211 | where: { |
211 | id, | 212 | id, |
212 | accountId | 213 | accountId |
@@ -215,7 +216,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
215 | 216 | ||
216 | return VideoChannelModel | 217 | return VideoChannelModel |
217 | .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) | 218 | .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) |
218 | .findOne(options) | 219 | .findOne(query) |
219 | } | 220 | } |
220 | 221 | ||
221 | static loadAndPopulateAccount (id: number) { | 222 | static loadAndPopulateAccount (id: number) { |
@@ -225,7 +226,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
225 | } | 226 | } |
226 | 227 | ||
227 | static loadByUUIDAndPopulateAccount (uuid: string) { | 228 | static loadByUUIDAndPopulateAccount (uuid: string) { |
228 | const options = { | 229 | const query = { |
229 | include: [ | 230 | include: [ |
230 | { | 231 | { |
231 | model: ActorModel, | 232 | model: ActorModel, |
@@ -239,36 +240,63 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
239 | 240 | ||
240 | return VideoChannelModel | 241 | return VideoChannelModel |
241 | .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) | 242 | .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) |
242 | .findOne(options) | 243 | .findOne(query) |
243 | } | 244 | } |
244 | 245 | ||
245 | static loadAndPopulateAccountAndVideos (id: number) { | 246 | static loadLocalByNameAndPopulateAccount (name: string) { |
246 | const options = { | 247 | const query = { |
247 | include: [ | 248 | include: [ |
248 | VideoModel | 249 | { |
250 | model: ActorModel, | ||
251 | required: true, | ||
252 | where: { | ||
253 | preferredUsername: name, | ||
254 | serverId: null | ||
255 | } | ||
256 | } | ||
249 | ] | 257 | ] |
250 | } | 258 | } |
251 | 259 | ||
252 | return VideoChannelModel | 260 | return VideoChannelModel |
253 | .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEOS ]) | 261 | .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) |
254 | .findById(id, options) | 262 | .findOne(query) |
255 | } | 263 | } |
256 | 264 | ||
257 | static loadLocalByName (name: string) { | 265 | static loadByNameAndHostAndPopulateAccount (name: string, host: string) { |
258 | const query = { | 266 | const query = { |
259 | include: [ | 267 | include: [ |
260 | { | 268 | { |
261 | model: ActorModel, | 269 | model: ActorModel, |
262 | required: true, | 270 | required: true, |
263 | where: { | 271 | where: { |
264 | preferredUsername: name, | 272 | preferredUsername: name |
265 | serverId: null | 273 | }, |
266 | } | 274 | include: [ |
275 | { | ||
276 | model: ServerModel, | ||
277 | required: true, | ||
278 | where: { host } | ||
279 | } | ||
280 | ] | ||
267 | } | 281 | } |
268 | ] | 282 | ] |
269 | } | 283 | } |
270 | 284 | ||
271 | return VideoChannelModel.findOne(query) | 285 | return VideoChannelModel |
286 | .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) | ||
287 | .findOne(query) | ||
288 | } | ||
289 | |||
290 | static loadAndPopulateAccountAndVideos (id: number) { | ||
291 | const options = { | ||
292 | include: [ | ||
293 | VideoModel | ||
294 | ] | ||
295 | } | ||
296 | |||
297 | return VideoChannelModel | ||
298 | .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEOS ]) | ||
299 | .findById(id, options) | ||
272 | } | 300 | } |
273 | 301 | ||
274 | toFormattedJSON (): VideoChannel { | 302 | toFormattedJSON (): VideoChannel { |
diff --git a/server/tests/api/check-params/user-subscriptions.ts b/server/tests/api/check-params/user-subscriptions.ts index 9f7d15b27..628a74476 100644 --- a/server/tests/api/check-params/user-subscriptions.ts +++ b/server/tests/api/check-params/user-subscriptions.ts | |||
@@ -5,7 +5,6 @@ import 'mocha' | |||
5 | import { | 5 | import { |
6 | createUser, | 6 | createUser, |
7 | flushTests, | 7 | flushTests, |
8 | getMyUserInformation, | ||
9 | killallServers, | 8 | killallServers, |
10 | makeDeleteRequest, | 9 | makeDeleteRequest, |
11 | makeGetRequest, | 10 | makeGetRequest, |
@@ -21,7 +20,6 @@ describe('Test user subscriptions API validators', function () { | |||
21 | const path = '/api/v1/users/me/subscriptions' | 20 | const path = '/api/v1/users/me/subscriptions' |
22 | let server: ServerInfo | 21 | let server: ServerInfo |
23 | let userAccessToken = '' | 22 | let userAccessToken = '' |
24 | let userChannelUUID: string | ||
25 | 23 | ||
26 | // --------------------------------------------------------------- | 24 | // --------------------------------------------------------------- |
27 | 25 | ||
@@ -40,11 +38,6 @@ describe('Test user subscriptions API validators', function () { | |||
40 | } | 38 | } |
41 | await createUser(server.url, server.accessToken, user.username, user.password) | 39 | await createUser(server.url, server.accessToken, user.username, user.password) |
42 | userAccessToken = await userLogin(server, user) | 40 | userAccessToken = await userLogin(server, user) |
43 | |||
44 | { | ||
45 | const res = await getMyUserInformation(server.url, server.accessToken) | ||
46 | userChannelUUID = res.body.videoChannels[ 0 ].uuid | ||
47 | } | ||
48 | }) | 41 | }) |
49 | 42 | ||
50 | describe('When listing my subscriptions', function () { | 43 | describe('When listing my subscriptions', function () { |
@@ -69,7 +62,7 @@ describe('Test user subscriptions API validators', function () { | |||
69 | }) | 62 | }) |
70 | 63 | ||
71 | it('Should success with the correct parameters', async function () { | 64 | it('Should success with the correct parameters', async function () { |
72 | await await makeGetRequest({ | 65 | await makeGetRequest({ |
73 | url: server.url, | 66 | url: server.url, |
74 | path, | 67 | path, |
75 | token: userAccessToken, | 68 | token: userAccessToken, |
@@ -102,7 +95,7 @@ describe('Test user subscriptions API validators', function () { | |||
102 | }) | 95 | }) |
103 | 96 | ||
104 | it('Should success with the correct parameters', async function () { | 97 | it('Should success with the correct parameters', async function () { |
105 | await await makeGetRequest({ | 98 | await makeGetRequest({ |
106 | url: server.url, | 99 | url: server.url, |
107 | path, | 100 | path, |
108 | token: userAccessToken, | 101 | token: userAccessToken, |
@@ -116,7 +109,7 @@ describe('Test user subscriptions API validators', function () { | |||
116 | await makePostBodyRequest({ | 109 | await makePostBodyRequest({ |
117 | url: server.url, | 110 | url: server.url, |
118 | path, | 111 | path, |
119 | fields: { uri: userChannelUUID + '@localhost:9001' }, | 112 | fields: { uri: 'user1_channel@localhost:9001' }, |
120 | statusCodeExpected: 401 | 113 | statusCodeExpected: 401 |
121 | }) | 114 | }) |
122 | }) | 115 | }) |
@@ -152,7 +145,7 @@ describe('Test user subscriptions API validators', function () { | |||
152 | url: server.url, | 145 | url: server.url, |
153 | path, | 146 | path, |
154 | token: server.accessToken, | 147 | token: server.accessToken, |
155 | fields: { uri: userChannelUUID + '@localhost:9001' }, | 148 | fields: { uri: 'user1_channel@localhost:9001' }, |
156 | statusCodeExpected: 204 | 149 | statusCodeExpected: 204 |
157 | }) | 150 | }) |
158 | }) | 151 | }) |
@@ -162,7 +155,7 @@ describe('Test user subscriptions API validators', function () { | |||
162 | it('Should fail with a non authenticated user', async function () { | 155 | it('Should fail with a non authenticated user', async function () { |
163 | await makeDeleteRequest({ | 156 | await makeDeleteRequest({ |
164 | url: server.url, | 157 | url: server.url, |
165 | path: path + '/' + userChannelUUID + '@localhost:9001', | 158 | path: path + '/user1_channel@localhost:9001', |
166 | statusCodeExpected: 401 | 159 | statusCodeExpected: 401 |
167 | }) | 160 | }) |
168 | }) | 161 | }) |
@@ -202,7 +195,7 @@ describe('Test user subscriptions API validators', function () { | |||
202 | it('Should success with the correct parameters', async function () { | 195 | it('Should success with the correct parameters', async function () { |
203 | await makeDeleteRequest({ | 196 | await makeDeleteRequest({ |
204 | url: server.url, | 197 | url: server.url, |
205 | path: path + '/' + userChannelUUID + '@localhost:9001', | 198 | path: path + '/user1_channel@localhost:9001', |
206 | token: server.accessToken, | 199 | token: server.accessToken, |
207 | statusCodeExpected: 204 | 200 | statusCodeExpected: 204 |
208 | }) | 201 | }) |
diff --git a/server/tests/api/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts index 0980de73b..bcf4b7473 100644 --- a/server/tests/api/check-params/video-channels.ts +++ b/server/tests/api/check-params/video-channels.ts | |||
@@ -31,7 +31,6 @@ describe('Test video channels API validator', function () { | |||
31 | const videoChannelPath = '/api/v1/video-channels' | 31 | const videoChannelPath = '/api/v1/video-channels' |
32 | let server: ServerInfo | 32 | let server: ServerInfo |
33 | let accessTokenUser: string | 33 | let accessTokenUser: string |
34 | let videoChannelUUID: string | ||
35 | 34 | ||
36 | // --------------------------------------------------------------- | 35 | // --------------------------------------------------------------- |
37 | 36 | ||
@@ -53,12 +52,6 @@ describe('Test video channels API validator', function () { | |||
53 | await createUser(server.url, server.accessToken, user.username, user.password) | 52 | await createUser(server.url, server.accessToken, user.username, user.password) |
54 | accessTokenUser = await userLogin(server, user) | 53 | accessTokenUser = await userLogin(server, user) |
55 | } | 54 | } |
56 | |||
57 | { | ||
58 | const res = await getMyUserInformation(server.url, server.accessToken) | ||
59 | const user: User = res.body | ||
60 | videoChannelUUID = user.videoChannels[0].uuid | ||
61 | } | ||
62 | }) | 55 | }) |
63 | 56 | ||
64 | describe('When listing a video channels', function () { | 57 | describe('When listing a video channels', function () { |
@@ -83,6 +76,7 @@ describe('Test video channels API validator', function () { | |||
83 | 76 | ||
84 | describe('When adding a video channel', function () { | 77 | describe('When adding a video channel', function () { |
85 | const baseCorrectParams = { | 78 | const baseCorrectParams = { |
79 | name: 'super_channel', | ||
86 | displayName: 'hello', | 80 | displayName: 'hello', |
87 | description: 'super description', | 81 | description: 'super description', |
88 | support: 'super support text' | 82 | support: 'super support text' |
@@ -104,6 +98,16 @@ describe('Test video channels API validator', function () { | |||
104 | }) | 98 | }) |
105 | 99 | ||
106 | it('Should fail without a name', async function () { | 100 | it('Should fail without a name', async function () { |
101 | const fields = omit(baseCorrectParams, 'name') | ||
102 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) | ||
103 | }) | ||
104 | |||
105 | it('Should fail with a bad name', async function () { | ||
106 | const fields = immutableAssign(baseCorrectParams, { name: 'super name' }) | ||
107 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) | ||
108 | }) | ||
109 | |||
110 | it('Should fail without a name', async function () { | ||
107 | const fields = omit(baseCorrectParams, 'displayName') | 111 | const fields = omit(baseCorrectParams, 'displayName') |
108 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) | 112 | await makePostBodyRequest({ url: server.url, path: videoChannelPath, token: server.accessToken, fields }) |
109 | }) | 113 | }) |
@@ -142,7 +146,7 @@ describe('Test video channels API validator', function () { | |||
142 | let path: string | 146 | let path: string |
143 | 147 | ||
144 | before(async function () { | 148 | before(async function () { |
145 | path = videoChannelPath + '/' + videoChannelUUID | 149 | path = videoChannelPath + '/super_channel' |
146 | }) | 150 | }) |
147 | 151 | ||
148 | it('Should fail with a non authenticated user', async function () { | 152 | it('Should fail with a non authenticated user', async function () { |
@@ -195,7 +199,7 @@ describe('Test video channels API validator', function () { | |||
195 | let path: string | 199 | let path: string |
196 | 200 | ||
197 | before(async function () { | 201 | before(async function () { |
198 | path = videoChannelPath + '/' + videoChannelUUID | 202 | path = videoChannelPath + '/super_channel' |
199 | }) | 203 | }) |
200 | 204 | ||
201 | it('Should fail with an incorrect input file', async function () { | 205 | it('Should fail with an incorrect input file', async function () { |
@@ -255,18 +259,10 @@ describe('Test video channels API validator', function () { | |||
255 | expect(res.body.data).to.be.an('array') | 259 | expect(res.body.data).to.be.an('array') |
256 | }) | 260 | }) |
257 | 261 | ||
258 | it('Should fail without a correct uuid', async function () { | ||
259 | await makeGetRequest({ | ||
260 | url: server.url, | ||
261 | path: videoChannelPath + '/coucou', | ||
262 | statusCodeExpected: 400 | ||
263 | }) | ||
264 | }) | ||
265 | |||
266 | it('Should return 404 with an incorrect video channel', async function () { | 262 | it('Should return 404 with an incorrect video channel', async function () { |
267 | await makeGetRequest({ | 263 | await makeGetRequest({ |
268 | url: server.url, | 264 | url: server.url, |
269 | path: videoChannelPath + '/4da6fde3-88f7-4d16-b119-108df5630b06', | 265 | path: videoChannelPath + '/super_channel2', |
270 | statusCodeExpected: 404 | 266 | statusCodeExpected: 404 |
271 | }) | 267 | }) |
272 | }) | 268 | }) |
@@ -274,7 +270,7 @@ describe('Test video channels API validator', function () { | |||
274 | it('Should succeed with the correct parameters', async function () { | 270 | it('Should succeed with the correct parameters', async function () { |
275 | await makeGetRequest({ | 271 | await makeGetRequest({ |
276 | url: server.url, | 272 | url: server.url, |
277 | path: videoChannelPath + '/' + videoChannelUUID, | 273 | path: videoChannelPath + '/super_channel', |
278 | statusCodeExpected: 200 | 274 | statusCodeExpected: 200 |
279 | }) | 275 | }) |
280 | }) | 276 | }) |
@@ -282,26 +278,23 @@ describe('Test video channels API validator', function () { | |||
282 | 278 | ||
283 | describe('When deleting a video channel', function () { | 279 | describe('When deleting a video channel', function () { |
284 | it('Should fail with a non authenticated user', async function () { | 280 | it('Should fail with a non authenticated user', async function () { |
285 | await deleteVideoChannel(server.url, 'coucou', videoChannelUUID, 401) | 281 | await deleteVideoChannel(server.url, 'coucou', 'super_channel', 401) |
286 | }) | 282 | }) |
287 | 283 | ||
288 | it('Should fail with another authenticated user', async function () { | 284 | it('Should fail with another authenticated user', async function () { |
289 | await deleteVideoChannel(server.url, accessTokenUser, videoChannelUUID, 403) | 285 | await deleteVideoChannel(server.url, accessTokenUser, 'super_channel', 403) |
290 | }) | 286 | }) |
291 | 287 | ||
292 | it('Should fail with an unknown video channel id', async function () { | 288 | it('Should fail with an unknown video channel id', async function () { |
293 | await deleteVideoChannel(server.url, server.accessToken,454554, 404) | 289 | await deleteVideoChannel(server.url, server.accessToken,'super_channel2', 404) |
294 | }) | 290 | }) |
295 | 291 | ||
296 | it('Should succeed with the correct parameters', async function () { | 292 | it('Should succeed with the correct parameters', async function () { |
297 | await deleteVideoChannel(server.url, server.accessToken, videoChannelUUID) | 293 | await deleteVideoChannel(server.url, server.accessToken, 'super_channel') |
298 | }) | 294 | }) |
299 | 295 | ||
300 | it('Should fail to delete the last user video channel', async function () { | 296 | it('Should fail to delete the last user video channel', async function () { |
301 | const res = await getVideoChannelsList(server.url, 0, 1) | 297 | await deleteVideoChannel(server.url, server.accessToken, 'root_channel', 409) |
302 | const lastVideoChannelUUID = res.body.data[0].uuid | ||
303 | |||
304 | await deleteVideoChannel(server.url, server.accessToken, lastVideoChannelUUID, 409) | ||
305 | }) | 298 | }) |
306 | }) | 299 | }) |
307 | 300 | ||
diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts index 1cad8998c..243fcd4e7 100644 --- a/server/tests/api/server/follows.ts +++ b/server/tests/api/server/follows.ts | |||
@@ -311,7 +311,7 @@ describe('Test follows', function () { | |||
311 | likes: 1, | 311 | likes: 1, |
312 | dislikes: 1, | 312 | dislikes: 1, |
313 | channel: { | 313 | channel: { |
314 | name: 'Default root channel', | 314 | name: 'Main root channel', |
315 | description: '', | 315 | description: '', |
316 | isLocal | 316 | isLocal |
317 | }, | 317 | }, |
diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts index 18a0d9ce3..df35b36eb 100644 --- a/server/tests/api/server/handle-down.ts +++ b/server/tests/api/server/handle-down.ts | |||
@@ -71,7 +71,7 @@ describe('Test handle downs', function () { | |||
71 | privacy: VideoPrivacy.PUBLIC, | 71 | privacy: VideoPrivacy.PUBLIC, |
72 | commentsEnabled: true, | 72 | commentsEnabled: true, |
73 | channel: { | 73 | channel: { |
74 | name: 'Default root channel', | 74 | name: 'Main root channel', |
75 | description: '', | 75 | description: '', |
76 | isLocal: false | 76 | isLocal: false |
77 | }, | 77 | }, |
diff --git a/server/tests/api/users/user-subscriptions.ts b/server/tests/api/users/user-subscriptions.ts index 2ba6cdfaf..ba59a9a60 100644 --- a/server/tests/api/users/user-subscriptions.ts +++ b/server/tests/api/users/user-subscriptions.ts | |||
@@ -3,7 +3,7 @@ | |||
3 | import * as chai from 'chai' | 3 | import * as chai from 'chai' |
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { createUser, doubleFollow, flushAndRunMultipleServers, follow, getVideosList, unfollow, userLogin } from '../../utils' | 5 | import { createUser, doubleFollow, flushAndRunMultipleServers, follow, getVideosList, unfollow, userLogin } from '../../utils' |
6 | import { getMyUserInformation, killallServers, ServerInfo, uploadVideo } from '../../utils/index' | 6 | import { killallServers, ServerInfo, uploadVideo } from '../../utils/index' |
7 | import { setAccessTokensToServers } from '../../utils/users/login' | 7 | import { setAccessTokensToServers } from '../../utils/users/login' |
8 | import { Video, VideoChannel } from '../../../../shared/models/videos' | 8 | import { Video, VideoChannel } from '../../../../shared/models/videos' |
9 | import { waitJobs } from '../../utils/server/jobs' | 9 | import { waitJobs } from '../../utils/server/jobs' |
@@ -18,8 +18,7 @@ const expect = chai.expect | |||
18 | 18 | ||
19 | describe('Test users subscriptions', function () { | 19 | describe('Test users subscriptions', function () { |
20 | let servers: ServerInfo[] = [] | 20 | let servers: ServerInfo[] = [] |
21 | const users: { accessToken: string, videoChannelName: string }[] = [] | 21 | const users: { accessToken: string }[] = [] |
22 | let rootChannelNameServer1: string | ||
23 | 22 | ||
24 | before(async function () { | 23 | before(async function () { |
25 | this.timeout(120000) | 24 | this.timeout(120000) |
@@ -32,19 +31,13 @@ describe('Test users subscriptions', function () { | |||
32 | // Server 1 and server 2 follow each other | 31 | // Server 1 and server 2 follow each other |
33 | await doubleFollow(servers[0], servers[1]) | 32 | await doubleFollow(servers[0], servers[1]) |
34 | 33 | ||
35 | const res = await getMyUserInformation(servers[0].url, servers[0].accessToken) | ||
36 | rootChannelNameServer1 = res.body.videoChannels[0].name | ||
37 | |||
38 | { | 34 | { |
39 | for (const server of servers) { | 35 | for (const server of servers) { |
40 | const user = { username: 'user' + server.serverNumber, password: 'password' } | 36 | const user = { username: 'user' + server.serverNumber, password: 'password' } |
41 | await createUser(server.url, server.accessToken, user.username, user.password) | 37 | await createUser(server.url, server.accessToken, user.username, user.password) |
42 | 38 | ||
43 | const accessToken = await userLogin(server, user) | 39 | const accessToken = await userLogin(server, user) |
44 | const res = await getMyUserInformation(server.url, accessToken) | 40 | users.push({ accessToken }) |
45 | const videoChannels: VideoChannel[] = res.body.videoChannels | ||
46 | |||
47 | users.push({ accessToken, videoChannelName: videoChannels[0].name }) | ||
48 | 41 | ||
49 | const videoName1 = 'video 1-' + server.serverNumber | 42 | const videoName1 = 'video 1-' + server.serverNumber |
50 | await uploadVideo(server.url, accessToken, { name: videoName1 }) | 43 | await uploadVideo(server.url, accessToken, { name: videoName1 }) |
@@ -64,10 +57,10 @@ describe('Test users subscriptions', function () { | |||
64 | }) | 57 | }) |
65 | 58 | ||
66 | it('User of server 1 should follow user of server 3 and root of server 1', async function () { | 59 | it('User of server 1 should follow user of server 3 and root of server 1', async function () { |
67 | this.timeout(30000) | 60 | this.timeout(60000) |
68 | 61 | ||
69 | await addUserSubscription(servers[0].url, users[0].accessToken, users[2].videoChannelName + '@localhost:9003') | 62 | await addUserSubscription(servers[0].url, users[0].accessToken, 'user3_channel@localhost:9003') |
70 | await addUserSubscription(servers[0].url, users[0].accessToken, rootChannelNameServer1 + '@localhost:9001') | 63 | await addUserSubscription(servers[0].url, users[0].accessToken, 'root_channel@localhost:9001') |
71 | 64 | ||
72 | await waitJobs(servers) | 65 | await waitJobs(servers) |
73 | 66 | ||
@@ -103,8 +96,8 @@ describe('Test users subscriptions', function () { | |||
103 | expect(subscriptions).to.be.an('array') | 96 | expect(subscriptions).to.be.an('array') |
104 | expect(subscriptions).to.have.lengthOf(2) | 97 | expect(subscriptions).to.have.lengthOf(2) |
105 | 98 | ||
106 | expect(subscriptions[0].name).to.equal(users[2].videoChannelName) | 99 | expect(subscriptions[0].name).to.equal('user3_channel') |
107 | expect(subscriptions[1].name).to.equal(rootChannelNameServer1) | 100 | expect(subscriptions[1].name).to.equal('root_channel') |
108 | } | 101 | } |
109 | }) | 102 | }) |
110 | 103 | ||
@@ -131,7 +124,7 @@ describe('Test users subscriptions', function () { | |||
131 | }) | 124 | }) |
132 | 125 | ||
133 | it('Should upload a video by root on server 1 and see it in the subscription videos', async function () { | 126 | it('Should upload a video by root on server 1 and see it in the subscription videos', async function () { |
134 | this.timeout(30000) | 127 | this.timeout(60000) |
135 | 128 | ||
136 | const videoName = 'video server 1 added after follow' | 129 | const videoName = 'video server 1 added after follow' |
137 | await uploadVideo(servers[0].url, servers[0].accessToken, { name: videoName }) | 130 | await uploadVideo(servers[0].url, servers[0].accessToken, { name: videoName }) |
@@ -172,7 +165,7 @@ describe('Test users subscriptions', function () { | |||
172 | }) | 165 | }) |
173 | 166 | ||
174 | it('Should have server 1 follow server 3 and display server 3 videos', async function () { | 167 | it('Should have server 1 follow server 3 and display server 3 videos', async function () { |
175 | this.timeout(30000) | 168 | this.timeout(60000) |
176 | 169 | ||
177 | await follow(servers[0].url, [ servers[2].url ], servers[0].accessToken) | 170 | await follow(servers[0].url, [ servers[2].url ], servers[0].accessToken) |
178 | 171 | ||
@@ -190,7 +183,7 @@ describe('Test users subscriptions', function () { | |||
190 | }) | 183 | }) |
191 | 184 | ||
192 | it('Should remove follow server 1 -> server 3 and hide server 3 videos', async function () { | 185 | it('Should remove follow server 1 -> server 3 and hide server 3 videos', async function () { |
193 | this.timeout(30000) | 186 | this.timeout(60000) |
194 | 187 | ||
195 | await unfollow(servers[0].url, servers[0].accessToken, servers[2]) | 188 | await unfollow(servers[0].url, servers[0].accessToken, servers[2]) |
196 | 189 | ||
@@ -230,7 +223,7 @@ describe('Test users subscriptions', function () { | |||
230 | }) | 223 | }) |
231 | 224 | ||
232 | it('Should remove user of server 3 subscription', async function () { | 225 | it('Should remove user of server 3 subscription', async function () { |
233 | await removeUserSubscription(servers[0].url, users[0].accessToken, users[2].videoChannelName + '@localhost:9003') | 226 | await removeUserSubscription(servers[0].url, users[0].accessToken, 'user3_channel@localhost:9003') |
234 | 227 | ||
235 | await waitJobs(servers) | 228 | await waitJobs(servers) |
236 | }) | 229 | }) |
@@ -249,7 +242,7 @@ describe('Test users subscriptions', function () { | |||
249 | }) | 242 | }) |
250 | 243 | ||
251 | it('Should remove the root subscription and not display the videos anymore', async function () { | 244 | it('Should remove the root subscription and not display the videos anymore', async function () { |
252 | await removeUserSubscription(servers[0].url, users[0].accessToken, rootChannelNameServer1 + '@localhost:9001') | 245 | await removeUserSubscription(servers[0].url, users[0].accessToken, 'root_channel@localhost:9001') |
253 | 246 | ||
254 | await waitJobs(servers) | 247 | await waitJobs(servers) |
255 | 248 | ||
@@ -275,9 +268,9 @@ describe('Test users subscriptions', function () { | |||
275 | }) | 268 | }) |
276 | 269 | ||
277 | it('Should follow user of server 3 again', async function () { | 270 | it('Should follow user of server 3 again', async function () { |
278 | this.timeout(30000) | 271 | this.timeout(60000) |
279 | 272 | ||
280 | await addUserSubscription(servers[0].url, users[0].accessToken, users[2].videoChannelName + '@localhost:9003') | 273 | await addUserSubscription(servers[0].url, users[0].accessToken, 'user3_channel@localhost:9003') |
281 | 274 | ||
282 | await waitJobs(servers) | 275 | await waitJobs(servers) |
283 | 276 | ||
diff --git a/server/tests/api/users/users-multiple-servers.ts b/server/tests/api/users/users-multiple-servers.ts index 81489021b..575e04546 100644 --- a/server/tests/api/users/users-multiple-servers.ts +++ b/server/tests/api/users/users-multiple-servers.ts | |||
@@ -12,10 +12,9 @@ import { | |||
12 | getVideoChannelsList, | 12 | getVideoChannelsList, |
13 | removeUser, | 13 | removeUser, |
14 | updateMyUser, | 14 | updateMyUser, |
15 | userLogin, | 15 | userLogin |
16 | wait | ||
17 | } from '../../utils' | 16 | } from '../../utils' |
18 | import { flushTests, getMyUserInformation, killallServers, ServerInfo, testImage, updateMyAvatar, uploadVideo } from '../../utils/index' | 17 | import { getMyUserInformation, killallServers, ServerInfo, testImage, updateMyAvatar, uploadVideo } from '../../utils/index' |
19 | import { checkActorFilesWereRemoved, getAccount, getAccountsList } from '../../utils/users/accounts' | 18 | import { checkActorFilesWereRemoved, getAccount, getAccountsList } from '../../utils/users/accounts' |
20 | import { setAccessTokensToServers } from '../../utils/users/login' | 19 | import { setAccessTokensToServers } from '../../utils/users/login' |
21 | import { User } from '../../../../shared/models/users' | 20 | import { User } from '../../../../shared/models/users' |
@@ -172,7 +171,7 @@ describe('Test users with multiple servers', function () { | |||
172 | 171 | ||
173 | const resVideoChannels = await getVideoChannelsList(server.url, 0, 10) | 172 | const resVideoChannels = await getVideoChannelsList(server.url, 0, 10) |
174 | const videoChannelDeleted = resVideoChannels.body.data.find(a => { | 173 | const videoChannelDeleted = resVideoChannels.body.data.find(a => { |
175 | return a.displayName === 'Default user1 channel' && a.host === 'localhost:9001' | 174 | return a.displayName === 'Main user1 channel' && a.host === 'localhost:9001' |
176 | }) as VideoChannel | 175 | }) as VideoChannel |
177 | expect(videoChannelDeleted).not.to.be.undefined | 176 | expect(videoChannelDeleted).not.to.be.undefined |
178 | } | 177 | } |
@@ -189,7 +188,7 @@ describe('Test users with multiple servers', function () { | |||
189 | 188 | ||
190 | const resVideoChannels = await getVideoChannelsList(server.url, 0, 10) | 189 | const resVideoChannels = await getVideoChannelsList(server.url, 0, 10) |
191 | const videoChannelDeleted = resVideoChannels.body.data.find(a => { | 190 | const videoChannelDeleted = resVideoChannels.body.data.find(a => { |
192 | return a.name === 'Default user1 channel' && a.host === 'localhost:9001' | 191 | return a.name === 'Main user1 channel' && a.host === 'localhost:9001' |
193 | }) as VideoChannel | 192 | }) as VideoChannel |
194 | expect(videoChannelDeleted).to.be.undefined | 193 | expect(videoChannelDeleted).to.be.undefined |
195 | } | 194 | } |
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts index cab096a12..3c3839338 100644 --- a/server/tests/api/videos/multiple-servers.ts +++ b/server/tests/api/videos/multiple-servers.ts | |||
@@ -6,7 +6,6 @@ import { join } from 'path' | |||
6 | import * as request from 'supertest' | 6 | import * as request from 'supertest' |
7 | import { VideoPrivacy } from '../../../../shared/models/videos' | 7 | import { VideoPrivacy } from '../../../../shared/models/videos' |
8 | import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' | 8 | import { VideoComment, VideoCommentThreadTree } from '../../../../shared/models/videos/video-comment.model' |
9 | |||
10 | import { | 9 | import { |
11 | addVideoChannel, | 10 | addVideoChannel, |
12 | checkVideoFilesWereRemoved, | 11 | checkVideoFilesWereRemoved, |
@@ -60,6 +59,7 @@ describe('Test multiple servers', function () { | |||
60 | 59 | ||
61 | { | 60 | { |
62 | const videoChannel = { | 61 | const videoChannel = { |
62 | name: 'super_channel_name', | ||
63 | displayName: 'my channel', | 63 | displayName: 'my channel', |
64 | description: 'super channel' | 64 | description: 'super channel' |
65 | } | 65 | } |
@@ -201,7 +201,7 @@ describe('Test multiple servers', function () { | |||
201 | tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ], | 201 | tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ], |
202 | privacy: VideoPrivacy.PUBLIC, | 202 | privacy: VideoPrivacy.PUBLIC, |
203 | channel: { | 203 | channel: { |
204 | name: 'Default user1 channel', | 204 | name: 'Main user1 channel', |
205 | description: 'super channel', | 205 | description: 'super channel', |
206 | isLocal | 206 | isLocal |
207 | }, | 207 | }, |
@@ -307,7 +307,7 @@ describe('Test multiple servers', function () { | |||
307 | tags: [ 'tag1p3' ], | 307 | tags: [ 'tag1p3' ], |
308 | privacy: VideoPrivacy.PUBLIC, | 308 | privacy: VideoPrivacy.PUBLIC, |
309 | channel: { | 309 | channel: { |
310 | name: 'Default root channel', | 310 | name: 'Main root channel', |
311 | description: '', | 311 | description: '', |
312 | isLocal | 312 | isLocal |
313 | }, | 313 | }, |
@@ -339,7 +339,7 @@ describe('Test multiple servers', function () { | |||
339 | tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ], | 339 | tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ], |
340 | privacy: VideoPrivacy.PUBLIC, | 340 | privacy: VideoPrivacy.PUBLIC, |
341 | channel: { | 341 | channel: { |
342 | name: 'Default root channel', | 342 | name: 'Main root channel', |
343 | description: '', | 343 | description: '', |
344 | isLocal | 344 | isLocal |
345 | }, | 345 | }, |
@@ -647,7 +647,7 @@ describe('Test multiple servers', function () { | |||
647 | tags: [ 'tag_up_1', 'tag_up_2' ], | 647 | tags: [ 'tag_up_1', 'tag_up_2' ], |
648 | privacy: VideoPrivacy.PUBLIC, | 648 | privacy: VideoPrivacy.PUBLIC, |
649 | channel: { | 649 | channel: { |
650 | name: 'Default root channel', | 650 | name: 'Main root channel', |
651 | description: '', | 651 | description: '', |
652 | isLocal | 652 | isLocal |
653 | }, | 653 | }, |
@@ -967,7 +967,7 @@ describe('Test multiple servers', function () { | |||
967 | tags: [ ], | 967 | tags: [ ], |
968 | privacy: VideoPrivacy.PUBLIC, | 968 | privacy: VideoPrivacy.PUBLIC, |
969 | channel: { | 969 | channel: { |
970 | name: 'Default root channel', | 970 | name: 'Main root channel', |
971 | description: '', | 971 | description: '', |
972 | isLocal | 972 | isLocal |
973 | }, | 973 | }, |
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts index ba4920d1b..12181ad67 100644 --- a/server/tests/api/videos/single-server.ts +++ b/server/tests/api/videos/single-server.ts | |||
@@ -56,7 +56,7 @@ describe('Test a single server', function () { | |||
56 | privacy: VideoPrivacy.PUBLIC, | 56 | privacy: VideoPrivacy.PUBLIC, |
57 | commentsEnabled: true, | 57 | commentsEnabled: true, |
58 | channel: { | 58 | channel: { |
59 | name: 'Default root channel', | 59 | name: 'Main root channel', |
60 | description: '', | 60 | description: '', |
61 | isLocal: true | 61 | isLocal: true |
62 | }, | 62 | }, |
@@ -87,7 +87,7 @@ describe('Test a single server', function () { | |||
87 | duration: 5, | 87 | duration: 5, |
88 | commentsEnabled: false, | 88 | commentsEnabled: false, |
89 | channel: { | 89 | channel: { |
90 | name: 'Default root channel', | 90 | name: 'Main root channel', |
91 | description: '', | 91 | description: '', |
92 | isLocal: true | 92 | isLocal: true |
93 | }, | 93 | }, |
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts index e4e3ce9d9..8138c65d6 100644 --- a/server/tests/api/videos/video-channels.ts +++ b/server/tests/api/videos/video-channels.ts | |||
@@ -4,12 +4,13 @@ import * as chai from 'chai' | |||
4 | import 'mocha' | 4 | import 'mocha' |
5 | import { User, Video } from '../../../../shared/index' | 5 | import { User, Video } from '../../../../shared/index' |
6 | import { | 6 | import { |
7 | createUser, | ||
7 | doubleFollow, | 8 | doubleFollow, |
8 | flushAndRunMultipleServers, | 9 | flushAndRunMultipleServers, |
9 | getVideoChannelVideos, testImage, | 10 | getVideoChannelVideos, serverLogin, testImage, |
10 | updateVideo, | 11 | updateVideo, |
11 | updateVideoChannelAvatar, | 12 | updateVideoChannelAvatar, |
12 | uploadVideo, wait | 13 | uploadVideo, wait, userLogin |
13 | } from '../../utils' | 14 | } from '../../utils' |
14 | import { | 15 | import { |
15 | addVideoChannel, | 16 | addVideoChannel, |
@@ -33,9 +34,7 @@ describe('Test video channels', function () { | |||
33 | let userInfo: User | 34 | let userInfo: User |
34 | let accountUUID: string | 35 | let accountUUID: string |
35 | let firstVideoChannelId: number | 36 | let firstVideoChannelId: number |
36 | let firstVideoChannelUUID: string | ||
37 | let secondVideoChannelId: number | 37 | let secondVideoChannelId: number |
38 | let secondVideoChannelUUID: string | ||
39 | let videoUUID: string | 38 | let videoUUID: string |
40 | 39 | ||
41 | before(async function () { | 40 | before(async function () { |
@@ -54,7 +53,6 @@ describe('Test video channels', function () { | |||
54 | accountUUID = user.account.uuid | 53 | accountUUID = user.account.uuid |
55 | 54 | ||
56 | firstVideoChannelId = user.videoChannels[0].id | 55 | firstVideoChannelId = user.videoChannels[0].id |
57 | firstVideoChannelUUID = user.videoChannels[0].uuid | ||
58 | } | 56 | } |
59 | 57 | ||
60 | await waitJobs(servers) | 58 | await waitJobs(servers) |
@@ -73,13 +71,13 @@ describe('Test video channels', function () { | |||
73 | 71 | ||
74 | { | 72 | { |
75 | const videoChannel = { | 73 | const videoChannel = { |
74 | name: 'second_video_channel', | ||
76 | displayName: 'second video channel', | 75 | displayName: 'second video channel', |
77 | description: 'super video channel description', | 76 | description: 'super video channel description', |
78 | support: 'super video channel support text' | 77 | support: 'super video channel support text' |
79 | } | 78 | } |
80 | const res = await addVideoChannel(servers[ 0 ].url, servers[ 0 ].accessToken, videoChannel) | 79 | const res = await addVideoChannel(servers[ 0 ].url, servers[ 0 ].accessToken, videoChannel) |
81 | secondVideoChannelId = res.body.videoChannel.id | 80 | secondVideoChannelId = res.body.videoChannel.id |
82 | secondVideoChannelUUID = res.body.videoChannel.uuid | ||
83 | } | 81 | } |
84 | 82 | ||
85 | // The channel is 1 is propagated to servers 2 | 83 | // The channel is 1 is propagated to servers 2 |
@@ -99,7 +97,10 @@ describe('Test video channels', function () { | |||
99 | expect(userInfo.videoChannels).to.have.lengthOf(2) | 97 | expect(userInfo.videoChannels).to.have.lengthOf(2) |
100 | 98 | ||
101 | const videoChannels = userInfo.videoChannels | 99 | const videoChannels = userInfo.videoChannels |
102 | expect(videoChannels[0].displayName).to.equal('Default root channel') | 100 | expect(videoChannels[0].name).to.equal('root_channel') |
101 | expect(videoChannels[0].displayName).to.equal('Main root channel') | ||
102 | |||
103 | expect(videoChannels[1].name).to.equal('second_video_channel') | ||
103 | expect(videoChannels[1].displayName).to.equal('second video channel') | 104 | expect(videoChannels[1].displayName).to.equal('second video channel') |
104 | expect(videoChannels[1].description).to.equal('super video channel description') | 105 | expect(videoChannels[1].description).to.equal('super video channel description') |
105 | expect(videoChannels[1].support).to.equal('super video channel support text') | 106 | expect(videoChannels[1].support).to.equal('super video channel support text') |
@@ -112,7 +113,10 @@ describe('Test video channels', function () { | |||
112 | expect(res.body.data).to.have.lengthOf(2) | 113 | expect(res.body.data).to.have.lengthOf(2) |
113 | 114 | ||
114 | const videoChannels = res.body.data | 115 | const videoChannels = res.body.data |
115 | expect(videoChannels[0].displayName).to.equal('Default root channel') | 116 | expect(videoChannels[0].name).to.equal('root_channel') |
117 | expect(videoChannels[0].displayName).to.equal('Main root channel') | ||
118 | |||
119 | expect(videoChannels[1].name).to.equal('second_video_channel') | ||
116 | expect(videoChannels[1].displayName).to.equal('second video channel') | 120 | expect(videoChannels[1].displayName).to.equal('second video channel') |
117 | expect(videoChannels[1].description).to.equal('super video channel description') | 121 | expect(videoChannels[1].description).to.equal('super video channel description') |
118 | expect(videoChannels[1].support).to.equal('super video channel support text') | 122 | expect(videoChannels[1].support).to.equal('super video channel support text') |
@@ -125,6 +129,7 @@ describe('Test video channels', function () { | |||
125 | expect(res.body.data).to.have.lengthOf(1) | 129 | expect(res.body.data).to.have.lengthOf(1) |
126 | 130 | ||
127 | const videoChannels = res.body.data | 131 | const videoChannels = res.body.data |
132 | expect(videoChannels[0].name).to.equal('second_video_channel') | ||
128 | expect(videoChannels[0].displayName).to.equal('second video channel') | 133 | expect(videoChannels[0].displayName).to.equal('second video channel') |
129 | expect(videoChannels[0].description).to.equal('super video channel description') | 134 | expect(videoChannels[0].description).to.equal('super video channel description') |
130 | expect(videoChannels[0].support).to.equal('super video channel support text') | 135 | expect(videoChannels[0].support).to.equal('super video channel support text') |
@@ -136,7 +141,8 @@ describe('Test video channels', function () { | |||
136 | expect(res.body.total).to.equal(2) | 141 | expect(res.body.total).to.equal(2) |
137 | expect(res.body.data).to.be.an('array') | 142 | expect(res.body.data).to.be.an('array') |
138 | expect(res.body.data).to.have.lengthOf(1) | 143 | expect(res.body.data).to.have.lengthOf(1) |
139 | expect(res.body.data[0].displayName).to.equal('Default root channel') | 144 | expect(res.body.data[0].name).to.equal('root_channel') |
145 | expect(res.body.data[0].displayName).to.equal('Main root channel') | ||
140 | }) | 146 | }) |
141 | 147 | ||
142 | it('Should update video channel', async function () { | 148 | it('Should update video channel', async function () { |
@@ -148,7 +154,7 @@ describe('Test video channels', function () { | |||
148 | support: 'video channel support text updated' | 154 | support: 'video channel support text updated' |
149 | } | 155 | } |
150 | 156 | ||
151 | await updateVideoChannel(servers[0].url, servers[0].accessToken, secondVideoChannelId, videoChannelAttributes) | 157 | await updateVideoChannel(servers[0].url, servers[0].accessToken, 'second_video_channel', videoChannelAttributes) |
152 | 158 | ||
153 | await waitJobs(servers) | 159 | await waitJobs(servers) |
154 | }) | 160 | }) |
@@ -160,6 +166,7 @@ describe('Test video channels', function () { | |||
160 | expect(res.body.total).to.equal(2) | 166 | expect(res.body.total).to.equal(2) |
161 | expect(res.body.data).to.be.an('array') | 167 | expect(res.body.data).to.be.an('array') |
162 | expect(res.body.data).to.have.lengthOf(1) | 168 | expect(res.body.data).to.have.lengthOf(1) |
169 | expect(res.body.data[0].name).to.equal('second_video_channel') | ||
163 | expect(res.body.data[0].displayName).to.equal('video channel updated') | 170 | expect(res.body.data[0].displayName).to.equal('video channel updated') |
164 | expect(res.body.data[0].description).to.equal('video channel description updated') | 171 | expect(res.body.data[0].description).to.equal('video channel description updated') |
165 | expect(res.body.data[0].support).to.equal('video channel support text updated') | 172 | expect(res.body.data[0].support).to.equal('video channel support text updated') |
@@ -174,7 +181,7 @@ describe('Test video channels', function () { | |||
174 | await updateVideoChannelAvatar({ | 181 | await updateVideoChannelAvatar({ |
175 | url: servers[0].url, | 182 | url: servers[0].url, |
176 | accessToken: servers[0].accessToken, | 183 | accessToken: servers[0].accessToken, |
177 | videoChannelId: secondVideoChannelId, | 184 | videoChannelName: 'second_video_channel', |
178 | fixture | 185 | fixture |
179 | }) | 186 | }) |
180 | 187 | ||
@@ -192,9 +199,10 @@ describe('Test video channels', function () { | |||
192 | }) | 199 | }) |
193 | 200 | ||
194 | it('Should get video channel', async function () { | 201 | it('Should get video channel', async function () { |
195 | const res = await getVideoChannel(servers[0].url, secondVideoChannelId) | 202 | const res = await getVideoChannel(servers[0].url, 'second_video_channel') |
196 | 203 | ||
197 | const videoChannel = res.body | 204 | const videoChannel = res.body |
205 | expect(videoChannel.name).to.equal('second_video_channel') | ||
198 | expect(videoChannel.displayName).to.equal('video channel updated') | 206 | expect(videoChannel.displayName).to.equal('video channel updated') |
199 | expect(videoChannel.description).to.equal('video channel description updated') | 207 | expect(videoChannel.description).to.equal('video channel description updated') |
200 | expect(videoChannel.support).to.equal('video channel support text updated') | 208 | expect(videoChannel.support).to.equal('video channel support text updated') |
@@ -204,7 +212,8 @@ describe('Test video channels', function () { | |||
204 | this.timeout(10000) | 212 | this.timeout(10000) |
205 | 213 | ||
206 | for (const server of servers) { | 214 | for (const server of servers) { |
207 | const res1 = await getVideoChannelVideos(server.url, server.accessToken, secondVideoChannelUUID, 0, 5) | 215 | const channelURI = 'second_video_channel@localhost:9001' |
216 | const res1 = await getVideoChannelVideos(server.url, server.accessToken, channelURI, 0, 5) | ||
208 | expect(res1.body.total).to.equal(1) | 217 | expect(res1.body.total).to.equal(1) |
209 | expect(res1.body.data).to.be.an('array') | 218 | expect(res1.body.data).to.be.an('array') |
210 | expect(res1.body.data).to.have.lengthOf(1) | 219 | expect(res1.body.data).to.have.lengthOf(1) |
@@ -224,10 +233,12 @@ describe('Test video channels', function () { | |||
224 | this.timeout(10000) | 233 | this.timeout(10000) |
225 | 234 | ||
226 | for (const server of servers) { | 235 | for (const server of servers) { |
227 | const res1 = await getVideoChannelVideos(server.url, server.accessToken, secondVideoChannelUUID, 0, 5) | 236 | const secondChannelURI = 'second_video_channel@localhost:9001' |
237 | const res1 = await getVideoChannelVideos(server.url, server.accessToken, secondChannelURI, 0, 5) | ||
228 | expect(res1.body.total).to.equal(0) | 238 | expect(res1.body.total).to.equal(0) |
229 | 239 | ||
230 | const res2 = await getVideoChannelVideos(server.url, server.accessToken, firstVideoChannelUUID, 0, 5) | 240 | const channelURI = 'root_channel@localhost:9001' |
241 | const res2 = await getVideoChannelVideos(server.url, server.accessToken, channelURI, 0, 5) | ||
231 | expect(res2.body.total).to.equal(1) | 242 | expect(res2.body.total).to.equal(1) |
232 | 243 | ||
233 | const videos: Video[] = res2.body.data | 244 | const videos: Video[] = res2.body.data |
@@ -238,7 +249,7 @@ describe('Test video channels', function () { | |||
238 | }) | 249 | }) |
239 | 250 | ||
240 | it('Should delete video channel', async function () { | 251 | it('Should delete video channel', async function () { |
241 | await deleteVideoChannel(servers[0].url, servers[0].accessToken, secondVideoChannelId) | 252 | await deleteVideoChannel(servers[0].url, servers[0].accessToken, 'second_video_channel') |
242 | }) | 253 | }) |
243 | 254 | ||
244 | it('Should have video channel deleted', async function () { | 255 | it('Should have video channel deleted', async function () { |
@@ -247,7 +258,23 @@ describe('Test video channels', function () { | |||
247 | expect(res.body.total).to.equal(1) | 258 | expect(res.body.total).to.equal(1) |
248 | expect(res.body.data).to.be.an('array') | 259 | expect(res.body.data).to.be.an('array') |
249 | expect(res.body.data).to.have.lengthOf(1) | 260 | expect(res.body.data).to.have.lengthOf(1) |
250 | expect(res.body.data[0].displayName).to.equal('Default root channel') | 261 | expect(res.body.data[0].displayName).to.equal('Main root channel') |
262 | }) | ||
263 | |||
264 | it('Should create the main channel with an uuid if there is a conflict', async function () { | ||
265 | { | ||
266 | const videoChannel = { name: 'toto_channel', displayName: 'My toto channel' } | ||
267 | await addVideoChannel(servers[ 0 ].url, servers[ 0 ].accessToken, videoChannel) | ||
268 | } | ||
269 | |||
270 | { | ||
271 | await createUser(servers[ 0 ].url, servers[ 0 ].accessToken, 'toto', 'password') | ||
272 | const accessToken = await userLogin(servers[ 0 ], { username: 'toto', password: 'password' }) | ||
273 | |||
274 | const res = await getMyUserInformation(servers[ 0 ].url, accessToken) | ||
275 | const videoChannel = res.body.videoChannels[ 0 ] | ||
276 | expect(videoChannel.name).to.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/) | ||
277 | } | ||
251 | }) | 278 | }) |
252 | 279 | ||
253 | after(async function () { | 280 | after(async function () { |
diff --git a/server/tests/cli/update-host.ts b/server/tests/cli/update-host.ts index 968b7bd7f..7f54c0e70 100644 --- a/server/tests/cli/update-host.ts +++ b/server/tests/cli/update-host.ts | |||
@@ -54,6 +54,7 @@ describe('Test update host scripts', function () { | |||
54 | 54 | ||
55 | // Create channel | 55 | // Create channel |
56 | const videoChannel = { | 56 | const videoChannel = { |
57 | name: 'second_channel', | ||
57 | displayName: 'second video channel', | 58 | displayName: 'second video channel', |
58 | description: 'super video channel description' | 59 | description: 'super video channel description' |
59 | } | 60 | } |
diff --git a/server/tests/real-world/populate-database.ts b/server/tests/real-world/populate-database.ts index d41ac8d36..a7fdbd1dc 100644 --- a/server/tests/real-world/populate-database.ts +++ b/server/tests/real-world/populate-database.ts | |||
@@ -66,6 +66,7 @@ function getRandomInt (min, max) { | |||
66 | 66 | ||
67 | function createCustomChannel (server: ServerInfo) { | 67 | function createCustomChannel (server: ServerInfo) { |
68 | const videoChannel = { | 68 | const videoChannel = { |
69 | name: Date.now().toString(), | ||
69 | displayName: Date.now().toString(), | 70 | displayName: Date.now().toString(), |
70 | description: Date.now().toString() | 71 | description: Date.now().toString() |
71 | } | 72 | } |
diff --git a/server/tests/utils/videos/video-channels.ts b/server/tests/utils/videos/video-channels.ts index 3ca39469c..1eea22b31 100644 --- a/server/tests/utils/videos/video-channels.ts +++ b/server/tests/utils/videos/video-channels.ts | |||
@@ -97,10 +97,10 @@ function updateVideoChannelAvatar (options: { | |||
97 | url: string, | 97 | url: string, |
98 | accessToken: string, | 98 | accessToken: string, |
99 | fixture: string, | 99 | fixture: string, |
100 | videoChannelId: string | number | 100 | videoChannelName: string | number |
101 | }) { | 101 | }) { |
102 | 102 | ||
103 | const path = '/api/v1/video-channels/' + options.videoChannelId + '/avatar/pick' | 103 | const path = '/api/v1/video-channels/' + options.videoChannelName + '/avatar/pick' |
104 | 104 | ||
105 | return updateAvatarRequest(Object.assign(options, { path })) | 105 | return updateAvatarRequest(Object.assign(options, { path })) |
106 | } | 106 | } |
diff --git a/server/tests/utils/videos/videos.ts b/server/tests/utils/videos/videos.ts index b280cccda..592248144 100644 --- a/server/tests/utils/videos/videos.ts +++ b/server/tests/utils/videos/videos.ts | |||
@@ -199,13 +199,13 @@ function getAccountVideos ( | |||
199 | function getVideoChannelVideos ( | 199 | function getVideoChannelVideos ( |
200 | url: string, | 200 | url: string, |
201 | accessToken: string, | 201 | accessToken: string, |
202 | videoChannelId: number | string, | 202 | videoChannelName: string, |
203 | start: number, | 203 | start: number, |
204 | count: number, | 204 | count: number, |
205 | sort?: string, | 205 | sort?: string, |
206 | query: { nsfw?: boolean } = {} | 206 | query: { nsfw?: boolean } = {} |
207 | ) { | 207 | ) { |
208 | const path = '/api/v1/video-channels/' + videoChannelId + '/videos' | 208 | const path = '/api/v1/video-channels/' + videoChannelName + '/videos' |
209 | 209 | ||
210 | return makeGetRequest({ | 210 | return makeGetRequest({ |
211 | url, | 211 | url, |
diff --git a/shared/models/videos/channel/video-channel-create.model.ts b/shared/models/videos/channel/video-channel-create.model.ts index 08cd5fb84..da8ce620c 100644 --- a/shared/models/videos/channel/video-channel-create.model.ts +++ b/shared/models/videos/channel/video-channel-create.model.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | export interface VideoChannelCreate { | 1 | export interface VideoChannelCreate { |
2 | name: string | ||
2 | displayName: string | 3 | displayName: string |
3 | description?: string | 4 | description?: string |
4 | support?: string | 5 | support?: string |