Add debug component to help admins to fix IP issues
This commit is contained in:
parent
2b3f1919fd
commit
5d79474cc6
|
@ -16,7 +16,7 @@
|
|||
Configuration
|
||||
</a>
|
||||
|
||||
<a i18n *ngIf="hasJobsRight() || hasLogsRight()" routerLink="/admin/system" routerLinkActive="active" class="title-page">
|
||||
<a i18n *ngIf="hasJobsRight() || hasLogsRight() || hasDebugRight()" routerLink="/admin/system" routerLinkActive="active" class="title-page">
|
||||
System
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -24,15 +24,19 @@ export class AdminComponent {
|
|||
return this.auth.getUser().hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)
|
||||
}
|
||||
|
||||
hasJobsRight () {
|
||||
return this.auth.getUser().hasRight(UserRight.MANAGE_JOBS)
|
||||
hasConfigRight () {
|
||||
return this.auth.getUser().hasRight(UserRight.MANAGE_CONFIGURATION)
|
||||
}
|
||||
|
||||
hasLogsRight () {
|
||||
return this.auth.getUser().hasRight(UserRight.MANAGE_LOGS)
|
||||
}
|
||||
|
||||
hasConfigRight () {
|
||||
return this.auth.getUser().hasRight(UserRight.MANAGE_CONFIGURATION)
|
||||
hasJobsRight () {
|
||||
return this.auth.getUser().hasRight(UserRight.MANAGE_JOBS)
|
||||
}
|
||||
|
||||
hasDebugRight () {
|
||||
return this.auth.getUser().hasRight(UserRight.MANAGE_DEBUG)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import { RedundancyService } from '@app/+admin/follows/shared/redundancy.service
|
|||
import { InstanceAccountBlocklistComponent, InstanceServerBlocklistComponent } from '@app/+admin/moderation/instance-blocklist'
|
||||
import { JobsComponent } from '@app/+admin/system/jobs/jobs.component'
|
||||
import { JobService, LogsComponent, LogsService, SystemComponent } from '@app/+admin/system'
|
||||
import { DebugComponent, DebugService } from '@app/+admin/system/debug'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -54,6 +55,7 @@ import { JobService, LogsComponent, LogsService, SystemComponent } from '@app/+a
|
|||
SystemComponent,
|
||||
JobsComponent,
|
||||
LogsComponent,
|
||||
DebugComponent,
|
||||
|
||||
ConfigComponent,
|
||||
EditCustomConfigComponent
|
||||
|
@ -68,6 +70,7 @@ import { JobService, LogsComponent, LogsService, SystemComponent } from '@app/+a
|
|||
RedundancyService,
|
||||
JobService,
|
||||
LogsService,
|
||||
DebugService,
|
||||
ConfigService
|
||||
]
|
||||
})
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<div class="root">
|
||||
<h4>IP</h4>
|
||||
|
||||
<p>PeerTube thinks your public IP is <strong>{{ debug?.ip }}</strong>.</p>
|
||||
|
||||
<p>If this is not your correct public IP, please consider fixing it because:</p>
|
||||
<ul>
|
||||
<li>Views may not be counted correctly (reduced compared to what they should be)</li>
|
||||
<li>Anti brute force system could be overzealous</li>
|
||||
<li>P2P system could not work correctly</li>
|
||||
</ul>
|
||||
|
||||
<p>To fix it:<p>
|
||||
<ul>
|
||||
<li>Check the <code>trust_proxy</code> configuration key</li>
|
||||
<li>If you run PeerTube using Docker, check you run the <code>reverse-proxy</code> with <code>network_mode: "host"</code>
|
||||
(see <a href="https://github.com/Chocobozzz/PeerTube/issues/1643#issuecomment-464789666">issue 1643</a>)</li>
|
||||
</ul>
|
||||
</div>
|
|
@ -0,0 +1,6 @@
|
|||
@import '_variables';
|
||||
@import '_mixins';
|
||||
|
||||
.root {
|
||||
font-size: 14px;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
import { Component, OnInit } from '@angular/core'
|
||||
import { Notifier } from '@app/core'
|
||||
import { Debug } from '@shared/models/server'
|
||||
import { DebugService } from '@app/+admin/system/debug/debug.service'
|
||||
|
||||
@Component({
|
||||
templateUrl: './debug.component.html',
|
||||
styleUrls: [ './debug.component.scss' ]
|
||||
})
|
||||
export class DebugComponent implements OnInit {
|
||||
debug: Debug
|
||||
|
||||
constructor (
|
||||
private debugService: DebugService,
|
||||
private notifier: Notifier
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit (): void {
|
||||
this.load()
|
||||
}
|
||||
|
||||
load () {
|
||||
this.debugService.getDebug()
|
||||
.subscribe(
|
||||
debug => this.debug = debug,
|
||||
|
||||
err => this.notifier.error(err.message)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { catchError } from 'rxjs/operators'
|
||||
import { HttpClient } from '@angular/common/http'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Observable } from 'rxjs'
|
||||
import { environment } from '../../../../environments/environment'
|
||||
import { RestExtractor, RestService } from '../../../shared'
|
||||
import { Debug } from '@shared/models/server'
|
||||
|
||||
@Injectable()
|
||||
export class DebugService {
|
||||
private static BASE_DEBUG_URL = environment.apiUrl + '/api/v1/server/debug'
|
||||
|
||||
constructor (
|
||||
private authHttp: HttpClient,
|
||||
private restService: RestService,
|
||||
private restExtractor: RestExtractor
|
||||
) {}
|
||||
|
||||
getDebug (): Observable<Debug> {
|
||||
return this.authHttp.get<Debug>(DebugService.BASE_DEBUG_URL)
|
||||
.pipe(
|
||||
catchError(err => this.restExtractor.handleError(err))
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export * from './debug.component'
|
||||
export * from './debug.service'
|
|
@ -9,7 +9,7 @@ import { LogLevel } from '@shared/models/server/log-level.type'
|
|||
|
||||
@Injectable()
|
||||
export class LogsService {
|
||||
private static BASE_JOB_URL = environment.apiUrl + '/api/v1/server/logs'
|
||||
private static BASE_LOG_URL = environment.apiUrl + '/api/v1/server/logs'
|
||||
|
||||
constructor (
|
||||
private authHttp: HttpClient,
|
||||
|
@ -17,14 +17,14 @@ export class LogsService {
|
|||
private restExtractor: RestExtractor
|
||||
) {}
|
||||
|
||||
getLogs (level: LogLevel, startDate: string, endDate?: string): Observable<any> {
|
||||
getLogs (level: LogLevel, startDate: string, endDate?: string): Observable<any[]> {
|
||||
let params = new HttpParams()
|
||||
params = params.append('startDate', startDate)
|
||||
params = params.append('level', level)
|
||||
|
||||
if (endDate) params.append('endDate', endDate)
|
||||
|
||||
return this.authHttp.get<any[]>(LogsService.BASE_JOB_URL, { params })
|
||||
return this.authHttp.get<any[]>(LogsService.BASE_LOG_URL, { params })
|
||||
.pipe(
|
||||
map(rows => rows.map(r => new LogRow(r))),
|
||||
catchError(err => this.restExtractor.handleError(err))
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
<div i18n class="form-sub-title">System</div>
|
||||
|
||||
<div class="admin-sub-nav">
|
||||
<a i18n routerLink="jobs" routerLinkActive="active">Jobs</a>
|
||||
<a *ngIf="hasJobsRight()" i18n routerLink="jobs" routerLinkActive="active">Jobs</a>
|
||||
|
||||
<a i18n routerLink="logs" routerLinkActive="active">Logs</a>
|
||||
<a *ngIf="hasLogsRight()" i18n routerLink="logs" routerLinkActive="active">Logs</a>
|
||||
|
||||
<a *ngIf="hasDebugRight()" i18n routerLink="debug" routerLinkActive="active">Debug</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,8 +1,24 @@
|
|||
import { Component } from '@angular/core'
|
||||
import { UserRight } from '@shared/models'
|
||||
import { AuthService } from '@app/core'
|
||||
|
||||
@Component({
|
||||
templateUrl: './system.component.html',
|
||||
styleUrls: [ './system.component.scss' ]
|
||||
})
|
||||
export class SystemComponent {
|
||||
|
||||
constructor (private auth: AuthService) {}
|
||||
|
||||
hasLogsRight () {
|
||||
return this.auth.getUser().hasRight(UserRight.MANAGE_LOGS)
|
||||
}
|
||||
|
||||
hasJobsRight () {
|
||||
return this.auth.getUser().hasRight(UserRight.MANAGE_JOBS)
|
||||
}
|
||||
|
||||
hasDebugRight () {
|
||||
return this.auth.getUser().hasRight(UserRight.MANAGE_DEBUG)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { UserRight } from '../../../../../shared'
|
|||
import { JobsComponent } from '@app/+admin/system/jobs/jobs.component'
|
||||
import { LogsComponent } from '@app/+admin/system/logs'
|
||||
import { SystemComponent } from '@app/+admin/system/system.component'
|
||||
import { DebugComponent } from '@app/+admin/system/debug'
|
||||
|
||||
export const SystemRoutes: Routes = [
|
||||
{
|
||||
|
@ -38,6 +39,17 @@ export const SystemRoutes: Routes = [
|
|||
title: 'Logs'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'debug',
|
||||
canActivate: [ UserRightGuard ],
|
||||
component: DebugComponent,
|
||||
data: {
|
||||
meta: {
|
||||
userRight: UserRight.MANAGE_DEBUG,
|
||||
title: 'Debug'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import * as express from 'express'
|
||||
import { UserRight } from '../../../../shared/models/users'
|
||||
import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares'
|
||||
|
||||
const debugRouter = express.Router()
|
||||
|
||||
debugRouter.get('/debug',
|
||||
authenticate,
|
||||
ensureUserHasRight(UserRight.MANAGE_DEBUG),
|
||||
asyncMiddleware(getDebug)
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
debugRouter
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function getDebug (req: express.Request, res: express.Response) {
|
||||
return res.json({
|
||||
ip: req.ip
|
||||
}).end()
|
||||
}
|
|
@ -5,6 +5,7 @@ import { serverRedundancyRouter } from './redundancy'
|
|||
import { serverBlocklistRouter } from './server-blocklist'
|
||||
import { contactRouter } from './contact'
|
||||
import { logsRouter } from './logs'
|
||||
import { debugRouter } from './debug'
|
||||
|
||||
const serverRouter = express.Router()
|
||||
|
||||
|
@ -14,6 +15,7 @@ serverRouter.use('/', statsRouter)
|
|||
serverRouter.use('/', serverBlocklistRouter)
|
||||
serverRouter.use('/', contactRouter)
|
||||
serverRouter.use('/', logsRouter)
|
||||
serverRouter.use('/', debugRouter)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/* tslint:disable:no-unused-expression */
|
||||
|
||||
import 'mocha'
|
||||
|
||||
import {
|
||||
createUser,
|
||||
flushTests,
|
||||
killallServers,
|
||||
runServer,
|
||||
ServerInfo,
|
||||
setAccessTokensToServers,
|
||||
userLogin
|
||||
} from '../../../../shared/utils'
|
||||
import { makeGetRequest } from '../../../../shared/utils/requests/requests'
|
||||
|
||||
describe('Test debug API validators', function () {
|
||||
const path = '/api/v1/server/debug'
|
||||
let server: ServerInfo
|
||||
let userAccessToken = ''
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
before(async function () {
|
||||
this.timeout(120000)
|
||||
|
||||
await flushTests()
|
||||
|
||||
server = await runServer(1)
|
||||
|
||||
await setAccessTokensToServers([ server ])
|
||||
|
||||
const user = {
|
||||
username: 'user1',
|
||||
password: 'my super password'
|
||||
}
|
||||
await createUser(server.url, server.accessToken, user.username, user.password)
|
||||
userAccessToken = await userLogin(server, user)
|
||||
})
|
||||
|
||||
describe('When getting debug endpoint', function () {
|
||||
|
||||
it('Should fail with a non authenticated user', async function () {
|
||||
await makeGetRequest({
|
||||
url: server.url,
|
||||
path,
|
||||
statusCodeExpected: 401
|
||||
})
|
||||
})
|
||||
|
||||
it('Should fail with a non admin user', async function () {
|
||||
await makeGetRequest({
|
||||
url: server.url,
|
||||
path,
|
||||
token: userAccessToken,
|
||||
statusCodeExpected: 403
|
||||
})
|
||||
})
|
||||
|
||||
it('Should succeed with the correct params', async function () {
|
||||
await makeGetRequest({
|
||||
url: server.url,
|
||||
path,
|
||||
token: server.accessToken,
|
||||
query: { startDate: new Date().toISOString() },
|
||||
statusCodeExpected: 200
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
killallServers([ server ])
|
||||
|
||||
// Keep the logs if the test failed
|
||||
if (this['ok']) {
|
||||
await flushTests()
|
||||
}
|
||||
})
|
||||
})
|
|
@ -2,6 +2,7 @@ import './accounts'
|
|||
import './blocklist'
|
||||
import './config'
|
||||
import './contact-form'
|
||||
import './debug'
|
||||
import './follows'
|
||||
import './jobs'
|
||||
import './logs'
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export interface Debug {
|
||||
ip: string
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
export * from './about.model'
|
||||
export * from './contact-form.model'
|
||||
export * from './custom-config.model'
|
||||
export * from './debug.model'
|
||||
export * from './job.model'
|
||||
export * from './server-config.model'
|
||||
export * from './server-stats.model'
|
||||
|
|
|
@ -7,6 +7,8 @@ export enum UserRight {
|
|||
|
||||
MANAGE_LOGS,
|
||||
|
||||
MANAGE_DEBUG,
|
||||
|
||||
MANAGE_SERVER_REDUNDANCY,
|
||||
|
||||
MANAGE_VIDEO_ABUSES,
|
||||
|
|
Loading…
Reference in New Issue