All files / centro/lib server_config.js

100% Statements 8/8
100% Branches 0/0
100% Functions 2/2
100% Lines 8/8

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251      1x 1x   1x   885x                                                                                           1x   885x   885x                                                                                                                                                                                                                                                                                                                                                                                           1x    
/*eslint-env node */
"use strict";
 
var authorize_jwt = require('authorize-jwt'),
    { get_topic_pattern } = require('./pattern');
 
exports.config_with_defaults = function (config)
{
    return Object.assign(
    {
        authorize: authorize_jwt,                  // centro server
        privileged: false,                         // centro server
        transport: [],                             // centro server
        realm: 'centro',                           // centro server
        auth_method: 'Bearer',                     // centro server
        max_issuer_length: 128,                    // centro server
        max_allow_publish_topics: 1000,            // centro server
        max_disallow_publish_topics: 1000,         // centro server
        max_allow_subscribe_topics: 1000,          // centro server
        max_disallow_subscribe_topics: 1000,       // centro server
        max_block_topics: 1000,                    // centro server
        max_subscribe_topics: 1000,                // centro server
        max_presence_data_length: 1 * 1024 * 1024, // centro server
        max_tokens: 10,                            // centro server
        max_token_length: 1 * 1024 * 1024,         // centro server
        max_topic_length: 4 * 1024,                // centro server,
                                                   // mqlobber-access-control
 
        max_publish_data_length: 16 * 1024 * 1024, // mqlobber-access-control
        max_subscriptions: 1000,                   // mqlobber-access-control
        max_publications: 10,                      // mqlobber-access-control
 
        db_type: 'pouchdb',                        // authorize-jwt
 
        send_expires: true,                        // mqlobber
        send_size: true,                           // mqlobber
        defer_to_final_handler: true,              // mqlobber
 
        max_open: 1000,                            // bpmux
        max_header_size: 1 * 1024 * 1024,          // bpmux
 
        maxSize: 1 * 1024 * 1024,                  // frame-stream
 
        multi_ttl: 5 * 60 * 1000,                  // qlobber-fsq
        single_ttl: 5 * 60 * 1000,                 // qlobber-fsq
 
        separator: '.',                            // qlobber
        wildcard_one: '*',                         // qlobber
        wildcard_some: '#',                        // qlobber
        max_words: 100,                            // qlobber
        max_wildcard_somes: 3                      // qlobber
    }, config);
};
 
exports.authz_token_schema = function (config, required)
{
    const topic_pattern = get_topic_pattern(config);
 
	return {
        title: 'Centro authorization token schema',
		description: 'Schema for authorization tokens sent by clients to a Centro server',
        '$schema': 'http://json-schema.org/draft-07/schema#',
        '$id': 'https://davedoesdev.com/schemas/centro.json',
		type: 'object',
		required: required,
		properties: {
			exp: {
				description: 'Token expiry time (in seconds since 1970-01-01)',
				type: 'integer'
			},
			iss: {
				description: 'Token issuer',
				type: 'string',
				maxLength: config.max_issuer_length
			},
			access_control: {
				description: 'Which topics clients presenting this token can subscribe and publish to. See <a href="https://github.com/davedoesdev/mqlobber-access-control">mqlobber-access-control</a>.',
				type: 'object',
				required: ['publish', 'subscribe'],
				additionalProperties: false,
				properties: {
					publish: {
						description: 'Allowed and disallowed topics for publish requests',
						type: 'object',
						required: ['allow', 'disallow'],
						additionalProperties: false,
						properties: {
							allow: {
								description: 'Clients can publish messages to these topics',
								type: 'array',
								maxItems: config.max_allow_publish_topics,
								items: {
									description: 'Topic',
									type: 'string',
									pattern: topic_pattern
								}
							},
							disallow: {
								description: 'Clients cannot publish messages to these topics',
								type: 'array',
								maxItems: config.max_disallow_publish_topics,
								items: {
									description: 'Topic',
									type: 'string',
									pattern: topic_pattern
								}
							},
                            disallow_single: {
                                description: 'If true then clients cannot publish messages to a single subscriber',
                                type: 'boolean'
                            },
                            disallow_multi: {
                                description: 'If true then clients cannot publish messages to multiple subscribers',
                                type: 'boolean'
                            }
						}
					},
					subscribe: {
						description: 'Allowed and disallowed topics for subscribe requests',
						type: 'object',
						required: ['allow', 'disallow'],
						additionalProperties: false,
						properties: {
							allow: {
								description: 'Clients can subscribe to messages published to these topics',
								type: 'array',
								maxItems: config.max_allow_subscribe_topics,
								items: {
									description: 'Topic',
									type: 'string',
									pattern: topic_pattern
								}
							},
							disallow: {
								description: 'Clients cannot subscribe to messages published to these topics',
								type: 'array',
								maxItems: config.max_disallow_subscribe_topics,
								items: {
									description: 'Topic',
									type: 'string',
									pattern: topic_pattern
								}
							}
						}
					},
					block: {
						description: "Clients cannot receive messages published to these topics. This is useful is subscribe.allow is a superset of subscribe.disallow but you don't want messages matching (a subset of) subscribe.disallow sent to clients",
						type: 'array',
						maxItems: config.max_block_topics,
						items: {
							description: 'Topic',
							type: 'string',
							pattern: topic_pattern
						}
					}
				}
			},
			subscribe: {
				description: 'Clients presenting this token are pre-subscribed to these topics',
				type: 'object',
				maxProperties: config.max_subscribe_topics,
				additionalProperties: false,
				patternProperties: {
                    [topic_pattern]: {
                        description: 'If true then presenting clients will be sent any existing, unexpired messages that match the topic, as well as new ones',
                        type: 'boolean'
                    }
                }
			},
			ack: {
				description: 'Publish an acknowledgement message when a client presenting this token acknowledges receipt of a message. See <a href="https://github.com/davedoesdev/mqlobber#mqlobberservereventsackinfo">mqlobber</a>.',
				type: 'object',
				required: ['prefix'],
				additionalProperties: false,
				properties: {
					prefix: {
						description: "The acknowledgement message's topic will be the original message's topic appended to this prefix. The body will be empty",
						type: 'string',
						pattern: topic_pattern
					}
				}
			},
			presence: {
				description: 'Publish a presence message when a client presenting this token connects or disconnects',
				type: 'object',
				required: ['connect', 'disconnect'],
				additionalProperties: false,
				properties: {
					connect: {
						description: 'Describes the message to publish when a client connects',
						type: 'object',
						required: ['topic'],
						additionalProperties: false,
						properties: {
							topic: {
								description: 'Message topic',
								type: 'string',
								pattern: topic_pattern
							},
							single: {
								description: 'Whether the message will be given to at most one interested client',
								type: 'boolean'
							},
							ttl: {
								description: 'Time-to-live (in seconds) for the message',
								type: 'integer',
								minimum: 0
							},
							data: {
								description: 'Message body',
								type: 'string',
								maxLength: config.max_presence_data_length
							}
						}
					},
					disconnect: {
						description: 'Describes the message to publish when a client disconnects',
						type: 'object',
						required: ['topic'],
						additionalProperties: false,
						properties: {
							topic: {
								description: 'Message topic',
								type: 'string',
								pattern: topic_pattern
							},
							single: {
								description: 'Whether the message will be given to at most one interested client',
								type: 'boolean'
							},
							ttl: {
								description: 'Time-to-live (in seconds) for the message',
								type: 'integer',
								minimum: 0
							},
							data: {
								description: 'Message body',
								type: 'string',
								maxLength: config.max_presence_data_length
							}
						}
					}
				}
			}
		}
    };
};
 
exports.default_authz_token_schema =
    exports.authz_token_schema(exports.config_with_defaults());