database and services updated and tested
This commit is contained in:
0
api_services/__init__.py
Normal file
0
api_services/__init__.py
Normal file
9
api_services/email/config.py
Normal file
9
api_services/email/config.py
Normal 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,
|
||||
)
|
||||
32
api_services/email/service.py
Normal file
32
api_services/email/service.py
Normal 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
|
||||
31
api_services/redis/conn.py
Normal file
31
api_services/redis/conn.py
Normal 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)
|
||||
|
||||
|
||||
240
api_services/redis/functions.py
Normal file
240
api_services/redis/functions.py
Normal 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."
|
||||
# ),
|
||||
# )
|
||||
96
api_services/redis/old_functions.py
Normal file
96
api_services/redis/old_functions.py
Normal 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."
|
||||
),
|
||||
)
|
||||
243
api_services/templates/password_templates.py
Normal file
243
api_services/templates/password_templates.py
Normal 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>© %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>© %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>© %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
|
||||
Reference in New Issue
Block a user