✨ Added email-verification
This commit is contained in:
+3
-3
@@ -12,14 +12,14 @@ async def cache_account(criteria: str, content: str) -> Union[User, None]:
|
|||||||
|
|
||||||
if criteria == "email":
|
if criteria == "email":
|
||||||
try:
|
try:
|
||||||
res = await User.objects.get(email=content)
|
res = await User.objects.get(email=content, verified=True)
|
||||||
except ormar.exceptions.NoMatch:
|
except ormar.exceptions.NoMatch:
|
||||||
return None
|
return None
|
||||||
await insert_into_redis(res, content)
|
await insert_into_redis(res, content)
|
||||||
return res
|
return res
|
||||||
elif criteria == "username":
|
elif criteria == "username":
|
||||||
try:
|
try:
|
||||||
res = await User.objects.get(username=content)
|
res = await User.objects.get(username=content, verified=True)
|
||||||
except ormar.exceptions.NoMatch:
|
except ormar.exceptions.NoMatch:
|
||||||
return None
|
return None
|
||||||
await insert_into_redis(res, content)
|
await insert_into_redis(res, content)
|
||||||
@@ -27,7 +27,7 @@ async def cache_account(criteria: str, content: str) -> Union[User, None]:
|
|||||||
elif criteria == "id":
|
elif criteria == "id":
|
||||||
|
|
||||||
try:
|
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:
|
except ormar.exceptions.NoMatch:
|
||||||
return None
|
return None
|
||||||
await insert_into_redis(res, content)
|
await insert_into_redis(res, content)
|
||||||
|
|||||||
@@ -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):
|
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')
|
||||||
|
|||||||
@@ -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">
|
||||||
|
💌 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>
|
||||||
+3
-32
@@ -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
|
<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>
|
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'>
|
<div style='box-sizing: border-box;width: 100%;margin-bottom: 30px;margin-top: 15px'>
|
||||||
@@ -63,7 +48,7 @@
|
|||||||
<tr>
|
<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"
|
<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
|
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'
|
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'
|
rel='external nofollow noopener noreferrer' target='_blank'
|
||||||
tabindex='-1'>Confirm Email Address</a></td>
|
tabindex='-1'>Confirm Email Address</a></td>
|
||||||
@@ -83,20 +68,6 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div style='box-sizing: border-box;clear: both;width: 100%'>
|
{% include 'footer.jinja2' %}
|
||||||
<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">
|
|
||||||
💌 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>
|
|
||||||
</div>
|
</div>
|
||||||
@@ -6,7 +6,7 @@ from classquiz.auth import *
|
|||||||
from fastapi.background import BackgroundTasks
|
from fastapi.background import BackgroundTasks
|
||||||
from classquiz.emails import send_mail
|
from classquiz.emails import send_mail
|
||||||
from classquiz.config import redis
|
from classquiz.config import redis
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse, RedirectResponse
|
||||||
|
|
||||||
from classquiz.db.models import *
|
from classquiz.db.models import *
|
||||||
|
|
||||||
@@ -96,3 +96,14 @@ async def logout(request: Request, response: Response):
|
|||||||
@router.get("/check")
|
@router.get("/check")
|
||||||
async def check_token(user: User = Depends(get_current_user)):
|
async def check_token(user: User = Depends(get_current_user)):
|
||||||
return {"email": user.email}
|
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")
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
isSubmitting = true;
|
isSubmitting = true;
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
responseData.data = loginData.password === '' ? 'magic' : 'password';
|
responseData.data = loginData.password === '' ? 'magic' : 'password';
|
||||||
} else if (res.status === 404) {
|
} else if (res.status === 401) {
|
||||||
responseData.data = '404';
|
responseData.data = '404';
|
||||||
} else {
|
} else {
|
||||||
responseData.data = 'error';
|
responseData.data = 'error';
|
||||||
|
|||||||
Reference in New Issue
Block a user