|
from aiohttp import web
|
|
import aiohttp_jinja2
|
|
import os
|
|
from pathlib import Path
|
|
from aiohttp.web_response import json_response
|
|
|
|
from ..helpers.auth import login_required
|
|
from .auth import CustomPydanticView
|
|
|
|
# PROJECT_DIR is no longer directly used for user files, as FileService manages them
|
|
# PROJECT_DIR = Path(__file__).parent.parent.parent / "project"
|
|
|
|
|
|
class SiteView(web.View):
|
|
async def get(self):
|
|
if self.request.path == "/dashboard":
|
|
return await self.dashboard()
|
|
elif self.request.path == "/solutions":
|
|
return await self.solutions()
|
|
elif self.request.path == "/pricing":
|
|
return await self.pricing()
|
|
elif self.request.path == "/security":
|
|
return await self.security()
|
|
elif self.request.path == "/support":
|
|
return await self.support()
|
|
elif self.request.path == "/use_cases":
|
|
return await self.use_cases()
|
|
elif self.request.path == "/terms":
|
|
return await self.terms()
|
|
elif self.request.path == "/privacy":
|
|
return await self.privacy()
|
|
elif self.request.path == "/shared":
|
|
return await self.shared()
|
|
elif self.request.path == "/recent":
|
|
return await self.recent()
|
|
elif self.request.path == "/favorites":
|
|
return await self.favorites()
|
|
elif self.request.path == "/trash":
|
|
return await self.trash()
|
|
elif self.request.path == "/users":
|
|
return await self.users()
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/index.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
|
)
|
|
|
|
@login_required
|
|
async def dashboard(self):
|
|
return web.HTTPFound(self.request.app.router["file_browser"].url_for())
|
|
|
|
async def solutions(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/solutions.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
|
)
|
|
|
|
async def pricing(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/pricing.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
|
)
|
|
|
|
async def security(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/security.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
|
)
|
|
|
|
@login_required
|
|
async def support(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/support.html", self.request, {"request": self.request, "errors": {}, "user": self.request["user"], "active_page": "support"}
|
|
)
|
|
|
|
async def use_cases(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/use_cases.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
|
)
|
|
|
|
async def terms(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/terms.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
|
)
|
|
|
|
async def privacy(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/privacy.html", self.request, {"request": self.request, "errors": {}, "user": self.request.get("user")}
|
|
)
|
|
|
|
@login_required
|
|
async def shared(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/shared.html", self.request, {"request": self.request, "errors": {}, "user": self.request["user"], "active_page": "shared"}
|
|
)
|
|
|
|
@login_required
|
|
async def recent(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/recent.html", self.request, {"request": self.request, "errors": {}, "user": self.request["user"], "active_page": "recent"}
|
|
)
|
|
|
|
@login_required
|
|
async def favorites(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/favorites.html", self.request, {"request": self.request, "errors": {}, "user": self.request["user"], "active_page": "favorites"}
|
|
)
|
|
|
|
@login_required
|
|
async def trash(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/trash.html", self.request, {"request": self.request, "errors": {}, "user": self.request["user"], "active_page": "trash"}
|
|
)
|
|
|
|
@login_required
|
|
async def users(self):
|
|
success_message = self.request.query.get("success")
|
|
error_message = self.request.query.get("error")
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/users.html", self.request, {
|
|
"request": self.request,
|
|
"errors": {},
|
|
"user": self.request["user"],
|
|
"active_page": "users",
|
|
"success_message": success_message,
|
|
"error_message": error_message
|
|
}
|
|
)
|
|
|
|
|
|
class FileBrowserView(web.View):
|
|
@login_required
|
|
async def get(self):
|
|
if self.request.match_info.get("file_path") is not None:
|
|
return await self.get_download_file()
|
|
|
|
user_email = self.request["user"]["email"]
|
|
file_service = self.request.app["file_service"]
|
|
|
|
path = self.request.query.get("path", "")
|
|
files = await file_service.list_files(user_email, path)
|
|
|
|
success_message = self.request.query.get("success")
|
|
error_message = self.request.query.get("error")
|
|
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/file_browser.html",
|
|
self.request,
|
|
{
|
|
"request": self.request,
|
|
"files": files,
|
|
"user": self.request["user"],
|
|
"current_path": path,
|
|
"success_message": success_message,
|
|
"error_message": error_message,
|
|
"active_page": "files",
|
|
},
|
|
)
|
|
|
|
@login_required
|
|
async def post(self):
|
|
user_email = self.request["user"]["email"]
|
|
file_service = self.request.app["file_service"]
|
|
route_name = self.request.match_info.route.name
|
|
|
|
if route_name == "new_folder":
|
|
data = await self.request.post()
|
|
folder_name = data.get("folder_name")
|
|
if not folder_name:
|
|
return web.HTTPFound(
|
|
self.request.app.router["file_browser"].url_for().with_query(
|
|
error="Folder name is required"
|
|
)
|
|
)
|
|
|
|
success = await file_service.create_folder(user_email, folder_name)
|
|
if success:
|
|
return web.HTTPFound(
|
|
self.request.app.router["file_browser"].url_for().with_query(
|
|
success=f"Folder '{folder_name}' created successfully"
|
|
)
|
|
)
|
|
else:
|
|
return web.HTTPFound(
|
|
self.request.app.router["file_browser"].url_for().with_query(
|
|
error=f"Folder '{folder_name}' already exists or could not be created"
|
|
)
|
|
)
|
|
|
|
elif route_name == "share_file":
|
|
file_path = self.request.match_info.get("file_path")
|
|
if not file_path:
|
|
return json_response({"error": "File path is required for sharing"}, status=400)
|
|
|
|
share_id = await file_service.generate_share_link(user_email, file_path)
|
|
if share_id:
|
|
share_link = f"{self.request.scheme}://{self.request.host}/shared_file/{share_id}"
|
|
return json_response({"share_link": share_link})
|
|
else:
|
|
return json_response({"error": "Failed to generate share link"}, status=500)
|
|
|
|
elif route_name == "delete_item":
|
|
item_path = self.request.match_info.get("file_path")
|
|
if not item_path:
|
|
return web.HTTPFound(
|
|
self.request.app.router["file_browser"].url_for().with_query(
|
|
error="Item path is required for deletion"
|
|
)
|
|
)
|
|
|
|
success = await file_service.delete_item(user_email, item_path)
|
|
if success:
|
|
return web.HTTPFound(
|
|
self.request.app.router["file_browser"].url_for().with_query(
|
|
success=f"Item deleted successfully"
|
|
)
|
|
)
|
|
else:
|
|
return web.HTTPFound(
|
|
self.request.app.router["file_browser"].url_for().with_query(
|
|
error="Failed to delete item - it may not exist"
|
|
)
|
|
)
|
|
|
|
return web.HTTPBadRequest(text="Unknown file action")
|
|
|
|
@login_required
|
|
async def get_download_file(self):
|
|
user_email = self.request["user"]["email"]
|
|
file_service = self.request.app["file_service"]
|
|
file_path = self.request.match_info.get("file_path")
|
|
|
|
if not file_path:
|
|
return web.HTTPBadRequest(text="File path is required for download")
|
|
|
|
result = await file_service.download_file(user_email, file_path)
|
|
if result:
|
|
content, filename = result
|
|
response = web.Response(body=content)
|
|
response.headers["Content-Disposition"] = f"attachment; filename={filename}"
|
|
response.headers["Content-Type"] = "application/octet-stream"
|
|
return response
|
|
else:
|
|
return web.HTTPNotFound(text="File not found")
|
|
|
|
|
|
class OrderView(CustomPydanticView):
|
|
template_name = "pages/order.html"
|
|
|
|
@login_required
|
|
async def get(self):
|
|
config_service = self.request.app["config_service"]
|
|
price_per_gb = config_service.get_price_per_gb()
|
|
return aiohttp_jinja2.render_template(
|
|
self.template_name, self.request, {
|
|
"request": self.request,
|
|
"errors": {},
|
|
"user": self.request["user"],
|
|
"price_per_gb": price_per_gb,
|
|
"active_page": "order"
|
|
}
|
|
)
|
|
|
|
@login_required
|
|
async def post(self):
|
|
config_service = self.request.app["config_service"]
|
|
price_per_gb = config_service.get_price_per_gb()
|
|
return aiohttp_jinja2.render_template(
|
|
self.template_name, self.request, {
|
|
"request": self.request,
|
|
"errors": {},
|
|
"user": self.request["user"],
|
|
"price_per_gb": price_per_gb,
|
|
"active_page": "order"
|
|
}
|
|
)
|
|
|
|
|
|
class UserManagementView(web.View):
|
|
@login_required
|
|
async def get(self):
|
|
route_name = self.request.match_info.route.name
|
|
|
|
if route_name == "add_user":
|
|
return await self.add_user_page()
|
|
elif route_name == "edit_user":
|
|
return await self.edit_user_page()
|
|
elif route_name == "user_details":
|
|
return await self.user_details_page()
|
|
|
|
return web.HTTPNotFound()
|
|
|
|
@login_required
|
|
async def post(self):
|
|
route_name = self.request.match_info.route.name
|
|
|
|
if route_name == "add_user":
|
|
return await self.add_user_submit()
|
|
elif route_name == "edit_user":
|
|
return await self.edit_user_submit()
|
|
elif route_name == "delete_user_page":
|
|
return await self.delete_user_submit()
|
|
|
|
return web.HTTPNotFound()
|
|
|
|
async def add_user_page(self):
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/add_user.html",
|
|
self.request,
|
|
{
|
|
"request": self.request,
|
|
"user": self.request["user"],
|
|
"errors": {},
|
|
"form_data": {},
|
|
"active_page": "users"
|
|
}
|
|
)
|
|
|
|
async def add_user_submit(self):
|
|
data = await self.request.post()
|
|
full_name = data.get("full_name", "").strip()
|
|
email = data.get("email", "").strip()
|
|
password = data.get("password", "")
|
|
confirm_password = data.get("confirm_password", "")
|
|
storage_quota_gb = data.get("storage_quota_gb", "10")
|
|
|
|
errors = {}
|
|
|
|
if not full_name:
|
|
errors["full_name"] = "Full name is required"
|
|
if not email:
|
|
errors["email"] = "Email is required"
|
|
if not password:
|
|
errors["password"] = "Password is required"
|
|
if password != confirm_password:
|
|
errors["confirm_password"] = "Passwords do not match"
|
|
|
|
try:
|
|
storage_quota_gb = int(storage_quota_gb)
|
|
if storage_quota_gb < 1:
|
|
errors["storage_quota_gb"] = "Storage quota must be at least 1 GB"
|
|
except ValueError:
|
|
errors["storage_quota_gb"] = "Invalid storage quota value"
|
|
|
|
if errors:
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/add_user.html",
|
|
self.request,
|
|
{
|
|
"request": self.request,
|
|
"user": self.request["user"],
|
|
"errors": errors,
|
|
"form_data": data,
|
|
"active_page": "users"
|
|
}
|
|
)
|
|
|
|
user_service = self.request.app["user_service"]
|
|
parent_email = self.request["user"]["email"]
|
|
|
|
try:
|
|
new_user = user_service.create_user(
|
|
full_name=full_name,
|
|
email=email,
|
|
password=password,
|
|
parent_email=parent_email
|
|
)
|
|
|
|
user_service.update_user_quota(email, float(storage_quota_gb))
|
|
|
|
return web.HTTPFound(
|
|
self.request.app.router["users"].url_for().with_query(
|
|
success=f"User {email} added successfully"
|
|
)
|
|
)
|
|
except ValueError as e:
|
|
errors["email"] = str(e)
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/add_user.html",
|
|
self.request,
|
|
{
|
|
"request": self.request,
|
|
"user": self.request["user"],
|
|
"errors": errors,
|
|
"form_data": data,
|
|
"active_page": "users"
|
|
}
|
|
)
|
|
|
|
async def edit_user_page(self):
|
|
email = self.request.match_info.get("email")
|
|
|
|
user_service = self.request.app["user_service"]
|
|
user_data = user_service.get_user_by_email(email)
|
|
|
|
if not user_data:
|
|
return web.HTTPNotFound(text="User not found")
|
|
|
|
success_message = self.request.query.get("success")
|
|
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/edit_user.html",
|
|
self.request,
|
|
{
|
|
"request": self.request,
|
|
"user": self.request["user"],
|
|
"user_data": user_data,
|
|
"errors": {},
|
|
"success_message": success_message,
|
|
"active_page": "users"
|
|
}
|
|
)
|
|
|
|
async def edit_user_submit(self):
|
|
email = self.request.match_info.get("email")
|
|
data = await self.request.post()
|
|
storage_quota_gb = data.get("storage_quota_gb", "")
|
|
|
|
errors = {}
|
|
|
|
try:
|
|
storage_quota_gb = float(storage_quota_gb)
|
|
if storage_quota_gb < 1:
|
|
errors["storage_quota_gb"] = "Storage quota must be at least 1 GB"
|
|
except ValueError:
|
|
errors["storage_quota_gb"] = "Invalid storage quota value"
|
|
|
|
user_service = self.request.app["user_service"]
|
|
user_data = user_service.get_user_by_email(email)
|
|
|
|
if not user_data:
|
|
return web.HTTPNotFound(text="User not found")
|
|
|
|
if errors:
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/edit_user.html",
|
|
self.request,
|
|
{
|
|
"request": self.request,
|
|
"user": self.request["user"],
|
|
"user_data": user_data,
|
|
"errors": errors,
|
|
"active_page": "users"
|
|
}
|
|
)
|
|
|
|
user_service.update_user_quota(email, storage_quota_gb)
|
|
|
|
return web.HTTPFound(
|
|
self.request.app.router["edit_user"].url_for(email=email).with_query(
|
|
success="User quota updated successfully"
|
|
)
|
|
)
|
|
|
|
async def user_details_page(self):
|
|
email = self.request.match_info.get("email")
|
|
|
|
user_service = self.request.app["user_service"]
|
|
user_data = user_service.get_user_by_email(email)
|
|
|
|
if not user_data:
|
|
return web.HTTPNotFound(text="User not found")
|
|
|
|
return aiohttp_jinja2.render_template(
|
|
"pages/user_details.html",
|
|
self.request,
|
|
{
|
|
"request": self.request,
|
|
"user": self.request["user"],
|
|
"user_data": user_data,
|
|
"active_page": "users"
|
|
}
|
|
)
|
|
|
|
async def delete_user_submit(self):
|
|
email = self.request.match_info.get("email")
|
|
|
|
user_service = self.request.app["user_service"]
|
|
user_data = user_service.get_user_by_email(email)
|
|
|
|
if not user_data:
|
|
return web.HTTPNotFound(text="User not found")
|
|
|
|
user_service.delete_user(email)
|
|
|
|
return web.HTTPFound(
|
|
self.request.app.router["users"].url_for().with_query(
|
|
success=f"User {email} deleted successfully"
|
|
)
|
|
)
|