diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e304045 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.words": [ + "resourcejs" + ] +} \ No newline at end of file diff --git a/src/arango.js b/src/arango.js index efccc4d..dafa8b6 100644 --- a/src/arango.js +++ b/src/arango.js @@ -1,68 +1,69 @@ -import { Database, aql } from 'arangojs' -import { log, warn, error, Verbose } from './services.js' -import conf, { revealConf } from './conf.js' +import { Database, aql } from "arangojs"; +import { log, error, Verbose } from "./services.js"; +import conf from "./conf.js"; -const verbose = Verbose('sd:arango'); verbose('') +const verbose = Verbose("sd:arango"); +verbose(""); -async function startArango () { - verbose('startArango') - try { - const dbInit = new Database(conf.arangodb.url) - await dbInit.createDatabase(conf.arangodb.database) - log('Database created:', conf.arangodb.database) - } catch (err) { - error('arango create db err:', err.message) - } +async function startArango() { + verbose("startArango"); + try { + const dbInit = new Database(conf.arangodb.url); + await dbInit.createDatabase(conf.arangodb.database); + log("Database created:", conf.arangodb.database); + } catch (err) { + error("arango create db err:", err.message); + } - let db = null - try { - db = new Database({ - url: conf.arangodb.url, - databaseName: conf.arangodb.database, - auth: { - username: conf.arangodb.auth.username, - password: conf.arangodb.auth.password, - }, - }) - log('Connected to Database') - } catch (err) { - error('arango connect to db err:', err.message) - } + let db = null; + try { + db = new Database({ + url: conf.arangodb.url, + databaseName: conf.arangodb.database, + auth: { + username: conf.arangodb.auth.username, + password: conf.arangodb.auth.password, + }, + }); + log("Connected to Database"); + } catch (err) { + error("arango connect to db err:", err.message); + } - const Pokemons = db.collection("my-pokemons") - try { - await Pokemons.create() - log('Collection created') - } catch (err) { - error('arango create collection err:', err.message) - } + const Pokemons = db.collection("my-pokemons"); + try { + await Pokemons.create(); + log("Collection created"); + } catch (err) { + error("arango create collection err:", err.message); + } - try { - const doc = { - type: 'fire', - a: 'foo', - b: 'bar', - c: Date() - } + try { + const doc = { + type: "fire", + a: "foo", + b: "bar", + c: Date(), + }; - let meta = await Pokemons.save(doc) - verbose('Arango document saved:', meta._rev) + const meta = await Pokemons.save(doc); + verbose("Arango document saved:", meta._rev); - const pokemons = await db.query(aql` + const pokemons = await db.query(aql` FOR pokemon IN ${Pokemons} FILTER pokemon.type == "fire" RETURN pokemon - `) - const allPokemons = await pokemons.all() - verbose("allPokemans:", allPokemons) - // for (let pokemon of allPokemons) { - // verbose('pokemon:', pokemon) - // } - } catch (err) { - error('arango main err:', err.message) - } + `); + const allPokemons = await pokemons.all(); + verbose("allPokemans:", allPokemons); + // for (let pokemon of allPokemons) { + // verbose('pokemon:', pokemon) + // } + } catch (err) { + error("arango main err:", err.message); + } } if (conf.arangodb.enable) { - startArango() + startArango(); } diff --git a/src/index.js b/src/index.js index a2b2103..fe9f480 100644 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,10 @@ -import https from 'https' -import http from 'http' -import { resolve } from 'path' -import { inspect } from 'util' -import { EventEmitter } from 'events' -import { readFileSync } from 'fs' +import https from 'node:https' +import http from 'node:http' +import { inspect } from 'node:util' +import { EventEmitter } from 'node:events' +import { readFileSync } from 'node:fs' import express from 'express' -import passport from 'passport' import morgan from 'morgan' import responseTime from 'response-time' import cookieParser from 'cookie-parser' diff --git a/src/mailer.js b/src/mailer.js index 383d081..df38f64 100644 --- a/src/mailer.js +++ b/src/mailer.js @@ -1,5 +1,5 @@ import { createTransport } from 'nodemailer' -import { log, Verbose } from './services.js' +import { Verbose } from './services.js' import conf from './conf.js' const verbose = Verbose('sd:mailer'); verbose('') diff --git a/src/middleware/session.js b/src/middleware/session.js index b84dd8a..2f73e8d 100644 --- a/src/middleware/session.js +++ b/src/middleware/session.js @@ -1,9 +1,8 @@ import session from 'express-session' import MongoStore from 'connect-mongo' -import mongoose from 'mongoose' import conf from '../conf.js' -import db, { mongoOptions } from '../mongo.js' +import { mongoOptions } from '../mongo.js' export const sessionStore = MongoStore.create({ mongoUrl: conf.db.url, diff --git a/src/models/user.js b/src/models/user.js index 3bf653a..5020760 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -6,7 +6,7 @@ import { error, Verbose } from '../services.js' const verbose = Verbose('sd:models/user'); verbose('') -const { Mixed } = mongoose.Schema.Types +// const { Mixed } = mongoose.Schema.Types const schema = mongoose.Schema({ email: { type: String, unique: true, required: true }, @@ -38,8 +38,7 @@ schema.methods.isAdmin = () => schema.static.getByEmail = async ({ email }) => { try { - const user = await db.collection('users').findOne({ email }) - return user + return await db.collection('users').findOne({ email }) } catch (err) { error('User.getByEmail error:', err) throw new Error(err) diff --git a/src/rest-api.js b/src/rest-api.js index 5e1ed6f..2529753 100644 --- a/src/rest-api.js +++ b/src/rest-api.js @@ -1,5 +1,4 @@ import crypto from 'crypto' -import { join } from 'path' import resourceJS from 'resourcejs' import lodash from 'lodash' const { isArray } = lodash diff --git a/src/routes/ask.js b/src/routes/ask.js index e2b84c3..bf9ff38 100644 --- a/src/routes/ask.js +++ b/src/routes/ask.js @@ -4,19 +4,14 @@ import { checkAuth, checkAPIAuth } from '../middleware/check-auth.js' import Dialog from '../models/dialog.js' import { Verbose } from '../services.js' import conf from '../conf.js' -// import util from 'util' -// import { exec } from 'child_process' const verbose = Verbose('sd:routes/ask'); verbose('') const router = Router() -const ask = async (req, res, next) => { - // verbose('ask req.headers:', req.headers) - // verbose('ask req.user:', req.user) +const ask = async (req, res) => { try { const { prompt } = req.body let reply = '' - // verbose('prompt:', prompt) if (conf.agency.enable) { const response = await axios.post(`${conf.agency.url}/chat`, { prompt diff --git a/src/routes/available.js b/src/routes/available.js index 9d3811c..faae5ac 100644 --- a/src/routes/available.js +++ b/src/routes/available.js @@ -1,16 +1,11 @@ import { Router } from 'express' -import axios from 'axios' import { Verbose } from '../services.js' -import conf from '../conf.js' const verbose = Verbose('sd:routes/available'); verbose('') const app = Router() -app.get('/', async (req, res, next) => { +app.get('/', async (req, res) => { try { - // const response = await axios.get(`${conf.snake.url}/available`) - // // verbose('response.data:', response.data) - // return res.json(response.data) return res.json({ result: 'ok', name: "selfdev-api v1", diff --git a/src/routes/forgot.js b/src/routes/forgot.js index c561a91..9af8fde 100644 --- a/src/routes/forgot.js +++ b/src/routes/forgot.js @@ -1,11 +1,8 @@ import { Router } from 'express' -import lodash from 'lodash' -const { isEmpty } = lodash import { randomBytes } from 'crypto' import { log, Verbose } from '../services.js' import User from '../models/user.js' -import { validateEmail } from '../utils/validation.js' import conf from '../conf.js' import { transporter } from '../mailer.js' @@ -13,7 +10,7 @@ const verbose = Verbose('sd:routes/forgot'); verbose('') const router = Router() const app = router -app.post('/', async (req, res, next) => { +app.post('/', async (req, res) => { // verbose('forgot req.body:', req.body) const { email } = req.body let token = null @@ -48,7 +45,7 @@ Hi, We just received a requested to reset your password on Self-developing AI. Please, click the link below to reset password: -${conf.webApp.origin + '/reset?token=' + token} +${conf.webApp.origin}/reset?token=${token} This link will expire within ${conf.reset.expiresMinutes} minutes. diff --git a/src/routes/interest.js b/src/routes/interest.js index a152193..fe248a4 100644 --- a/src/routes/interest.js +++ b/src/routes/interest.js @@ -1,13 +1,7 @@ import { Router } from 'express' -import lodash from 'lodash' -const { isEmpty } = lodash -import { log, warn, Verbose } from '../services.js' -import { validateEmail, validatePhone, validatePassword } from '../utils/validation.js' -import { transporter } from '../mailer.js' -import conf from '../conf.js' import Landing from '../models/landing.js' import Interest from '../models/interest.js' -import { checkAuth, checkAPIAuth } from '../middleware/check-auth.js' +import { checkAPIAuth } from '../middleware/check-auth.js' const verbose = Verbose('sd:routes/land'); verbose('') const router = Router() diff --git a/src/routes/land.js b/src/routes/land.js index 2223f80..6473f01 100644 --- a/src/routes/land.js +++ b/src/routes/land.js @@ -1,17 +1,12 @@ import { Router } from 'express' -import lodash from 'lodash' -const { isEmpty } = lodash -import { log, warn, Verbose } from '../services.js' -import { validateEmail, validatePhone, validatePassword } from '../utils/validation.js' -import { transporter } from '../mailer.js' -import conf from '../conf.js' +import { Verbose } from '../services.js' import Landing from '../models/landing.js' -import { checkAuth, checkAPIAuth } from '../middleware/check-auth.js' +import { checkAPIAuth } from '../middleware/check-auth.js' const verbose = Verbose('sd:routes/land'); verbose('') const router = Router() -const land = async (req, res, next) => { +const land = async (req, res) => { // verbose('Land req.body:', req.body) try { const { body, title, favicon, interestForm } = req.body diff --git a/src/routes/login.js b/src/routes/login.js index e222ff7..2050100 100644 --- a/src/routes/login.js +++ b/src/routes/login.js @@ -20,7 +20,7 @@ const rememberMe = (req, res, next) => { } router.post('/', rememberMe, (req, res, next) => { - passport.authenticate('local', (err, user, info) => { + passport.authenticate('local', (err, user, _info) => { if (err) { return next(err) } diff --git a/src/routes/mail.js b/src/routes/mail.js index 05031f3..a0d5147 100644 --- a/src/routes/mail.js +++ b/src/routes/mail.js @@ -1,8 +1,6 @@ import { Router } from 'express' -import lodash from 'lodash' -const { isEmpty } = lodash import { log, warn, Verbose } from '../services.js' -import { validateEmail, validatePhone, validatePassword } from '../utils/validation.js' +import { validateEmail } from '../utils/validation.js' import { transporter } from '../mailer.js' import conf from '../conf.js' import Mailed from '../models/mailed.js' @@ -11,25 +9,29 @@ import { checkAuth, checkAPIAuth } from '../middleware/check-auth.js' const verbose = Verbose('sd:routes/mail'); verbose('') const router = Router() -const mail = async (req, res, next) => { +const mail = async (req, res) => { verbose('Mail req.body:', req.body) try { const { to, from, subject, text } = req.body - if (!to) { - to = user.email - warn('The field "to" is omitted, substitute with default:', to) + let newTo = to + let newFrom = from + + if (!newTo) { + newTo = user.email + warn('The field "to" is omitted, substitute with default:', newTo) } - if (!from) { - from = conf.smtp.from - warn('The field "from" is omitted, substitute with default:', from) + + if (!newFrom) { + newFrom = conf.smtp.from + warn('The field "from" is omitted, substitute with default:', newFrom) } let validationError = '' - if (to && !validateEmail(to)) { + if (newTo && !validateEmail(newTo)) { validationError += 'Invalid email to address. ' } - if (from && !validateEmail(from)) { + if (newFrom && !validateEmail(newFrom)) { validationError += 'Invalid email from address. ' } @@ -40,16 +42,16 @@ const mail = async (req, res, next) => { }) } - log('Sending a mail to:', to, ', from:', from) + log('Sending a mail to:', newTo, ', from:', newFrom) const mail = await transporter.sendMail({ - from, - to, + from: newFrom, + to: newTo, subject, text, }) log('Mail sent:', mail) - const mailed = new Mailed({ userId: req.user._id, from, to, subject, text }) + const mailed = new Mailed({ userId: req.user._id, from: newFrom, to: newTo, subject, text }) await mailed.save() res.json({ result: 'ok', diff --git a/src/routes/reset.js b/src/routes/reset.js index cf5d903..4f687ed 100644 --- a/src/routes/reset.js +++ b/src/routes/reset.js @@ -1,19 +1,14 @@ import { Router } from 'express' -import lodash from 'lodash' -const { isEmpty } = lodash -import { randomBytes } from 'crypto' import { log, warn, error, Verbose } from '../services.js' import User from '../models/user.js' -import { validateEmail } from '../utils/validation.js' import conf from '../conf.js' -import { transporter } from '../mailer.js' const verbose = Verbose('sd:routes/reset'); verbose('') const router = Router() const app = router -app.post('/', async (req, res, next) => { +app.post('/', async (req, res) => { // verbose('reset req.body:', req.body) const { token, password } = req.body diff --git a/src/routes/run.js b/src/routes/run.js index 1c75743..0661e7e 100644 --- a/src/routes/run.js +++ b/src/routes/run.js @@ -8,7 +8,7 @@ import conf from '../conf.js' const verbose = Verbose('sd:routes/run'); verbose('') const app = Router() -const run = async (req, res, next) => { +const run = async (req, res) => { // verbose('run req.headers:', req.headers) // verbose('run req.user:', req.user) try { diff --git a/src/routes/signup.js b/src/routes/signup.js index 1816571..cfd5461 100644 --- a/src/routes/signup.js +++ b/src/routes/signup.js @@ -11,7 +11,7 @@ const verbose = Verbose('sd:routes/signup'); verbose('') const router = Router() const app = router -app.post('/', async (req, res, next) => { +app.post('/', async (req, res) => { // verbose('signup req.body:', req.body) const { email, password, firstName, lastName, phone } = req.body diff --git a/src/routes/subscriptions.js b/src/routes/subscriptions.js index 77b1965..527015b 100644 --- a/src/routes/subscriptions.js +++ b/src/routes/subscriptions.js @@ -1,7 +1,7 @@ import { Router, raw } from 'express' import Stripe from 'stripe' import conf from '../conf.js' -import { checkAuth, checkAPIAuth } from '../middleware/check-auth.js' +import { checkAuth } from '../middleware/check-auth.js' import { Verbose } from '../services.js' import Subscription from '../models/subscription.js' @@ -150,7 +150,7 @@ app.post('/webhook', raw({ type: 'application/json' }), (request, response) => { conf.stripe.endpointSecret ) } catch (err) { - console.log(`⚠️ Webhook signature verification failed.`, err.message) + console.log("⚠️ Webhook signature verification failed.", err.message) return response.sendStatus(400) } } diff --git a/src/routes/xmpp.js b/src/routes/xmpp.js index 2101e12..797200a 100644 --- a/src/routes/xmpp.js +++ b/src/routes/xmpp.js @@ -1,22 +1,22 @@ import { Router } from 'express' import axios from 'axios' import { v4 as uuidv4 } from 'uuid' -import { checkAuth, checkAPIAuth } from '../middleware/check-auth.js' +import { checkAuth } from '../middleware/check-auth.js' import { Verbose } from '../services.js' import conf from '../conf.js' const verbose = Verbose('sd:routes/xmpp'); verbose('') const router = Router() -const credentials = async (req, res, next) => { +async function credentials(req, res) { try { let user = null let password = null if (req.user?.xmpp?.user && req.user?.xmpp?.password) { - user = req.user.xmpp.user; - password = req.user.xmpp.password; - verbose('Using existing XMPP credentials> user:', user, ', password:', password); + user = req.user.xmpp.user + password = req.user.xmpp.password + verbose('Using existing XMPP credentials> user:', user, ', password:', password) } else { // FIXME: The problem of uniqueness. What if this user is not unique? // It registers the same user with a new password that is not accessible @@ -37,26 +37,26 @@ const credentials = async (req, res, next) => { host: conf.xmpp.host }, headers: { 'Content-Type': 'application/json' } - }); - verbose('XMPP Registration Status Code:', response.status); - verbose('XMPP Registration Data:', response.data); + }) + verbose('XMPP Registration Status Code:', response.status) + verbose('XMPP Registration Data:', response.data) if (!req.user.xmpp) { - req.user.xmpp = {}; + req.user.xmpp = {} } - req.user.xmpp.user = user; - req.user.xmpp.password = password; - await req.user.save(); + req.user.xmpp.user = user + req.user.xmpp.password = password + await req.user.save() // verbose('Saved new XMPP credentials to user document:', req.user); } catch (err) { - verbose('XMPP registration error:', err.message); + verbose('XMPP registration error:', err.message) if (err.response) { - verbose('XMPP Error Status:', err.response.status); - verbose('XMPP Error Data:', err.response.data); + verbose('XMPP Error Status:', err.response.status) + verbose('XMPP Error Data:', err.response.data) } else if (err.request) { - verbose('XMPP Error: No response received'); + verbose('XMPP Error: No response received') } - throw new Error('Failed to register XMPP user: ' + err.message); + throw new Error(`Failed to register XMPP user: ${err.message}`) } } const out = { @@ -68,7 +68,7 @@ const credentials = async (req, res, next) => { verbose('out:', out) res.json(out) } catch (err) { - res.status(500).json({ result: 'error', message: err.toString()}) + res.status(500).json({ result: 'error', message: err.toString() }) } } diff --git a/src/utils/token.js b/src/utils/token.js index 6c7f444..24971f5 100644 --- a/src/utils/token.js +++ b/src/utils/token.js @@ -1,8 +1,9 @@ -import crypto from 'crypto' +import crypto from 'node:crypto' -export const randomToken = (len = 16) => - crypto.randomBytes(Math.ceil(len * 3 / 4)) +export function randomToken(len = 16) { + return crypto.randomBytes(Math.ceil(len * 3 / 4)) .toString('base64') // convert to base64 format .slice(0, len) // return required number of characters .replace(/\+/g, '0') // replace '+' with '0' - .replace(/\//g, '0') // replace '/' with '0' + .replace(/\//g, '0') +} // replace '/' with '0' diff --git a/src/utils/validation.js b/src/utils/validation.js index 955b039..bd6d0c7 100644 --- a/src/utils/validation.js +++ b/src/utils/validation.js @@ -1,4 +1,4 @@ -export const validateEmail = (email) => { +export function validateEmail(email) { return String(email) .toLowerCase() .match( @@ -6,11 +6,11 @@ export const validateEmail = (email) => { ) } -export const validatePhone = (phone) => { +export function validatePhone(phone) { return String(phone).match(/^\+(?:[0-9] ?){6,14}[0-9]$/) } -export const validatePassword = (password) => { +export function validatePassword(password) { // https://stackoverflow.com/questions/19605150/regex-for-password-must-contain-at-least-eight-characters-at-least-one-number-a const pw = String(password)