fix some issues in authentication
This commit is contained in:
parent
bf9348699a
commit
e566d5048c
16
app/main.py
16
app/main.py
|
@ -33,18 +33,20 @@ class Indexer:
|
|||
TEMPLATES_ROOT = pathlib.Path(__file__).parent / "templates"
|
||||
|
||||
def __init__(self):
|
||||
self.server = web.Application(
|
||||
middlewares=[
|
||||
middlewares = []
|
||||
if authenticated:
|
||||
middlewares.append(
|
||||
session_middleware(
|
||||
EncryptedCookieStorage(
|
||||
secret_key=SECRET_KEY.encode(),
|
||||
max_age=60 * SESSION_COOKIE_LIFETIME,
|
||||
cookie_name="TG_INDEX_SESSION"
|
||||
cookie_name="TG_INDEX_SESSION",
|
||||
)
|
||||
),
|
||||
middleware_factory(),
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
middlewares.append(middleware_factory())
|
||||
self.server = web.Application(middlewares=middlewares)
|
||||
self.loop = asyncio.get_event_loop()
|
||||
self.tg_client = Client(session_string, api_id, api_hash)
|
||||
|
||||
|
|
|
@ -22,16 +22,30 @@ async def setup_routes(app, handler):
|
|||
web.get("/login", h.login_get, name="login_page"),
|
||||
web.post("/login", h.login_post, name="login_handle"),
|
||||
web.get("/logout", h.logout_get, name="logout"),
|
||||
web.get("/favicon.ico", h.faviconicon, name="favicon"),
|
||||
]
|
||||
|
||||
def get_common_routes(p):
|
||||
def get_common_routes(alias_id):
|
||||
p = "/{chat:" + alias_id + "}"
|
||||
return [
|
||||
web.get(p, h.index),
|
||||
web.get(p + r"/logo", h.logo),
|
||||
web.get(p + r"/{id:\d+}/view", h.info),
|
||||
web.get(p + r"/{id:\d+}/thumbnail", h.thumbnail_get),
|
||||
web.get(p + r"/{id:\d+}/{filename}", h.download_get),
|
||||
web.head(p + r"/{id:\d+}/{filename}", h.download_head),
|
||||
web.get(p, h.index, name=f"index_{alias_id}"),
|
||||
web.get(p + r"/logo", h.logo, name=f"logo_{alias_id}"),
|
||||
web.get(p + r"/{id:\d+}/view", h.info, name=f"info_{alias_id}"),
|
||||
web.get(
|
||||
p + r"/{id:\d+}/thumbnail",
|
||||
h.thumbnail_get,
|
||||
name=f"thumbnail_get_{alias_id}",
|
||||
),
|
||||
web.get(
|
||||
p + r"/{id:\d+}/{filename}",
|
||||
h.download_get,
|
||||
name=f"download_get_{alias_id}",
|
||||
),
|
||||
web.head(
|
||||
p + r"/{id:\d+}/{filename}",
|
||||
h.download_head,
|
||||
name=f"download_head_{alias_id}",
|
||||
),
|
||||
]
|
||||
|
||||
if index_all:
|
||||
|
@ -56,16 +70,14 @@ async def setup_routes(app, handler):
|
|||
continue
|
||||
|
||||
alias_id = h.generate_alias_id(chat)
|
||||
p = "/{chat:" + alias_id + "}"
|
||||
routes.extend(get_common_routes(p))
|
||||
routes.extend(get_common_routes(alias_id))
|
||||
log.debug(f"Index added for {chat.id} at /{alias_id}")
|
||||
|
||||
else:
|
||||
for chat_id in include_chats:
|
||||
chat = await client.get_entity(chat_id)
|
||||
alias_id = h.generate_alias_id(chat)
|
||||
p = "/{chat:" + alias_id + "}"
|
||||
routes.extend(get_common_routes(p)) # returns list() of common routes
|
||||
routes.extend(get_common_routes(alias_id)) # returns list() of common routes
|
||||
log.debug(f"Index added for {chat.id} at /{alias_id}")
|
||||
routes.append(web.view(r"/{wildcard:.*}", h.wildcard))
|
||||
app.add_routes(routes)
|
||||
|
|
|
@ -12,27 +12,37 @@ class Client(TelegramClient):
|
|||
self.log = logging.getLogger(__name__)
|
||||
|
||||
async def download(self, file, file_size, offset, limit):
|
||||
part_size_kb = utils.get_appropriated_part_size(file_size)
|
||||
part_size = int(part_size_kb * 1024)
|
||||
part_size = utils.get_appropriated_part_size(file_size) * 1024
|
||||
first_part_cut = offset % part_size
|
||||
first_part = math.floor(offset / part_size)
|
||||
last_part_cut = part_size - (limit % part_size)
|
||||
last_part = math.ceil(limit / part_size)
|
||||
part_count = math.ceil(file_size / part_size)
|
||||
part = first_part
|
||||
self.log.debug(
|
||||
f"""Request Details
|
||||
part_size(bytes) = {part_size},
|
||||
first_part = {first_part}, cut = {first_part_cut}(length={part_size-first_part_cut}),
|
||||
last_part = {last_part}, cut = {last_part_cut}(length={last_part_cut}),
|
||||
parts_count = {part_count}
|
||||
"""
|
||||
)
|
||||
try:
|
||||
async for chunk in self.iter_download(
|
||||
file, offset=first_part * part_size, request_size=part_size
|
||||
):
|
||||
self.log.debug(f"Part {part}/{last_part} (total {part_count}) served!")
|
||||
if part == first_part:
|
||||
yield chunk[first_part_cut:]
|
||||
elif part == last_part - 1:
|
||||
elif part == last_part:
|
||||
yield chunk[:last_part_cut]
|
||||
break
|
||||
else:
|
||||
yield chunk
|
||||
self.log.debug(f"Part {part}/{last_part} (total {part_count}) served!")
|
||||
|
||||
part += 1
|
||||
self.log.debug("serving finished")
|
||||
|
||||
self.log.debug(f"serving finished")
|
||||
except (GeneratorExit, StopAsyncIteration, asyncio.CancelledError):
|
||||
self.log.debug("file serve interrupted")
|
||||
raise
|
||||
|
|
|
@ -12,6 +12,7 @@ from .logo_view import LogoView
|
|||
from .thumbnail_view import ThumbnailView
|
||||
from .login_view import LoginView
|
||||
from .logout_view import LogoutView
|
||||
from .faviconicon_view import FaviconIconView
|
||||
from .middlewhere import middleware_factory
|
||||
|
||||
|
||||
|
@ -25,6 +26,7 @@ class Views(
|
|||
WildcardView,
|
||||
LoginView,
|
||||
LogoutView,
|
||||
FaviconIconView,
|
||||
):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
@ -38,7 +40,7 @@ class Views(
|
|||
while True:
|
||||
orig_id = f"{chat_id}" # the original id
|
||||
unique_hash = hashlib.md5(orig_id.encode()).digest()
|
||||
alias_id = base64.urlsafe_b64encode(unique_hash).decode()[: self.url_len]
|
||||
alias_id = base64.b64encode(unique_hash, b"__").decode()[: self.url_len]
|
||||
|
||||
if alias_id in self.chat_ids:
|
||||
self.url_len += (
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import random
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
from aiohttp import web
|
||||
|
||||
from app.config import logo_folder
|
||||
|
||||
|
||||
class FaviconIconView:
|
||||
async def faviconicon(self, req):
|
||||
favicon_path = logo_folder.joinpath("favicon.ico")
|
||||
text = "T"
|
||||
if not favicon_path.exists():
|
||||
W, H = (360, 360)
|
||||
color = tuple((random.randint(0, 255) for _ in range(3)))
|
||||
im = Image.new("RGB", (W, H), color)
|
||||
draw = ImageDraw.Draw(im)
|
||||
font = ImageFont.truetype("arial.ttf", 50)
|
||||
w, h = draw.textsize(text, font=font)
|
||||
draw.text(((W - w) / 2, (H - h) / 2), text, fill="white", font=font)
|
||||
im.save(favicon_path)
|
||||
|
||||
with open(favicon_path, "rb") as fp:
|
||||
body = fp.read()
|
||||
|
||||
return web.Response(
|
||||
status=200,
|
||||
body=body,
|
||||
headers={
|
||||
"Content-Type": "image/jpeg",
|
||||
"Content-Disposition": 'inline; filename="favicon.ico"',
|
||||
},
|
||||
)
|
|
@ -105,5 +105,5 @@ class IndexView:
|
|||
"block_downloads": block_downloads,
|
||||
"m3u_option": ""
|
||||
if not req.app["is_authenticated"]
|
||||
else f"{req.app['is_authenticated']}:{req.app['is_authenticated']}@",
|
||||
else f"{req.app['username']}:{req.app['password']}@",
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import logging
|
||||
import math
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import random
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import time
|
||||
import logging
|
||||
|
||||
from aiohttp.web import middleware, HTTPFound
|
||||
from aiohttp.web import middleware, HTTPFound, Response
|
||||
from aiohttp import BasicAuth, hdrs
|
||||
from aiohttp_session import get_session
|
||||
|
||||
|
@ -12,6 +12,17 @@ log = logging.getLogger(__name__)
|
|||
def _do_basic_auth_check(request):
|
||||
auth_header = request.headers.get(hdrs.AUTHORIZATION)
|
||||
if not auth_header:
|
||||
if "download_" in request.match_info.route.name:
|
||||
return Response(
|
||||
body=b"",
|
||||
status=401,
|
||||
reason="UNAUTHORIZED",
|
||||
headers={
|
||||
hdrs.WWW_AUTHENTICATE: 'Basic realm=""',
|
||||
hdrs.CONTENT_TYPE: "text/html; charset=utf-8",
|
||||
hdrs.CONNECTION: "keep-alive",
|
||||
},
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
|
@ -25,6 +36,12 @@ def _do_basic_auth_check(request):
|
|||
if auth.login is None or auth.password is None:
|
||||
return
|
||||
|
||||
if (
|
||||
auth.login != request.app["username"]
|
||||
or auth.password != request.app["password"]
|
||||
):
|
||||
return
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
@ -50,7 +67,7 @@ def middleware_factory():
|
|||
|
||||
basic_auth_check_resp = _do_basic_auth_check(request)
|
||||
|
||||
if basic_auth_check_resp is not None:
|
||||
if basic_auth_check_resp is True:
|
||||
return await handler(request)
|
||||
|
||||
cookies_auth_check_resp = await _do_cookies_auth_check(request)
|
||||
|
@ -58,6 +75,9 @@ def middleware_factory():
|
|||
if cookies_auth_check_resp is not None:
|
||||
return await handler(request)
|
||||
|
||||
if isinstance(basic_auth_check_resp, Response):
|
||||
return basic_auth_check_resp
|
||||
|
||||
return HTTPFound(url)
|
||||
|
||||
return await handler(request)
|
||||
|
|
Loading…
Reference in New Issue