Backend API looks fine
This commit is contained in:
parent
c6951c0838
commit
562485134a
|
@ -12,6 +12,8 @@
|
|||
"@kobalte/core": "^0.6.2",
|
||||
"@types/pouchdb": "^6.4.0",
|
||||
"lodash": "^4.17.21",
|
||||
"nodemailer": "^6.9.1",
|
||||
"nodemailer-express-handlebars": "^6.0.0",
|
||||
"pouchdb": "^8.0.1",
|
||||
"pouchdb-server": "^4.2.0",
|
||||
"tippy.js": "^6.3.7",
|
||||
|
@ -23,6 +25,8 @@
|
|||
"@solidjs/testing-library": "^0.6.1",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"@types/nodemailer": "^6.4.7",
|
||||
"@types/nodemailer-express-handlebars": "^4.0.2",
|
||||
"@types/testing-library__jest-dom": "^5.14.5",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"@vitest/coverage-c8": "^0.29.2",
|
||||
|
@ -2948,6 +2952,12 @@
|
|||
"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/express-handlebars": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-handlebars/-/express-handlebars-5.3.1.tgz",
|
||||
"integrity": "sha512-DSzaERLO4gHb8AqnrL58jzSDyT0yDdl6HqDc+bGz1Hf0nrG1FK30nHGzv8NBEGR8QV9eUGB/YaE0Qj3NjF7siw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/istanbul-lib-coverage": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
|
||||
|
@ -3031,6 +3041,25 @@
|
|||
"integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/nodemailer": {
|
||||
"version": "6.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.7.tgz",
|
||||
"integrity": "sha512-f5qCBGAn/f0qtRcd4SEn88c8Fp3Swct1731X4ryPKqS61/A3LmmzN8zaEz7hneJvpjFbUUgY7lru/B/7ODTazg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/nodemailer-express-handlebars": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/nodemailer-express-handlebars/-/nodemailer-express-handlebars-4.0.2.tgz",
|
||||
"integrity": "sha512-LnKnqgl6C3osQKQDcIxB6P4iS2Iixq+p0ZCC93pzhSRLvo4PgGHmrTFE38ZGrFxc/DyZefYGEsYHSblxJtwuxw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/express-handlebars": "^5",
|
||||
"@types/nodemailer": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/pouchdb": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/pouchdb/-/pouchdb-6.4.0.tgz",
|
||||
|
@ -5497,6 +5526,56 @@
|
|||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/express-handlebars": {
|
||||
"version": "6.0.7",
|
||||
"resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-6.0.7.tgz",
|
||||
"integrity": "sha512-iYeMFpc/hMD+E6FNAZA5fgWeXnXr4rslOSPkeEV6TwdmpJ5lEXuWX0u9vFYs31P2MURctQq2batR09oeNj0LIg==",
|
||||
"dependencies": {
|
||||
"glob": "^8.1.0",
|
||||
"graceful-fs": "^4.2.10",
|
||||
"handlebars": "^4.7.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v12.22.9"
|
||||
}
|
||||
},
|
||||
"node_modules/express-handlebars/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/express-handlebars/node_modules/glob": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
|
||||
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^5.0.1",
|
||||
"once": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/express-handlebars/node_modules/minimatch": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
|
||||
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/express-pouchdb": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/express-pouchdb/-/express-pouchdb-4.2.0.tgz",
|
||||
|
@ -5832,8 +5911,7 @@
|
|||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"devOptional": true
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
|
@ -6058,6 +6136,26 @@
|
|||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
|
||||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
|
||||
},
|
||||
"node_modules/handlebars": {
|
||||
"version": "4.7.7",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
|
||||
"integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.5",
|
||||
"neo-async": "^2.6.0",
|
||||
"source-map": "^0.6.1",
|
||||
"wordwrap": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"handlebars": "bin/handlebars"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.7"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"uglify-js": "^3.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
|
@ -7687,6 +7785,11 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/neo-async": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
|
@ -7784,6 +7887,25 @@
|
|||
"integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/nodemailer": {
|
||||
"version": "6.9.1",
|
||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz",
|
||||
"integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA==",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nodemailer-express-handlebars": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nodemailer-express-handlebars/-/nodemailer-express-handlebars-6.0.0.tgz",
|
||||
"integrity": "sha512-xo5nVCn2GDaE8o0ppOWVq0s3Tt5xLn+R2pDROQrZALKCoP6WsEOXrNGQwH/tYJ4vucWtWd+zdcHm734S6CSA7w==",
|
||||
"dependencies": {
|
||||
"express-handlebars": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "14.* || 16.* || >= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/noop-fn": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/noop-fn/-/noop-fn-1.0.0.tgz",
|
||||
|
@ -9996,7 +10118,6 @@
|
|||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
@ -10508,6 +10629,18 @@
|
|||
"integrity": "sha512-LQc2s/ZDMaCN3QLpa+uzHUOQ7SdV0qgv3VBXOolQGXTaaZpIur6PwUclF5nN2hNkiTRcUugXd1zFOW3FLJ135Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/uglify-js": {
|
||||
"version": "3.17.4",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
|
||||
"integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"uglifyjs": "bin/uglifyjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uid-safe": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
"@solidjs/testing-library": "^0.6.1",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"@types/nodemailer": "^6.4.7",
|
||||
"@types/nodemailer-express-handlebars": "^4.0.2",
|
||||
"@types/testing-library__jest-dom": "^5.14.5",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"@vitest/coverage-c8": "^0.29.2",
|
||||
|
@ -36,6 +38,8 @@
|
|||
"@kobalte/core": "^0.6.2",
|
||||
"@types/pouchdb": "^6.4.0",
|
||||
"lodash": "^4.17.21",
|
||||
"nodemailer": "^6.9.1",
|
||||
"nodemailer-express-handlebars": "^6.0.0",
|
||||
"pouchdb": "^8.0.1",
|
||||
"pouchdb-server": "^4.2.0",
|
||||
"tippy.js": "^6.3.7",
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import { adminCredentials } from '~/components/credentials';
|
||||
|
||||
export const getUrl = (id: string, db = 'dyomedea_users') => {
|
||||
const credentials = adminCredentials();
|
||||
export const getUrl = (
|
||||
id: string,
|
||||
db = 'dyomedea_users',
|
||||
credentials = adminCredentials()
|
||||
) => {
|
||||
if (!credentials) {
|
||||
return '';
|
||||
}
|
||||
|
|
|
@ -2,19 +2,24 @@ import { adminCredentials } from '~/components/credentials';
|
|||
import { getUrl } from './get-url';
|
||||
import { headersWithAuth } from './headers-with-auth';
|
||||
|
||||
export const get = async (id: string, db = 'dyomedea_users') => {
|
||||
const credentials = adminCredentials();
|
||||
export const get = async (
|
||||
id: string,
|
||||
db = 'dyomedea_users',
|
||||
credentials = adminCredentials()
|
||||
) => {
|
||||
if (!credentials) {
|
||||
return null;
|
||||
}
|
||||
const { database } = credentials;
|
||||
|
||||
const headers = headersWithAuth();
|
||||
const headers = headersWithAuth(credentials);
|
||||
if (!headers) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const response = await fetch(getUrl(id, db), {
|
||||
// console.log({ caller: 'get', id, db, credentials, headers });
|
||||
|
||||
const response = await fetch(getUrl(id, db, credentials), {
|
||||
method: 'GET',
|
||||
mode: 'cors',
|
||||
headers,
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
export const obfuscateMail = (mail: string) => {
|
||||
const [user, hostname] = mail.split('@');
|
||||
const obfuscatedUser =
|
||||
user.length < 4
|
||||
? user[0] + new Array(user.length).join('.')
|
||||
: user[0] + new Array(user.length - 1).join('.') + user[user.length - 1];
|
||||
const obfuscatedHostname =
|
||||
hostname[0] +
|
||||
new Array(hostname.length - 1).join('.') +
|
||||
hostname[hostname.length - 1];
|
||||
return obfuscatedUser + '@' + obfuscatedHostname;
|
||||
};
|
|
@ -8,36 +8,46 @@ export const put = async (
|
|||
content: any,
|
||||
isNew: boolean = false,
|
||||
db = 'dyomedea_users',
|
||||
overwrite_ = false
|
||||
overwrite_ = false,
|
||||
credentials = adminCredentials()
|
||||
) => {
|
||||
const credentials = adminCredentials();
|
||||
console.log({ caller: 'put', id, isNew, db, content, credentials });
|
||||
|
||||
if (!credentials) {
|
||||
return null;
|
||||
}
|
||||
const { database } = credentials;
|
||||
|
||||
if (!isNew) {
|
||||
const previous = await get(id, db);
|
||||
const previous = await get(id, db, credentials);
|
||||
// console.log({
|
||||
// caller: 'put / after get',
|
||||
// id,
|
||||
// isNew,
|
||||
// db,
|
||||
// content,
|
||||
// previous,
|
||||
// });
|
||||
if (!!previous) {
|
||||
content._rev = previous._rev;
|
||||
if (!overwrite_) {
|
||||
content.__ = previous.__;
|
||||
content.$ = previous.$;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const headers = headersWithAuth();
|
||||
const headers = headersWithAuth(credentials);
|
||||
if (!headers) {
|
||||
return null;
|
||||
}
|
||||
headers.set('Content-type', 'application/json; charset=UTF-8');
|
||||
|
||||
const response = await fetch(getUrl(id, db), {
|
||||
const response = await fetch(getUrl(id, db, credentials), {
|
||||
method: 'PUT',
|
||||
mode: 'cors',
|
||||
headers,
|
||||
body: JSON.stringify(content),
|
||||
});
|
||||
console.log({ caller: 'put', id, isNew, db, status: response.status });
|
||||
// console.log({ caller: 'put', id, isNew, db, status: response.status });
|
||||
return await response.json();
|
||||
};
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title>Validation</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Bonjour {{id}}! </h2>
|
||||
<p>Le code de validation de votre configuration pour l'application Dyomedea est <code>{{code}}</code>.</p>
|
||||
<p>Ce code est valable pendant quinze minutes.</p>
|
||||
<p>Eric</p>
|
||||
</body>
|
||||
</html>
|
|
@ -1,6 +1,22 @@
|
|||
import { APIEvent, json } from 'solid-start/api';
|
||||
import { findUserByToken } from '~/lib/find-user-by-token';
|
||||
import { readConfig } from '~/server-only-lib/read-config';
|
||||
|
||||
export async function GET({ params, env }: APIEvent) {
|
||||
console.log({ caller: 'api/conf GET', params });
|
||||
return json({ params, env, response: 'OK' });
|
||||
const { credentials } = readConfig();
|
||||
const user = await findUserByToken(params.token, credentials);
|
||||
console.log({ caller: 'api/conf GET', params, credentials, user });
|
||||
if (!user) {
|
||||
return json({ params, response: 'NOT FOUND' });
|
||||
}
|
||||
const { code, expiration } = user.$;
|
||||
if (
|
||||
!code ||
|
||||
!expiration ||
|
||||
params.code !== code ||
|
||||
new Date() > new Date(expiration)
|
||||
) {
|
||||
return json({ params, response: 'NOT FOUND' });
|
||||
}
|
||||
return json({ params, response: 'OK', user });
|
||||
}
|
||||
|
|
|
@ -1,11 +1,60 @@
|
|||
import { APIEvent, json } from 'solid-start/api';
|
||||
import { findUserByToken } from '~/lib/find-user-by-token';
|
||||
import { readConfig } from '~/server-only-lib/read-config';
|
||||
import { createTransport } from 'nodemailer';
|
||||
import { resolve } from 'path';
|
||||
import hbs from 'nodemailer-express-handlebars';
|
||||
import { put } from '~/lib/put';
|
||||
import { obfuscateMail } from '~/lib/obfuscate-mail';
|
||||
|
||||
export async function GET({ params }: APIEvent) {
|
||||
const { credentials } = readConfig();
|
||||
const { credentials, mailer } = readConfig();
|
||||
console.log({ caller: 'api/conf GET', params, credentials });
|
||||
const user = await findUserByToken(params.token, credentials);
|
||||
console.log({ caller: 'api/conf GET', params, credentials, user });
|
||||
return json({ params, response: 'OK' });
|
||||
if (!user) {
|
||||
return json({ params, response: 'NOT FOUND' });
|
||||
}
|
||||
const transporter = createTransport(mailer);
|
||||
|
||||
const handlebarOptions = {
|
||||
viewEngine: {
|
||||
partialsDir: resolve('src/mail-template/'),
|
||||
defaultLayout: false,
|
||||
},
|
||||
viewPath: resolve('src/mail-template/'),
|
||||
};
|
||||
transporter.use('compile', hbs(handlebarOptions));
|
||||
|
||||
const code = [...Array(6)].map((_) => (Math.random() * 10) | 0).join('');
|
||||
|
||||
const mailOptions = {
|
||||
from: '"Dyomedea app" <app@dyomedea.com>', // sender address
|
||||
to: user.mail, // list of receivers
|
||||
subject: 'Validation!',
|
||||
template: 'email', // the name of the template file i.e email.handlebars
|
||||
context: {
|
||||
id: user._id,
|
||||
code,
|
||||
},
|
||||
};
|
||||
|
||||
await transporter.sendMail(mailOptions);
|
||||
|
||||
await put(
|
||||
user._id,
|
||||
{
|
||||
...user,
|
||||
$: {
|
||||
code,
|
||||
expiration: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
|
||||
},
|
||||
},
|
||||
false,
|
||||
undefined,
|
||||
true,
|
||||
credentials
|
||||
);
|
||||
|
||||
return json({ params, status: 'OK', mail: obfuscateMail(user.mail) });
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue