diff --git a/client/src/app/+admin/admin.component.html b/client/src/app/+admin/admin.component.html
index 065d92509..98f45a7d1 100644
--- a/client/src/app/+admin/admin.component.html
+++ b/client/src/app/+admin/admin.component.html
@@ -16,7 +16,7 @@
Configuration
-
+
System
diff --git a/client/src/app/+admin/admin.component.ts b/client/src/app/+admin/admin.component.ts
index fc775a5a4..408de4837 100644
--- a/client/src/app/+admin/admin.component.ts
+++ b/client/src/app/+admin/admin.component.ts
@@ -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)
}
}
diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts
index ae0af686b..71a4dfc4a 100644
--- a/client/src/app/+admin/admin.module.ts
+++ b/client/src/app/+admin/admin.module.ts
@@ -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
]
})
diff --git a/client/src/app/+admin/system/debug/debug.component.html b/client/src/app/+admin/system/debug/debug.component.html
new file mode 100644
index 000000000..f35414b37
--- /dev/null
+++ b/client/src/app/+admin/system/debug/debug.component.html
@@ -0,0 +1,19 @@
+
+
IP
+
+
PeerTube thinks your public IP is {{ debug?.ip }}.
+
+
If this is not your correct public IP, please consider fixing it because:
+
+ - Views may not be counted correctly (reduced compared to what they should be)
+ - Anti brute force system could be overzealous
+ - P2P system could not work correctly
+
+
+
To fix it:
+
+ - Check the
trust_proxy
configuration key
+ - If you run PeerTube using Docker, check you run the
reverse-proxy
with network_mode: "host"
+ (see issue 1643)
+
+
diff --git a/client/src/app/+admin/system/debug/debug.component.scss b/client/src/app/+admin/system/debug/debug.component.scss
new file mode 100644
index 000000000..90addd284
--- /dev/null
+++ b/client/src/app/+admin/system/debug/debug.component.scss
@@ -0,0 +1,6 @@
+@import '_variables';
+@import '_mixins';
+
+.root {
+ font-size: 14px;
+}
diff --git a/client/src/app/+admin/system/debug/debug.component.ts b/client/src/app/+admin/system/debug/debug.component.ts
new file mode 100644
index 000000000..8a77f79f7
--- /dev/null
+++ b/client/src/app/+admin/system/debug/debug.component.ts
@@ -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)
+ )
+ }
+}
diff --git a/client/src/app/+admin/system/debug/debug.service.ts b/client/src/app/+admin/system/debug/debug.service.ts
new file mode 100644
index 000000000..6c722d177
--- /dev/null
+++ b/client/src/app/+admin/system/debug/debug.service.ts
@@ -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 {
+ return this.authHttp.get(DebugService.BASE_DEBUG_URL)
+ .pipe(
+ catchError(err => this.restExtractor.handleError(err))
+ )
+ }
+}
diff --git a/client/src/app/+admin/system/debug/index.ts b/client/src/app/+admin/system/debug/index.ts
new file mode 100644
index 000000000..7fc7a0721
--- /dev/null
+++ b/client/src/app/+admin/system/debug/index.ts
@@ -0,0 +1,2 @@
+export * from './debug.component'
+export * from './debug.service'
diff --git a/client/src/app/+admin/system/logs/logs.service.ts b/client/src/app/+admin/system/logs/logs.service.ts
index 4db79a1fa..24b9cb6d1 100644
--- a/client/src/app/+admin/system/logs/logs.service.ts
+++ b/client/src/app/+admin/system/logs/logs.service.ts
@@ -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 {
+ getLogs (level: LogLevel, startDate: string, endDate?: string): Observable {
let params = new HttpParams()
params = params.append('startDate', startDate)
params = params.append('level', level)
if (endDate) params.append('endDate', endDate)
- return this.authHttp.get(LogsService.BASE_JOB_URL, { params })
+ return this.authHttp.get(LogsService.BASE_LOG_URL, { params })
.pipe(
map(rows => rows.map(r => new LogRow(r))),
catchError(err => this.restExtractor.handleError(err))
diff --git a/client/src/app/+admin/system/system.component.html b/client/src/app/+admin/system/system.component.html
index 345a101e6..7c4278d35 100644
--- a/client/src/app/+admin/system/system.component.html
+++ b/client/src/app/+admin/system/system.component.html
@@ -2,9 +2,11 @@
System
diff --git a/client/src/app/+admin/system/system.component.ts b/client/src/app/+admin/system/system.component.ts
index 992d9c8af..b544c2a97 100644
--- a/client/src/app/+admin/system/system.component.ts
+++ b/client/src/app/+admin/system/system.component.ts
@@ -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)
+ }
}
diff --git a/client/src/app/+admin/system/system.routes.ts b/client/src/app/+admin/system/system.routes.ts
index e6d45b760..2d851794d 100644
--- a/client/src/app/+admin/system/system.routes.ts
+++ b/client/src/app/+admin/system/system.routes.ts
@@ -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'
+ }
+ }
}
]
}
diff --git a/server/controllers/api/server/debug.ts b/server/controllers/api/server/debug.ts
new file mode 100644
index 000000000..4450038f6
--- /dev/null
+++ b/server/controllers/api/server/debug.ts
@@ -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()
+}
diff --git a/server/controllers/api/server/index.ts b/server/controllers/api/server/index.ts
index de09588df..6b8793a19 100644
--- a/server/controllers/api/server/index.ts
+++ b/server/controllers/api/server/index.ts
@@ -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)
// ---------------------------------------------------------------------------
diff --git a/server/tests/api/check-params/debug.ts b/server/tests/api/check-params/debug.ts
new file mode 100644
index 000000000..9bf664657
--- /dev/null
+++ b/server/tests/api/check-params/debug.ts
@@ -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()
+ }
+ })
+})
diff --git a/server/tests/api/check-params/index.ts b/server/tests/api/check-params/index.ts
index bdac95025..844fa31c5 100644
--- a/server/tests/api/check-params/index.ts
+++ b/server/tests/api/check-params/index.ts
@@ -2,6 +2,7 @@ import './accounts'
import './blocklist'
import './config'
import './contact-form'
+import './debug'
import './follows'
import './jobs'
import './logs'
diff --git a/shared/models/server/debug.model.ts b/shared/models/server/debug.model.ts
new file mode 100644
index 000000000..61cba6518
--- /dev/null
+++ b/shared/models/server/debug.model.ts
@@ -0,0 +1,3 @@
+export interface Debug {
+ ip: string
+}
diff --git a/shared/models/server/index.ts b/shared/models/server/index.ts
index c42f6f67f..bf61ab270 100644
--- a/shared/models/server/index.ts
+++ b/shared/models/server/index.ts
@@ -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'
diff --git a/shared/models/users/user-right.enum.ts b/shared/models/users/user-right.enum.ts
index 5ec255ea5..71701bdb4 100644
--- a/shared/models/users/user-right.enum.ts
+++ b/shared/models/users/user-right.enum.ts
@@ -7,6 +7,8 @@ export enum UserRight {
MANAGE_LOGS,
+ MANAGE_DEBUG,
+
MANAGE_SERVER_REDUNDANCY,
MANAGE_VIDEO_ABUSES,