Skip to content

Commit

Permalink
Give moderators access to edit channels (Chocobozzz#4608)
Browse files Browse the repository at this point in the history
* give admins access to edit all channels

closes Chocobozzz#4598

* test(channels): +admin update another users channel

* Fix tests

* fix(server): delete another users channel

Since the channel owner isn't necessary the auth user we need to check
the right account whether it's the last video or not.

* REMOVE_ANY_VIDEO_CHANNEL > MANAGE_ANY_VIDEO_CHANNEL

Merge REMOVE_ANY_VIDEO_CHANNEL and MANY_VIDEO_CHANNELS to
MANAGE_ANY_VIDEO_CHANNEL.

* user-right: moderator can't manage admins channel

* client: MyVideoChannelCreateComponent > VideoChannelCreateComponent

* client: MyVideoChannelEdit > VideoChannelEdit

* Revert "user-right: moderator can't manage admins channel"

This reverts commit 2c627c1.

* server: clean dupl validator functionality

* fix ensureUserCanManageChannel usage

It's not async anymore.

* server: merge channel validator middleares

ensureAuthUserOwnsChannelValidator & ensureUserCanManageChannel gets
merged into one middleware.

* client(VideoChannelEdit): redirect to prev route

* fix(VideoChannels): handle anon users

* client: new routes for create/update channel

* Refactor channel validators

Co-authored-by: Chocobozzz <me@florianbigard.com>
  • Loading branch information
kontrollanten and Chocobozzz committed Jan 15, 2022
1 parent d3dc490 commit defe4b8
Show file tree
Hide file tree
Showing 27 changed files with 320 additions and 247 deletions.
31 changes: 31 additions & 0 deletions client/src/app/+manage/manage-routing.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { VideoChannelCreateComponent } from './video-channel-edit/video-channel-create.component'
import { VideoChannelUpdateComponent } from './video-channel-edit/video-channel-update.component'

const manageRoutes: Routes = [
{
path: 'create',
component: VideoChannelCreateComponent,
data: {
meta: {
title: $localize`Create a new video channel`
}
}
},
{
path: 'update/:videoChannelName',
component: VideoChannelUpdateComponent,
data: {
meta: {
title: $localize`Update video channel`
}
}
}
]

@NgModule({
imports: [ RouterModule.forChild(manageRoutes) ],
exports: [ RouterModule ]
})
export class ManageRoutingModule {}
31 changes: 31 additions & 0 deletions client/src/app/+manage/manage.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { NgModule } from '@angular/core'
import { SharedFormModule } from '@app/shared/shared-forms'
import { SharedGlobalIconModule } from '@app/shared/shared-icons'
import { SharedMainModule } from '@app/shared/shared-main'
import { SharedActorImageModule } from '../shared/shared-actor-image/shared-actor-image.module'
import { SharedActorImageEditModule } from '@app/shared/shared-actor-image-edit'
import { VideoChannelCreateComponent } from './video-channel-edit/video-channel-create.component'
import { VideoChannelUpdateComponent } from './video-channel-edit/video-channel-update.component'
import { ManageRoutingModule } from './manage-routing.module'

@NgModule({
imports: [
ManageRoutingModule,
SharedMainModule,
SharedFormModule,
SharedGlobalIconModule,
SharedActorImageModule,
SharedActorImageEditModule
],

declarations: [
VideoChannelCreateComponent,
VideoChannelUpdateComponent
],

exports: [
],

providers: []
})
export class ManageModule { }
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import {
import { FormValidatorService } from '@app/shared/shared-forms'
import { VideoChannel, VideoChannelService } from '@app/shared/shared-main'
import { HttpStatusCode, VideoChannelCreate } from '@shared/models'
import { MyVideoChannelEdit } from './my-video-channel-edit'
import { VideoChannelEdit } from './video-channel-edit'

@Component({
templateUrl: './my-video-channel-edit.component.html',
styleUrls: [ './my-video-channel-edit.component.scss' ]
templateUrl: './video-channel-edit.component.html',
styleUrls: [ './video-channel-edit.component.scss' ]
})
export class MyVideoChannelCreateComponent extends MyVideoChannelEdit implements OnInit {
export class VideoChannelCreateComponent extends VideoChannelEdit implements OnInit {
error: string
videoChannel = new VideoChannel({})

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>

<div class="margin-content">
<form role="form" (ngSubmit)="formValidated()" [formGroup]="form">

<div class="form-row"> <!-- channel grid -->
<div class="form-group col-12 col-lg-4 col-xl-3">
<div *ngIf="isCreation()" class="video-channel-title" i18n>NEW CHANNEL</div>
<div *ngIf="!isCreation() && videoChannel" class="video-channel-title" i18n>CHANNEL</div>
</div>

<div class="form-group col-12 col-lg-8 col-xl-9">
<h6 i18n>Banner image of the channel</h6>

<my-actor-banner-edit
*ngIf="videoChannel" [previewImage]="isCreation()"
[actor]="videoChannel" (bannerChange)="onBannerChange($event)" (bannerDelete)="onBannerDelete()"
></my-actor-banner-edit>

<my-actor-avatar-edit
*ngIf="videoChannel" [previewImage]="isCreation()"
[actor]="videoChannel" (avatarChange)="onAvatarChange($event)" (avatarDelete)="onAvatarDelete()"
[displayUsername]="!isCreation()" [displaySubscribers]="!isCreation()"
></my-actor-avatar-edit>

<div class="form-group" *ngIf="isCreation()">
<label i18n for="name">Name</label>
<div class="input-group">
<input
type="text" id="name" i18n-placeholder placeholder="Example: my_channel"
formControlName="name" [ngClass]="{ 'input-error': formErrors['name'] }" class="form-control"
>
<div class="input-group-append">
<span class="input-group-text">@{{ instanceHost }}</span>
</div>
</div>
<div *ngIf="formErrors['name']" class="form-error">
{{ formErrors['name'] }}
</div>
</div>

<div class="form-group">
<label i18n for="display-name">Display name</label>
<input
type="text" id="display-name" class="form-control"
formControlName="display-name" [ngClass]="{ 'input-error': formErrors['display-name'] }"
>
<div *ngIf="formErrors['display-name']" class="form-error">
{{ formErrors['display-name'] }}
</div>
</div>

<div class="form-group">
<label i18n for="description">Description</label>
<textarea
id="description" formControlName="description" class="form-control"
[ngClass]="{ 'input-error': formErrors['description'] }"
></textarea>
<div *ngIf="formErrors.description" class="form-error">
{{ formErrors.description }}
</div>
</div>

<div class="form-group">
<label for="support">Support</label>
<my-help
helpType="markdownEnhanced" i18n-preHtml preHtml="Short text to tell people how they can support the channel (membership platform...).<br /><br />
When a video is uploaded in this channel, the video support field will be automatically filled by this text."
></my-help>
<my-markdown-textarea
id="support" formControlName="support" textareaMaxWidth="500px" markdownType="enhanced"
[classes]="{ 'input-error': formErrors['support'] }"
></my-markdown-textarea>
<div *ngIf="formErrors.support" class="form-error">
{{ formErrors.support }}
</div>
</div>

<div class="form-group" *ngIf="isBulkUpdateVideosDisplayed()">
<my-peertube-checkbox
inputName="bulkVideosSupportUpdate" formControlName="bulkVideosSupportUpdate"
i18n-labelText labelText="Overwrite support field of all videos of this channel"
></my-peertube-checkbox>
</div>

</div>
</div>

<div class="form-row"> <!-- submit placement block -->
<div class="col-md-7 col-xl-5"></div>
<div class="col-md-5 col-xl-5 d-inline-flex">
<input type="submit" value="{{ getFormButtonTitle() }}" [disabled]="!form.valid">
</div>
</div>
</form>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
@use '_variables' as *;
@use '_mixins' as *;

.margin-content {
padding-top: 20px;
}

label {
font-weight: $font-regular;
font-size: 100%;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FormReactive } from '@app/shared/shared-forms'
import { VideoChannel } from '@app/shared/shared-main'

export abstract class MyVideoChannelEdit extends FormReactive {
export abstract class VideoChannelEdit extends FormReactive {
videoChannel: VideoChannel

abstract isCreation (): boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Subscription } from 'rxjs'
import { HttpErrorResponse } from '@angular/common/http'
import { Component, OnDestroy, OnInit } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { AuthService, Notifier, ServerService } from '@app/core'
import { AuthService, Notifier, RedirectService, ServerService } from '@app/core'
import { genericUploadErrorHandler } from '@app/helpers'
import {
VIDEO_CHANNEL_DESCRIPTION_VALIDATOR,
Expand All @@ -12,14 +12,14 @@ import {
import { FormValidatorService } from '@app/shared/shared-forms'
import { VideoChannel, VideoChannelService } from '@app/shared/shared-main'
import { HTMLServerConfig, VideoChannelUpdate } from '@shared/models'
import { MyVideoChannelEdit } from './my-video-channel-edit'
import { VideoChannelEdit } from './video-channel-edit'

@Component({
selector: 'my-video-channel-update',
templateUrl: './my-video-channel-edit.component.html',
styleUrls: [ './my-video-channel-edit.component.scss' ]
templateUrl: './video-channel-edit.component.html',
styleUrls: [ './video-channel-edit.component.scss' ]
})
export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements OnInit, OnDestroy {
export class VideoChannelUpdateComponent extends VideoChannelEdit implements OnInit, OnDestroy {
error: string
videoChannel: VideoChannel

Expand All @@ -34,7 +34,8 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
private router: Router,
private route: ActivatedRoute,
private videoChannelService: VideoChannelService,
private serverService: ServerService
private serverService: ServerService,
private redirectService: RedirectService
) {
super()
}
Expand All @@ -50,9 +51,9 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
})

this.paramsSub = this.route.params.subscribe(routeParams => {
const videoChannelId = routeParams['videoChannelId']
const videoChannelName = routeParams['videoChannelName']

this.videoChannelService.getVideoChannel(videoChannelId)
this.videoChannelService.getVideoChannel(videoChannelName)
.subscribe({
next: videoChannelToUpdate => {
this.videoChannel = videoChannelToUpdate
Expand Down Expand Up @@ -95,7 +96,7 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements

this.notifier.success($localize`Video channel ${videoChannelUpdate.displayName} updated.`)

this.router.navigate([ '/my-library', 'video-channels' ])
this.redirectService.redirectToPreviousRoute([ '/c', this.videoChannel.name ])
},

error: err => {
Expand Down

This file was deleted.

Loading

0 comments on commit defe4b8

Please sign in to comment.