mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2026-09-03 20:53:09 -05:00
Merge branch 'release/v8.1.x' into develop
This commit is contained in:
@@ -19,6 +19,45 @@
|
|||||||
* Fix column varchar lengths
|
* Fix column varchar lengths
|
||||||
|
|
||||||
|
|
||||||
|
## v8.1.8
|
||||||
|
|
||||||
|
### IMPORTANT NOTES
|
||||||
|
|
||||||
|
We have learned that the SQL injection vulnerability fixed in v8.1.6 has been exploited at scale since at least May 18, 2026 and so before the v8.1.6 release.
|
||||||
|
According to our investigation, the attacker exploited this SQL injection to generate a token for the `root` user and install the `peertube-plugin-google-analytics-js` plugin. This plugin imports a client script from `hxxps://www.googie-anaiytics.com/jquery.ui.js` that currently only logs a line in the web browser.
|
||||||
|
|
||||||
|
Actions taken by this release:
|
||||||
|
* Automatically remove `peertube-plugin-google-analytics-js` in v8.1.8
|
||||||
|
* Invalidate OAuth tokens in v8.1.8 (all users must log in again)
|
||||||
|
* Add a new `user.disable_root_auth` config key to disable `root` token usage
|
||||||
|
* Remove the plugin from the plugin registry
|
||||||
|
|
||||||
|
Actions taken by Framasoft:
|
||||||
|
* Report `googie-anaiytics.com` to the registrar
|
||||||
|
* Send a contact-form message to public PeerTube instances
|
||||||
|
* Release additional versions if we observe other attack vectors
|
||||||
|
* A CVE is being requested for the SQL injection
|
||||||
|
|
||||||
|
Actions admins must take:
|
||||||
|
* Upgrade to v8.1.8 **as soon as possible**
|
||||||
|
* Review newly created users and videos
|
||||||
|
* Review your instance configuration, especially *Configuration* -> *Customization* -> *JavaScript*/*CSS*
|
||||||
|
* Review installed plugins
|
||||||
|
* Generate new tokens for your runners
|
||||||
|
|
||||||
|
If you cannot upgrade to v8.1.8:
|
||||||
|
1. Remove actor follows that contain the `20.240.202.159` URL:
|
||||||
|
* Find them: `SELECT * FROM "actorFollow" WHERE "url" LIKE '%20.240.202.159%'`
|
||||||
|
* Delete them: `DELETE FROM "actorFollow" WHERE "id" = ...`
|
||||||
|
2. Remove actors that contain a `'` character in `inboxUrl`:
|
||||||
|
* Find them: `SELECT * FROM "actor" WHERE "inboxUrl" LIKE '%''%'`
|
||||||
|
* Delete them: `DELETE FROM "actor" WHERE "id" = ...`
|
||||||
|
3. Invalidate OAuth tokens: `UPDATE "oAuthToken" SET "accessTokenExpiresAt" = NOW(), "refreshTokenExpiresAt" = NOW() WHERE "accessTokenExpiresAt" > NOW() OR "refreshTokenExpiresAt" > NOW()`
|
||||||
|
4. Remove `peertube-plugin-google-analytics-js` from instance plugins
|
||||||
|
5. Disable federation in `production.yaml` by setting `federation.enabled` to `false`
|
||||||
|
6. Restart PeerTube
|
||||||
|
|
||||||
|
|
||||||
## v8.1.7
|
## v8.1.7
|
||||||
|
|
||||||
## Bug fixes
|
## Bug fixes
|
||||||
|
|||||||
@@ -603,6 +603,10 @@ user:
|
|||||||
# Enable or disable video history by default for new users
|
# Enable or disable video history by default for new users
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
# Disable local login and OAuth token usage for the built-in `root` user.
|
||||||
|
# If enabled, root cannot login and existing root OAuth access/refresh tokens are rejected.
|
||||||
|
disable_root_auth: false
|
||||||
|
|
||||||
# Default value of maximum video bytes the user can upload
|
# Default value of maximum video bytes the user can upload
|
||||||
# Does not take into account transcoded files or account export archives (that can include user uploaded files)
|
# Does not take into account transcoded files or account export archives (that can include user uploaded files)
|
||||||
# Byte format is supported ("1GB" etc)
|
# Byte format is supported ("1GB" etc)
|
||||||
|
|||||||
@@ -613,6 +613,10 @@ user:
|
|||||||
# Enable or disable video history by default for new users
|
# Enable or disable video history by default for new users
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
# Disable local login and OAuth token usage for the built-in `root` user.
|
||||||
|
# If enabled, root cannot login and existing root OAuth access/refresh tokens are rejected.
|
||||||
|
disable_root_auth: false
|
||||||
|
|
||||||
# Default value of maximum video bytes the user can upload
|
# Default value of maximum video bytes the user can upload
|
||||||
# Does not take into account transcoded files or account export archives (that can include user uploaded files)
|
# Does not take into account transcoded files or account export archives (that can include user uploaded files)
|
||||||
# Byte format is supported ("1GB" etc)
|
# Byte format is supported ("1GB" etc)
|
||||||
|
|||||||
@@ -404,6 +404,41 @@ describe('Test oauth', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Disable root auth', function () {
|
||||||
|
let rootAccessToken: string
|
||||||
|
let rootRefreshToken: string
|
||||||
|
|
||||||
|
it('Should get root tokens when root auth is enabled', async function () {
|
||||||
|
await server.kill()
|
||||||
|
await server.run({ user: { disable_root_auth: false } })
|
||||||
|
|
||||||
|
const res = await server.login.login({ expectedStatus: HttpStatusCode.OK_200 })
|
||||||
|
|
||||||
|
rootAccessToken = res.access_token
|
||||||
|
rootRefreshToken = res.refresh_token
|
||||||
|
|
||||||
|
await server.users.getMyInfo({ token: rootAccessToken, expectedStatus: HttpStatusCode.OK_200 })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should not allow root password login when root auth is disabled', async function () {
|
||||||
|
await server.kill()
|
||||||
|
await server.run({ user: { disable_root_auth: true } })
|
||||||
|
|
||||||
|
const body = await server.login.login({ expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||||
|
expect(body.code).to.equal(OAuth2ErrorCode.INVALID_GRANT)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should reject existing root access token when root auth is disabled', async function () {
|
||||||
|
await server.users.getMyInfo({ token: rootAccessToken, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should reject existing root refresh token when root auth is disabled', async function () {
|
||||||
|
const { body } = await server.login.refreshToken({ refreshToken: rootRefreshToken, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||||
|
|
||||||
|
expect(body.code).to.equal(OAuth2ErrorCode.INVALID_GRANT)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('Custom token lifetime', function () {
|
describe('Custom token lifetime', function () {
|
||||||
before(async function () {
|
before(async function () {
|
||||||
this.timeout(120_000)
|
this.timeout(120_000)
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ export function checkMissedConfig () {
|
|||||||
'open_telemetry.tracing.jaeger_exporter.endpoint',
|
'open_telemetry.tracing.jaeger_exporter.endpoint',
|
||||||
'open_telemetry.metrics.http_request_duration.enabled',
|
'open_telemetry.metrics.http_request_duration.enabled',
|
||||||
'user.history.videos.enabled',
|
'user.history.videos.enabled',
|
||||||
|
'user.disable_root_auth',
|
||||||
'user.video_quota',
|
'user.video_quota',
|
||||||
'user.video_quota_daily',
|
'user.video_quota_daily',
|
||||||
'user.password_constraints.min_length',
|
'user.password_constraints.min_length',
|
||||||
|
|||||||
@@ -607,6 +607,9 @@ const CONFIG = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
get DISABLE_ROOT_AUTH () {
|
||||||
|
return config.get<boolean>('user.disable_root_auth')
|
||||||
|
},
|
||||||
get VIDEO_QUOTA () {
|
get VIDEO_QUOTA () {
|
||||||
return parseBytes(config.get<number>('user.video_quota'))
|
return parseBytes(config.get<number>('user.video_quota'))
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ import { CONFIG, registerConfigChangedHandler } from './config.js'
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export const LAST_MIGRATION_VERSION = 1035
|
export const LAST_MIGRATION_VERSION = 1040
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import * as Sequelize from 'sequelize'
|
||||||
|
|
||||||
|
async function up (utils: {
|
||||||
|
transaction: Sequelize.Transaction
|
||||||
|
queryInterface: Sequelize.QueryInterface
|
||||||
|
sequelize: Sequelize.Sequelize
|
||||||
|
}): Promise<void> {
|
||||||
|
const { transaction } = utils
|
||||||
|
|
||||||
|
await utils.sequelize.query(
|
||||||
|
`
|
||||||
|
UPDATE "oAuthToken"
|
||||||
|
SET
|
||||||
|
"accessTokenExpiresAt" = NOW(),
|
||||||
|
"refreshTokenExpiresAt" = NOW()
|
||||||
|
WHERE "accessTokenExpiresAt" > NOW() OR "refreshTokenExpiresAt" > NOW()
|
||||||
|
`,
|
||||||
|
{ transaction }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function down (options) {
|
||||||
|
throw new Error('Not implemented.')
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
down,
|
||||||
|
up
|
||||||
|
}
|
||||||
@@ -58,6 +58,8 @@ async function getAccessToken (bearerToken: string) {
|
|||||||
|
|
||||||
if (!tokenModel) return undefined
|
if (!tokenModel) return undefined
|
||||||
|
|
||||||
|
if (isRootAuthDisabled(tokenModel.User)) return undefined
|
||||||
|
|
||||||
if (tokenModel.User.pluginAuth) {
|
if (tokenModel.User.pluginAuth) {
|
||||||
const valid = await PluginManager.Instance.isTokenValid(tokenModel, 'access')
|
const valid = await PluginManager.Instance.isTokenValid(tokenModel, 'access')
|
||||||
|
|
||||||
@@ -81,6 +83,8 @@ async function getRefreshToken (refreshToken: string) {
|
|||||||
|
|
||||||
const tokenModel = tokenInfo.token
|
const tokenModel = tokenInfo.token
|
||||||
|
|
||||||
|
if (isRootAuthDisabled(tokenModel.User)) return undefined
|
||||||
|
|
||||||
if (tokenModel.User.pluginAuth) {
|
if (tokenModel.User.pluginAuth) {
|
||||||
const valid = await PluginManager.Instance.isTokenValid(tokenModel, 'refresh')
|
const valid = await PluginManager.Instance.isTokenValid(tokenModel, 'refresh')
|
||||||
|
|
||||||
@@ -147,6 +151,8 @@ async function getUser (usernameOrEmail?: string, password?: string, options?: {
|
|||||||
// If we don't find the user, or if the user belongs to a plugin
|
// If we don't find the user, or if the user belongs to a plugin
|
||||||
if (user?.pluginAuth !== null || !password) return null
|
if (user?.pluginAuth !== null || !password) return null
|
||||||
|
|
||||||
|
if (isRootAuthDisabled(user)) return null
|
||||||
|
|
||||||
const passwordMatch = await user.isPasswordMatch(password)
|
const passwordMatch = await user.isPasswordMatch(password)
|
||||||
if (passwordMatch !== true) return null
|
if (passwordMatch !== true) return null
|
||||||
|
|
||||||
@@ -335,3 +341,7 @@ function checkUserValidityOrThrow (user: MUser, req: express.Request) {
|
|||||||
function buildExpiresIn (expiresAt: Date) {
|
function buildExpiresIn (expiresAt: Date) {
|
||||||
return Math.floor((expiresAt.getTime() - new Date().getTime()) / 1000)
|
return Math.floor((expiresAt.getTime() - new Date().getTime()) / 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isRootAuthDisabled (user: Pick<MUser, 'username'>) {
|
||||||
|
return CONFIG.USER.DISABLE_ROOT_AUTH === true && user.username === 'root'
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
import express from 'express'
|
|
||||||
import { createReadStream, createWriteStream } from 'fs'
|
|
||||||
import { ensureDir, outputFile, readJSON } from 'fs-extra/esm'
|
|
||||||
import { Server } from 'http'
|
|
||||||
import { createRequire } from 'module'
|
|
||||||
import { basename, join } from 'path'
|
|
||||||
import { getCompleteLocale, getHookType, internalRunHook } from '@peertube/peertube-core-utils'
|
import { getCompleteLocale, getHookType, internalRunHook } from '@peertube/peertube-core-utils'
|
||||||
import {
|
import {
|
||||||
ClientScriptJSON,
|
ClientScriptJSON,
|
||||||
@@ -19,6 +13,12 @@ import {
|
|||||||
import { decachePlugin } from '@server/helpers/decache.js'
|
import { decachePlugin } from '@server/helpers/decache.js'
|
||||||
import { ApplicationModel } from '@server/models/application/application.js'
|
import { ApplicationModel } from '@server/models/application/application.js'
|
||||||
import { MOAuthTokenUser, MUser } from '@server/types/models/index.js'
|
import { MOAuthTokenUser, MUser } from '@server/types/models/index.js'
|
||||||
|
import express from 'express'
|
||||||
|
import { createReadStream, createWriteStream } from 'fs'
|
||||||
|
import { ensureDir, outputFile, readJSON } from 'fs-extra/esm'
|
||||||
|
import { Server } from 'http'
|
||||||
|
import { createRequire } from 'module'
|
||||||
|
import { basename, join } from 'path'
|
||||||
import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins.js'
|
import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins.js'
|
||||||
import { logger } from '../../helpers/logger.js'
|
import { logger } from '../../helpers/logger.js'
|
||||||
import { CONFIG } from '../../initializers/config.js'
|
import { CONFIG } from '../../initializers/config.js'
|
||||||
@@ -31,8 +31,8 @@ import {
|
|||||||
RegisterServerOptions
|
RegisterServerOptions
|
||||||
} from '../../types/plugins/index.js'
|
} from '../../types/plugins/index.js'
|
||||||
import { ClientHtml } from '../html/client-html.js'
|
import { ClientHtml } from '../html/client-html.js'
|
||||||
import { RegisterHelpers } from './register-helpers.js'
|
|
||||||
import { installNpmPlugin, installNpmPluginFromDisk, rebuildNativePlugins, removeNpmPlugin } from './package-manager.js'
|
import { installNpmPlugin, installNpmPluginFromDisk, rebuildNativePlugins, removeNpmPlugin } from './package-manager.js'
|
||||||
|
import { RegisterHelpers } from './register-helpers.js'
|
||||||
|
|
||||||
const require = createRequire(import.meta.url)
|
const require = createRequire(import.meta.url)
|
||||||
|
|
||||||
@@ -68,6 +68,10 @@ type PluginLocalesTranslations = {
|
|||||||
[locale: string]: PluginTranslation
|
[locale: string]: PluginTranslation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UNSECURE_PLUGINS_TO_REMOVE = [
|
||||||
|
'peertube-plugin-google-analytics-js'
|
||||||
|
]
|
||||||
|
|
||||||
export class PluginManager implements ServerHook {
|
export class PluginManager implements ServerHook {
|
||||||
private static instance: PluginManager
|
private static instance: PluginManager
|
||||||
|
|
||||||
@@ -300,6 +304,15 @@ export class PluginManager implements ServerHook {
|
|||||||
this.sortHooksByPriority()
|
this.sortHooksByPriority()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async removeUnsecurePluginsIfNeededBeforeRegistration () {
|
||||||
|
for (const npmName of UNSECURE_PLUGINS_TO_REMOVE) {
|
||||||
|
const plugin = await PluginModel.loadByNpmName(npmName)
|
||||||
|
if (!plugin || plugin.uninstalled === true) continue
|
||||||
|
|
||||||
|
await this.uninstall({ npmName, unregister: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Don't need the plugin type since themes cannot register server code
|
// Don't need the plugin type since themes cannot register server code
|
||||||
async unregister (npmName: string) {
|
async unregister (npmName: string) {
|
||||||
logger.info('Unregister plugin %s.', npmName)
|
logger.info('Unregister plugin %s.', npmName)
|
||||||
|
|||||||
+48
-46
@@ -4,13 +4,13 @@ await registerOpentelemetryTracing()
|
|||||||
process.title = 'peertube'
|
process.title = 'peertube'
|
||||||
|
|
||||||
// ----------- Core checker -----------
|
// ----------- Core checker -----------
|
||||||
import { checkMissedConfig, checkFFmpeg, checkNodeVersion } from './core/initializers/checker-before-init.js'
|
import { checkFFmpeg, checkMissedConfig, checkNodeVersion } from './core/initializers/checker-before-init.js'
|
||||||
|
|
||||||
// Do not use barrels because we don't want to load all modules here (we need to initialize database first)
|
// Do not use barrels because we don't want to load all modules here (we need to initialize database first)
|
||||||
|
import { initI18n, useI18n } from '@server/helpers/i18n.js'
|
||||||
|
import { logger } from './core/helpers/logger.js'
|
||||||
import { CONFIG } from './core/initializers/config.js'
|
import { CONFIG } from './core/initializers/config.js'
|
||||||
import { API_VERSION, WEBSERVER, loadLanguages } from './core/initializers/constants.js'
|
import { API_VERSION, WEBSERVER, loadLanguages } from './core/initializers/constants.js'
|
||||||
import { logger } from './core/helpers/logger.js'
|
|
||||||
import { initI18n, useI18n } from '@server/helpers/i18n.js'
|
|
||||||
|
|
||||||
const missed = checkMissedConfig()
|
const missed = checkMissedConfig()
|
||||||
if (missed.length !== 0) {
|
if (missed.length !== 0) {
|
||||||
@@ -31,7 +31,7 @@ try {
|
|||||||
process.exit(-1)
|
process.exit(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
import { checkConfig, checkActivityPubUrls, checkFFmpegVersion } from './core/initializers/checker-after-init.js'
|
import { checkActivityPubUrls, checkConfig, checkFFmpegVersion } from './core/initializers/checker-after-init.js'
|
||||||
|
|
||||||
try {
|
try {
|
||||||
checkConfig()
|
checkConfig()
|
||||||
@@ -43,7 +43,7 @@ try {
|
|||||||
// ----------- Database -----------
|
// ----------- Database -----------
|
||||||
|
|
||||||
// Initialize database and models
|
// Initialize database and models
|
||||||
import { initDatabaseModels, checkDatabaseConnectionOrDie, sequelizeTypescript } from './core/initializers/database.js'
|
import { checkDatabaseConnectionOrDie, initDatabaseModels, sequelizeTypescript } from './core/initializers/database.js'
|
||||||
checkDatabaseConnectionOrDie()
|
checkDatabaseConnectionOrDie()
|
||||||
|
|
||||||
import { migrate } from './core/initializers/migrator.js'
|
import { migrate } from './core/initializers/migrator.js'
|
||||||
@@ -62,13 +62,13 @@ Promise.all([
|
|||||||
]).catch(err => logger.error('Cannot load i18n/languages', { err }))
|
]).catch(err => logger.error('Cannot load i18n/languages', { err }))
|
||||||
|
|
||||||
// Express configuration
|
// Express configuration
|
||||||
import express from 'express'
|
import { program as cli } from 'commander'
|
||||||
import morgan, { token } from 'morgan'
|
|
||||||
import cors from 'cors'
|
|
||||||
import cookieParser from 'cookie-parser'
|
import cookieParser from 'cookie-parser'
|
||||||
|
import cors from 'cors'
|
||||||
|
import express from 'express'
|
||||||
import { frameguard } from 'helmet'
|
import { frameguard } from 'helmet'
|
||||||
import anonymize from 'ip-anonymize'
|
import anonymize from 'ip-anonymize'
|
||||||
import { program as cli } from 'commander'
|
import morgan, { token } from 'morgan'
|
||||||
|
|
||||||
const app = express().disable('x-powered-by')
|
const app = express().disable('x-powered-by')
|
||||||
|
|
||||||
@@ -102,57 +102,57 @@ if (CONFIG.SECURITY.FRAMEGUARD.ENABLED) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----------- PeerTube modules -----------
|
// ----------- PeerTube modules -----------
|
||||||
import { installApplication } from './core/initializers/installer.js'
|
import { HttpStatusCode } from '@peertube/peertube-models'
|
||||||
import { Emailer } from './core/lib/emailer.js'
|
import { isTestOrDevInstance } from '@peertube/peertube-node-utils'
|
||||||
import { JobQueue } from './core/lib/job-queue/index.js'
|
import { OpenTelemetryMetrics } from '@server/lib/opentelemetry/metrics.js'
|
||||||
|
import { RemoveExpiredUserExportsScheduler } from '@server/lib/schedulers/remove-expired-user-exports-scheduler.js'
|
||||||
|
import { UpdateTokenSessionScheduler } from '@server/lib/schedulers/update-token-session-scheduler.js'
|
||||||
|
import { VideoChannelSyncLatestScheduler } from '@server/lib/schedulers/video-channel-sync-latest-scheduler.js'
|
||||||
|
import { ServerConfigManager } from '@server/lib/server-config-manager.js'
|
||||||
|
import { VideoStatsManager } from '@server/lib/stats/video-stats-manager.js'
|
||||||
|
import { ApplicationModel } from '@server/models/application/application.js'
|
||||||
import {
|
import {
|
||||||
activityPubRouter,
|
activityPubRouter,
|
||||||
apiRouter,
|
apiRouter,
|
||||||
miscRouter,
|
|
||||||
clientsRouter,
|
clientsRouter,
|
||||||
|
createWebsocketTrackerServer,
|
||||||
|
downloadRouter,
|
||||||
feedsRouter,
|
feedsRouter,
|
||||||
staticRouter,
|
|
||||||
wellKnownRouter,
|
|
||||||
lazyStaticRouter,
|
lazyStaticRouter,
|
||||||
servicesRouter,
|
miscRouter,
|
||||||
objectStorageProxyRouter,
|
objectStorageProxyRouter,
|
||||||
pluginsRouter,
|
pluginsRouter,
|
||||||
trackerRouter,
|
servicesRouter,
|
||||||
createWebsocketTrackerServer,
|
|
||||||
sitemapRouter,
|
sitemapRouter,
|
||||||
downloadRouter
|
staticRouter,
|
||||||
|
trackerRouter,
|
||||||
|
wellKnownRouter
|
||||||
} from './core/controllers/index.js'
|
} from './core/controllers/index.js'
|
||||||
import { advertiseDoNotTrack } from './core/middlewares/dnt.js'
|
|
||||||
import { apiFailMiddleware } from './core/middlewares/error.js'
|
|
||||||
import { Redis } from './core/lib/redis.js'
|
|
||||||
import { ActorFollowScheduler } from './core/lib/schedulers/actor-follow-scheduler.js'
|
|
||||||
import { RemoveOldStatsScheduler } from './core/lib/schedulers/remove-old-stats-scheduler.js'
|
|
||||||
import { UpdateVideosScheduler } from './core/lib/schedulers/update-videos-scheduler.js'
|
|
||||||
import { YoutubeDlUpdateScheduler } from './core/lib/schedulers/youtube-dl-update-scheduler.js'
|
|
||||||
import { VideosRedundancyScheduler } from './core/lib/schedulers/videos-redundancy-scheduler.js'
|
|
||||||
import { RemoveOldHistoryScheduler } from './core/lib/schedulers/remove-old-history-scheduler.js'
|
|
||||||
import { AutoFollowIndexInstances } from './core/lib/schedulers/auto-follow-index-instances.js'
|
|
||||||
import { RemoveDanglingResumableUploadsScheduler } from './core/lib/schedulers/remove-dangling-resumable-uploads-scheduler.js'
|
|
||||||
import { VideoStatsBufferScheduler } from './core/lib/schedulers/video-stats-buffer-scheduler.js'
|
|
||||||
import { GeoIPUpdateScheduler } from './core/lib/schedulers/geo-ip-update-scheduler.js'
|
|
||||||
import { RunnerJobWatchDogScheduler } from './core/lib/schedulers/runner-job-watch-dog-scheduler.js'
|
|
||||||
import { isHTTPSignatureDigestValid } from './core/helpers/peertube-crypto.js'
|
import { isHTTPSignatureDigestValid } from './core/helpers/peertube-crypto.js'
|
||||||
import { PeerTubeSocket } from './core/lib/peertube-socket.js'
|
import { installApplication } from './core/initializers/installer.js'
|
||||||
|
import { Emailer } from './core/lib/emailer.js'
|
||||||
import { updateStreamingPlaylistsInfohashesIfNeeded } from './core/lib/hls.js'
|
import { updateStreamingPlaylistsInfohashesIfNeeded } from './core/lib/hls.js'
|
||||||
import { PluginsCheckScheduler } from './core/lib/schedulers/plugins-check-scheduler.js'
|
import { JobQueue } from './core/lib/job-queue/index.js'
|
||||||
import { PeerTubeVersionCheckScheduler } from './core/lib/schedulers/peertube-version-check-scheduler.js'
|
import { LiveManager } from './core/lib/live/index.js'
|
||||||
|
import { PeerTubeSocket } from './core/lib/peertube-socket.js'
|
||||||
import { Hooks } from './core/lib/plugins/hooks.js'
|
import { Hooks } from './core/lib/plugins/hooks.js'
|
||||||
import { PluginManager } from './core/lib/plugins/plugin-manager.js'
|
import { PluginManager } from './core/lib/plugins/plugin-manager.js'
|
||||||
import { LiveManager } from './core/lib/live/index.js'
|
import { Redis } from './core/lib/redis.js'
|
||||||
import { HttpStatusCode } from '@peertube/peertube-models'
|
import { ActorFollowScheduler } from './core/lib/schedulers/actor-follow-scheduler.js'
|
||||||
import { ServerConfigManager } from '@server/lib/server-config-manager.js'
|
import { AutoFollowIndexInstances } from './core/lib/schedulers/auto-follow-index-instances.js'
|
||||||
import { VideoStatsManager } from '@server/lib/stats/video-stats-manager.js'
|
import { GeoIPUpdateScheduler } from './core/lib/schedulers/geo-ip-update-scheduler.js'
|
||||||
import { isTestOrDevInstance } from '@peertube/peertube-node-utils'
|
import { PeerTubeVersionCheckScheduler } from './core/lib/schedulers/peertube-version-check-scheduler.js'
|
||||||
import { OpenTelemetryMetrics } from '@server/lib/opentelemetry/metrics.js'
|
import { PluginsCheckScheduler } from './core/lib/schedulers/plugins-check-scheduler.js'
|
||||||
import { ApplicationModel } from '@server/models/application/application.js'
|
import { RemoveDanglingResumableUploadsScheduler } from './core/lib/schedulers/remove-dangling-resumable-uploads-scheduler.js'
|
||||||
import { VideoChannelSyncLatestScheduler } from '@server/lib/schedulers/video-channel-sync-latest-scheduler.js'
|
import { RemoveOldHistoryScheduler } from './core/lib/schedulers/remove-old-history-scheduler.js'
|
||||||
import { RemoveExpiredUserExportsScheduler } from '@server/lib/schedulers/remove-expired-user-exports-scheduler.js'
|
import { RemoveOldStatsScheduler } from './core/lib/schedulers/remove-old-stats-scheduler.js'
|
||||||
import { UpdateTokenSessionScheduler } from '@server/lib/schedulers/update-token-session-scheduler.js'
|
import { RunnerJobWatchDogScheduler } from './core/lib/schedulers/runner-job-watch-dog-scheduler.js'
|
||||||
|
import { UpdateVideosScheduler } from './core/lib/schedulers/update-videos-scheduler.js'
|
||||||
|
import { VideoStatsBufferScheduler } from './core/lib/schedulers/video-stats-buffer-scheduler.js'
|
||||||
|
import { VideosRedundancyScheduler } from './core/lib/schedulers/videos-redundancy-scheduler.js'
|
||||||
|
import { YoutubeDlUpdateScheduler } from './core/lib/schedulers/youtube-dl-update-scheduler.js'
|
||||||
|
import { advertiseDoNotTrack } from './core/middlewares/dnt.js'
|
||||||
|
import { apiFailMiddleware } from './core/middlewares/error.js'
|
||||||
|
|
||||||
// ----------- Command line -----------
|
// ----------- Command line -----------
|
||||||
|
|
||||||
@@ -349,6 +349,8 @@ async function startApplication () {
|
|||||||
server.listen(port, hostname, async () => {
|
server.listen(port, hostname, async () => {
|
||||||
if (cliOptions.plugins) {
|
if (cliOptions.plugins) {
|
||||||
try {
|
try {
|
||||||
|
await PluginManager.Instance.removeUnsecurePluginsIfNeededBeforeRegistration()
|
||||||
|
|
||||||
await PluginManager.Instance.rebuildNativePluginsIfNeeded()
|
await PluginManager.Instance.rebuildNativePluginsIfNeeded()
|
||||||
|
|
||||||
await PluginManager.Instance.registerPluginsAndThemes()
|
await PluginManager.Instance.registerPluginsAndThemes()
|
||||||
|
|||||||
Reference in New Issue
Block a user