XMPP external components.
This commit is contained in:
		@ -2,6 +2,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## (unreleased yet)
 | 
					## (unreleased yet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Builtin Prosody: you can now allow «external XMPP components» to connect. This can be used for exemple to connect bots or bridges. For now, only connections from localhost will be allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Minor changes and fixes
 | 
					### Minor changes and fixes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Spanish translations (thanks [rnek0](https://github.com/rnek0)).
 | 
					* Spanish translations (thanks [rnek0](https://github.com/rnek0)).
 | 
				
			||||||
 | 
				
			|||||||
@ -211,12 +211,19 @@ function register ({ registerHook, registerSettingsScript, peertubeHelpers }: Re
 | 
				
			|||||||
        case 'prosody-muc-log-by-default':
 | 
					        case 'prosody-muc-log-by-default':
 | 
				
			||||||
        case 'prosody-muc-expiration':
 | 
					        case 'prosody-muc-expiration':
 | 
				
			||||||
        case 'prosody-c2s':
 | 
					        case 'prosody-c2s':
 | 
				
			||||||
 | 
					        case 'prosody-components':
 | 
				
			||||||
          return options.formValues['chat-type'] !== ('builtin-prosody' as ChatType)
 | 
					          return options.formValues['chat-type'] !== ('builtin-prosody' as ChatType)
 | 
				
			||||||
        case 'prosody-c2s-port':
 | 
					        case 'prosody-c2s-port':
 | 
				
			||||||
          return !(
 | 
					          return !(
 | 
				
			||||||
            options.formValues['chat-type'] === ('builtin-prosody' as ChatType) &&
 | 
					            options.formValues['chat-type'] === ('builtin-prosody' as ChatType) &&
 | 
				
			||||||
            options.formValues['prosody-c2s'] === true
 | 
					            options.formValues['prosody-c2s'] === true
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
 | 
					        case 'prosody-components-port':
 | 
				
			||||||
 | 
					        case 'prosody-components-list':
 | 
				
			||||||
 | 
					          return !(
 | 
				
			||||||
 | 
					            options.formValues['chat-type'] === ('builtin-prosody' as ChatType) &&
 | 
				
			||||||
 | 
					            options.formValues['prosody-components'] === true
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
        case 'chat-server':
 | 
					        case 'chat-server':
 | 
				
			||||||
        case 'chat-room':
 | 
					        case 'chat-room':
 | 
				
			||||||
        case 'chat-bosh-uri':
 | 
					        case 'chat-bosh-uri':
 | 
				
			||||||
 | 
				
			|||||||
@ -100,6 +100,15 @@ The port that will be used by the c2s module of the builtin Prosody server.
 | 
				
			|||||||
XMPP clients shall use this port to connect.
 | 
					XMPP clients shall use this port to connect.
 | 
				
			||||||
Change it if this port is already in use on your server.
 | 
					Change it if this port is already in use on your server.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Enable external XMPP components
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This settings enable XMPP external components to connect to the server.
 | 
				
			||||||
 | 
					For now, this option **only allows connections from localhost components**.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This feature could be used to connect bridges or bots.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More informations on Prosody external components [here](https://prosody.im/doc/components).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Moderation
 | 
					## Moderation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can access rooms settings and moderation tools by opening the chat in a new window,
 | 
					You can access rooms settings and moderation tools by opening the chat in a new window,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					import type { ProsodyLogLevel } from './config/content'
 | 
				
			||||||
import * as fs from 'fs'
 | 
					import * as fs from 'fs'
 | 
				
			||||||
import * as path from 'path'
 | 
					import * as path from 'path'
 | 
				
			||||||
import { getBaseRouterRoute } from '../helpers'
 | 
					import { getBaseRouterRoute } from '../helpers'
 | 
				
			||||||
@ -5,7 +6,7 @@ import { ProsodyFilePaths } from './config/paths'
 | 
				
			|||||||
import { ConfigLogExpiration, ProsodyConfigContent } from './config/content'
 | 
					import { ConfigLogExpiration, ProsodyConfigContent } from './config/content'
 | 
				
			||||||
import { getProsodyDomain } from './config/domain'
 | 
					import { getProsodyDomain } from './config/domain'
 | 
				
			||||||
import { getAPIKey } from '../apikey'
 | 
					import { getAPIKey } from '../apikey'
 | 
				
			||||||
import type { ProsodyLogLevel } from './config/content'
 | 
					import { parseExternalComponents } from './config/components'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function getWorkingDir (options: RegisterServerOptions): Promise<string> {
 | 
					async function getWorkingDir (options: RegisterServerOptions): Promise<string> {
 | 
				
			||||||
  const peertubeHelpers = options.peertubeHelpers
 | 
					  const peertubeHelpers = options.peertubeHelpers
 | 
				
			||||||
@ -72,7 +73,7 @@ interface ProsodyConfig {
 | 
				
			|||||||
  roomType: 'video' | 'channel'
 | 
					  roomType: 'video' | 'channel'
 | 
				
			||||||
  logByDefault: boolean
 | 
					  logByDefault: boolean
 | 
				
			||||||
  logExpiration: ConfigLogExpiration
 | 
					  logExpiration: ConfigLogExpiration
 | 
				
			||||||
  valuesToHideInDiagnostic: {[key: string]: string}
 | 
					  valuesToHideInDiagnostic: Map<string, string>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
async function getProsodyConfig (options: RegisterServerOptions): Promise<ProsodyConfig> {
 | 
					async function getProsodyConfig (options: RegisterServerOptions): Promise<ProsodyConfig> {
 | 
				
			||||||
  const logger = options.peertubeHelpers.logger
 | 
					  const logger = options.peertubeHelpers.logger
 | 
				
			||||||
@ -83,12 +84,15 @@ async function getProsodyConfig (options: RegisterServerOptions): Promise<Prosod
 | 
				
			|||||||
    'prosody-muc-log-by-default',
 | 
					    'prosody-muc-log-by-default',
 | 
				
			||||||
    'prosody-muc-expiration',
 | 
					    'prosody-muc-expiration',
 | 
				
			||||||
    'prosody-c2s',
 | 
					    'prosody-c2s',
 | 
				
			||||||
 | 
					    'prosody-c2s-port',
 | 
				
			||||||
    'prosody-room-type',
 | 
					    'prosody-room-type',
 | 
				
			||||||
    'prosody-peertube-uri',
 | 
					    'prosody-peertube-uri',
 | 
				
			||||||
    'prosody-c2s-port'
 | 
					    'prosody-components',
 | 
				
			||||||
 | 
					    'prosody-components-port',
 | 
				
			||||||
 | 
					    'prosody-components-list'
 | 
				
			||||||
  ])
 | 
					  ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const valuesToHideInDiagnostic: {[key: string]: string} = {}
 | 
					  const valuesToHideInDiagnostic = new Map<string, string>()
 | 
				
			||||||
  const port = (settings['prosody-port'] as string) || '52800'
 | 
					  const port = (settings['prosody-port'] as string) || '52800'
 | 
				
			||||||
  if (!/^\d+$/.test(port)) {
 | 
					  if (!/^\d+$/.test(port)) {
 | 
				
			||||||
    throw new Error('Invalid port')
 | 
					    throw new Error('Invalid port')
 | 
				
			||||||
@ -96,12 +100,13 @@ async function getProsodyConfig (options: RegisterServerOptions): Promise<Prosod
 | 
				
			|||||||
  const logByDefault = (settings['prosody-muc-log-by-default'] as boolean) ?? true
 | 
					  const logByDefault = (settings['prosody-muc-log-by-default'] as boolean) ?? true
 | 
				
			||||||
  const logExpirationSetting = (settings['prosody-muc-expiration'] as string) ?? DEFAULTLOGEXPIRATION
 | 
					  const logExpirationSetting = (settings['prosody-muc-expiration'] as string) ?? DEFAULTLOGEXPIRATION
 | 
				
			||||||
  const enableC2s = (settings['prosody-c2s'] as boolean) || false
 | 
					  const enableC2s = (settings['prosody-c2s'] as boolean) || false
 | 
				
			||||||
 | 
					  const enableComponents = (settings['prosody-c2s'] as boolean) || false
 | 
				
			||||||
  const prosodyDomain = await getProsodyDomain(options)
 | 
					  const prosodyDomain = await getProsodyDomain(options)
 | 
				
			||||||
  const paths = await getProsodyFilePaths(options)
 | 
					  const paths = await getProsodyFilePaths(options)
 | 
				
			||||||
  const roomType = settings['prosody-room-type'] === 'channel' ? 'channel' : 'video'
 | 
					  const roomType = settings['prosody-room-type'] === 'channel' ? 'channel' : 'video'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const apikey = await getAPIKey(options)
 | 
					  const apikey = await getAPIKey(options)
 | 
				
			||||||
  valuesToHideInDiagnostic.APIKey = apikey
 | 
					  valuesToHideInDiagnostic.set('APIKey', apikey)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let baseApiUrl = settings['prosody-peertube-uri'] as string
 | 
					  let baseApiUrl = settings['prosody-peertube-uri'] as string
 | 
				
			||||||
  if (baseApiUrl && !/^https?:\/\/[a-z0-9.-_]+(?::\d+)?$/.test(baseApiUrl)) {
 | 
					  if (baseApiUrl && !/^https?:\/\/[a-z0-9.-_]+(?::\d+)?$/.test(baseApiUrl)) {
 | 
				
			||||||
@ -129,6 +134,18 @@ async function getProsodyConfig (options: RegisterServerOptions): Promise<Prosod
 | 
				
			|||||||
    config.useC2S(c2sPort)
 | 
					    config.useC2S(c2sPort)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (enableComponents) {
 | 
				
			||||||
 | 
					    const componentsPort = (settings['prosody-components-port'] as string) || '53470'
 | 
				
			||||||
 | 
					    if (!/^\d+$/.test(componentsPort)) {
 | 
				
			||||||
 | 
					      throw new Error('Invalid external components port')
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const components = parseExternalComponents((settings['prosody-components-list'] as string) || '', prosodyDomain)
 | 
				
			||||||
 | 
					    for (const component of components) {
 | 
				
			||||||
 | 
					      valuesToHideInDiagnostic.set('Component ' + component.name + ' secret', component.secret)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    config.useExternalComponents(componentsPort, components)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const logExpiration = readLogExpiration(options, logExpirationSetting)
 | 
					  const logExpiration = readLogExpiration(options, logExpirationSetting)
 | 
				
			||||||
  config.useMam(logByDefault, logExpiration)
 | 
					  config.useMam(logByDefault, logExpiration)
 | 
				
			||||||
  // TODO: add a settings to choose?
 | 
					  // TODO: add a settings to choose?
 | 
				
			||||||
@ -238,9 +255,9 @@ function readLogExpiration (options: RegisterServerOptions, logExpiration: strin
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function getProsodyConfigContentForDiagnostic (config: ProsodyConfig, content?: string): string {
 | 
					function getProsodyConfigContentForDiagnostic (config: ProsodyConfig, content?: string): string {
 | 
				
			||||||
  let r: string = content ?? config.content
 | 
					  let r: string = content ?? config.content
 | 
				
			||||||
  for (const key in config.valuesToHideInDiagnostic) {
 | 
					  for (const [key, value] of config.valuesToHideInDiagnostic.entries()) {
 | 
				
			||||||
    // replaceAll not available, using trick:
 | 
					    // replaceAll not available, using trick:
 | 
				
			||||||
    r = r.split(config.valuesToHideInDiagnostic[key]).join(`***${key}***`)
 | 
					    r = r.split(value).join(`***${key}***`)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return r
 | 
					  return r
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										38
									
								
								server/lib/prosody/config/components.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								server/lib/prosody/config/components.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					interface ExternalComponent {
 | 
				
			||||||
 | 
					  name: string
 | 
				
			||||||
 | 
					  secret: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function parseExternalComponents (s: string, prosodyDomain: string): ExternalComponent[] {
 | 
				
			||||||
 | 
					  if (!s) {
 | 
				
			||||||
 | 
					    return []
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  let lines = s.split('\n')
 | 
				
			||||||
 | 
					  lines = lines.map(line => {
 | 
				
			||||||
 | 
					    return line.replace(/#.*$/, '')
 | 
				
			||||||
 | 
					      .replace(/^\s+/, '')
 | 
				
			||||||
 | 
					      .replace(/\s+$/, '')
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					  lines = lines.filter(line => line !== '')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const r: ExternalComponent[] = []
 | 
				
			||||||
 | 
					  for (const line of lines) {
 | 
				
			||||||
 | 
					    const matches = line.match(/^([\w.]+)\s*:\s*(\w+)$/)
 | 
				
			||||||
 | 
					    if (matches) {
 | 
				
			||||||
 | 
					      let name = matches[1]
 | 
				
			||||||
 | 
					      if (!name.includes('.')) {
 | 
				
			||||||
 | 
					        name = name + '.' + prosodyDomain
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      r.push({
 | 
				
			||||||
 | 
					        name,
 | 
				
			||||||
 | 
					        secret: matches[2]
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export {
 | 
				
			||||||
 | 
					  ExternalComponent,
 | 
				
			||||||
 | 
					  parseExternalComponents
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
import type { ProsodyFilePaths } from './paths'
 | 
					import type { ProsodyFilePaths } from './paths'
 | 
				
			||||||
 | 
					import type { ExternalComponent } from './components'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ConfigEntryValue = boolean | number | string | ConfigEntryValue[]
 | 
					type ConfigEntryValue = boolean | number | string | ConfigEntryValue[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -102,17 +103,20 @@ class ProsodyConfigVirtualHost extends ProsodyConfigBlock {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ProsodyConfigComponent extends ProsodyConfigBlock {
 | 
					class ProsodyConfigComponent extends ProsodyConfigBlock {
 | 
				
			||||||
  name: string
 | 
					  name: string
 | 
				
			||||||
  type: string
 | 
					  type?: string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor (type: string, name: string) {
 | 
					  constructor (name: string, type?: string) {
 | 
				
			||||||
    super('  ')
 | 
					    super('  ')
 | 
				
			||||||
    this.type = type
 | 
					    this.type = type
 | 
				
			||||||
    this.name = name
 | 
					    this.name = name
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  write (): string {
 | 
					  write (): string {
 | 
				
			||||||
 | 
					    if (this.type !== undefined) {
 | 
				
			||||||
      return `Component "${this.name}" "${this.type}"\n` + super.write()
 | 
					      return `Component "${this.name}" "${this.type}"\n` + super.write()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    return `Component "${this.name}"\n` + super.write()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ProsodyLogLevel = 'debug' | 'info' | 'warn' | 'error'
 | 
					type ProsodyLogLevel = 'debug' | 'info' | 'warn' | 'error'
 | 
				
			||||||
@ -123,6 +127,7 @@ class ProsodyConfigContent {
 | 
				
			|||||||
  authenticated?: ProsodyConfigVirtualHost
 | 
					  authenticated?: ProsodyConfigVirtualHost
 | 
				
			||||||
  anon: ProsodyConfigVirtualHost
 | 
					  anon: ProsodyConfigVirtualHost
 | 
				
			||||||
  muc: ProsodyConfigComponent
 | 
					  muc: ProsodyConfigComponent
 | 
				
			||||||
 | 
					  externalComponents: ProsodyConfigComponent[] = []
 | 
				
			||||||
  log: string
 | 
					  log: string
 | 
				
			||||||
  prosodyDomain: string
 | 
					  prosodyDomain: string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -132,7 +137,7 @@ class ProsodyConfigContent {
 | 
				
			|||||||
    this.log = ''
 | 
					    this.log = ''
 | 
				
			||||||
    this.prosodyDomain = prosodyDomain
 | 
					    this.prosodyDomain = prosodyDomain
 | 
				
			||||||
    this.anon = new ProsodyConfigVirtualHost('anon.' + prosodyDomain)
 | 
					    this.anon = new ProsodyConfigVirtualHost('anon.' + prosodyDomain)
 | 
				
			||||||
    this.muc = new ProsodyConfigComponent('muc', 'room.' + prosodyDomain)
 | 
					    this.muc = new ProsodyConfigComponent('room.' + prosodyDomain, 'muc')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.global.set('daemonize', false)
 | 
					    this.global.set('daemonize', false)
 | 
				
			||||||
    this.global.set('allow_registration', false)
 | 
					    this.global.set('allow_registration', false)
 | 
				
			||||||
@ -228,6 +233,17 @@ class ProsodyConfigContent {
 | 
				
			|||||||
    this.global.set('c2s_ports', [c2sPort])
 | 
					    this.global.set('c2s_ports', [c2sPort])
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useExternalComponents (componentsPort: string, components: ExternalComponent[]): void {
 | 
				
			||||||
 | 
					    this.global.set('component_ports', [componentsPort])
 | 
				
			||||||
 | 
					    this.global.set('component_interfaces', ['127.0.0.1', '::1'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const component of components) {
 | 
				
			||||||
 | 
					      const c = new ProsodyConfigComponent(component.name)
 | 
				
			||||||
 | 
					      c.set('component_secret', component.secret)
 | 
				
			||||||
 | 
					      this.externalComponents.push(c)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useMucHttpDefault (url: string): void {
 | 
					  useMucHttpDefault (url: string): void {
 | 
				
			||||||
    this.muc.add('modules_enabled', 'muc_http_defaults')
 | 
					    this.muc.add('modules_enabled', 'muc_http_defaults')
 | 
				
			||||||
    this.muc.add('muc_create_api_url', url)
 | 
					    this.muc.add('muc_create_api_url', url)
 | 
				
			||||||
@ -309,6 +325,11 @@ class ProsodyConfigContent {
 | 
				
			|||||||
    content += '\n\n'
 | 
					    content += '\n\n'
 | 
				
			||||||
    content += this.muc.write()
 | 
					    content += this.muc.write()
 | 
				
			||||||
    content += '\n\n'
 | 
					    content += '\n\n'
 | 
				
			||||||
 | 
					    for (const externalComponent of this.externalComponents) {
 | 
				
			||||||
 | 
					      content += '\n\n'
 | 
				
			||||||
 | 
					      content += externalComponent.write()
 | 
				
			||||||
 | 
					      content += '\n\n'
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return content
 | 
					    return content
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -380,7 +380,53 @@ This option alone only allows connections from localhost clients.`
 | 
				
			|||||||
`The port that will be used by the c2s module of the builtin Prosody server.<br>
 | 
					`The port that will be used by the c2s module of the builtin Prosody server.<br>
 | 
				
			||||||
XMPP clients shall use this port to connect.<br>
 | 
					XMPP clients shall use this port to connect.<br>
 | 
				
			||||||
Change it if this port is already in use on your server.<br>
 | 
					Change it if this port is already in use on your server.<br>
 | 
				
			||||||
Keep it close this port on your firewall for now, it will not be accessed from the outer world.`
 | 
					You can keep this port closed on your firewall for now, it will not be accessed from the outer world.`
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  registerSetting({
 | 
				
			||||||
 | 
					    name: 'prosody-components',
 | 
				
			||||||
 | 
					    label: 'Enable custom Prosody external components',
 | 
				
			||||||
 | 
					    type: 'input-checkbox',
 | 
				
			||||||
 | 
					    default: false,
 | 
				
			||||||
 | 
					    private: true,
 | 
				
			||||||
 | 
					    descriptionHTML:
 | 
				
			||||||
 | 
					`Enable the use of external XMPP components.<br>
 | 
				
			||||||
 | 
					This option alone only allows connections from localhost.<br>
 | 
				
			||||||
 | 
					This feature can for example be used to connect some bots to the chatting rooms.`
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  registerSetting({
 | 
				
			||||||
 | 
					    name: 'prosody-components-port',
 | 
				
			||||||
 | 
					    label: 'Prosody external components port',
 | 
				
			||||||
 | 
					    type: 'input',
 | 
				
			||||||
 | 
					    default: '53470',
 | 
				
			||||||
 | 
					    private: true,
 | 
				
			||||||
 | 
					    descriptionHTML:
 | 
				
			||||||
 | 
					`The port that will be used by XMPP components to connect to the Prosody server.<br>
 | 
				
			||||||
 | 
					Change it if this port is already in use on your server.<br>
 | 
				
			||||||
 | 
					You can keep this port closed on your firewall for now, it will not be accessed from the outer world.`
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  registerSetting({
 | 
				
			||||||
 | 
					    name: 'prosody-components-list',
 | 
				
			||||||
 | 
					    label: 'External components',
 | 
				
			||||||
 | 
					    type: 'input-textarea',
 | 
				
			||||||
 | 
					    default: '',
 | 
				
			||||||
 | 
					    private: true,
 | 
				
			||||||
 | 
					    descriptionHTML:
 | 
				
			||||||
 | 
					`The external components to create:
 | 
				
			||||||
 | 
					<ul>
 | 
				
			||||||
 | 
					  <li>One per line.</li>
 | 
				
			||||||
 | 
					  <li>Use the format «component_name:component_secret» (spaces will be trimmed)</li>
 | 
				
			||||||
 | 
					  <li>You can add comments: everything after the # character will be stripped off, and empty lines ignored</li>
 | 
				
			||||||
 | 
					  <li>The name can only contain alphanumeric characters and dots</li>
 | 
				
			||||||
 | 
					  <li>
 | 
				
			||||||
 | 
					    If the name contains only alphanumeric characters, it will be suffixed with the XMPP domain.
 | 
				
			||||||
 | 
					    For exemple «bridge» will become «bridge.your_domain.tld».
 | 
				
			||||||
 | 
					    You can also specify a full domain name, but you have to make sure to configure your DNS correctly.
 | 
				
			||||||
 | 
					  </li>
 | 
				
			||||||
 | 
					  <li>Only use alphanumeric characters in the secret passphrase (use at least 15 characters).</li>
 | 
				
			||||||
 | 
					</ul>`
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // ********** settings changes management
 | 
					  // ********** settings changes management
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user