Added email-verification

This commit is contained in:
Mawoka
2022-03-05 15:48:07 +01:00
parent bd00612401
commit df5f73a1d8
6 changed files with 80 additions and 38 deletions
+3 -3
View File
@@ -12,14 +12,14 @@ async def cache_account(criteria: str, content: str) -> Union[User, None]:
if criteria == "email":
try:
res = await User.objects.get(email=content)
res = await User.objects.get(email=content, verified=True)
except ormar.exceptions.NoMatch:
return None
await insert_into_redis(res, content)
return res
elif criteria == "username":
try:
res = await User.objects.get(username=content)
res = await User.objects.get(username=content, verified=True)
except ormar.exceptions.NoMatch:
return None
await insert_into_redis(res, content)
@@ -27,7 +27,7 @@ async def cache_account(criteria: str, content: str) -> Union[User, None]:
elif criteria == "id":
try:
res = await User.objects.get(id=uuid.UUID(content))
res = await User.objects.get(id=uuid.UUID(content), verified=True)
except ormar.exceptions.NoMatch:
return None
await insert_into_redis(res, content)
+37 -1
View File
@@ -1,4 +1,40 @@
from jinja2 import Environment, PackageLoader, select_autoescape
from classquiz.db.models import User
from email.mime.multipart import MIMEMultipart
from classquiz.config import settings
from email.mime.text import MIMEText
import smtplib
import ssl
jinja = Environment(
loader=PackageLoader('classquiz.emails', 'templates'),
autoescape=select_autoescape(['html', 'xml']),
enable_async=True)
def _sendMail(template: str, to: str, subject: str):
msg = MIMEMultipart('alternative')
msg['Subject'] = subject
msg['From'] = settings.mail_address
msg['To'] = to
msg.attach(MIMEText(template, 'html'))
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
server = smtplib.SMTP(host=settings.mail_server, port=settings.mail_port)
server.ehlo()
server.starttls(context=context)
server.ehlo()
server.login(settings.mail_username, settings.mail_password)
server.sendmail(settings.mail_address, to, msg.as_string())
async def send_mail(email: str):
pass
user = await User.objects.get_or_none(email=email, verified=False)
if user is None:
raise ValueError('User not found')
template = jinja.get_template('register.jinja2')
template = await template.render_async(
base_url=settings.root_address,
token=user.verify_key
)
_sendMail(template=template, to=email, subject='Verify your email')
+24
View File
@@ -0,0 +1,24 @@
<style>
.link-hover {
background: linear-gradient(90deg, #009444, #39b54a, #8dc63f);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-decoration: none;
}
</style>
<div style='box-sizing: border-box;clear: both;width: 100%'>
<table
style='box-sizing: border-box;width: 100%;border-spacing: 0;mso-table-rspace: 0pt;mso-table-lspace: 0pt;font-size: 12px;border-collapse: separate !important'
width='100%'>
<tbody>
<tr style='font-size: 12px'>
<td style="box-sizing: border-box;font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;vertical-align: top;font-size: 12px;text-align: center;padding: 20px 0"
valign='top' align='center'>
<p style="margin: 0;color: #294661;font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;font-weight: 300;font-size: 12px;margin-bottom: 5px">
&#128140; Send with love by <a href='https://mawoka.eu/?utm_source=ClassQuiz&utm_medium=Email'
class='link-hover' target='_blank'>Mawoka</a>
</p></td>
</tr>
</tbody>
</table>
</div>
@@ -1,18 +1,3 @@
<!--<h1>Confirm your email-address</h1>
<p>
Thank you for registering at ClassQuiz.
Please confirm your email-address by clicking on the link below.
</p>
<a href='/confirm/{{TEMPLATE}}' style='text-align: center; background: #2aff10' target='_blank'>Confirm your email</a>-->
<style>
.link-hover {
background: linear-gradient(90deg, #009444, #39b54a, #8dc63f);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-decoration: none;
}
</style>
<div style='box-sizing: border-box;display: block;max-width: 600px;margin: 0 auto;padding: 10px'><span
style='color: transparent;height: 0;max-height: 0;max-width: 0;opacity: 0;overflow: hidden;mso-hide: all;visibility: hidden;width: 0'>Let's confirm your email address.</span>
<div style='box-sizing: border-box;width: 100%;margin-bottom: 30px;margin-top: 15px'>
@@ -63,7 +48,7 @@
<tr>
<td style="box-sizing: border-box;padding: 0;font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;font-size: 16px;vertical-align: top;background-color: #348eda;border-radius: 2px;text-align: center;background-color: #348eda"
valign='top' align='center'><a
href='CONFIRM_URL'
href='{{ base_url }}/api/v1/users/verify/{{ token }}'
style='box-sizing: border-box;font-weight: 400;text-decoration: none;display: inline-block;margin: 0;color: #ffffff;background: linear-gradient(90deg, #009444, #39b54a, #8dc63f);border: solid 1px black;border-radius: 2px;font-size: 14px;padding: 12px 45px'
rel='external nofollow noopener noreferrer' target='_blank'
tabindex='-1'>Confirm Email Address</a></td>
@@ -83,20 +68,6 @@
</tbody>
</table>
</div>
<div style='box-sizing: border-box;clear: both;width: 100%'>
<table
style='box-sizing: border-box;width: 100%;border-spacing: 0;mso-table-rspace: 0pt;mso-table-lspace: 0pt;font-size: 12px;border-collapse: separate !important'
width='100%'>
<tbody>
<tr style='font-size: 12px'>
<td style="box-sizing: border-box;font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;vertical-align: top;font-size: 12px;text-align: center;padding: 20px 0"
valign='top' align='center'>
<p style="margin: 0;color: #294661;font-family: 'Open Sans', 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;font-weight: 300;font-size: 12px;margin-bottom: 5px">
&#128140; Send with love by <a href='https://mawoka.eu/?utm_source=ClassQuiz&utm_medium=Email'
class='link-hover' target='_blank'>Mawoka</a>
</p></td>
</tr>
</tbody>
</table>
</div>
{% include 'footer.jinja2' %}
</div>
+12 -1
View File
@@ -6,7 +6,7 @@ from classquiz.auth import *
from fastapi.background import BackgroundTasks
from classquiz.emails import send_mail
from classquiz.config import redis
from fastapi.responses import JSONResponse
from fastapi.responses import JSONResponse, RedirectResponse
from classquiz.db.models import *
@@ -96,3 +96,14 @@ async def logout(request: Request, response: Response):
@router.get("/check")
async def check_token(user: User = Depends(get_current_user)):
return {"email": user.email}
@router.get("/verify/{verify_key}")
async def verify_user(verify_key: str):
user = await User.objects.filter(verify_key=verify_key).get_or_none()
if user is None:
raise HTTPException(status_code=404, detail="User not found")
user.verified = True
user.verify_key = None
await user.update()
return RedirectResponse(url="/account/login?verified=true")
+1 -1
View File
@@ -53,7 +53,7 @@
isSubmitting = true;
if (res.status === 200) {
responseData.data = loginData.password === '' ? 'magic' : 'password';
} else if (res.status === 404) {
} else if (res.status === 401) {
responseData.data = '404';
} else {
responseData.data = 'error';