Skip to content

Commit

Permalink
✅ Add logging and 🐛 Fix reset password
Browse files Browse the repository at this point in the history
  • Loading branch information
rapeeza1598 committed Apr 30, 2024
1 parent 09eec93 commit aa0a5d7
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 17 deletions.
57 changes: 57 additions & 0 deletions app/crud/logs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import datetime
from sqlalchemy.orm import Session
from app.models.logs import Logs
import logging

logging.basicConfig(level=logging.INFO,format="%(asctime)s - %(levelname)s - %(message)s")

def create_log_info(db: Session, user_id: str, message: str, station_id: str = None, charging_booth_id: str = None): # type: ignore
current_datetime = datetime.datetime.now()
formatted_datetime = current_datetime.strftime("%Y-%m-%d %H:%M:%S,%f")[:-3]
message = f"{formatted_datetime} - INFO - {message}"
try:
db_log = Logs(user_id=user_id, message=message, station_id=station_id, charging_booth_id=charging_booth_id)
db.add(db_log)
db.commit()
db.refresh(db_log)
return db_log
except Exception as e:
print(e)
return None

def get_logs(db: Session, skip: int = 0, limit: int = 10):
try:
return db.query(Logs).offset(skip).limit(limit).all() # type: ignore
except Exception as e:
print(e)
return None

def get_logs_by_user_id(db: Session, user_id: str, skip: int = 0, limit: int = 10):
try:
return db.query(Logs).filter(Logs.user_id == user_id).offset(skip).limit(limit).all() # type: ignore
except Exception as e:
print(e)
return None

def get_logs_by_station_id(db: Session, station_id: str, skip: int = 0, limit: int = 10):
try:
return db.query(Logs).filter(Logs.station_id == station_id).offset(skip).limit(limit).all() # type: ignore
except Exception as e:
print(e)
return None

def get_logs_by_charging_booth_id(db: Session, charging_booth_id: str, skip: int = 0, limit: int = 10):
try:
return db.query(Logs).filter(Logs.charging_booth_id == charging_booth_id).offset(skip).limit(limit).all() # type: ignore
except Exception as e:
print(e)
return None

def delete_log_by_time(db: Session, start_time: str, end_time: str):
try:
db.query(Logs).filter(Logs.created_at >= start_time).filter(Logs.created_at <= end_time).delete() # type: ignore
db.commit()
return True
except Exception as e:
print(e)
return False
18 changes: 11 additions & 7 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
topups,
tokens,
user_avatars,
logs,
)
from app.schemas.token import setNewPassword
from app.schemas.user import createUser
from app.schemas.user import ResetPassword, createUser
from app.routers import (
user,
super_admin,
Expand All @@ -33,6 +34,7 @@
station_admin,
topup,
image,
log,
)
import smtplib
from email.mime.multipart import MIMEMultipart
Expand All @@ -49,6 +51,7 @@
topups.Topups,
tokens.Token,
user_avatars.UserAvatar,
logs.Logs,
]
Base.metadata.create_all(bind=engine, tables=[model.__table__ for model in models])

Expand Down Expand Up @@ -149,16 +152,16 @@ async def register_user(user: createUser, db: Session = Depends(get_db)):


@app.post("/reset_password/")
async def reset_password(email: str, background_tasks: BackgroundTasks,db: Session = Depends(get_db)):
async def reset_password(email: ResetPassword, background_tasks: BackgroundTasks,db: Session = Depends(get_db)):
token = generate_token()
print(f"Generated token: {token}")
if update_token_by_email(db, token, email):
if update_token_by_email(db, token, email.email):
print("Token updated")
background_tasks.add_task(send_reset_email, email, token)
elif get_user_by_email(db, email):
create_token(db, token, email)
background_tasks.add_task(send_reset_email, email.email, token)
elif get_user_by_email(db, email.email):
create_token(db, token, email.email)
print("Token created")
background_tasks.add_task(send_reset_email, email, token)
background_tasks.add_task(send_reset_email, email.email, token)
return {"message": "Password reset email sent"}

@app.get("/reset_password/{token}")
Expand Down Expand Up @@ -195,3 +198,4 @@ async def set_new_password(setNewPassword: setNewPassword, db: Session = Depends
app.include_router(charging_session.router)
app.include_router(topup.router)
app.include_router(image.router)
app.include_router(log.router)
22 changes: 22 additions & 0 deletions app/models/logs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import datetime
import uuid
from sqlalchemy import Column, DateTime, ForeignKey, String
from app.database import Base

class Logs(Base):
__tablename__ = "logs"

id = Column(String, primary_key=True, index=True)
user_id = Column(String, ForeignKey("users.id"), nullable=False)
station_id = Column(String, ForeignKey("stations.id"), nullable=True)
booth_id = Column(String, ForeignKey("charging_booth.booth_id"),nullable=True)
message = Column(String)
created_at = Column(DateTime, default=datetime.datetime.now())

def __init__(self, user_id, message, station_id=None, charging_booth_id=None):
self.id = str(uuid.uuid4())
self.user_id = user_id
self.station_id = station_id
self.charging_booth_id = charging_booth_id
self.message = message
self.created_at = datetime.datetime.now()
82 changes: 82 additions & 0 deletions app/routers/log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.core.security import get_current_user
from app.crud.logs import (
delete_log_by_time,
get_logs,
get_logs_by_charging_booth_id,
get_logs_by_station_id,
get_logs_by_user_id,
)
from app.database import get_db
from app.schemas.log import DeleteLogs
from app.schemas.user import User

router = APIRouter(
prefix="/log",
tags=["Log"],
responses={404: {"description": "Not found"}},
)


@router.get("/")
async def read_logs(
db: Session = Depends(get_db), current_user: User = Depends(get_current_user)
):
if current_user.role not in ["superadmin", "stationadmin"]:
raise HTTPException(status_code=401, detail="Unauthorized")
if logs := get_logs(db):
return logs
raise HTTPException(status_code=400, detail="Logs not found")


@router.get("/{user_id}")
async def read_logs_by_user_id(
user_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
if current_user.role not in ["superadmin", "stationadmin"]:
raise HTTPException(status_code=401, detail="Unauthorized")
if logs := get_logs_by_user_id(db, user_id):
return logs
raise HTTPException(status_code=400, detail="Logs not found")


@router.get("/{station_id}")
async def read_logs_by_station_id(
station_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
if current_user.role not in ["superadmin", "stationadmin"]:
raise HTTPException(status_code=401, detail="Unauthorized")
if logs := get_logs_by_station_id(db, station_id):
return logs
raise HTTPException(status_code=400, detail="Logs not found")


@router.get("/{charging_booth_id}")
async def read_logs_by_charging_booth_id(
charging_booth_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
if current_user.role not in ["superadmin", "stationadmin"]:
raise HTTPException(status_code=401, detail="Unauthorized")
if logs := get_logs_by_charging_booth_id(db, charging_booth_id):
return logs
raise HTTPException(status_code=400, detail="Logs not found")


@router.delete("/")
async def delete_log(
delete_time: DeleteLogs,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
if current_user.role not in ["superadmin"]:
raise HTTPException(status_code=401, detail="Unauthorized")
if delete_log_by_time(db, delete_time.start_date, delete_time.end_date):
return {"message": "Logs deleted successfully"}
raise HTTPException(status_code=400, detail="Logs not deleted")
21 changes: 18 additions & 3 deletions app/routers/station.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from fastapi import APIRouter, Depends, HTTPException, WebSocket, WebSocketDisconnect
import datetime
import logging
from fastapi import APIRouter, Depends, HTTPException, WebSocket, WebSocketDisconnect, BackgroundTasks
from sqlalchemy.orm import Session

from app.crud.charging_session import get_charging_session_by_station_id
from app.crud import station
from app.crud.logs import create_log_info
from app.database import get_db
from app.schemas.station import Station, createStation, updateStation
from app.schemas.user import User
Expand All @@ -29,6 +32,8 @@ async def create_new_station(
if current_user.role != "superadmin":
raise HTTPException(status_code=401, detail="Unauthorized")
if db_station := station.create_station(db, station_new):
user_activity = f"User {current_user.email} created station {station_new.name}"
create_log_info(db, str(current_user.id), user_activity)
return db_station
else:
raise HTTPException(status_code=400, detail="Station not created")
Expand All @@ -41,6 +46,8 @@ async def read_station_by_id(
current_user: User = Depends(get_current_user),
):
if stations := station.get_station_by_id(db, station_id):
user_activity = f"User {current_user.email} read station {station_id}"
create_log_info(db, str(current_user.id), user_activity)
return stations
else:
raise HTTPException(status_code=404, detail="Station not found")
Expand All @@ -56,6 +63,10 @@ async def update_station(
if current_user.role not in ["superadmin", "stationadmin"]:
raise HTTPException(status_code=401, detail="Unauthorized")
if db_station := station.update_station(db, station_id, station_update):
user_activity = (
f"User {current_user.email} updated station {station_update.name}"
)
create_log_info(db, str(current_user.id), user_activity)
return db_station
else:
raise HTTPException(status_code=400, detail="Station not updated")
Expand All @@ -73,6 +84,8 @@ async def delete_station_by_superadmin(
if not station.get_station_by_id(db, station_id):
raise HTTPException(status_code=404, detail="Station not found")
station.delete_station(db, station_id)
user_activity = f"User {current_user.email} deleted station {station_id}"
create_log_info(db, str(current_user.id), user_activity)
return {"message": "Station deleted successfully"}
except Exception as e:
print(e)
Expand Down Expand Up @@ -128,6 +141,7 @@ async def read_station_admins(
except Exception as e:
raise HTTPException(status_code=400, detail="Station Admins not found") from e


@router.get("/{station_id}/booths/status")
async def get_station_booths_status(
station_id: str,
Expand All @@ -139,5 +153,6 @@ async def get_station_booths_status(
raise HTTPException(status_code=401, detail="Unauthorized")
return station.get_station_booths_status(db, station_id)
except Exception as e:
raise HTTPException(status_code=400, detail="Station Booths status not found") from e

raise HTTPException(
status_code=400, detail="Station Booths status not found"
) from e
12 changes: 9 additions & 3 deletions app/routers/station_admin.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, Depends, HTTPException,BackgroundTasks
from sqlalchemy.orm import Session
from app.core.security import get_current_user
from app.crud import station
from app.crud import station,logs
from app.crud.station_admin import add_admin_station, delete_admin_station
from app.database import get_db
from app.schemas.user import User

from app.crud.logs import create_log_info

router = APIRouter(
prefix="/station_admin",
Expand Down Expand Up @@ -38,6 +38,10 @@ async def create_station_admin(
if current_user.role not in ["superadmin", "stationadmin"]:
raise HTTPException(status_code=401, detail="Unauthorized")
if add_admin_station(db, station_id, user_id):
user_activity = (
f"User {current_user.email} added as station admin for station {station_id}"
)
create_log_info(db, str(current_user.id), user_activity)
return {"message": "Station Admin added successfully"}
else:
raise HTTPException(status_code=400, detail="Station Admin not added")
Expand All @@ -53,6 +57,8 @@ async def delete_station_admin_by_superadmin(
if current_user.role not in ["superadmin", "stationadmin"]:
raise HTTPException(status_code=401, detail="Unauthorized")
if delete_admin_station(db, station_id, user_id):
user_activity = f"User {current_user.email} deleted as station admin for station {station_id}"
create_log_info(db, str(current_user.id), user_activity)
return {"message": "Station Admin deleted successfully"}
else:
raise HTTPException(status_code=400, detail="Station Admin not deleted")
15 changes: 12 additions & 3 deletions app/routers/super_admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
from sqlalchemy.orm import Session
from app.crud.station import delete_station, get_station_admins, get_station_by_id
from app.crud.station_admin import add_admin_station, delete_admin_station
Expand All @@ -21,6 +21,7 @@
updateUserBySuperAdmin,
)
from app.core.security import get_current_user, password_hash
from app.crud.logs import create_log_info


router = APIRouter(
Expand All @@ -43,8 +44,12 @@ async def register_user_by_super_admin(
if user.password != user.confirmPassword:
raise HTTPException(status_code=400, detail="Passwords do not match")
user.password = password_hash(user.password)
create_user_by_super_admin(db, user)
return {"message": "User registered successfully"}
if create_user_by_super_admin(db, user):
user_activity = f"User {current_user.email} registered user {user.email}"
create_log_info(db, str(current_user.id), user_activity)

return {"message": "User registered successfully"}
raise HTTPException(status_code=400, detail="User registration failed")


@router.get("/users", response_model=List[User])
Expand Down Expand Up @@ -90,6 +95,8 @@ async def disable_user(
raise HTTPException(status_code=404, detail="User not found")
user.is_active = False # type: ignore
db.commit()
user_activity = f"User {current_user.email} disabled user {user_id}"
create_log_info(db, str(current_user.id), user_activity)
return {"message": "User disabled successfully"}


Expand All @@ -109,4 +116,6 @@ async def update_user_password_by_superadmin(
raise HTTPException(status_code=400, detail="Passwords do not match")
user.hashed_password = password_hash(password.password)
db.commit()
user_activity = f"User {current_user.email} updated password for user {user_id}"
create_log_info(db, str(current_user.id), message=user_activity)
return {"message": "Password updated successfully"}
5 changes: 4 additions & 1 deletion app/routers/topup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import base64
from decimal import Decimal
import os
from fastapi import APIRouter, Depends, HTTPException, Response
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Response
from sqlalchemy.orm import Session
from app.core.security import get_current_user
from app.crud.topup import approve_topup, create_topup, get_topup_by_id, get_topups
Expand All @@ -14,6 +14,7 @@
from enum import Enum
from io import BytesIO
import httpx
from app.crud.logs import create_log_info


class TopupType(str, Enum):
Expand Down Expand Up @@ -141,6 +142,8 @@ async def approve_topup_by_sueradmin(
"promptpay",
"Topup approved",
)
user_activity = f"User {current_user.email} approved topup {topup_id}"
create_log_info(db, str(current_user.id), user_activity)
return {"message": "Transaction approved successfully"}


Expand Down
Loading

0 comments on commit aa0a5d7

Please sign in to comment.