first commit
This commit is contained in:
commit
e6b95c16bf
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
__pycache__/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
config.py
|
15
LICENSE
Normal file
15
LICENSE
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
ISC License
|
||||||
|
|
||||||
|
Copyright (c) 2020, iou1name <iou1name@steelbea.me>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
13
README.md
Normal file
13
README.md
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# Stickup
|
||||||
|
A frontend for managing a user's email password.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
Python 3.8+
|
||||||
|
Python packages: `gunicorn aiohttp aiohttp_jinja2 uvloop asyncpg passlib argon2_cffi`
|
||||||
|
|
||||||
|
## Install
|
||||||
|
1. Get on the floor
|
||||||
|
2. Walk the dinosaur
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
`gunicorn stickup:init_app --bind localhost:5050 --worker-class aiohttp.GunicornWebWorker`
|
73
buckler_aiohttp.py
Normal file
73
buckler_aiohttp.py
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Session interface middlewares to integrate the aiohttp app with Buckler.
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
from aiohttp import web
|
||||||
|
|
||||||
|
import config
|
||||||
|
|
||||||
|
@web.middleware
|
||||||
|
async def buckler_session(request, handler):
|
||||||
|
"""
|
||||||
|
Verifies the user with the configured Buckler app and retrieves any
|
||||||
|
session data they may have. Redirects them to the login page otherwise.
|
||||||
|
"""
|
||||||
|
user_id = request.cookies.get('userid', '')
|
||||||
|
user_sid = request.cookies.get('session', '')
|
||||||
|
|
||||||
|
url = config.buckler['url'] + '/get_session'
|
||||||
|
params = {
|
||||||
|
'app_id': config.buckler['app_id'],
|
||||||
|
'app_key': config.buckler['app_key'],
|
||||||
|
'userid': user_id,
|
||||||
|
'session': user_sid
|
||||||
|
}
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get(url, params=params) as resp:
|
||||||
|
data = await resp.json()
|
||||||
|
if data.get('error'):
|
||||||
|
resp = web.HTTPFound(config.buckler['login_url'])
|
||||||
|
resp.set_cookie(
|
||||||
|
'redirect',
|
||||||
|
request.url,
|
||||||
|
domain=config.server_domain,
|
||||||
|
secure=True,
|
||||||
|
httponly=True)
|
||||||
|
#samesite='strict')
|
||||||
|
raise resp
|
||||||
|
request['session'] = data['session_data']
|
||||||
|
request['meta'] = data['meta']
|
||||||
|
|
||||||
|
resp = await handler(request)
|
||||||
|
|
||||||
|
if request['session'] != data['session_data']: # session data modified
|
||||||
|
url = config.buckler['url'] + '/set_session'
|
||||||
|
data = json.dumps(request['session'])
|
||||||
|
session.post(url, params=params, data=data) # TODO: error handle?
|
||||||
|
|
||||||
|
last_used = datetime.fromisoformat(request['meta']['last_used'])
|
||||||
|
now = datetime.now(last_used.tzinfo)
|
||||||
|
delta = now - last_used
|
||||||
|
if delta.seconds > 600:
|
||||||
|
resp.set_cookie(
|
||||||
|
'userid',
|
||||||
|
user_id,
|
||||||
|
domain=config.server_domain,
|
||||||
|
max_age=30*24*60*60,
|
||||||
|
secure=True,
|
||||||
|
httponly=True)
|
||||||
|
#samesite='strict')
|
||||||
|
resp.set_cookie(
|
||||||
|
'session',
|
||||||
|
user_sid,
|
||||||
|
domain=config.server_domain,
|
||||||
|
max_age=30*24*60*60,
|
||||||
|
secure=True,
|
||||||
|
httponly=True)
|
||||||
|
#samesite='strict')
|
||||||
|
|
||||||
|
return resp
|
23
config.py.template
Normal file
23
config.py.template
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Configuration settings for the Scorch musc streaming app.
|
||||||
|
`url_prefix` is the root path you wish app to reside at
|
||||||
|
eg. https://example.com/scorch.
|
||||||
|
`buckler` specifies settings pertaining to the Buckler server.
|
||||||
|
"""
|
||||||
|
url_prefix = '/scorch'
|
||||||
|
music_dir = "/home/iou1name/music/Music"
|
||||||
|
db = {
|
||||||
|
'database': 'scorch',
|
||||||
|
'user': 'scorch',
|
||||||
|
'password': """password""",
|
||||||
|
'host': 'localhost',
|
||||||
|
'port': 5432,
|
||||||
|
}
|
||||||
|
|
||||||
|
buckler = {
|
||||||
|
'url': "http://127.0.0.1:5400/buckler",
|
||||||
|
'app_id': 1,
|
||||||
|
'app_key': """password""",
|
||||||
|
'login_url': "/buckler/login",
|
||||||
|
}
|
43
stickup.py
Executable file
43
stickup.py
Executable file
|
@ -0,0 +1,43 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
An email management frontend.
|
||||||
|
"""
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
from aiohttp import web
|
||||||
|
import jinja2
|
||||||
|
import aiohttp_jinja2
|
||||||
|
from aiohttp_jinja2 import render_template
|
||||||
|
import uvloop
|
||||||
|
|
||||||
|
import config
|
||||||
|
import buckler_aiohttp
|
||||||
|
|
||||||
|
uvloop.install()
|
||||||
|
routes = web.RouteTableDef()
|
||||||
|
|
||||||
|
@routes.get('/', name='index')
|
||||||
|
async def index(request):
|
||||||
|
"""The index page."""
|
||||||
|
return render_template('index.html', request, locals())
|
||||||
|
|
||||||
|
|
||||||
|
async def init_app():
|
||||||
|
"""Initializes the application."""
|
||||||
|
app = web.Application(middlewares=[buckler_aiohttp.buckler_session])
|
||||||
|
#app = web.Application()
|
||||||
|
aiohttp_jinja2.setup(
|
||||||
|
app,
|
||||||
|
trim_blocks=True,
|
||||||
|
lstrip_blocks=True,
|
||||||
|
undefined=jinja2.StrictUndefined,
|
||||||
|
loader=jinja2.FileSystemLoader('templates'),
|
||||||
|
)
|
||||||
|
app.router.add_routes(routes)
|
||||||
|
app_wrap = web.Application()
|
||||||
|
app_wrap.add_subapp(config.url_prefix, app)
|
||||||
|
return app_wrap
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = asyncio.run(init_app())
|
||||||
|
aiohttp.web.run_app(app, host='0.0.0.0', port=5050)
|
11
templates/index.html
Normal file
11
templates/index.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Stickup</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=0.8">
|
||||||
|
<meta name="description" content="An email management frontend.">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>This is a stickup!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user