Copy maqpi code

This commit is contained in:
Scoder12
2020-07-27 17:12:47 -07:00
parent a7accdba19
commit dd4ea94021
6 changed files with 241 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
"""A basic example of repl auth."""
import simple
app = simple.App("app")
@app.route("/")
def index():
if simple.signed_in:
return "Hello " + simple.auth.name
else:
return simple.signin() # optionally: simple.sigin(title="My title")
if __name__ == "__main__":
app.run()
+20
View File
@@ -0,0 +1,20 @@
"""Make apps quickly in python."""
import os
import flask
from werkzeug.local import LocalProxy
from . import html
from .app import App
from .html import Page, Paragraph
from .utils import sign_in_snippet, signin
# TODO: import new db package package name
db = ReplitDb(os.environ["REPLIT_DB_URL"])
auth = LocalProxy(lambda: flask.request.auth)
signed_in = LocalProxy(lambda: flask.request.signed_in)
# TODO: signinwall(exclude=['/a', '/b'])
# TODO: @need_signin
# TODO: Param checking with @needs_params
+77
View File
@@ -0,0 +1,77 @@
"""Core of maqpi."""
from dataclasses import dataclass
from typing import Any
import flask
@dataclass
class ReplitAuthContext:
"""A dataclass defining a Repl Auth state."""
user_id: int
name: str
roles: str
@classmethod
def from_headers(cls, headers: dict):
"""Initialize an instance using the Replit magic headers.
Args:
headers (dict): A dictionary of headers received
Returns:
[type]: An initialized class instance
"""
return cls(
user_id=headers.get("X-Replit-User-Id"),
name=headers.get("X-Replit-User-Name"),
roles=headers.get("X-Replit-User-Roles"),
)
@property
def signed_in(self) -> bool:
"""Return whether or not the authentication is activated."""
return self.name != ""
class Request(flask.Request):
"""Represents a client request."""
def __init__(self, *args: Any, **kwargs: Any) -> None:
"""Initialize request and run update_auth."""
super().__init__(*args, **kwargs)
self.update_auth()
def update_auth(self) -> None:
"""Update the auth property to be a ReplitAuthContext."""
self.auth = ReplitAuthContext.from_headers(self.headers)
@property
def signed_in(self) -> bool:
"""Return whether or not the authentication is activated."""
return self.auth.signed_in
class App(flask.Flask):
"""Represents a web application."""
request_class = Request
def all_pages_sign_in(self) -> None:
"""Require sign-in on all pages."""
raise NotImplementedError()
def _run(self, *args: Any, **kwargs: Any) -> Any:
"""Interface with the underlying flask instance's run function."""
return super().run(*args, **kwargs)
def run(self, port: int = 8080, localhost: bool = False) -> None:
"""Run the app.
Args:
port (int): The port to run the app on. Defaults to 8080.
localhost (bool): Whether to run the app without exposing it on all
interfaces. Defaults to False.
"""
super().run(host="localhost" if localhost else "0.0.0.0", port=port)
+65
View File
@@ -0,0 +1,65 @@
"""Utitilities for interacting with static files."""
import flask
class FileCache:
"""A simple cache for files."""
def __init__(self) -> None:
self.data = {}
def add_to_cache(self, filename: str, content: str) -> None:
"""Add a filename to the cache.
Args:
filename (str): The filename to add.
content (str): The content to add to the cache.
"""
self.data[filename] = content
def has(self, filename: str) -> bool:
"""Whether the cache has a certain filename.
Args:
filename (str): The filename to check for.
Returns:
bool: Whether the cache has filename.
"""
return filename in self.data
def invalidate(self, filename: str) -> None:
"""Remove a filename from the cache.
Args:
filename (str): The filename to remove.
"""
try:
self.data.pop(filename)
except KeyError:
pass
def flush(self) -> None:
"""Remove all values from the cache."""
self.data = {}
cache = FileCache()
class File(flask.Response):
"""Represents a static file."""
def __init__(self, filename: str, no_cache: bool = False) -> None:
self.filename = str(filename)
self.no_cache = no_cache
# load file
if filename not in cache:
with open(filename, "r") as f:
self.content = f.read()
if not no_cache:
cache.add_to_cache(filename, self.content)
super().__init__(self.content)
+43
View File
@@ -0,0 +1,43 @@
"""Class-representations for HTML elements."""
from abc import ABC
from dataclasses import dataclass
import flask
class HTMLElement(ABC):
"""Base class for an HTML element."""
pass
@dataclass
class Paragraph:
"""Represents a Paragraph (p) tag."""
content: str
def __str__(self) -> str:
return f"<p>{self.content}</p>"
class Page(flask.Response):
"""Represents an HTML page."""
def __init__(self, title: str = None, head: str = "", body: str = "") -> None:
self.title = title
self.head = head
self.body = body
title_html = f"<title>{self.title}</title>\n " if self.title else ""
super().__init__(
f"""<!DOCTYPE html>
<html>
<head>
{title_html}{self.head}
</head>
<body>
{self.body}
</body>
</html>"""
)
+20
View File
@@ -0,0 +1,20 @@
"""Utitilities to make development easier."""
from .html import Page
sign_in_snippet = (
'<script authed="location.reload()" '
'src="https://auth.turbio.repl.co/script.js"></script>'
)
def signin(title: str = "Please Sign In") -> Page:
"""Return a sign-in page.
Args:
title (str): The title of the sign in page. Defaults to "Please Sign In".
Returns:
Page: The sign-in page.
"""
return Page(title=title, body=sign_in_snippet)