registration email added
Some checks failed
Gitea Docker Redeploy / Redploy-App-on-self-via-SSH (push) Failing after 17s

This commit is contained in:
Tobias Weise 2024-09-11 20:58:03 +02:00
parent e9c1d1815f
commit 83ea3a7a64
12 changed files with 156 additions and 52 deletions

View File

@ -21,6 +21,10 @@ jobs:
git pull git pull
echo "============ Git pull finished! =========" echo "============ Git pull finished! ========="
echo '${{ vars.ENV }}' > .env echo '${{ vars.ENV }}' > .env
echo '\n' >> .env
echo '${{ secrets.CB_EMAIL_SMTP }}\n' >> .env
echo '${{ secrets.CB_EMAIL_ADDR }}\n' >> .env
echo '${{ secrets.CB_EMAIL_PWD }}\n' >> .env
echo "============ Env creation finished! =========" echo "============ Env creation finished! ========="

View File

@ -19,7 +19,6 @@ from flask import Flask, send_from_directory, send_file, Response, request, json
from flask_openapi3 import Info, Tag, OpenAPI, Server #FileStorage from flask_openapi3 import Info, Tag, OpenAPI, Server #FileStorage
from flask_socketio import SocketIO, join_room, leave_room, rooms, send from flask_socketio import SocketIO, join_room, leave_room, rooms, send
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
import asyncio import asyncio
import logging import logging
@ -133,6 +132,9 @@ def uses_jwt(logger=None, required=True):
def create_app(): def create_app():
app_name = "Creative Bots"
# JWT Bearer Sample # JWT Bearer Sample
jwt = { jwt = {
"type": "http", "type": "http",
@ -144,7 +146,7 @@ def create_app():
info = Info( info = Info(
title="CreativeBots-API", title=app_name + " API",
version=__version__, version=__version__,
summary="The REST-API to manage bots, users and more!", summary="The REST-API to manage bots, users and more!",
description="" description=""
@ -192,13 +194,10 @@ def create_app():
@socket.on('client message') @socket.on('client message')
def handle_message(message): def handle_message(message):
SocketMessage.model_validate(message) SocketMessage.model_validate(message)
logger.info("Starting stream") logger.info("Starting stream")
#try:
room = message["room"] room = message["room"]
question = message["question"] question = message["question"]
system_prompt = message["system_prompt"] system_prompt = message["system_prompt"]
@ -305,12 +304,20 @@ def create_app():
case [user]: case [user]:
if user["password_hash"] == hash_password(form.password + form.email): if user["password_hash"] == hash_password(form.password + form.email):
token = pyjwt.encode({"email": form.email}, jwt_secret, algorithm="HS256") if not user["isEmailVerified"]:
#logger.info(token) msg = "E-Mail unverified!"
return jsonify({ logger.error(msg)
'status': 'success', return jsonify({
'jwt': token 'status': 'error',
}) 'message': msg
}), 400
else:
token = pyjwt.encode({"email": form.email}, jwt_secret, algorithm="HS256")
#logger.info(token)
return jsonify({
'status': 'success',
'jwt': token
})
else: else:
msg = "Invalid password!" msg = "Invalid password!"
logger.error(msg) logger.error(msg)
@ -341,12 +348,15 @@ def create_app():
if User.get(id=form.email, ignore=404) is not None: if User.get(id=form.email, ignore=404) is not None:
msg = "User with that e-mail address already exists!"
logger.error(msg)
return jsonify({ return jsonify({
'status': 'error', 'status': 'error',
"message": "User with that e-mail address already exists!" "message": msg
}) })
else: else:
logger.info("Try creating user...!")
user = User(meta={'id': form.email}) user = User(meta={'id': form.email})
user.creation_date = datetime.now() user.creation_date = datetime.now()
user.email = form.email user.email = form.email
@ -354,21 +364,23 @@ def create_app():
user.role = "User" user.role = "User"
user.isEmailVerified = False user.isEmailVerified = False
user.save() user.save()
logger.info("User created!")
msg = """ msg = f"""
<h1>Verify E-Mail</h1> <h1>Verify E-Mail</h1>
Hi!
Please click on the following link to verify your e-mail: Please click on the following link to verify your e-mail:
<a href="http://127.0.0.1:5000/verify?id={user.password_hash}">Click here!</a>
<a href="http://127.0.0.1:5000/">Click here!</a>
""" """
send_mail(user.email, "User registration @ Creative Bots", "Creative Bots", msg) send_mail(
target_mail=user.email,
subject="User registration @ " + app_name,
msg=msg
)
logger.info("Mail send!")
return jsonify({ return jsonify({
'status': 'success' 'status': 'success'
}) })
@ -599,9 +611,6 @@ def create_app():
"score_docs": xs "score_docs": xs
}) })
#-----------------Embedding---------------------- #-----------------Embedding----------------------
class TrainTextRequest(BaseModel): class TrainTextRequest(BaseModel):
@ -659,15 +668,41 @@ def create_app():
d = {} d = {}
d["module_versions"] = get_module_versions() d["module_versions"] = get_module_versions()
d["OLLAMA_NUM_PARALLEL"] = os.getenv("OLLAMA_NUM_PARALLEL") #d["OLLAMA_NUM_PARALLEL"] = os.getenv("OLLAMA_NUM_PARALLEL")
d["OLLAMA_MAX_LOADED_MODELS"] = os.getenv("OLLAMA_MAX_LOADED_MODELS") #d["OLLAMA_MAX_LOADED_MODELS"] = os.getenv("OLLAMA_MAX_LOADED_MODELS")
d["cpus"] = multiprocessing.cpu_count() d["cpus"] = multiprocessing.cpu_count()
#return "CPUs: " + str(cpus) + "<br>" + json.dumps(get_module_versions(), indent=4).replace("\n", "<br>") #return "CPUs: " + str(cpus) + "<br>" + json.dumps(get_module_versions(), indent=4).replace("\n", "<br>")
return json.dumps(d, indent=4).replace("\n", "<br>") return json.dumps(d, indent=4).replace("\n", "<br>")
@app.route("/verify", methods=['GET'])
def verify_email():
x = request.args.get('id')
s = User.search()
s = s.filter('term', isEmailVerified=False).query('match', password_hash=x)
results = s.execute()
# when you execute the search the results are wrapped in your document class (Post)
for user in results:
#print(post.meta.score, post.title)
if user.password_hash == x:
user.isEmailVerified = True
user.save()
return "E-Mail verified!"
return "Verrification Error!"
"""
match get_by_id(index="user", id_field_name="password_hash", id_value=x):
case [d]:
#user.isEmailVerified = True
#user.save()
return "E-Mail verified!"
case _:
return "Verrification Error!"
"""
@app.route('/<path:path>') #generische Route (auch Unterordner) @app.route('/<path:path>') #generische Route (auch Unterordner)

View File

@ -9,8 +9,7 @@ from elasticsearch.exceptions import ConnectionError
def get_by_id(index: str, id_field_name: str, id_value: str): def get_by_id(index: str, id_field_name: str, id_value: str):
client = connections.get_connection() response = Search(using=connections.get_connection(), index=index).filter("term", **{id_field_name: id_value})[0:10000].execute()
response = Search(using=client, index=index).filter("term", **{id_field_name: id_value})[0:10000].execute()
return [hit.to_dict() for hit in response] return [hit.to_dict() for hit in response]
@ -30,15 +29,13 @@ def update_by_id(index: str, id_field_name: str, id_value: str, values_to_set: D
def delete_by_id(index: str, id_field_name: str, id_value: str): def delete_by_id(index: str, id_field_name: str, id_value: str):
client = connections.get_connection() s = Search(using=connections.get_connection(), index=index).filter("term", **{id_field_name: id_value})
s = Search(using=client, index=index).filter("term", **{id_field_name: id_value})
response = s.delete() response = s.delete()
#if not response.success(): #if not response.success():
# raise Exception("Unable to delete id '%s' in index '%' !" % (index, id_value)) # raise Exception("Unable to delete id '%s' in index '%' !" % (index, id_value))
print(response, flush=True) print(response, flush=True)
def get_datetime_interval(search: Search, start, end) -> Search: def get_datetime_interval(search: Search, start, end) -> Search:
return search.filter("range", timest={"gte": start}).filter("range", timest={"lte": end}) return search.filter("range", timest={"gte": start}).filter("range", timest={"lte": end})
@ -57,21 +54,18 @@ def simplify_properties(d):
def get_type_schema(): def get_type_schema():
client = connections.get_connection() d = connections.get_connection().indices.get(index="*").body
d = client.indices.get(index="*").body
new_d = {} new_d = {}
for index, d2 in d.items(): for index, d2 in d.items():
new_d[index] = simplify_properties(d2["mappings"]) new_d[index] = simplify_properties(d2["mappings"])
return new_d return new_d
def wait_for_elasticsearch(): def wait_for_elasticsearch():
i = 1 i = 1
while True: while True:
try: try:
client = connections.get_connection() connections.get_connection().indices.get_alias(index="*")
client.indices.get_alias(index="*")
print("Elasticsearch found! Run Flask-app!", flush=True) print("Elasticsearch found! Run Flask-app!", flush=True)
return return
except ConnectionError: except ConnectionError:

View File

@ -1,14 +1,33 @@
import os
from jinja2 import Environment, FileSystemLoader
from smtplib import * from smtplib import *
from email.mime.text import MIMEText from email.message import EmailMessage
def send_mail(target_mail, subject, sender_mail, msg): env = Environment(loader=FileSystemLoader('templates'))
msg = MIMEText(msg) # Credentials
username = os.getenv("EMAIL_ADDR")
password = os.getenv("EMAIL_PWD")
smtp_domain_and_port = os.getenv("EMAIL_SMTP")
assert username
assert password
def send_mail(target_mail, subject, msg, sender_mail=username):
html = env.get_template('html_mail.twig').render(
subject=subject,
msg=msg
)
msg = EmailMessage()
msg['Subject'] = subject msg['Subject'] = subject
msg['From'] = sender_mail msg['From'] = sender_mail
msg['To'] = target_mail msg['To'] = target_mail
msg.set_content(html, subtype='html')
smtp = SMTP('mailserver', port=10025) domain, port = smtp_domain_and_port.split(":")
smtp.sendmail("Creative Bots", [target_mail], msg.as_string())
smtp.quit()
#with SMTP_SSL('smtp.gmx.de', port=465) as smtp:
with SMTP_SSL(domain, port=int(port)) as smtp:
smtp.login(username, password)
smtp.send_message(msg)

View File

@ -4,7 +4,10 @@ from elasticsearch_dsl import Document, InnerDoc, Nested, Date, Integer, Keyword
class User(Document): class User(Document):
creation_date = Date() creation_date = Date()
email = Keyword() email = Keyword()
password_hash = Text(index=False) #password_hash = Text(index=False)
password_hash = Keyword()
#password_hash = Text(index=True)
role = Keyword() role = Keyword()
#salt = Text(index=False) #salt = Text(index=False)

View File

@ -2,6 +2,7 @@
All around managing users All around managing users
""" """
import os, json, hashlib, traceback, logging import os, json, hashlib, traceback, logging
from datetime import datetime, date
from elasticsearch import NotFoundError, Elasticsearch # for normal read/write without vectors from elasticsearch import NotFoundError, Elasticsearch # for normal read/write without vectors
from lib.models import User from lib.models import User
@ -15,7 +16,6 @@ assert elastic_url
def hash_password(s: str) -> str: def hash_password(s: str) -> str:
return hashlib.md5(s.encode('utf-8')).hexdigest() return hashlib.md5(s.encode('utf-8')).hexdigest()
def create_user(email, password, role="user", verified=False): def create_user(email, password, role="user", verified=False):
user = User(meta={'id': email}, email=email, password_hash=hash_password(password + email), role=role) user = User(meta={'id': email}, email=email, password_hash=hash_password(password + email), role=role)
user.creation_date = datetime.now() user.creation_date = datetime.now()

View File

@ -260,7 +260,7 @@
<br> <br>
<div class="input-group"> <div class="input-group">
<span class="input-group-text">@ <span class="input-group-text">
<select name="bots" id="bot_select" class="form-select"></select> <select name="bots" id="bot_select" class="form-select"></select>
</span> </span>
<input class="form-control" list="questions" name="question" id="user_input" placeholder="What is..."> <input class="form-control" list="questions" name="question" id="user_input" placeholder="What is...">
@ -270,7 +270,7 @@
<option value="Is a monad a burito?"> <option value="Is a monad a burito?">
<option value="Give the JSON of a graph linking Germanys 9 biggest cities"> <option value="Give the JSON of a graph linking Germanys 9 biggest cities">
</datalist> </datalist>
<button id="submit_btn" class="btn btn-success" type="button">Send</button> <button id="submit_btn" class="btn btn-success" type="button"></button>
</div> </div>
<div class="input-group"> <div class="input-group">
<!-- Button to open the offcanvas sidebar --> <!-- Button to open the offcanvas sidebar -->
@ -459,6 +459,8 @@
</div> </div>
<!--
<footer> <footer>
<div id="fun2" class="container-fluid p-3 bg-primary text-white mt-5"> <div id="fun2" class="container-fluid p-3 bg-primary text-white mt-5">
<div class="row"> <div class="row">
@ -482,6 +484,8 @@
</div> </div>
</div> </div>
</footer> </footer>
-->
<script src="main.js"></script> <script src="main.js"></script>
</body> </body>
</html> </html>

View File

@ -684,6 +684,7 @@ window.onload = async ()=>{
} }
catch(e){ catch(e){
console.error(e);
console.error("Registration failed!"); console.error("Registration failed!");
} }
}; };

View File

@ -3,6 +3,7 @@ webdriver_manager
requests==2.32.3 requests==2.32.3
selenium==4.23.1 selenium==4.23.1
bs4 bs4
jinja2
elasticsearch==8.15.0 elasticsearch==8.15.0
elasticsearch-dsl==8.15.1 elasticsearch-dsl==8.15.1

View File

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>{{ subject }}</title>
<meta charset="utf-8">
<!--
<link rel="stylesheet" type="text/css" hs-webfonts="true" href="https://fonts.googleapis.com/css?family=Lato|Lato:i,b,bi">
-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style type="text/css">
h1{font-size:56px}
h2{font-size:28px;font-weight:900}
p{font-weight:100}
td{vertical-align:top}
#email{margin:auto;width:600px;background-color:#fff}
</style>
</head>
<body bgcolor="#F5F8FA" style="width: 100%; font-family:Lato, sans-serif; font-size:18px;">
<div id="email">
<table role="presentation" width="100%">
<tr>
<td bgcolor="#00A4BD" align="center" style="color: white;">
<h1>{{ subject }}</h1>
</td>
</table>
<table role="presentation" border="0" cellpadding="0" cellspacing="10px" style="padding: 30px 30px 30px 60px;">
<tr>
<td>
<p>
{{ msg }}
</p>
</td>
</tr>
</table>
</div>
</body>
</html>

View File

@ -19,6 +19,7 @@ services:
minio: minio:
container_name: ${APP_PREFIX}_minio container_name: ${APP_PREFIX}_minio
image: minio/minio image: minio/minio
restart: always
ports: ports:
- "29000:9000" - "29000:9000"
- "29001:9001" - "29001:9001"
@ -37,7 +38,8 @@ services:
image: neo4j image: neo4j
#image: neo4j:3.5 #image: neo4j:3.5
#image: neo4j:4.1 #image: neo4j:4.1
restart: unless-stopped #restart: unless-stopped
restart: always
ports: ports:
- 7474:7474 - 7474:7474
- 7687:7687 - 7687:7687
@ -104,12 +106,6 @@ services:
- /dev/dri - /dev/dri
#ollama-webui: #ollama-webui:
# container_name: ${APP_PREFIX}_ollama-webui # container_name: ${APP_PREFIX}_ollama-webui
# image: ghcr.io/ollama-webui/ollama-webui:main # image: ghcr.io/ollama-webui/ollama-webui:main

View File

@ -9,3 +9,9 @@ SECRET=23A344F670E
#WARN INFO FATAL #WARN INFO FATAL
LOG_LEVEL=WARN LOG_LEVEL=WARN
#Admin E-Mail sender account
EMAIL_SMTP=smtp.mail.net:465
EMAIL_ADDR=user@mail.net
EMAIL_PWD=somepass