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"
|
TEMPLATES_ROOT = pathlib.Path(__file__).parent / "templates"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.server = web.Application(
|
middlewares = []
|
||||||
middlewares=[
|
if authenticated:
|
||||||
|
middlewares.append(
|
||||||
session_middleware(
|
session_middleware(
|
||||||
EncryptedCookieStorage(
|
EncryptedCookieStorage(
|
||||||
secret_key=SECRET_KEY.encode(),
|
secret_key=SECRET_KEY.encode(),
|
||||||
max_age=60 * SESSION_COOKIE_LIFETIME,
|
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.loop = asyncio.get_event_loop()
|
||||||
self.tg_client = Client(session_string, api_id, api_hash)
|
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.get("/login", h.login_get, name="login_page"),
|
||||||
web.post("/login", h.login_post, name="login_handle"),
|
web.post("/login", h.login_post, name="login_handle"),
|
||||||
web.get("/logout", h.logout_get, name="logout"),
|
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 [
|
return [
|
||||||
web.get(p, h.index),
|
web.get(p, h.index, name=f"index_{alias_id}"),
|
||||||
web.get(p + r"/logo", h.logo),
|
web.get(p + r"/logo", h.logo, name=f"logo_{alias_id}"),
|
||||||
web.get(p + r"/{id:\d+}/view", h.info),
|
web.get(p + r"/{id:\d+}/view", h.info, name=f"info_{alias_id}"),
|
||||||
web.get(p + r"/{id:\d+}/thumbnail", h.thumbnail_get),
|
web.get(
|
||||||
web.get(p + r"/{id:\d+}/{filename}", h.download_get),
|
p + r"/{id:\d+}/thumbnail",
|
||||||
web.head(p + r"/{id:\d+}/{filename}", h.download_head),
|
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:
|
if index_all:
|
||||||
|
@ -56,16 +70,14 @@ async def setup_routes(app, handler):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
alias_id = h.generate_alias_id(chat)
|
alias_id = h.generate_alias_id(chat)
|
||||||
p = "/{chat:" + alias_id + "}"
|
routes.extend(get_common_routes(alias_id))
|
||||||
routes.extend(get_common_routes(p))
|
|
||||||
log.debug(f"Index added for {chat.id} at /{alias_id}")
|
log.debug(f"Index added for {chat.id} at /{alias_id}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for chat_id in include_chats:
|
for chat_id in include_chats:
|
||||||
chat = await client.get_entity(chat_id)
|
chat = await client.get_entity(chat_id)
|
||||||
alias_id = h.generate_alias_id(chat)
|
alias_id = h.generate_alias_id(chat)
|
||||||
p = "/{chat:" + alias_id + "}"
|
routes.extend(get_common_routes(alias_id)) # returns list() of common routes
|
||||||
routes.extend(get_common_routes(p)) # returns list() of common routes
|
|
||||||
log.debug(f"Index added for {chat.id} at /{alias_id}")
|
log.debug(f"Index added for {chat.id} at /{alias_id}")
|
||||||
routes.append(web.view(r"/{wildcard:.*}", h.wildcard))
|
routes.append(web.view(r"/{wildcard:.*}", h.wildcard))
|
||||||
app.add_routes(routes)
|
app.add_routes(routes)
|
||||||
|
|
|
@ -12,27 +12,37 @@ class Client(TelegramClient):
|
||||||
self.log = logging.getLogger(__name__)
|
self.log = logging.getLogger(__name__)
|
||||||
|
|
||||||
async def download(self, file, file_size, offset, limit):
|
async def download(self, file, file_size, offset, limit):
|
||||||
part_size_kb = utils.get_appropriated_part_size(file_size)
|
part_size = utils.get_appropriated_part_size(file_size) * 1024
|
||||||
part_size = int(part_size_kb * 1024)
|
|
||||||
first_part_cut = offset % part_size
|
first_part_cut = offset % part_size
|
||||||
first_part = math.floor(offset / part_size)
|
first_part = math.floor(offset / part_size)
|
||||||
last_part_cut = part_size - (limit % part_size)
|
last_part_cut = part_size - (limit % part_size)
|
||||||
last_part = math.ceil(limit / part_size)
|
last_part = math.ceil(limit / part_size)
|
||||||
part_count = math.ceil(file_size / part_size)
|
part_count = math.ceil(file_size / part_size)
|
||||||
part = first_part
|
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:
|
try:
|
||||||
async for chunk in self.iter_download(
|
async for chunk in self.iter_download(
|
||||||
file, offset=first_part * part_size, request_size=part_size
|
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:
|
if part == first_part:
|
||||||
yield chunk[first_part_cut:]
|
yield chunk[first_part_cut:]
|
||||||
elif part == last_part - 1:
|
elif part == last_part:
|
||||||
yield chunk[:last_part_cut]
|
yield chunk[:last_part_cut]
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
yield chunk
|
yield chunk
|
||||||
self.log.debug(f"Part {part}/{last_part} (total {part_count}) served!")
|
|
||||||
part += 1
|
part += 1
|
||||||
self.log.debug("serving finished")
|
|
||||||
|
self.log.debug(f"serving finished")
|
||||||
except (GeneratorExit, StopAsyncIteration, asyncio.CancelledError):
|
except (GeneratorExit, StopAsyncIteration, asyncio.CancelledError):
|
||||||
self.log.debug("file serve interrupted")
|
self.log.debug("file serve interrupted")
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -12,6 +12,7 @@ from .logo_view import LogoView
|
||||||
from .thumbnail_view import ThumbnailView
|
from .thumbnail_view import ThumbnailView
|
||||||
from .login_view import LoginView
|
from .login_view import LoginView
|
||||||
from .logout_view import LogoutView
|
from .logout_view import LogoutView
|
||||||
|
from .faviconicon_view import FaviconIconView
|
||||||
from .middlewhere import middleware_factory
|
from .middlewhere import middleware_factory
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ class Views(
|
||||||
WildcardView,
|
WildcardView,
|
||||||
LoginView,
|
LoginView,
|
||||||
LogoutView,
|
LogoutView,
|
||||||
|
FaviconIconView,
|
||||||
):
|
):
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
self.client = client
|
self.client = client
|
||||||
|
@ -38,7 +40,7 @@ class Views(
|
||||||
while True:
|
while True:
|
||||||
orig_id = f"{chat_id}" # the original id
|
orig_id = f"{chat_id}" # the original id
|
||||||
unique_hash = hashlib.md5(orig_id.encode()).digest()
|
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:
|
if alias_id in self.chat_ids:
|
||||||
self.url_len += (
|
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,
|
"block_downloads": block_downloads,
|
||||||
"m3u_option": ""
|
"m3u_option": ""
|
||||||
if not req.app["is_authenticated"]
|
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 logging
|
||||||
import math
|
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from aiohttp.web import middleware, HTTPFound
|
from aiohttp.web import middleware, HTTPFound, Response
|
||||||
from aiohttp import BasicAuth, hdrs
|
from aiohttp import BasicAuth, hdrs
|
||||||
from aiohttp_session import get_session
|
from aiohttp_session import get_session
|
||||||
|
|
||||||
|
@ -12,6 +12,17 @@ log = logging.getLogger(__name__)
|
||||||
def _do_basic_auth_check(request):
|
def _do_basic_auth_check(request):
|
||||||
auth_header = request.headers.get(hdrs.AUTHORIZATION)
|
auth_header = request.headers.get(hdrs.AUTHORIZATION)
|
||||||
if not auth_header:
|
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
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -25,6 +36,12 @@ def _do_basic_auth_check(request):
|
||||||
if auth.login is None or auth.password is None:
|
if auth.login is None or auth.password is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if (
|
||||||
|
auth.login != request.app["username"]
|
||||||
|
or auth.password != request.app["password"]
|
||||||
|
):
|
||||||
|
return
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,7 +67,7 @@ def middleware_factory():
|
||||||
|
|
||||||
basic_auth_check_resp = _do_basic_auth_check(request)
|
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)
|
return await handler(request)
|
||||||
|
|
||||||
cookies_auth_check_resp = await _do_cookies_auth_check(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:
|
if cookies_auth_check_resp is not None:
|
||||||
return await handler(request)
|
return await handler(request)
|
||||||
|
|
||||||
|
if isinstance(basic_auth_check_resp, Response):
|
||||||
|
return basic_auth_check_resp
|
||||||
|
|
||||||
return HTTPFound(url)
|
return HTTPFound(url)
|
||||||
|
|
||||||
return await handler(request)
|
return await handler(request)
|
||||||
|
|
Loading…
Reference in New Issue