2141 ReplyTo param
gitea/salix/pipeline/head There was a failure building this commit Details

This commit is contained in:
Joan Sanchez 2020-05-20 16:23:53 +02:00
parent dbd23f4880
commit f6efa7160e
34 changed files with 98 additions and 79 deletions

View File

@ -21,7 +21,7 @@
"required": true "required": true
}, },
"priority": { "priority": {
"type": "nomber", "type": "number",
"required": true "required": true
} }
}, },

View File

@ -87,17 +87,31 @@ class Component {
return component; return component;
} }
async render() { component() {
if (this._component)
return this._component;
const component = this.build(); const component = this.build();
const i18n = new VueI18n(config.i18n); const i18n = new VueI18n(config.i18n);
const app = new Vue({ this._component = new Vue({
i18n: i18n, i18n: i18n,
render: h => h(component, { render: h => h(component, {
props: this.args props: this.args
}) })
}); });
return renderer.renderToString(app); return this._component;
}
/**
* @return {Promise} Rendered component
*/
async render() {
const c = this.component();
console.log(c);
return renderer.renderToString(
this.component()
);
} }
} }

View File

@ -15,6 +15,7 @@ module.exports = {
const props = this.args; const props = this.args;
let query = ''; let query = '';
for (let param in props) { for (let param in props) {
if (param instanceof Object) return;
if (query != '') if (query != '')
query += '&'; query += '&';
query += `${param}=${props[param]}`; query += `${param}=${props[param]}`;

View File

@ -2,7 +2,7 @@ const path = require('path');
const smtp = require('./smtp'); const smtp = require('./smtp');
const Component = require('./component'); const Component = require('./component');
const Report = require('./report'); const Report = require('./report');
const db = require('./database'); // const db = require('./database');
const config = require('./config'); const config = require('./config');
if (!process.env.OPENSSL_CONF) if (!process.env.OPENSSL_CONF)
@ -20,9 +20,9 @@ class Email extends Component {
} }
async getSubject() { async getSubject() {
if (!this.lang) await this.getLang(); const lang = this.args.auth.lang;
const locale = this.locale.messages; const locale = this.locale.messages;
const userLocale = locale[this.lang]; const userLocale = locale[lang];
if (!userLocale) { if (!userLocale) {
const fallbackLocale = config.i18n.fallbackLocale; const fallbackLocale = config.i18n.fallbackLocale;
@ -33,7 +33,7 @@ class Email extends Component {
return userLocale.subject; return userLocale.subject;
} }
async getLang() { /* async getLang() {
const clientId = this.args.clientId; const clientId = this.args.clientId;
const lang = await db.findOne(` const lang = await db.findOne(`
SELECT lang FROM account.user SELECT lang FROM account.user
@ -41,10 +41,11 @@ class Email extends Component {
return rows.lang; return rows.lang;
}); });
this.lang = lang; this.lang = lang;
} } */
async send() { async send() {
const instance = this.build(); const instance = this.build();
const component = this.component();
const rendered = await this.render(); const rendered = await this.render();
const attachments = []; const attachments = [];
const getAttachments = async(componentPath, files) => { const getAttachments = async(componentPath, files) => {
@ -77,9 +78,12 @@ class Email extends Component {
if (this.attachments) if (this.attachments)
await getAttachments(this.path, this.attachments); await getAttachments(this.path, this.attachments);
console.log(await component.getLang(101));
const localeSubject = await this.getSubject(); const localeSubject = await this.getSubject();
const options = { const options = {
to: this.args.recipient, to: this.args.recipient,
replyTo: this.args.auth.email,
subject: localeSubject, subject: localeSubject,
html: rendered, html: rendered,
attachments: attachments attachments: attachments

View File

@ -19,8 +19,7 @@ const validator = {
throw new Error(`Required properties not found [${required}]`); throw new Error(`Required properties not found [${required}]`);
} }
}, },
props: ['isPreview'] props: ['isPreview', 'authorization']
}; };
Vue.mixin(validator); Vue.mixin(validator);

View File

@ -4,15 +4,16 @@ const config = require('../config');
const fallbackLocale = config.i18n.fallbackLocale; const fallbackLocale = config.i18n.fallbackLocale;
const userLocale = { const userLocale = {
async serverPrefetch() { async serverPrefetch() {
console.log(this.auth); /* if (this.clientId)
if (this.clientId) this.locale = await this.getLocale(this.clientId); */
this.locale = await this.getLocale(this.clientId);
if (this.locale) if (this.clientLang) {
this.$i18n.locale = this.locale; if (this.auth)
this.$i18n.locale = this.auth.lang;
}
}, },
methods: { methods: {
getLocale(clientId) { getLang(clientId) {
return db.findOne(` return db.findOne(`
SELECT IF(u.lang IS NOT NULL, u.lang, LOWER(ct.code)) lang SELECT IF(u.lang IS NOT NULL, u.lang, LOWER(ct.code)) lang
FROM client c FROM client c
@ -23,6 +24,10 @@ const userLocale = {
return rows.lang; return rows.lang;
else return fallbackLocale; else return fallbackLocale;
}); });
},
setLocale() {
this.$i18n.locale = this.auth.lang;
} }
}, },
props: ['auth', 'clientId'] props: ['auth', 'clientId']

View File

@ -17,20 +17,30 @@ module.exports = app => {
for (let method of methods) for (let method of methods)
paths.push(`/api/${method}/*`); paths.push(`/api/${method}/*`);
app.use(paths, async function(request, response, next) { app.use(paths, async function(req, res, next) {
const authorization = getToken(request); const token = getToken(req);
const query = `SELECT userId, ttl, created const query = `SELECT at.id, at.userId, eu.email, u.lang, at.ttl, at.created
FROM salix.AccessToken WHERE id = ?`; FROM salix.AccessToken at
JOIN account.user u ON u.id = at.userid
JOIN account.emailUser eu ON eu.userFk = u.id
WHERE at.id = ?`;
try { try {
const authToken = await db.findOne(query, [authorization]); const auth = await db.findOne(query, [token]);
if (!authToken || isTokenExpired(authToken.created, authToken.ttl)) if (!auth || isTokenExpired(auth.created, auth.ttl))
throw new Error('Invalid authorization token'); throw new Error('Invalid authorization token');
request.body.auth = { const args = Object.assign({}, req.query);
userId: authToken.userId, const props = Object.assign(args, req.body);
token: authorization props.authorization = auth.id;
req.args = props;
req.args.auth = {
userId: auth.userId,
token: auth.id,
email: auth.email,
lang: auth.lang
}; };
next(); next();
@ -41,12 +51,9 @@ module.exports = app => {
function getToken(request) { function getToken(request) {
const headers = request.headers; const headers = request.headers;
const params = request.query; const queryParams = request.query;
if (headers.authorization) return headers.authorization || queryParams.authorization;
params.authorization = headers.authorization;
return headers.authorization || params.authorization;
} }
function isTokenExpired(created, ttl) { function isTokenExpired(created, ttl) {

View File

@ -27,7 +27,7 @@ module.exports = {
await db.rawSql(` await db.rawSql(`
INSERT INTO vn.mail (sender, replyTo, sent, subject, body, status) INSERT INTO vn.mail (sender, replyTo, sent, subject, body, status)
VALUES (:recipient, :sender, 1, :subject, :body, :status)`, { VALUES (:recipient, :sender, 1, :subject, :body, :status)`, {
sender: config.app.senderEmail, sender: options.replyTo,
recipient: options.to, recipient: options.to,
subject: options.subject, subject: options.subject,
body: options.text || options.html, body: options.text || options.html,

View File

@ -2,19 +2,11 @@ const Email = require('../core/email');
module.exports = app => { module.exports = app => {
app.get(`/api/email/:name`, async(req, res, next) => { app.get(`/api/email/:name`, async(req, res, next) => {
const args = req.query;
const requiredArgs = ['clientId', 'recipient'];
const argList = requiredArgs.join(',');
const hasRequiredArgs = requiredArgs.every(arg => {
return args[arg];
});
try { try {
if (!hasRequiredArgs) const reportName = req.params.name;
throw new Error(`Required properties not found [${argList}]`); const email = new Email(reportName, req.args);
const email = new Email(req.params.name, args); if (req.args.isPreview === 'true') {
if (args.isPreview === 'true') {
const rendered = await email.render(); const rendered = await email.render();
res.send(rendered); res.send(rendered);

View File

@ -2,15 +2,10 @@ const Report = require('../core/report');
module.exports = app => { module.exports = app => {
app.get(`/api/report/:name`, async(req, res, next) => { app.get(`/api/report/:name`, async(req, res, next) => {
const query = req.query;
const body = re.body;
const args = Object.assign({}, req.query);
// merge params
try { try {
const reportName = req.params.name; const reportName = req.params.name;
const fileName = getFileName(reportName, args); const fileName = getFileName(reportName, req.args);
const report = new Report(reportName, args); const report = new Report(reportName, req.args);
const stream = await report.toPdfStream(); const stream = await report.toPdfStream();
res.setHeader('Content-type', 'application/pdf'); res.setHeader('Content-type', 'application/pdf');
@ -33,8 +28,7 @@ module.exports = app => {
const keys = Object.keys(args); const keys = Object.keys(args);
for (let arg of keys) { for (let arg of keys) {
// FIXME: #2197 - Remove clientId as a required param if (arg.endsWith('Id'))
if (arg != 'clientId' && arg.endsWith('Id'))
identifiers.push(arg); identifiers.push(arg);
} }

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">
@ -23,7 +23,7 @@
<!-- Block --> <!-- Block -->
<div class="grid-row"> <div class="grid-row">
<div class="grid-block vn-pa-lg"> <div class="grid-block vn-pa-lg">
<h1>{{ $t('title') }}</h1> <h1>{{ $t('title') }} {{$i18n.locale}}</h1>
<p>{{ $t('sections.introduction.title') }},</p> <p>{{ $t('sections.introduction.title') }},</p>
<p>{{ $t('sections.introduction.description') }}</p> <p>{{ $t('sections.introduction.description') }}</p>

View File

@ -37,9 +37,6 @@ module.exports = {
'attachment': attachment.build() 'attachment': attachment.build()
}, },
props: { props: {
authorization: {
required: true
},
clientId: { clientId: {
required: true required: true
}, },

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@ -13,6 +13,9 @@ module.exports = {
data() { data() {
return {attachments}; return {attachments};
}, },
getClient() {
return this.clientId;
},
methods: { methods: {
fetchClient(clientId) { fetchClient(clientId) {
return db.findOne(` return db.findOne(`
@ -29,6 +32,9 @@ module.exports = {
LEFT JOIN worker w ON w.id = c.salesPersonFk LEFT JOIN worker w ON w.id = c.salesPersonFk
LEFT JOIN account.user wu ON wu.id = w.userFk LEFT JOIN account.user wu ON wu.id = w.userFk
WHERE c.id = ?`, [clientId]); WHERE c.id = ?`, [clientId]);
},
getClient() {
return this.clientId;
} }
}, },
components: { components: {

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<head> <head>
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<body> <body>
<table class="grid"> <table class="grid">
<tbody> <tbody>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<body> <body>
<table class="grid"> <table class="grid">
<tbody> <tbody>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<body> <body>
<table class="grid"> <table class="grid">
<tbody> <tbody>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<body> <body>
<table class="grid"> <table class="grid">
<tbody> <tbody>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<body> <body>
<table class="grid"> <table class="grid">
<tbody> <tbody>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<body> <body>
<table class="grid"> <table class="grid">
<tbody> <tbody>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<body> <body>
<table class="grid"> <table class="grid">
<tbody> <tbody>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<body> <body>
<table class="grid"> <table class="grid">
<tbody> <tbody>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<body> <body>
<table class="grid"> <table class="grid">
<tbody> <tbody>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html v-bind:lang="locale"> <html v-bind:lang="$i18n.locale">
<body> <body>
<table class="grid"> <table class="grid">
<tbody> <tbody>