privateone commited on
Commit
6ccc851
·
1 Parent(s): 38342f7

Addition of Middlewares

Browse files
FileStream/server/API/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
  import aiohttp_cors
2
  from aiohttp import web
3
 
4
-
5
  from .listings import (
6
  list_all_files_db,
7
  list_all_files,
@@ -13,17 +13,26 @@ from .listings import (
13
  from .downloads import stream_handler
14
  from .uploads import upload_file
15
 
 
 
16
  async def handle_v2(request):
17
  return web.Response(text="Hello from app api!")
18
 
19
- # Web server setup with optimized CORS handling
20
- api = web.Application()
 
21
  cors = aiohttp_cors.setup(api, defaults={"*": aiohttp_cors.ResourceOptions(
22
  allow_credentials=False,
23
  expose_headers="*",
24
  allow_headers="*",
25
  allow_methods="*"
26
  )})
 
 
 
 
 
 
27
 
28
  cors.add(api.router.add_get('/', handle_v2))
29
 
 
1
  import aiohttp_cors
2
  from aiohttp import web
3
 
4
+ #---------------------- Local Imports --------------------#
5
  from .listings import (
6
  list_all_files_db,
7
  list_all_files,
 
13
  from .downloads import stream_handler
14
  from .uploads import upload_file
15
 
16
+
17
+ #-----------------------------Functions------------------------#
18
  async def handle_v2(request):
19
  return web.Response(text="Hello from app api!")
20
 
21
+
22
+
23
+ """
24
  cors = aiohttp_cors.setup(api, defaults={"*": aiohttp_cors.ResourceOptions(
25
  allow_credentials=False,
26
  expose_headers="*",
27
  allow_headers="*",
28
  allow_methods="*"
29
  )})
30
+ """
31
+
32
+ #---------------------------Routes ---------------------------#
33
+ # Web server setup with optimized CORS handling
34
+ api = web.Application()
35
+
36
 
37
  cors.add(api.router.add_get('/', handle_v2))
38
 
FileStream/server/APP/__init__.py CHANGED
@@ -2,24 +2,20 @@ import os
2
  from aiohttp import web
3
  from aiohttp.http_exceptions import BadStatusLine
4
 
5
-
6
  from .render_template import render_page, render_upload
7
  from .routes_app import stream_handler,upload_handler
8
  from FileStream.Exceptions import FIleNotFound, InvalidHash
9
 
10
-
11
-
12
-
13
  async def handle_v2(request):
14
  return web.Response(text="Hello from app v2!")
15
 
16
- sub_app = web.Application()
17
-
18
 
 
 
19
  #static_dir = os.path.join("FileStream", "bot", "server", "template")
20
  #sub_app.router.add_static('/static/', path=static_dir, name='static')
21
-
22
-
23
- sub_app.router.add_get('/', handle_v2)
24
- sub_app.router.add_get('/watch/{path}', stream_handler)
25
- sub_app.router.add_get('/up', upload_handler)
 
2
  from aiohttp import web
3
  from aiohttp.http_exceptions import BadStatusLine
4
 
5
+ #-----------------------------Local Imports-----------------------------#
6
  from .render_template import render_page, render_upload
7
  from .routes_app import stream_handler,upload_handler
8
  from FileStream.Exceptions import FIleNotFound, InvalidHash
9
 
10
+ #------------------------------Functions--------------------------------#
 
 
11
  async def handle_v2(request):
12
  return web.Response(text="Hello from app v2!")
13
 
 
 
14
 
15
+ #----------------------------Server Routes-----------------------------#
16
+ app = web.Application()
17
  #static_dir = os.path.join("FileStream", "bot", "server", "template")
18
  #sub_app.router.add_static('/static/', path=static_dir, name='static')
19
+ app.router.add_get('/', handle_v2)
20
+ app.router.add_get('/watch/{path}', stream_handler)
21
+ app.router.add_get('/up', upload_handler)
 
 
FileStream/server/APP/routes_app.py CHANGED
@@ -2,10 +2,13 @@ import os
2
  from aiohttp import web
3
  from aiohttp.http_exceptions import BadStatusLine
4
 
 
5
  from ..Functions.downloader import media_streamer
6
  from .render_template import render_page, render_upload
7
  from FileStream.Exceptions import FIleNotFound, InvalidHash
8
 
 
 
9
  #@sub_app.get("/watch/{path}", allow_head=True)
10
  async def stream_handler(request: web.Request):
11
  try:
 
2
  from aiohttp import web
3
  from aiohttp.http_exceptions import BadStatusLine
4
 
5
+ #--------------------------Local Import -----------------------------#
6
  from ..Functions.downloader import media_streamer
7
  from .render_template import render_page, render_upload
8
  from FileStream.Exceptions import FIleNotFound, InvalidHash
9
 
10
+
11
+ #------------------------------Functions------------------------------#
12
  #@sub_app.get("/watch/{path}", allow_head=True)
13
  async def stream_handler(request: web.Request):
14
  try:
FileStream/server/Authentication/__init__.py ADDED
File without changes
FileStream/server/Middlewares/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from .app_token_middleware import app_token_middleware
2
+ from .jwt_middleware import jwt_middleware,create_jwt
3
+ from .logging_middleware import logging_middleware
4
+ from .rate_limit_middleware import rate_limit_middleware
5
+ from .security_headers_middleware import security_headers_middleware
FileStream/server/Middlewares/app_token_middleware.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from aiohttp import web
2
+
3
+ DEFAULT_APP_TOKEN = "supersecureapptoken"
4
+
5
+ @web.middleware
6
+ async def app_token_middleware(request, handler):
7
+ """Middleware to enforce token authentication for /app."""
8
+ if request.path.startswith("/app"):
9
+ token = request.headers.get("App-Token")
10
+ if token != DEFAULT_APP_TOKEN:
11
+ raise web.HTTPUnauthorized(reason="Invalid or missing App-Token")
12
+ return await handler(request)
FileStream/server/Middlewares/jwt_middleware.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import jwt
2
+ from aiohttp import web
3
+
4
+ SECRET_KEY = "your_secret_key" # Use a strong, randomly generated secret key
5
+
6
+ def create_jwt(user_id: str):
7
+ """Create a JWT token."""
8
+ payload = {"sub": user_id, "role": "api_user"}
9
+ return jwt.encode(payload, SECRET_KEY, algorithm="HS256")
10
+
11
+ @web.middleware
12
+ async def jwt_middleware(request, handler):
13
+ """JWT Middleware for /api endpoints."""
14
+ if request.path.startswith("/api"):
15
+ token = request.headers.get("Authorization")
16
+ if not token or not token.startswith("Bearer "):
17
+ raise web.HTTPUnauthorized(reason="Authorization header missing or malformed")
18
+ token = token.split("Bearer ")[1]
19
+ try:
20
+ decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
21
+ request["user"] = decoded # Attach user info to the request
22
+ except jwt.ExpiredSignatureError:
23
+ raise web.HTTPUnauthorized(reason="Token has expired")
24
+ except jwt.InvalidTokenError:
25
+ raise web.HTTPUnauthorized(reason="Invalid token")
26
+ return await handler(request)
FileStream/server/Middlewares/logging_middleware.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from aiohttp import web
3
+
4
+ @web.middleware
5
+ async def logging_middleware(request, handler):
6
+ """Log each request."""
7
+ logging.info(f"Incoming request: {request.method} {request.path}")
8
+ return await handler(request)
FileStream/server/Middlewares/rate_limit_middleware.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ from aiohttp_rate_limiter import RateLimiter
2
+
3
+ rate_limiter = RateLimiter(per_minute=60)
4
+
5
+ @rate_limiter.limit("60/minute")
6
+ async def rate_limit_middleware(request, handler):
7
+ """Rate limiter middleware."""
8
+ return await handler(request)
FileStream/server/Middlewares/security_headers_middleware.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from aiohttp import web
2
+
3
+ @web.middleware
4
+ async def security_headers_middleware(request, handler):
5
+ """Add security headers."""
6
+ response = await handler(request)
7
+ response.headers.update({
8
+ "Content-Security-Policy": "default-src 'self'",
9
+ "X-Content-Type-Options": "nosniff",
10
+ "X-Frame-Options": "DENY",
11
+ "Referrer-Policy": "no-referrer",
12
+ "Strict-Transport-Security": "max-age=31536000; includeSubDomains"
13
+ })
14
+ return response
FileStream/server/__init__.py CHANGED
@@ -4,10 +4,15 @@ from aiohttp import web
4
 
5
  #-----------------------Local Imports-------------------------#
6
  from .API import api
7
- from .APP import sub_app
 
8
  from .routes_main import routes
9
  from FileStream.bot import MULTI_CLIENTS, WORK_LOADS, ACTIVE_CLIENTS
10
 
 
 
 
 
11
 
12
  # Set time to consider a client inactive (e.g., 10 minutes)
13
  INACTIVITY_TIMEOUT = 180 # 3 minutes
@@ -32,9 +37,20 @@ async def root_route_handler(request):
32
 
33
  def web_server():
34
  web_app = web.Application(client_max_size=500)
 
 
 
 
 
 
 
 
 
 
35
  web_app.router.add_get('/', root_route_handler)
36
  web_app.add_routes(routes)
37
- web_app.add_subapp('/app', sub_app)
38
  web_app.add_subapp('/api', api)
 
39
  # Return the app to be used with AppRunner
40
  return web_app
 
4
 
5
  #-----------------------Local Imports-------------------------#
6
  from .API import api
7
+ from .APP import app
8
+ from .Authentication import auth
9
  from .routes_main import routes
10
  from FileStream.bot import MULTI_CLIENTS, WORK_LOADS, ACTIVE_CLIENTS
11
 
12
+ from .Middlewares.jwt_middleware import jwt_middleware
13
+ from .Middlewares.app_token_middleware import app_token_middleware
14
+ from .Middlewares.logging_middleware import logging_middleware
15
+ from .Middlewares.rate_limit_middleware import rate_limit_middleware
16
 
17
  # Set time to consider a client inactive (e.g., 10 minutes)
18
  INACTIVITY_TIMEOUT = 180 # 3 minutes
 
37
 
38
  def web_server():
39
  web_app = web.Application(client_max_size=500)
40
+
41
+ # Add middlewares
42
+ web_app.middleware.extend([
43
+ logging_middleware,
44
+ security_headers_middleware,
45
+ jwt_middleware,
46
+ app_token_middleware,
47
+ rate_limit_middleware
48
+ ])
49
+
50
  web_app.router.add_get('/', root_route_handler)
51
  web_app.add_routes(routes)
52
+ web_app.add_subapp('/app', app)
53
  web_app.add_subapp('/api', api)
54
+ web_app.add_subapp('/auth', auth)
55
  # Return the app to be used with AppRunner
56
  return web_app
requirements.txt CHANGED
@@ -2,6 +2,8 @@ tmdbv3api==1.9.0
2
  aiofiles==23.2.1
3
  aiohttp==3.9.3
4
  aiohttp_cors
 
 
5
  aiosignal==1.3.1
6
  aiosqlite==0.20.0
7
  async-timeout==4.0.3
 
2
  aiofiles==23.2.1
3
  aiohttp==3.9.3
4
  aiohttp_cors
5
+ aiohttp-rate-limiter==0.3.0
6
+ PyJWT==2.6.0
7
  aiosignal==1.3.1
8
  aiosqlite==0.20.0
9
  async-timeout==4.0.3