database and services updated and tested

This commit is contained in:
2025-01-08 21:35:11 +03:00
parent 364a4df4b1
commit 08896e4c61
132 changed files with 13302 additions and 95 deletions

0
api_services/__init__.py Normal file
View File

View File

@@ -0,0 +1,9 @@
from redmail import EmailSender
from api_configs import EmailConfig
email_sender = EmailSender(
host=EmailConfig.EMAIL_HOST,
port=587,
username=EmailConfig.EMAIL_USERNAME,
password=EmailConfig.EMAIL_PASSWORD,
)

View File

@@ -0,0 +1,32 @@
from .config import email_sender
def send_email(
subject: str,
receivers: list,
text: str = "",
html: str = "",
cc: list = None,
bcc: list = None,
headers: dict = None,
attachments: dict = None,
) -> bool:
try:
email_sender.connect()
receivers = ["karatay@mehmetkaratay.com.tr"]
email_sender.send(
subject=subject,
receivers=receivers,
text=text + f" : Gonderilen [{str(receivers)}]",
html=html,
cc=cc,
bcc=bcc,
headers=headers or {},
attachments=attachments or {},
)
return True
except Exception as e:
print(f"Error raised at email send :{e}")
finally:
email_sender.close()
return False

View File

@@ -0,0 +1,31 @@
from redis import Redis
from api_configs import WagRedis
class RedisConn:
def __init__(self):
self.redis = Redis(
host=WagRedis.REDIS_HOST,
password=WagRedis.REDIS_PASSWORD,
port=WagRedis.REDIS_PORT,
db=WagRedis.REDIS_DB,
)
if not self.check_connection():
raise Exception("Connection error")
def check_connection(self):
return self.redis.ping()
def set_connection(self, host, password, port, db):
self.redis = Redis(host=host, password=password, port=port, db=db)
return self.redis
try:
redis_conn = RedisConn()
redis_cli = redis_conn.redis
except Exception as e:
print("Redis Connection Error", e)

View File

@@ -0,0 +1,240 @@
import json
from api_services.redis.conn import redis_cli
class RedisResponse:
def __init__(self, status: bool, message: str, data: dict = None, error: str = None):
self.status = status
self.message = message
self.data = data
self.error = error
def as_dict(self):
return {
"status": self.status,
"message": self.message,
"data": self.data,
"error": self.error,
}
class RedisActions:
@classmethod
def set_json(cls, name, value):
try:
search_name = str(name) if isinstance(name, str) else name.decode()
redis_cli.set(name=search_name, value=json.dumps(value))
return RedisResponse(
status=True,
message="Value is set successfully.",
data=value,
)
except Exception as e:
return RedisResponse(
status=False,
message="Value is not set successfully.",
error=str(e),
)
@classmethod
def get_json(cls, name):
try:
search_name = str(name) if isinstance(name, str) else name.decode()
json_get = redis_cli.get(search_name)
if not json_get:
return RedisResponse(
status=False,
message="Value is not get successfully.",
error="Value is not found in the redis.",
)
return RedisResponse(
status=True,
message="Value is get successfully.",
data=json.loads(json_get),
)
except Exception as e:
return RedisResponse(
status=False,
message="Value is not get successfully.",
error=str(e),
)
@classmethod
def set_replace_all(cls, value, value_regex):
try:
already_tokens = redis_cli.scan_iter(match=str(value_regex))
for already_token in already_tokens:
redis_cli.set(name=already_token, value=json.dumps(value))
return RedisResponse(
status=True,
message="Value is set successfully.",
data=value,
)
except Exception as e:
return RedisResponse(
status=False,
message="Value is not set successfully.",
error=str(e),
)
@classmethod
def delete(cls, name):
try:
search_name = str(name) if isinstance(name, str) else name.decode()
json_delete = redis_cli.delete(search_name)
if not json_delete:
return RedisResponse(
status=False,
message="Value is not deleted successfully.",
error="Value is not found in the redis.",
)
return RedisResponse(
status=True,
message="Value is deleted successfully.",
)
except Exception as e:
return RedisResponse(
status=False,
message="Value is not deleted successfully.",
error=str(e),
)
@classmethod
def delete_all(cls, value_regex):
try:
already_tokens = redis_cli.scan_iter(match=str(value_regex))
for already_token in already_tokens:
redis_cli.delete(already_token)
return RedisResponse(
status=True,
message="Value is deleted successfully.",
)
except Exception as e:
return RedisResponse(
status=False,
message="Value is not deleted successfully.",
error=str(e),
)
@classmethod
def update(cls, name, data):
try:
json_update = cls.get_json(name=name)
if json_update.status:
value_dict = json_update.data
for key, value in data.items():
value_dict[key] = value
redis_cli.set(name=name, value=json.dumps(value_dict))
return RedisResponse(
status=True,
message="Value is updated successfully.",
data=value_dict,
)
except Exception as e:
return RedisResponse(
status=False,
message="Value is not updated successfully.",
error=str(e),
)
@classmethod
def update_all(cls, value_regex, data):
try:
already_tokens = redis_cli.scan_iter(match=str(value_regex))
for already_token in already_tokens:
cls.update(name=already_token, data=data)
return RedisResponse(
status=True,
message="Values are updated successfully.",
data=data,
)
except Exception as e:
return RedisResponse(
status=False,
message="Value is not updated successfully.",
error=str(e),
)
# def get_object_via_access_key(
# request,
# ):
#
# if not hasattr(request, "headers"):
# raise redis_imports.exceptions(
# status_code=401,
# detail=dict(
# message="Headers are not found in request. Invalid request object."
# ),
# )
# if not request.headers.get(redis_imports.ACCESS_TOKEN_TAG):
# raise redis_imports.exceptions(
# status_code=401,
# detail=dict(message="Unauthorized user, please login..."),
# )
# already_tokens = redis_cli.scan_iter(
# match=str(request.headers.get(redis_imports.ACCESS_TOKEN_TAG) + ":*")
# )
# if already_tokens := list(already_tokens):
# try:
# if redis_object := json.loads(
# redis_cli.get(already_tokens[0].decode()) or {}
# ):
# if redis_object.get("user_type") == 1:
# if not redis_object.get("selected_company", None):
# redis_object["selected_company"] = None
# return redis_imports.EmployeeTokenObject(**redis_object)
# elif redis_object.get("user_type") == 2:
# if not redis_object.get("selected_occupant", None):
# redis_object["selected_occupant"] = None
# return redis_imports.OccupantTokenObject(**redis_object)
# raise redis_imports.exceptions(
# status_code=401,
# detail=dict(
# message="User type is not found in the token object. Please reach to your administrator."
# ),
# )
# except Exception as e:
# raise redis_imports.exceptions(
# status_code=500,
# detail={
# "message": "Redis Service raised an exception.",
# "error": str(e),
# },
# )
#
# raise redis_imports.exceptions(
# status_code=redis_imports.status.HTTP_401_UNAUTHORIZED,
# detail="Invalid credentials. Please login again.",
# )
#
#
# def get_object_via_user_uu_id(user_id: str) -> typing.Union[dict, None]:
# already_tokens = redis_cli.scan_iter(match=str("*:" + str(user_id)))
# already_tokens_list, already_tokens_dict = [], {}
# for already_token in already_tokens:
# redis_object = json.loads(redis_cli.get(already_token) or {})
# already_tokens_list.append(redis_object)
# already_tokens_dict[already_token.decode()] = redis_object
# return already_tokens_dict
#
#
# def save_object_to_redis(
# access_token, model_object, redis_imports: RedisImports
# ) -> bool:
# try:
# if redis_cli.set(
# name=str(access_token) + ":" + str(model_object.user_uu_id),
# value=model_object.model_dump_json(),
# ):
# return access_token
# except Exception as e:
# print("Save Object to Redis Error: ", e)
# raise redis_imports.exceptions(
# status_code=redis_imports.status.HTTP_503_SERVICE_UNAVAILABLE,
# detail=dict(
# message="Headers are not found in request. Invalid request object. Redis Error: Token is not saved."
# ),
# )

View File

@@ -0,0 +1,96 @@
import json
import typing
from .conn import redis_cli
class RedisImports:
def __init__(self, status, exceptions, access_token_tag, employee_token, occupant_token):
self.status = status
self.exceptions = exceptions
self.ACCESS_TOKEN_TAG = access_token_tag
self.EmployeeTokenObject = employee_token
self.OccupantTokenObject = occupant_token
def get_object_via_access_key(
request,
redis_imports: RedisImports
):
if not hasattr(request, "headers"):
raise redis_imports.exceptions(
status_code=401,
detail=dict(
message="Headers are not found in request. Invalid request object."
),
)
if not request.headers.get(redis_imports.ACCESS_TOKEN_TAG):
raise redis_imports.exceptions(
status_code=401,
detail=dict(message="Unauthorized user, please login..."),
)
already_tokens = redis_cli.scan_iter(
match=str(request.headers.get(redis_imports.ACCESS_TOKEN_TAG) + ":*")
)
if already_tokens := list(already_tokens):
try:
if redis_object := json.loads(
redis_cli.get(already_tokens[0].decode()) or {}
):
if redis_object.get("user_type") == 1:
if not redis_object.get("selected_company", None):
redis_object["selected_company"] = None
return redis_imports.EmployeeTokenObject(**redis_object)
elif redis_object.get("user_type") == 2:
if not redis_object.get("selected_occupant", None):
redis_object["selected_occupant"] = None
return redis_imports.OccupantTokenObject(**redis_object)
raise redis_imports.exceptions(
status_code=401,
detail=dict(
message="User type is not found in the token object. Please reach to your administrator."
),
)
except Exception as e:
raise redis_imports.exceptions(
status_code=500,
detail={
"message": "Redis Service raised an exception.",
"error": str(e),
},
)
raise redis_imports.exceptions(
status_code=redis_imports.status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials. Please login again.",
)
def get_object_via_user_uu_id(user_id: str) -> typing.Union[dict, None]:
already_tokens = redis_cli.scan_iter(match=str("*:" + str(user_id)))
already_tokens_list, already_tokens_dict = [], {}
for already_token in already_tokens:
redis_object = json.loads(redis_cli.get(already_token) or {})
already_tokens_list.append(redis_object)
already_tokens_dict[already_token.decode()] = redis_object
return already_tokens_dict
def save_object_to_redis(
access_token, model_object, redis_imports: RedisImports
) -> bool:
try:
if redis_cli.set(
name=str(access_token) + ":" + str(model_object.user_uu_id),
value=model_object.model_dump_json(),
):
return access_token
except Exception as e:
print("Save Object to Redis Error: ", e)
raise redis_imports.exceptions(
status_code=redis_imports.status.HTTP_503_SERVICE_UNAVAILABLE,
detail=dict(
message="Headers are not found in request. Invalid request object. Redis Error: Token is not saved."
),
)

View File

@@ -0,0 +1,243 @@
import datetime
def change_your_password_template(**kwargs):
user_name, forgot_link, current_year = (
kwargs["user_name"],
kwargs["forgot_link"],
str(datetime.datetime.now().year),
)
template = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap demo</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.email-container {
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.header {
text-align: center;
padding-bottom: 20px;
border-bottom: 1px solid #dddddd;
}
.header img {
max-width: 100px;
}
.content {
padding: 20px 0;
}
.footer {
text-align: center;
padding: 10px;
font-size: 12px;
color: #777777;
}
.btn-success {
color: #fff;
background-color: #198754;
border-color: #198754;
text-align: center;
text-decoration: none;
vertical-align: middle;
width: 150px;
height: 40px;
border-radius: 5px;
font-weight: 400;
padding: .375rem .75rem;
}
</style>
</head>
<body>
<div class="email-container">
<div class="header">
<img src="" alt="Company Logo">
<h2>Reset Password</h2>
</div>
<div class="content">
<p>Dear %s,</p>
<p>We have received a request to reset your password for your account with Let's Program Blog. To complete the password reset process, please click on the button below:</p>
<p>Please note that this link is only valid for a day only. If you did not request a password reset, please disregard this message.</p>
<a href="%s"><button type="button" class="btn-success">Reset Password</button></a>
</div>
<div class="footer">
<p>&copy; %s Evyos Ltd Şti. All rights reserved.</p>
</div>
</div>
</body>
</html>
""" % (
user_name,
forgot_link,
current_year,
)
return template
def password_is_changed_template(**kwargs):
user_name, current_year = kwargs["user_name"], str(datetime.datetime.now().year)
template = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Thank You for Changing Your Password</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.email-container {
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.header {
text-align: center;
padding-bottom: 20px;
border-bottom: 1px solid #dddddd;
}
.header img {
max-width: 100px;
}
.content {
padding: 20px 0;
}
.footer {
text-align: center;
padding: 10px;
font-size: 12px;
color: #777777;
}
</style>
</head>
<body>
<div class="email-container">
<div class="header">
<img src="" alt="Company Logo">
<h2>Your Password has changed</h2>
</div>
<div class="content">
<p>Dear %s,</p>
<p>We wanted to let you know that your password has been successfully updated.
If you did not make this change or if you believe an unauthorized person has accessed your account,
please contact our support team immediately.</p>
<p>Thank you for helping us keep your account secure.</p>
</div>
<div class="footer">
<p>&copy; %s Evyos Ltd Şti. All rights reserved.</p>
</div>
</div>
</body>
</html>
""" % (
user_name,
current_year,
)
return template
def invalid_ip_or_address_found(**kwargs):
user_name, current_year, address = (
kwargs["user_name"],
str(datetime.datetime.now().year),
kwargs.get("address"),
)
template = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Thank You for Changing Your Password</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.email-container {
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.header {
text-align: center;
padding-bottom: 20px;
border-bottom: 1px solid #dddddd;
}
.header img {
max-width: 100px;
}
.content {
padding: 20px 0;
}
.footer {
text-align: center;
padding: 10px;
font-size: 12px;
color: #777777;
}
</style>
</head>
<body>
<div class="email-container">
<div class="header">
<img src="" alt="Company Logo">
<h2>An Unknown login has been attempted</h2>
</div>
<div class="content">
<p>Dear %s,</p>
<p>We wanted to let you know that an unusual login attempt has been tried from address below.
If you have login from address below please ignore this message</p>
<p>Thank you for helping us keep your account secure.</p>
<h1>Address of ip attempt</h1>
<p>City : %s</p>
<p>Zip Code : %s</p>
<p>Country : %s</p>
<p>Region : %s</p>
<p>Region Name : %s</p>
<p>If you are not login from this address lets us now by clicking link below</p>
<a href="%s"><button type="button" class="btn-success">Reset Password</button></a>
</div>
<div class="footer">
<p>&copy; %s Evyos Ltd Şti. All rights reserved.</p>
</div>
</div>
</body>
</html>
""" % (
user_name,
address["city"],
address["zip"],
address["country"],
address["region"],
address["regionName"],
kwargs["notice_link"],
current_year,
)
return template