mirror of
https://codeberg.org/timelimit/timelimit-server.git
synced 2025-10-03 09:49:32 +02:00
Show the source device in login code mails
This commit is contained in:
parent
add8787624
commit
3a59743de9
12 changed files with 190 additions and 209 deletions
|
@ -24,7 +24,8 @@ see [this JSON schema](../schema/sendmaillogincoderequest.md)
|
|||
```
|
||||
{
|
||||
"mail": "test@timelimit.io",
|
||||
"locale": "de"
|
||||
"locale": "de",
|
||||
"deviceAuthToken": "1234abcde"
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -34,6 +35,8 @@ If the request body is malformed or the mail address is invalid: HTTP status cod
|
|||
|
||||
If the rate limit was exceeded: HTTP status code 429 Too Many Requests
|
||||
|
||||
If a deviceAuthToken was sent which is invalid: HTTP status code 401 Unauthorized
|
||||
|
||||
If a whitelist was configured and the mail address is not within it: ``{"mailAddressNotWhitelisted": true}``
|
||||
|
||||
If a blacklist was configured and the mail server is within it: ``{"mailServerBlacklisted": true}``
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
},
|
||||
"locale": {
|
||||
"type": "string"
|
||||
},
|
||||
"deviceAuthToken": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# Untitled string in SendMailLoginCodeRequest Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SendMailLoginCodeRequest#/properties/deviceAuthToken
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :--------------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SendMailLoginCodeRequest.schema.json*](SendMailLoginCodeRequest.schema.json "open original schema") |
|
||||
|
||||
## deviceAuthToken Type
|
||||
|
||||
`string`
|
|
@ -16,10 +16,11 @@ https://timelimit.io/SendMailLoginCodeRequest
|
|||
|
||||
# SendMailLoginCodeRequest Properties
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :---------------- | :------- | :------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [mail](#mail) | `string` | Required | cannot be null | [SendMailLoginCodeRequest](sendmaillogincoderequest-properties-mail.md "https://timelimit.io/SendMailLoginCodeRequest#/properties/mail") |
|
||||
| [locale](#locale) | `string` | Required | cannot be null | [SendMailLoginCodeRequest](sendmaillogincoderequest-properties-locale.md "https://timelimit.io/SendMailLoginCodeRequest#/properties/locale") |
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :---------------------------------- | :------- | :------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [mail](#mail) | `string` | Required | cannot be null | [SendMailLoginCodeRequest](sendmaillogincoderequest-properties-mail.md "https://timelimit.io/SendMailLoginCodeRequest#/properties/mail") |
|
||||
| [locale](#locale) | `string` | Required | cannot be null | [SendMailLoginCodeRequest](sendmaillogincoderequest-properties-locale.md "https://timelimit.io/SendMailLoginCodeRequest#/properties/locale") |
|
||||
| [deviceAuthToken](#deviceauthtoken) | `string` | Optional | cannot be null | [SendMailLoginCodeRequest](sendmaillogincoderequest-properties-deviceauthtoken.md "https://timelimit.io/SendMailLoginCodeRequest#/properties/deviceAuthToken") |
|
||||
|
||||
## mail
|
||||
|
||||
|
@ -57,4 +58,22 @@ https://timelimit.io/SendMailLoginCodeRequest
|
|||
|
||||
`string`
|
||||
|
||||
## deviceAuthToken
|
||||
|
||||
|
||||
|
||||
`deviceAuthToken`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SendMailLoginCodeRequest](sendmaillogincoderequest-properties-deviceauthtoken.md "https://timelimit.io/SendMailLoginCodeRequest#/properties/deviceAuthToken")
|
||||
|
||||
### deviceAuthToken Type
|
||||
|
||||
`string`
|
||||
|
||||
# SendMailLoginCodeRequest Definitions
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
|
||||
<head>
|
||||
<title> </title>
|
||||
<!--[if !mso]><!-- -->
|
||||
<title>
|
||||
</title>
|
||||
<!--[if !mso]><!-->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<!--<![endif]-->
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
|
@ -13,18 +14,6 @@
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
.ReadMsgBody {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ExternalClass {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ExternalClass * {
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
@ -53,29 +42,19 @@
|
|||
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]>
|
||||
<noscript>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG/>
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
</noscript>
|
||||
<![endif]-->
|
||||
<!--[if lte mso 11]>
|
||||
<style type="text/css">
|
||||
.outlook-group-fix { width:100% !important; }
|
||||
.mj-outlook-group-fix { width:100% !important; }
|
||||
</style>
|
||||
<![endif]-->
|
||||
<style type="text/css">
|
||||
|
@ -86,224 +65,126 @@
|
|||
}
|
||||
}
|
||||
</style>
|
||||
<style media="screen and (min-width:480px)">
|
||||
.moz-text-html .mj-column-per-100 {
|
||||
width: 100% !important;
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body style="word-spacing:normal;">
|
||||
<div style="">
|
||||
<!--[if mso | IE]>
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
|
||||
>
|
||||
<tr>
|
||||
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
|
||||
<![endif]-->
|
||||
<div style="background:#009688;background-color:#009688;Margin:0px auto;max-width:600px;">
|
||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" bgcolor="#009688" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
<div style="background:#009688;background-color:#009688;margin:0px auto;max-width:600px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#009688;background-color:#009688;width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="direction:ltr;font-size:0px;padding:20px 0;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:600px;"
|
||||
>
|
||||
<![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%;">
|
||||
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]-->
|
||||
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;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="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:20px;line-height:1;text-align:left;color:#ffffff;"> TimeLimit </div>
|
||||
</td>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:20px;line-height:1;text-align:left;color:#ffffff;">TimeLimit</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<![endif]-->
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
|
||||
>
|
||||
<tr>
|
||||
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
|
||||
<![endif]-->
|
||||
<div style="Margin:0px auto;max-width:600px;">
|
||||
<!--[if mso | IE]></td></tr></table><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
<div style="margin:0px auto;max-width:600px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="direction:ltr;font-size:0px;padding:20px 0;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:600px;"
|
||||
>
|
||||
<![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%;">
|
||||
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]-->
|
||||
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;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="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:1;text-align:left;color:#000000;">
|
||||
<p>
|
||||
<%= introtext %>
|
||||
</p>
|
||||
<p><b><%= code %></b></p>
|
||||
<p>
|
||||
<%= outrotext %>
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:1;text-align:left;color:#000000;">
|
||||
<p> <%= introtext %> </p>
|
||||
<p><b><%= code %></b></p>
|
||||
<p><%= outrotext %></p> <% if (deviceName !== null) { -%> <p><%= deviceNameIntro %> <b><%= deviceName %></b> <%= deviceNameOutro %></p> <% } -%>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<![endif]-->
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
|
||||
>
|
||||
<tr>
|
||||
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
|
||||
<![endif]-->
|
||||
<div style="Margin:0px auto;max-width:600px;">
|
||||
<!--[if mso | IE]></td></tr></table><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
<div style="margin:0px auto;max-width:600px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="direction:ltr;font-size:0px;padding:20px 0;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:600px;"
|
||||
>
|
||||
<![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%;">
|
||||
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]-->
|
||||
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;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 style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<p style="border-top:dashed 1px lightgrey;font-size:1;margin:0px auto;width:100%;"> </p>
|
||||
<!--[if mso | IE]>
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" style="border-top:dashed 1px lightgrey;font-size:1;margin:0px auto;width:550px;" role="presentation" width="550px"
|
||||
>
|
||||
<tr>
|
||||
<td style="height:0;line-height:0;">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<p style="border-top:dashed 1px lightgrey;font-size:1px;margin:0px auto;width:100%;">
|
||||
</p>
|
||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" style="border-top:dashed 1px lightgrey;font-size:1px;margin:0px auto;width:550px;" role="presentation" width="550px" ><tr><td style="height:0;line-height:0;">
|
||||
</td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<![endif]-->
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table
|
||||
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
|
||||
>
|
||||
<tr>
|
||||
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
|
||||
<![endif]-->
|
||||
<div style="Margin:0px auto;max-width:600px;">
|
||||
<!--[if mso | IE]></td></tr></table><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" ><tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;"><![endif]-->
|
||||
<div style="margin:0px auto;max-width:600px;">
|
||||
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="direction:ltr;font-size:0px;padding:20px 0;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:600px;"
|
||||
>
|
||||
<![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%;">
|
||||
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
|
||||
<!--[if mso | IE]><table role="presentation" border="0" cellpadding="0" cellspacing="0"><tr><td class="" style="vertical-align:top;width:600px;" ><![endif]-->
|
||||
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;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="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:1;text-align:left;color:#000000;">
|
||||
<p> You got this mail because your mail address was entered at the TimeLimit App for signing in. If you did not request this mail, then you can ignore it. If you have got any questions, then you can reply to this messagge. </p>
|
||||
<p>
|
||||
Sie erhalten diese Nachricht, da Ihre E-Mail-Adresse in der TimeLimit-App zum Anmelden eingegeben wurde. Wenn Sie diese E-Mail nicht angefordert haben, können Sie diese ignorieren. Falls Sie Fragen haben können Sie einfach auf
|
||||
diese E-Mail antworten. </p>
|
||||
<p> ©
|
||||
<%= mailimprint %>
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
|
||||
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:1;text-align:left;color:#000000;">
|
||||
<p> You got this mail because your mail address was entered at the TimeLimit App for signing in. If you did not request this mail, then you can ignore it. If you have got any questions, then you can reply to this messagge. </p>
|
||||
<p> Sie erhalten diese Nachricht, da Ihre E-Mail-Adresse in der TimeLimit-App zum Anmelden eingegeben wurde. Wenn Sie diese E-Mail nicht angefordert haben, können Sie diese ignorieren. Falls Sie Fragen haben können Sie einfach auf diese E-Mail antworten. </p>
|
||||
<p> © <%= mailimprint %> </p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<![endif]-->
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<![endif]-->
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
</p>
|
||||
<p><b><%= code %></b></p>
|
||||
<p><%= outrotext %></p>
|
||||
<% if (deviceName !== null) { -%>
|
||||
<p><%= deviceNameIntro %> <b><%= deviceName %></b> <%= deviceNameOutro %></p>
|
||||
<% } -%>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
</mj-section>
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
<%- outrotext %>
|
||||
|
||||
<% if (deviceName !== null) { -%>
|
||||
<%- deviceNameIntro %> <%- deviceName %> <%- deviceNameOutro %>
|
||||
|
||||
<% } -%>
|
||||
----------------------
|
||||
|
||||
You got this mail because your mail address was entered at the TimeLimit App for signing in.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2020 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2021 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
|
@ -48,6 +48,7 @@ export const createAuthRouter = (database: Database) => {
|
|||
} else {
|
||||
const { mailLoginToken } = await sendLoginCode({
|
||||
mail,
|
||||
deviceAuthToken: req.body.deviceAuthToken,
|
||||
locale: req.body.locale,
|
||||
database
|
||||
})
|
||||
|
|
|
@ -132,6 +132,7 @@ export interface RequestWithAuthToken {
|
|||
export interface SendMailLoginCodeRequest {
|
||||
mail: string
|
||||
locale: string
|
||||
deviceAuthToken?: string
|
||||
}
|
||||
|
||||
export interface SignInByMailCodeRequest {
|
||||
|
|
|
@ -2966,6 +2966,9 @@ export const isSendMailLoginCodeRequest: (value: object) => value is SendMailLog
|
|||
},
|
||||
"locale": {
|
||||
"type": "string"
|
||||
},
|
||||
"deviceAuthToken": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2020 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2021 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
|
@ -15,7 +15,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Forbidden, Gone, TooManyRequests } from 'http-errors'
|
||||
import { Forbidden, Gone, TooManyRequests, Unauthorized } from 'http-errors'
|
||||
import { Database } from '../../database'
|
||||
import { sendAuthenticationMail } from '../../util/mail'
|
||||
import { areWordSequencesEqual, randomWords } from '../../util/random-words'
|
||||
|
@ -23,12 +23,52 @@ import { checkMailSendLimit } from '../../util/ratelimit-authmail'
|
|||
import { generateAuthToken } from '../../util/token'
|
||||
import { createAuthTokenByMailAddress } from './index'
|
||||
|
||||
export const sendLoginCode = async ({ mail, locale, database }: {
|
||||
export const sendLoginCode = async ({ mail, deviceAuthToken, locale, database }: {
|
||||
mail: string
|
||||
deviceAuthToken?: string
|
||||
locale: string
|
||||
database: Database
|
||||
// no transaction here because this is directly called from an API endpoint
|
||||
}): Promise<{ mailLoginToken: string }> => {
|
||||
let deviceName = null
|
||||
|
||||
if (deviceAuthToken !== undefined) {
|
||||
const info = await database.transaction(async (transaction) => {
|
||||
const deviceEntryUnsafe = await database.device.findOne({
|
||||
where: { deviceAuthToken },
|
||||
attributes: ['familyId', 'name'],
|
||||
transaction
|
||||
})
|
||||
|
||||
if (!deviceEntryUnsafe) {
|
||||
throw new Unauthorized()
|
||||
}
|
||||
|
||||
const deviceEntry = {
|
||||
familyId: deviceEntryUnsafe.familyId,
|
||||
name: deviceEntryUnsafe.name
|
||||
}
|
||||
|
||||
const userEntryCounter = await database.user.count({
|
||||
where: {
|
||||
familyId: deviceEntry.familyId,
|
||||
mail
|
||||
},
|
||||
transaction
|
||||
})
|
||||
|
||||
if (userEntryCounter === 1) {
|
||||
return { deviceName: deviceEntry.name }
|
||||
} else {
|
||||
// do not show the device name if it is from another family
|
||||
// otherwise third parties could chose a part of the content of the mail
|
||||
return { deviceName: null }
|
||||
}
|
||||
})
|
||||
|
||||
deviceName = info.deviceName
|
||||
}
|
||||
|
||||
try {
|
||||
await checkMailSendLimit(mail)
|
||||
} catch (ex) {
|
||||
|
@ -41,7 +81,8 @@ export const sendLoginCode = async ({ mail, locale, database }: {
|
|||
await sendAuthenticationMail({
|
||||
receiver: mail,
|
||||
code,
|
||||
locale
|
||||
locale,
|
||||
deviceName
|
||||
})
|
||||
|
||||
await database.transaction(async (transaction) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2020 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2021 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
|
@ -36,7 +36,11 @@ const email = new Email({
|
|||
}
|
||||
})
|
||||
|
||||
export const sendAuthenticationMail = async ({ receiver, code, locale }: {receiver: string, code: string, locale: string}) => {
|
||||
export const sendAuthenticationMail = async ({
|
||||
receiver, code, locale, deviceName
|
||||
}: {
|
||||
receiver: string, code: string, locale: string, deviceName: string | null
|
||||
}) => {
|
||||
await email.send({
|
||||
template: join(__dirname, '../../other/mail/login'),
|
||||
message: {
|
||||
|
@ -47,7 +51,10 @@ export const sendAuthenticationMail = async ({ receiver, code, locale }: {receiv
|
|||
introtext: locale === 'de' ? 'Geben Sie zum Authentifizieren folgenden Code in TimeLimit ein' : 'To authenticate, enter the following code in TimeLimit',
|
||||
code,
|
||||
outrotext: locale === 'de' ? 'Geben Sie diesen Code nicht an Dritte weiter.' : 'Do not share this code with third parties.',
|
||||
mailimprint
|
||||
mailimprint,
|
||||
deviceName,
|
||||
deviceNameIntro: locale === 'de' ? 'Die Anmeldung wurde am Gerät' : 'The login was attempted at the device',
|
||||
deviceNameOutro: locale === 'de' ? 'versucht.' : '.'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue