Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e99a03048a | |||
| 62a618ed60 | |||
| d1317628d0 | |||
| 4895ca0d09 | |||
| ffa66977c3 | |||
| 1e0d1002d7 |
@@ -9,7 +9,7 @@ const {port} = require('./config')
|
||||
const app = require('express')()
|
||||
const helmet = require('helmet')
|
||||
const routes = require('./src/routes')
|
||||
const { errors } = require('celebrate')
|
||||
const {errors} = require('celebrate')
|
||||
const body_parser = require('body-parser')
|
||||
const {request_logger, error_logger} = require('./src/middlewares/logger')
|
||||
const {options, cors} = require('./src/middlewares/cors')
|
||||
|
||||
+1
-1
Submodule lib updated: b3fa29e4c5...2daac94e92
@@ -5,34 +5,34 @@ const {get_fastest_session_server, run_session} = require('../modules/session_se
|
||||
const create_session = async (req, res, next) => {
|
||||
const {title} = req.body
|
||||
|
||||
var free_servers = await database.get_free_session_servers(title)
|
||||
let free_servers = await database.get_free_session_servers(title)
|
||||
|
||||
if (!free_servers) {
|
||||
next(new not_found_error('no free session server or title not exists'))
|
||||
return
|
||||
}
|
||||
|
||||
var session_server = await get_fastest_session_server(free_servers)
|
||||
let session_server = await get_fastest_session_server(free_servers)
|
||||
|
||||
if (!session_server) {
|
||||
next(new not_found_error('all session servers are not available'))
|
||||
return
|
||||
}
|
||||
|
||||
var session_id = await database.generate_session_id()
|
||||
let session_id = await database.generate_session_id()
|
||||
if (!session_id) {
|
||||
next(new not_found_error('can not generate session id'))
|
||||
return
|
||||
}
|
||||
|
||||
var websocket_url = await run_session(session_server.url, session_id, title)
|
||||
let websocket_url = await run_session(session_server.url, session_id, title)
|
||||
|
||||
if (!websocket_url) {
|
||||
next(new not_found_error('can not run session'))
|
||||
return
|
||||
}
|
||||
|
||||
var add_active_session_result = await database.add_active_session(session_server.url, session_id, websocket_url)
|
||||
let add_active_session_result = await database.add_active_session(title, session_server.url, session_id, websocket_url)
|
||||
|
||||
if (!add_active_session_result) {
|
||||
next(new not_found_error('add_active_session error'))
|
||||
@@ -42,7 +42,7 @@ const create_session = async (req, res, next) => {
|
||||
}
|
||||
|
||||
const connect_session = async (req, res, next) => {
|
||||
var websocket_url = await database.get_session_websocket_url(req.query.session_id)
|
||||
let websocket_url = await database.get_session_websocket_url(req.query.session_id)
|
||||
if (!websocket_url) {
|
||||
next(new not_found_error('session not exists'))
|
||||
return
|
||||
|
||||
@@ -2,12 +2,42 @@ const server_error = require('../../lib/src/http/errors/server_error')
|
||||
const database = require('../database/database')
|
||||
|
||||
const session_closed = async (req, res, next) => {
|
||||
var remove_result = await database.remove_active_session(req.body.session_id)
|
||||
|
||||
const {
|
||||
session_id,
|
||||
title,
|
||||
max_uniq_users,
|
||||
users_at_close,
|
||||
time,
|
||||
unix_timestamp,
|
||||
time_end,
|
||||
unix_timestamp_end
|
||||
} = req.body
|
||||
|
||||
let active_session = await database.get_active_session(session_id)
|
||||
if (active_session) {
|
||||
await database.add_session_to_history(
|
||||
session_id,
|
||||
title,
|
||||
active_session.server_url,
|
||||
active_session.websocket_url,
|
||||
max_uniq_users,
|
||||
users_at_close,
|
||||
time,
|
||||
unix_timestamp,
|
||||
time_end,
|
||||
unix_timestamp_end
|
||||
)
|
||||
}
|
||||
|
||||
let remove_result = await database.remove_active_session(session_id)
|
||||
|
||||
if (!remove_result) {
|
||||
next(new server_error('remove session error'))
|
||||
return
|
||||
}
|
||||
res.json({message:"removed"})
|
||||
|
||||
res.json({message:"successfully removed"})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
const request = require('request')
|
||||
const database = require('../database/database.js')
|
||||
const not_found_error = require('../../lib/src/http/errors/not_found_error')
|
||||
const {ping_session_server} = require('../modules/session_server.js')
|
||||
|
||||
const max_response_timeout = 500
|
||||
|
||||
const validate_url = async (domain) => {
|
||||
let options = {
|
||||
url: domain,
|
||||
method: "GET",
|
||||
path: '/',
|
||||
timeout: max_response_timeout
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
request(options,
|
||||
async function(err, answer, data) {
|
||||
if (err || !answer.socket) {
|
||||
resolve(false)
|
||||
return
|
||||
} else if (answer.socket.authorized) {
|
||||
resolve(true)
|
||||
} else {
|
||||
resolve(false)
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const validate_all_urls = async (urls) => {
|
||||
return Promise.all(urls.map(async (url) => {
|
||||
const status = await validate_url(url)
|
||||
return {url:url, status:status}
|
||||
}))
|
||||
}
|
||||
|
||||
const ping_all_session_servers = async (urls) => {
|
||||
return Promise.all(urls.map(async (url) => {
|
||||
const status = await ping_session_server(url)
|
||||
return {url:url, status:status}
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
|
||||
const get_status = async (req, res, next) => {
|
||||
let statuses = await database.get_statuses()
|
||||
let urls = statuses[0].urls
|
||||
|
||||
let session_servers = await database.get_all_session_servers()
|
||||
|
||||
let session_servers_urls = []
|
||||
|
||||
session_servers.forEach(server => {
|
||||
session_servers_urls.push(server.url)
|
||||
})
|
||||
|
||||
urls = urls.concat(session_servers_urls)
|
||||
|
||||
// all ssl statuses
|
||||
let ssl_statuses = await validate_all_urls(urls)
|
||||
|
||||
let session_server_statuses = await ping_all_session_servers(session_servers_urls)
|
||||
|
||||
let errors = await database.get_errors()
|
||||
|
||||
let active_sessions = await database.get_all_active_sessions()
|
||||
if (active_sessions) {
|
||||
active_sessions.forEach(function(part, index) {
|
||||
this[index].websocket_url = ""
|
||||
this[index].session_id = ""
|
||||
}, active_sessions)
|
||||
}
|
||||
|
||||
let sessions_history = await database.get_all_session_history()
|
||||
if (sessions_history) {
|
||||
sessions_history.forEach(function(part, index) {
|
||||
this[index].websocket_url = ""
|
||||
this[index].session_id = ""
|
||||
}, sessions_history)
|
||||
}
|
||||
|
||||
res.json([{ssl_statuses:ssl_statuses}, {session_server_statuses:session_server_statuses}, {errors:errors}, {active_sessions:active_sessions}, {sessions_history:sessions_history}])
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
get_status
|
||||
}
|
||||
@@ -2,7 +2,7 @@ const database = require('../database/database.js')
|
||||
const not_found_error = require('../../lib/src/http/errors/not_found_error')
|
||||
|
||||
const get_titles = async (req, res, next) => {
|
||||
var titles = await database.get_titles(req.query.start, req.query.count)
|
||||
let titles = await database.get_titles(req.query.start, req.query.count)
|
||||
|
||||
if (!titles) {
|
||||
next(new not_found_error('titles not found'))
|
||||
@@ -13,7 +13,7 @@ const get_titles = async (req, res, next) => {
|
||||
}
|
||||
|
||||
const get_titles_for_language = async (req, res, next) => {
|
||||
var titles = await database.get_titles_for_language(req.query.start, req.query.count, req.query.language.toLowerCase())
|
||||
let titles = await database.get_titles_for_language(req.query.start, req.query.count, req.query.language.toLowerCase())
|
||||
|
||||
if (!titles) {
|
||||
next(new not_found_error('titles not found'))
|
||||
@@ -23,7 +23,20 @@ const get_titles_for_language = async (req, res, next) => {
|
||||
res.json(titles)
|
||||
}
|
||||
|
||||
const get_private_titles = async (req, res, next) => {
|
||||
const {key} = req.query
|
||||
let titles = await database.get_private_titles_with_key(key)
|
||||
|
||||
if (!titles) {
|
||||
next(new not_found_error('title not found'))
|
||||
return
|
||||
}
|
||||
|
||||
res.json(titles)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
get_titles,
|
||||
get_titles_for_language
|
||||
get_titles_for_language,
|
||||
get_private_titles
|
||||
}
|
||||
+162
-22
@@ -1,6 +1,7 @@
|
||||
const { MongoClient } = require("mongodb")
|
||||
const { database_url, database_name } = require('../../config')
|
||||
const crypto = require("crypto")
|
||||
const time = require('../../lib/src/time')
|
||||
let max_database_connection_timeout = 1000
|
||||
|
||||
const client = new MongoClient(database_url, {
|
||||
@@ -21,41 +22,50 @@ const get_db = async () => {
|
||||
}
|
||||
|
||||
const get_titles = async (start, count) => {
|
||||
var db = await get_db()
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
var titles = await db.collection('title').find().skip(parseInt(start)).limit(parseInt(count)).toArray()
|
||||
let titles = await db.collection('title').find().skip(parseInt(start)).limit(parseInt(count)).toArray()
|
||||
return (!titles.length) ? null : titles
|
||||
}
|
||||
|
||||
const get_titles_for_language = async (start, count, language) => {
|
||||
var db = await get_db()
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
var titles = await db.collection('title').find({language:language}).skip(parseInt(start)).limit(parseInt(count)).toArray()
|
||||
let titles = await db.collection('title').find({language:language}).skip(parseInt(start)).limit(parseInt(count)).toArray()
|
||||
return (!titles.length) ? null : titles
|
||||
}
|
||||
|
||||
const get_private_titles_with_key = async (key) => {
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
let titles = await db.collection('private_title').find({key:key}).toArray()
|
||||
return (!titles.length) ? null : titles
|
||||
}
|
||||
|
||||
const get_free_session_servers = async (title) => {
|
||||
var db = await get_db()
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
|
||||
var servers = await db.collection('session_server').find({title:title}).toArray()
|
||||
let servers = await db.collection('session_server').find({title:title}).toArray()
|
||||
|
||||
if (!servers.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
var active_session = db.collection('active_session')
|
||||
let active_session = db.collection('active_session')
|
||||
|
||||
var free_servers = []
|
||||
let free_servers = []
|
||||
|
||||
for (const server of servers) {
|
||||
var sessions = await active_session.find({server_url:server.url}).toArray()
|
||||
let sessions = await active_session.find({server_url:server.url}).toArray()
|
||||
if (server.limit > sessions.length) {
|
||||
free_servers.push(server)
|
||||
}
|
||||
@@ -63,33 +73,35 @@ const get_free_session_servers = async (title) => {
|
||||
return (free_servers.length) ? free_servers : null
|
||||
}
|
||||
|
||||
const add_active_session = async (server_url, session_id, websocket_url) => {
|
||||
var db = await get_db()
|
||||
const add_active_session = async (title, server_url, session_id, websocket_url) => {
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return false
|
||||
}
|
||||
|
||||
var active_session = db.collection('active_session')
|
||||
let active_session = db.collection('active_session')
|
||||
|
||||
await active_session.insertOne({
|
||||
title: title,
|
||||
server_url: server_url,
|
||||
session_id: session_id,
|
||||
websocket_url: websocket_url
|
||||
})
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
const generate_session_id = async () => {
|
||||
var db = await get_db()
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
|
||||
var active_session = db.collection('active_session')
|
||||
var session_id = {}
|
||||
let active_session = db.collection('active_session')
|
||||
let session_id = {}
|
||||
|
||||
var max_id_len = 6
|
||||
var sessions_with_id = 0
|
||||
let max_id_len = 6
|
||||
let sessions_with_id = 0
|
||||
while(true) {
|
||||
session_id = crypto.randomBytes(max_id_len/2).toString('hex').toUpperCase()
|
||||
sessions_with_id = await active_session.find({session_id:session_id}).toArray().length
|
||||
@@ -99,8 +111,18 @@ const generate_session_id = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const get_active_session = async (session_id) => {
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
|
||||
let active_session = await db.collection('active_session').findOne({session_id:session_id})
|
||||
return active_session
|
||||
}
|
||||
|
||||
const remove_active_session = async (session_id) => {
|
||||
var db = await get_db()
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return false
|
||||
}
|
||||
@@ -110,24 +132,142 @@ const remove_active_session = async (session_id) => {
|
||||
}
|
||||
|
||||
const get_session_websocket_url = async (session_id) => {
|
||||
var db = await get_db()
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
var active_session = db.collection('active_session')
|
||||
var session = await active_session.findOne({session_id:session_id})
|
||||
let active_session = db.collection('active_session')
|
||||
let session = await active_session.findOne({session_id:session_id})
|
||||
if (!session) {
|
||||
return null
|
||||
}
|
||||
return session.websocket_url
|
||||
}
|
||||
|
||||
const get_statuses = async () => {
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
let statuses = await db.collection('status').find().toArray()
|
||||
return (!statuses.length) ? null : statuses
|
||||
}
|
||||
|
||||
const get_all_session_servers = async () => {
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
|
||||
let servers = await db.collection('session_server').find().toArray()
|
||||
|
||||
if (!servers.length) {
|
||||
return null
|
||||
}
|
||||
return servers
|
||||
}
|
||||
|
||||
const add_error = async (error_message) => {
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return false
|
||||
}
|
||||
|
||||
let error_collection = db.collection('error_history')
|
||||
|
||||
await error_collection.insertOne({error_message:error_message, time: time.get_date_time(), unix_timestamp: time.get_unix_timestamp()})
|
||||
return true
|
||||
}
|
||||
|
||||
const get_errors = async () => {
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
let errors = await db.collection('error_history').find().toArray()
|
||||
return (!errors.length) ? null : errors
|
||||
}
|
||||
|
||||
const get_all_active_sessions = async () => {
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
|
||||
let active_sessions = await db.collection('active_session').find().toArray()
|
||||
|
||||
if (!active_sessions.length) {
|
||||
return null
|
||||
}
|
||||
return active_sessions
|
||||
}
|
||||
|
||||
const add_session_to_history = async (session_id,
|
||||
title,
|
||||
server_url,
|
||||
websocket_url,
|
||||
max_uniq_users,
|
||||
users_at_close,
|
||||
time_start,
|
||||
unix_timestamp_start,
|
||||
time_end,
|
||||
unix_timestamp_end
|
||||
) => {
|
||||
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return false
|
||||
}
|
||||
|
||||
let session_history = db.collection('session_history')
|
||||
|
||||
let duration_in_seconds = unix_timestamp_end - unix_timestamp_start
|
||||
await session_history.insertOne({
|
||||
session_id: session_id,
|
||||
title: title,
|
||||
server_url: server_url,
|
||||
websocket_url: websocket_url,
|
||||
max_uniq_users: max_uniq_users,
|
||||
users_at_close: users_at_close,
|
||||
time_start: time_start,
|
||||
unix_timestamp_start: unix_timestamp_start,
|
||||
time_end: time_end,
|
||||
unix_timestamp_end: unix_timestamp_end,
|
||||
duration_in_seconds: duration_in_seconds,
|
||||
duration_in_minutes: duration_in_seconds / 60
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
const get_all_session_history = async () => {
|
||||
let db = await get_db()
|
||||
if (!db) {
|
||||
return null
|
||||
}
|
||||
|
||||
let session_history = await db.collection('session_history').find().toArray()
|
||||
|
||||
if (!session_history.length) {
|
||||
return null
|
||||
}
|
||||
return session_history
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
get_titles,
|
||||
get_free_session_servers,
|
||||
add_active_session,
|
||||
generate_session_id,
|
||||
remove_active_session,
|
||||
get_active_session,
|
||||
get_session_websocket_url,
|
||||
get_titles_for_language
|
||||
get_titles_for_language,
|
||||
get_private_titles_with_key,
|
||||
get_statuses,
|
||||
get_all_session_servers,
|
||||
add_error,
|
||||
get_errors,
|
||||
get_all_active_sessions,
|
||||
add_session_to_history,
|
||||
get_all_session_history
|
||||
}
|
||||
@@ -7,12 +7,13 @@ const options = (req, res) => {
|
||||
}
|
||||
|
||||
const cors = (req, res, next) => {
|
||||
const {origin} = req.headers
|
||||
if (allowed_cors.includes(origin)) {
|
||||
res.setHeader('Access-Control-Allow-Origin', origin)
|
||||
}
|
||||
// const {origin} = req.headers
|
||||
// if (allowed_cors.includes(origin)) {
|
||||
// res.setHeader('Access-Control-Allow-Origin', origin)
|
||||
// }
|
||||
res.setHeader('Access-Control-Allow-Credentials', true)
|
||||
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type')
|
||||
res.setHeader("Access-Control-Allow-Origin", "*")
|
||||
next()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
const server_error = require('../../lib/src/http/errors/server_error')
|
||||
const database = require('../database/database')
|
||||
|
||||
const error_handler = (err, req, res, next) => {
|
||||
if (!err.status_code) {
|
||||
err = new server_error(err.message)
|
||||
}
|
||||
res.status(err.status_code).json({message:err.message})
|
||||
|
||||
database.add_error(err.message)
|
||||
next(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ const {log_path} = require('../../config')
|
||||
const logger_runtime = new _logger(log_path)
|
||||
|
||||
const request_logger = (req, res, next) => {
|
||||
var {url} = req
|
||||
let {url} = req
|
||||
logger_runtime.log(url)
|
||||
next()
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
var request = require('request')
|
||||
let request = require('request')
|
||||
const max_response_timeout = 2000
|
||||
const max_run_session_timeout = 20000
|
||||
|
||||
|
||||
const ping_session_server = async (url) => {
|
||||
|
||||
var options = {
|
||||
let options = {
|
||||
url: url + '/ping',
|
||||
method: "GET",
|
||||
timeout: max_response_timeout
|
||||
@@ -25,7 +25,7 @@ const ping_session_server = async (url) => {
|
||||
}
|
||||
|
||||
const get_fastest_session_server = async (free_servers) => {
|
||||
var fastest_server = null
|
||||
let fastest_server = null
|
||||
|
||||
Promise.all(free_servers.map(async (server) => {
|
||||
const is_working = await ping_session_server(server.url)
|
||||
@@ -36,8 +36,8 @@ const get_fastest_session_server = async (free_servers) => {
|
||||
}
|
||||
}))
|
||||
|
||||
var timeout_count = 0
|
||||
var check_times = 100
|
||||
let timeout_count = 0
|
||||
let check_times = 100
|
||||
|
||||
while (true) {
|
||||
++timeout_count
|
||||
@@ -53,7 +53,7 @@ const get_fastest_session_server = async (free_servers) => {
|
||||
}
|
||||
|
||||
const run_session = async (server_url, session_id, title) => {
|
||||
var options = {
|
||||
let options = {
|
||||
url: server_url + '/session/run',
|
||||
method: "POST",
|
||||
timeout: max_run_session_timeout,
|
||||
@@ -79,7 +79,29 @@ const run_session = async (server_url, session_id, title) => {
|
||||
})
|
||||
}
|
||||
|
||||
const get_overal_status = async (url) => {
|
||||
|
||||
let options = {
|
||||
url: url + '/get_overal_status',
|
||||
method: "GET",
|
||||
timeout: max_response_timeout
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
request(options,
|
||||
async function(err, answer, data) {
|
||||
if (err || answer.statusCode != 200) {
|
||||
resolve(false)
|
||||
} else {
|
||||
resolve(true)
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
get_fastest_session_server,
|
||||
run_session
|
||||
run_session,
|
||||
ping_session_server
|
||||
}
|
||||
@@ -2,9 +2,11 @@ const router = require('express').Router()
|
||||
const router_title = require('./title')
|
||||
const router_session = require('./session')
|
||||
const router_session_server = require('./session_server')
|
||||
const router_status = require('./status')
|
||||
|
||||
router.use('/title', router_title)
|
||||
router.use('/session', router_session)
|
||||
router.use('/session_server', router_session_server)
|
||||
router.use('/status', router_status)
|
||||
|
||||
module.exports = router
|
||||
@@ -4,7 +4,14 @@ const { celebrate, Joi, Segments} = require('celebrate')
|
||||
|
||||
router.post('/session_closed', celebrate({
|
||||
[Segments.BODY]: Joi.object().keys({
|
||||
session_id: Joi.string().required()
|
||||
session_id: Joi.string().required(),
|
||||
title: Joi.string().required(),
|
||||
max_uniq_users: Joi.number().required(),
|
||||
users_at_close: Joi.number().required(),
|
||||
time: Joi.string().required(),
|
||||
unix_timestamp: Joi.number().required(),
|
||||
time_end: Joi.string().required(),
|
||||
unix_timestamp_end: Joi.number().required()
|
||||
})
|
||||
}), session_closed)
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
const router = require('express').Router()
|
||||
const {get_status} = require('../controllers/status')
|
||||
|
||||
router.get('/', get_status)
|
||||
|
||||
module.exports = router
|
||||
+7
-1
@@ -1,6 +1,6 @@
|
||||
const router = require('express').Router()
|
||||
const { celebrate, Joi, Segments} = require('celebrate')
|
||||
const {get_titles, get_titles_for_language} = require('../controllers/title')
|
||||
const {get_titles, get_titles_for_language, get_private_titles} = require('../controllers/title')
|
||||
|
||||
router.get('/get', celebrate({
|
||||
[Segments.QUERY]: Joi.object().keys({
|
||||
@@ -17,4 +17,10 @@ router.get('/get_for_language', celebrate({
|
||||
})
|
||||
}), get_titles_for_language)
|
||||
|
||||
router.get('/get_private', celebrate({
|
||||
[Segments.QUERY]: Joi.object().keys({
|
||||
key: Joi.string().required()
|
||||
})
|
||||
}), get_private_titles)
|
||||
|
||||
module.exports = router
|
||||
Reference in New Issue
Block a user