Commit 465b4a48 authored by FORESTIER Fabien's avatar FORESTIER Fabien
Browse files

Add feedback endpoint

parent 06e0c4bb
Pipeline #2478 passed with stages
in 2 minutes and 42 seconds
......@@ -5809,7 +5809,6 @@
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
"dev": true,
"requires": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
......@@ -6615,8 +6614,7 @@
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
"p-defer": {
"version": "1.0.0",
......@@ -6990,8 +6988,7 @@
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
"dev": true
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
},
"psl": {
"version": "1.1.31",
......@@ -8989,6 +8986,14 @@
"next-tick": "1"
}
},
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"requires": {
"os-tmpdir": "~1.0.2"
}
},
"tmpl": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
......@@ -9840,6 +9845,15 @@
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
"dev": true
},
"useragent": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
"integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==",
"requires": {
"lru-cache": "4.1.x",
"tmp": "0.0.x"
}
},
"util": {
"version": "0.10.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
......@@ -10678,8 +10692,7 @@
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
"dev": true
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
},
"yargs": {
"version": "11.1.0",
......
......@@ -29,7 +29,8 @@
"moment": "^2.24.0",
"reflect-metadata": "^0.1.12",
"rxjs": "^6.2.2",
"typescript": "^3.0.1"
"typescript": "^3.0.1",
"useragent": "^2.3.0"
},
"devDependencies": {
"@nestjs/testing": "^5.1.0",
......
<!doctype html><html lang="fr" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"><head><title>Feedback</title><!--[if !mso]><!-- --><meta http-equiv="X-UA-Compatible" content="IE=edge"><!--<![endif]--><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style type="text/css">#outlook a { padding:0; }
.ReadMsgBody { width:100%; }
.ExternalClass { width:100%; }
.ExternalClass * { line-height:100%; }
body { margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%; }
table, td { border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt; }
img { border:0;height:auto;line-height:100%; outline:none;text-decoration:none;-ms-interpolation-mode:bicubic; }
p { display:block;margin:13px 0; }</style><!--[if !mso]><!--><style type="text/css">@media only screen and (max-width:480px) {
@-ms-viewport { width:320px; }
@viewport { width:320px; }
}</style><!--<![endif]--><!--[if mso]>
<xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
<![endif]--><!--[if lte mso 11]>
<style type="text/css">
.outlook-group-fix { width:100% !important; }
</style>
<![endif]--><!--[if !mso]><!--><link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet" type="text/css"><style type="text/css">@import url(https://fonts.googleapis.com/css?family=Lato);</style><!--<![endif]--><style type="text/css">@media only screen and (min-width:480px) {
.mj-column-per-100 { width:100% !important; max-width: 100%; }
.mj-column-per-50 { width:50% !important; max-width: 50%; }
}</style><style type="text/css">@media only screen and (max-width:480px) {
table.full-width-mobile { width: 100% !important; }
td.full-width-mobile { width: auto !important; }
}</style><style type="text/css">.warn-message {
color: "white";
}
.link {
color: white;
font-weight: bold;
}
.pre {
white-space: pre;
}
@media (max-width:480px) {
.title {
padding: 7% 10% !important;
}
}</style></head><body><div class="body"><!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:800px;" width="800" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="Margin:0px auto;max-width:800px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0;text-align:center;vertical-align:top;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" width="800px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:800px;" width="800" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="background:#333744;background-color:#333744;Margin:0px auto;max-width:800px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#333744;background-color:#333744;width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:3% 6%;text-align:center;vertical-align:top;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="width:788px;" ><![endif]--><div class="mj-column-per-100 outlook-group-fix" style="font-size:0;line-height:0;text-align:left;display:inline-block;width:100%;direction:ltr;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;width:394px;" ><![endif]--><div class="mj-column-per-50 outlook-group-fix" style="font-size:13px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:50%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tr><td align="left" style="font-size:0px;padding:0;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"><tbody><tr><td style="width:130px;"><img alt="Logo data.grandlyon.com" height="auto" src="${options.imageHost}/logo_data_neg.png" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;" width="130"></td></tr></tbody></table></td></tr></table></div><!--[if mso | IE]></td><td style="vertical-align:top;width:394px;" ><![endif]--><div class="mj-column-per-50 outlook-group-fix" style="font-size:13px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:50%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tr><td align="right" style="font-size:0px;padding:0;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"><tbody><tr><td style="width:80px;"><img alt="Logo Grand Lyon" height="auto" src="${options.imageHost}/logo_gl_négatif.png" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;" width="80"></td></tr></tbody></table></td></tr></table></div><!--[if mso | IE]></td></tr></table><![endif]--></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="800px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:800px;" width="800" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="background:#f2f2f2;background-color:#f2f2f2;Margin:0px auto;max-width:800px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#f2f2f2;background-color:#f2f2f2;width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:3% 6%;text-align:center;vertical-align:top;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:788px;" ><![endif]--><div class="mj-column-per-100 outlook-group-fix" style="font-size:13px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%"><tbody><tr><td style="background-color:white;vertical-align:top;padding:3% 6%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%"><tr><td align="center" class="title" style="font-size:0px;padding:3% 10%;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:18px;font-weight:bold;line-height:18px;text-align:center;color:#333744;">Feedback</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;line-height:18px;text-align:left;color:#333744;">Un nouveau feedback a été déposée le ${options.datetime}.</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;line-height:18px;text-align:left;color:#333744;">Voici un résumé de la demande :</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-weight:bold;line-height:18px;text-align:left;color:#333744;">Url:</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-style:italic;line-height:18px;text-align:left;color:#333744;">${options.url}</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-weight:bold;line-height:18px;text-align:left;color:#333744;">Version:</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-style:italic;line-height:18px;text-align:left;color:#333744;">${options.version}</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-weight:bold;line-height:18px;text-align:left;color:#333744;">User-Agent:</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-style:italic;line-height:18px;text-align:left;color:#333744;">${options.userAgent}</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-weight:bold;line-height:18px;text-align:left;color:#333744;">Message:</div></td></tr><tr><td align="left" class="pre" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-style:italic;line-height:18px;text-align:left;color:#333744;">${options.message}</div></td></tr><tr><td align="right" style="font-size:0px;padding:3% 0 0 0;padding-top:3%;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;line-height:18px;text-align:right;color:#333744;">L'équipe data.grandlyon.com</div></td></tr><tr><td align="right" style="font-size:0px;padding:10px 25px;padding-top:1%;padding-right:0;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"><tbody><tr><td style="width:105px;"><img alt="Logo data.grandlyon.com" height="auto" src="${options.imageHost}/logo_data.png" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;" width="105"></td></tr></tbody></table></td></tr></table></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="800px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:800px;" width="800" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="background:#333744;background-color:#333744;Margin:0px auto;max-width:800px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#333744;background-color:#333744;width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:3% 6%;text-align:center;vertical-align:top;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:788px;" ><![endif]--><div class="mj-column-per-100 outlook-group-fix" style="font-size:13px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tr><td align="center" style="font-size:0px;padding:0;word-break:break-word;"><!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" ><tr><td><![endif]--><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"><tr><td style="padding:0 5px 0 5px;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:16px;"><tr><td style="font-size:0;height:16px;vertical-align:middle;width:16px;"><a href="https://download.data.grandlyon.com/catalogue/srv/fre/rss.search?sortBy=publicationDate&amp;georss=simplepoint&amp;data" target="_blank"><img alt="Logo rss" height="16" src="${options.imageHost}/logo_rss.png" style="border-radius:3px;" width="16"></a></td></tr></table></td></tr></table><!--[if mso | IE]></td><td><![endif]--><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"><tr><td style="padding:0 5px 0 5px;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:16px;"><tr><td style="font-size:0;height:16px;vertical-align:middle;width:16px;"><a href="http://www.facebook.com/legrandlyon" target="_blank"><img alt="Logo Facebook" height="16" src="${options.imageHost}/logo_fb.png" style="border-radius:3px;" width="16"></a></td></tr></table></td></tr></table><!--[if mso | IE]></td><td><![endif]--><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"><tr><td style="padding:0 5px 0 5px;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:16px;"><tr><td style="font-size:0;height:16px;vertical-align:middle;width:16px;"><a href="https://twitter.com/grandlyon" target="_blank"><img alt="Logo Twitter" height="16" src="${options.imageHost}/logo_twi.png" style="border-radius:3px;" width="16"></a></td></tr></table></td></tr></table><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></div></body></html>
\ No newline at end of file
<mjml lang="fr">
<mj-head>
<mj-title>Feedback</mj-title>
<mj-font name="Lato" href="https://fonts.googleapis.com/css?family=Lato" />
<mj-attributes>
<mj-text font-family="Lato, sans-serif" line-height="18px" font-size="14px" padding="3% 0 0 0" color="#333744"></mj-text>
<mj-social-element padding="0 5px 0 5px"></mj-social-element>
</mj-attributes>
<mj-style>
.warn-message {
color: "white";
}
.link {
color: white;
font-weight: bold;
}
.pre {
white-space: pre;
}
@media (max-width:480px) {
.title {
padding: 7% 10% !important;
}
}
</mj-style>
</mj-head>
<mj-body width="800px" css-class="body">
<mj-wrapper padding="0">
<mj-section background-color="#333744" padding="3% 6%">
<mj-group>
<mj-column>
<mj-image width="130px" align="left" padding="0" alt="Logo data.grandlyon.com" src="${options.imageHost}/logo_data_neg.png"></mj-image>
</mj-column>
<mj-column>
<mj-image width="80px" align="right" padding="0" alt="Logo Grand Lyon" src="${options.imageHost}/logo_gl_négatif.png"></mj-image>
</mj-column>
</mj-group>
</mj-section>
<mj-section background-color="#f2f2f2" padding="3% 6%">
<mj-column background-color="white" padding="3% 6%">
<mj-text align="center" css-class="title" font-size="18px" font-weight="bold" padding="3% 10%">
Feedback
</mj-text>
<mj-text>
Un nouveau feedback a été déposée le ${options.datetime}.
</mj-text>
<mj-text>
Voici un résumé de la demande :
</mj-text>
<mj-text font-weight="bold">
Url:
</mj-text>
<mj-text font-style="italic">
${options.url}
</mj-text>
<mj-text font-weight="bold">
Version:
</mj-text>
<mj-text font-style="italic">${options.version}</mj-text>
<mj-text font-weight="bold">
User-Agent:
</mj-text>
<mj-text font-style="italic">
${options.userAgent}
</mj-text>
<mj-text font-weight="bold">
Message:
</mj-text>
<mj-text css-class="pre" font-style="italic">
${options.message}
</mj-text>
<mj-text align="right" padding-top="3%">
L'équipe data.grandlyon.com
</mj-text>
<mj-image align="right" width="105px" padding-right="0" padding-top="1%" alt="Logo data.grandlyon.com" src="${options.imageHost}/logo_data.png"></mj-image>
</mj-column>
</mj-section>
<mj-section background-color="#333744" padding="3% 6%">
<mj-column>
<mj-social padding="0" font-size="15px" icon-size="16px" mode="horizontal">
<mj-social-element alt="Logo rss" href="https://download.data.grandlyon.com/catalogue/srv/fre/rss.search?sortBy=publicationDate&amp;georss=simplepoint&amp;data" src="${options.imageHost}/logo_rss.png">
</mj-social-element>
<mj-social-element alt="Logo Facebook" href="http://www.facebook.com/legrandlyon" src="${options.imageHost}/logo_fb.png">
</mj-social-element>
<mj-social-element alt="Logo Twitter" href="https://twitter.com/grandlyon" src="${options.imageHost}/logo_twi.png">
</mj-social-element>
</mj-social>
</mj-column>
</mj-section>
</mj-wrapper>
</mj-body>
</mjml>
\ No newline at end of file
export const buildFeedbackEmail = (options: FeedbackEmailBodyOptions) => {
const html = `<!doctype html><html lang="fr" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"><head><title>Feedback</title><!--[if !mso]><!-- --><meta http-equiv="X-UA-Compatible" content="IE=edge"><!--<![endif]--><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style type="text/css">#outlook a { padding:0; }
.ReadMsgBody { width:100%; }
.ExternalClass { width:100%; }
.ExternalClass * { line-height:100%; }
body { margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%; }
table, td { border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt; }
img { border:0;height:auto;line-height:100%; outline:none;text-decoration:none;-ms-interpolation-mode:bicubic; }
p { display:block;margin:13px 0; }</style><!--[if !mso]><!--><style type="text/css">@media only screen and (max-width:480px) {
@-ms-viewport { width:320px; }
@viewport { width:320px; }
}</style><!--<![endif]--><!--[if mso]>
<xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
<![endif]--><!--[if lte mso 11]>
<style type="text/css">
.outlook-group-fix { width:100% !important; }
</style>
<![endif]--><!--[if !mso]><!--><link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet" type="text/css"><style type="text/css">@import url(https://fonts.googleapis.com/css?family=Lato);</style><!--<![endif]--><style type="text/css">@media only screen and (min-width:480px) {
.mj-column-per-100 { width:100% !important; max-width: 100%; }
.mj-column-per-50 { width:50% !important; max-width: 50%; }
}</style><style type="text/css">@media only screen and (max-width:480px) {
table.full-width-mobile { width: 100% !important; }
td.full-width-mobile { width: auto !important; }
}</style><style type="text/css">.warn-message {
color: "white";
}
.link {
color: white;
font-weight: bold;
}
.pre {
white-space: pre;
}
@media (max-width:480px) {
.title {
padding: 7% 10% !important;
}
}</style></head><body><div class="body"><!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:800px;" width="800" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="Margin:0px auto;max-width:800px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:0;text-align:center;vertical-align:top;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" width="800px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:800px;" width="800" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="background:#333744;background-color:#333744;Margin:0px auto;max-width:800px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#333744;background-color:#333744;width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:3% 6%;text-align:center;vertical-align:top;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="width:788px;" ><![endif]--><div class="mj-column-per-100 outlook-group-fix" style="font-size:0;line-height:0;text-align:left;display:inline-block;width:100%;direction:ltr;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td style="vertical-align:top;width:394px;" ><![endif]--><div class="mj-column-per-50 outlook-group-fix" style="font-size:13px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:50%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tr><td align="left" style="font-size:0px;padding:0;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"><tbody><tr><td style="width:130px;"><img alt="Logo data.grandlyon.com" height="auto" src="${options.imageHost}/logo_data_neg.png" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;" width="130"></td></tr></tbody></table></td></tr></table></div><!--[if mso | IE]></td><td style="vertical-align:top;width:394px;" ><![endif]--><div class="mj-column-per-50 outlook-group-fix" style="font-size:13px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:50%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tr><td align="right" style="font-size:0px;padding:0;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"><tbody><tr><td style="width:80px;"><img alt="Logo Grand Lyon" height="auto" src="${options.imageHost}/logo_gl_négatif.png" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;" width="80"></td></tr></tbody></table></td></tr></table></div><!--[if mso | IE]></td></tr></table><![endif]--></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="800px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:800px;" width="800" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="background:#f2f2f2;background-color:#f2f2f2;Margin:0px auto;max-width:800px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#f2f2f2;background-color:#f2f2f2;width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:3% 6%;text-align:center;vertical-align:top;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:788px;" ><![endif]--><div class="mj-column-per-100 outlook-group-fix" style="font-size:13px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%"><tbody><tr><td style="background-color:white;vertical-align:top;padding:3% 6%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" width="100%"><tr><td align="center" class="title" style="font-size:0px;padding:3% 10%;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:18px;font-weight:bold;line-height:18px;text-align:center;color:#333744;">Feedback</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;line-height:18px;text-align:left;color:#333744;">Un nouveau feedback a été déposée le ${options.datetime}.</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;line-height:18px;text-align:left;color:#333744;">Voici un résumé de la demande :</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-weight:bold;line-height:18px;text-align:left;color:#333744;">Url:</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-style:italic;line-height:18px;text-align:left;color:#333744;">${options.url}</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-weight:bold;line-height:18px;text-align:left;color:#333744;">Version:</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-style:italic;line-height:18px;text-align:left;color:#333744;">${options.version}</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-weight:bold;line-height:18px;text-align:left;color:#333744;">User-Agent:</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-style:italic;line-height:18px;text-align:left;color:#333744;">${options.userAgent}</div></td></tr><tr><td align="left" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-weight:bold;line-height:18px;text-align:left;color:#333744;">Message:</div></td></tr><tr><td align="left" class="pre" style="font-size:0px;padding:3% 0 0 0;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;font-style:italic;line-height:18px;text-align:left;color:#333744;">${options.message}</div></td></tr><tr><td align="right" style="font-size:0px;padding:3% 0 0 0;padding-top:3%;word-break:break-word;"><div style="font-family:Lato, sans-serif;font-size:14px;line-height:18px;text-align:right;color:#333744;">L'équipe data.grandlyon.com</div></td></tr><tr><td align="right" style="font-size:0px;padding:10px 25px;padding-top:1%;padding-right:0;word-break:break-word;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:collapse;border-spacing:0px;"><tbody><tr><td style="width:105px;"><img alt="Logo data.grandlyon.com" height="auto" src="${options.imageHost}/logo_data.png" style="border:0;display:block;outline:none;text-decoration:none;height:auto;width:100%;" width="105"></td></tr></tbody></table></td></tr></table></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr><tr><td class="" width="800px" ><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:800px;" width="800" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]--><div style="background:#333744;background-color:#333744;Margin:0px auto;max-width:800px;"><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#333744;background-color:#333744;width:100%;"><tbody><tr><td style="direction:ltr;font-size:0px;padding:3% 6%;text-align:center;vertical-align:top;"><!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:788px;" ><![endif]--><div class="mj-column-per-100 outlook-group-fix" style="font-size:13px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%"><tr><td align="center" style="font-size:0px;padding:0;word-break:break-word;"><!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" ><tr><td><![endif]--><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"><tr><td style="padding:0 5px 0 5px;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:16px;"><tr><td style="font-size:0;height:16px;vertical-align:middle;width:16px;"><a href="https://download.data.grandlyon.com/catalogue/srv/fre/rss.search?sortBy=publicationDate&amp;georss=simplepoint&amp;data" target="_blank"><img alt="Logo rss" height="16" src="${options.imageHost}/logo_rss.png" style="border-radius:3px;" width="16"></a></td></tr></table></td></tr></table><!--[if mso | IE]></td><td><![endif]--><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"><tr><td style="padding:0 5px 0 5px;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:16px;"><tr><td style="font-size:0;height:16px;vertical-align:middle;width:16px;"><a href="http://www.facebook.com/legrandlyon" target="_blank"><img alt="Logo Facebook" height="16" src="${options.imageHost}/logo_fb.png" style="border-radius:3px;" width="16"></a></td></tr></table></td></tr></table><!--[if mso | IE]></td><td><![endif]--><table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"><tr><td style="padding:0 5px 0 5px;"><table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:16px;"><tr><td style="font-size:0;height:16px;vertical-align:middle;width:16px;"><a href="https://twitter.com/grandlyon" target="_blank"><img alt="Logo Twitter" height="16" src="${options.imageHost}/logo_twi.png" style="border-radius:3px;" width="16"></a></td></tr></table></td></tr></table><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></table></div><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if mso | IE]></td></tr></table><![endif]--></div></body></html>`;
return html;
};
class FeedbackEmailBodyOptions {
url: string;
message: string;
version: string;
userAgent: string;
datetime: string;
imageHost: string;
}
\ No newline at end of file
import { Controller, Post, Body, InternalServerErrorException, Logger, HttpCode } from '@nestjs/common';
import { ContactForm, EmailWithoutFrom } from './email';
import { Controller, Post, Body, InternalServerErrorException, Logger, HttpCode, Req } from '@nestjs/common';
import { ContactForm, EmailWithoutFrom, FeedbackForm } from './email';
import { EmailService } from './email.service';
import { ApiBadRequestResponse, ApiOkResponse, ApiUseTags, ApiOperation, ApiInternalServerErrorResponse } from '@nestjs/swagger';
import { Groups } from '../decorators/groups.decorators';
......@@ -28,6 +28,22 @@ export class EmailController {
}
}
@Post('feedback')
// tslint:disable-next-line:max-line-length
@ApiOperation({ title: 'Send email to admin with the user feedback' })
@ApiOkResponse({ description: 'OK' })
@ApiBadRequestResponse({ description: 'Missing fields' })
@ApiInternalServerErrorResponse({ description: 'Internal error, this is probably a rabbitMQ related error (unreachable service...)'})
@HttpCode(200)
async sendFeedback(@Body() feedbackForm: FeedbackForm, @Req() req) {
try {
return await this.emailService.sendFeedback(feedbackForm, req.headers['user-agent']);
} catch (error) {
Logger.log(error);
throw new InternalServerErrorException();
}
}
@Post('send')
@Groups('emailWriter')
@ApiOperation({ title: 'Send email.' })
......
import { Injectable, Logger, InternalServerErrorException } from '@nestjs/common';
import * as amqp from 'amqplib';
import { ContactForm, Email, EmailWithoutFrom } from './email';
import { ContactForm, Email, EmailWithoutFrom, FeedbackForm } from './email';
import { ConfigService } from '../configuration/config.service';
import { buildContactAdminEmail, buildContactUserEmail } from '../email-templates/contact';
import moment = require('moment');
import { buildFeedbackEmail } from 'email-templates/feedback';
import * as useragent from 'useragent';
@Injectable()
export class EmailService {
......@@ -16,7 +18,6 @@ export class EmailService {
async sendContactEmails(contactForm: ContactForm) {
Logger.log('[-] sendContactEmails method');
// contactForm.text = contactForm.text.replace(/(?:\r\n|\r|\n)/g, '<br />');
const adminEmailBody = buildContactAdminEmail({
subject: contactForm.subject,
message: contactForm.text,
......@@ -51,13 +52,43 @@ export class EmailService {
return;
}
async sendFeedback(feedbackForm: FeedbackForm, userAgent) {
Logger.log('[-] sendFeedback method');
const userAgentParsed = useragent.parse(userAgent);
let userAgentString = '';
if (userAgentParsed) {
userAgentString = `Family: ${userAgentParsed.family},`;
userAgentString += `Version:${userAgentParsed.major}.${userAgentParsed.minor}.${userAgentParsed.patch},`;
userAgentString += `Source: ${userAgentParsed.source}`;
}
const feedbackEmailBody = buildFeedbackEmail({
url: feedbackForm.url,
userAgent: userAgentString,
version: feedbackForm.version,
message: feedbackForm.message,
datetime: moment().format('DD/MM/YYYY à HH:mm'),
imageHost: this.config.imageHost,
});
const feedbackEmail = new EmailWithoutFrom();
feedbackEmail.to = [this.config.plateformDataEmail];
feedbackEmail.subject = 'Feedback';
feedbackEmail.html = feedbackEmailBody;
await this.send(feedbackEmail);
return;
}
async send(emailInfo: EmailWithoutFrom) {
let conn, ch;
// tslint:disable-next-line:max-line-length
const rabbitmqUrl = `amqp://${this.config.rabbitMQ.user}:${this.config.rabbitMQ.password}@${this.config.rabbitMQ.host}:${this.config.rabbitMQ.port}`;
const mailerQueue = this.config.mailerQueue;
let email = new Email();
let email = new Email();
email.from = this.config.plateformDataEmail;
email = Object.assign(email, emailInfo);
......
......@@ -79,4 +79,18 @@ export class EmailWithoutFrom {
@IsDefined()
html: string;
}
export class FeedbackForm {
@ApiModelProperty()
@IsDefined()
url: string;
@ApiModelProperty()
@IsDefined()
version: string;
@ApiModelProperty()
@IsDefined()
message: string;
}
\ No newline at end of file
......@@ -10,11 +10,18 @@ export class GroupsGuard implements CanActivate {
Logger.log('[+] GroupMiddleware');
// We get the groups specified on the endpoint with the @Groups annotation
// We need then to get the real group names associated to those keys from the config file
const groups = this.reflector.get<string[]>('groups', context.getHandler()).map((e) => {
let groups = this.reflector.get<string[]>('groups', context.getHandler());
// if no groups specified then access is always ok
if (!groups) {
return true;
}
groups = groups.map((e) => {
return this.configService.config.groupNames[e];
});
// if no groups specified then access is always ok
// if the spcified group is not found
if (!groups) {
return true;
}
......
{"swagger":"2.0","info":{"description":"Service providing the method to send emails.","version":"0.1","title":"Email service API"},"basePath":"/","tags":[{"name":"email","description":""}],"schemes":["http"],"paths":{"/email/contact":{"post":{"summary":"Send email to admin (emails defined as var env of the project, see docker-compose.yml file) and recap email to user email.","parameters":[{"name":"ContactForm","required":true,"in":"body","schema":{"$ref":"#/definitions/ContactForm"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Missing fields"},"500":{"description":"Internal error, this is probably a rabbitMQ related error (unreachable service...)"}},"tags":["email"],"produces":["application/json"],"consumes":["application/json"]}},"/email/send":{"post":{"summary":"Send email.","parameters":[{"name":"EmailWithoutFrom","required":true,"in":"body","schema":{"$ref":"#/definitions/EmailWithoutFrom"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Missing fields"},"500":{"description":"Internal error, this is probably a rabbitMQ related error (unreachable service...)"}},"tags":["email"],"produces":["application/json"],"consumes":["application/json"]}}},"definitions":{"ContactForm":{"type":"object","properties":{"email":{"type":"string"},"subject":{"type":"string"},"firstname":{"type":"string"},"lastname":{"type":"string"},"text":{"type":"string"}},"required":["email","subject","firstname","lastname","text"]},"EmailWithoutFrom":{"type":"object","properties":{"to":{"type":"array","items":{"type":"string"}},"replyTo":{"type":"string"},"cc":{"type":"array","items":{"type":"string"}},"bcc":{"type":"array","items":{"type":"string"}},"subject":{"type":"string"},"html":{"type":"string"}},"required":["to","subject","html"]}}}
\ No newline at end of file
{"swagger":"2.0","info":{"description":"Service providing the method to send emails.","version":"0.1","title":"Email service API"},"basePath":"/","tags":[{"name":"email","description":""}],"schemes":["http"],"paths":{"/email/contact":{"post":{"summary":"Send email to admin (emails defined as var env of the project, see docker-compose.yml file) and recap email to user email.","parameters":[{"name":"ContactForm","required":true,"in":"body","schema":{"$ref":"#/definitions/ContactForm"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Missing fields"},"500":{"description":"Internal error, this is probably a rabbitMQ related error (unreachable service...)"}},"tags":["email"],"produces":["application/json"],"consumes":["application/json"]}},"/email/feedback":{"post":{"summary":"Send email to admin with the user feedback","parameters":[{"name":"FeedbackForm","required":true,"in":"body","schema":{"$ref":"#/definitions/FeedbackForm"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Missing fields"},"500":{"description":"Internal error, this is probably a rabbitMQ related error (unreachable service...)"}},"tags":["email"],"produces":["application/json"],"consumes":["application/json"]}},"/email/send":{"post":{"summary":"Send email.","parameters":[{"name":"EmailWithoutFrom","required":true,"in":"body","schema":{"$ref":"#/definitions/EmailWithoutFrom"}}],"responses":{"200":{"description":"OK"},"400":{"description":"Missing fields"},"500":{"description":"Internal error, this is probably a rabbitMQ related error (unreachable service...)"}},"tags":["email"],"produces":["application/json"],"consumes":["application/json"]}}},"definitions":{"ContactForm":{"type":"object","properties":{"email":{"type":"string"},"subject":{"type":"string"},"firstname":{"type":"string"},"lastname":{"type":"string"},"text":{"type":"string"}},"required":["email","subject","firstname","lastname","text"]},"FeedbackForm":{"type":"object","properties":{"url":{"type":"string"},"version":{"type":"string"},"message":{"type":"string"}},"required":["url","version","message"]},"EmailWithoutFrom":{"type":"object","properties":{"to":{"type":"array","items":{"type":"string"}},"replyTo":{"type":"string"},"cc":{"type":"array","items":{"type":"string"}},"bcc":{"type":"array","items":{"type":"string"}},"subject":{"type":"string"},"html":{"type":"string"}},"required":["to","subject","html"]}}}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment