Initial commit

This commit is contained in:
Andrew Bryant 2024-04-22 21:14:54 -04:00
commit 994bad056b
21 changed files with 282 additions and 0 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# Environment variables
.env
.flaskenv

11
Makefile Normal file
View File

@ -0,0 +1,11 @@
####
# Target definitions
####
# Development targets
.PHONY: development-server
development-server: # Start a development server
python3 dev-server.py

41
README.md Normal file
View File

@ -0,0 +1,41 @@
# allpawcare-accounts
Flask blueprint for All Paw Care website.
## Usage
Include as a submodule or install as a package.
## What works
Not much, at the moment.
## Work to be done
- Database connection
- Database models
* Users
* Dogs
* Clients
- Login page
- Authentication
- Registration page
- Registration backend
- Installing as package
## Routes
Routes handled by this blueprint.
### /accounts/register
Account registration and creation.
### /accounts/login
User login and authentication.

9
accounts/__init__.py Normal file
View File

@ -0,0 +1,9 @@
from flask import Blueprint
accounts = Blueprint('accounts', __name__,
template_folder='templates',
url_prefix='/accounts')
# Placed here to avoid circular import error
from accounts import views

View File

@ -0,0 +1,10 @@
{% extends "base.html" %}
{% set title %}Account Login{% endset %}
{% block content %}
Login here
---------------
Soon to come ;)
{% endblock %}

View File

@ -0,0 +1,10 @@
{% extends "base.html" %}
{% set title %}Account Registration{% endset %}
{% block content %}
Register for an account
-----------------------
Soon to come ;)
{% endblock %}

View File

@ -0,0 +1,3 @@
from accounts.views import login
from accounts.views import register

13
accounts/views/login.py Normal file
View File

@ -0,0 +1,13 @@
from flask import jsonify
from flask import render_template
from accounts import accounts
@accounts.route('/login', methods=['GET'])
def login():
return render_template('login.html')
@accounts.route('/login', methods=['POST'])
def authenticate():
return jsonify({"message": "Login successful"}), 201

View File

@ -0,0 +1,14 @@
from flask import jsonify
from flask import render_template
from accounts import accounts
@accounts.route('/register', methods=['GET'])
def sign_up():
return render_template('registration.html')
@accounts.route('/register', methods=['POST'])
def register():
# Registration logic
return jsonify({"message": "Registration successful"}), 201

16
dev-server.py Executable file
View File

@ -0,0 +1,16 @@
#! /usr/bin/env python3
from flask import Flask
from accounts import accounts
from tests.config import TestConfig
def create_app():
accounts_app = Flask(__name__, template_folder='tests/templates')
accounts_app.register_blueprint(accounts)
accounts_app.config.from_object(TestConfig)
return accounts_app
if __name__ == '__main__':
create_app().run(debug=True)

30
shell.nix Normal file
View File

@ -0,0 +1,30 @@
{ pkgs ? import <nixpkgs> {} }:
with pkgs;
pkgs.mkShell {
nativeBuildInputs = [
inlyne # markdown viewer
# Python development environment
(python3.withPackages(ps: with ps; [
# For blueprint configuration
python-dotenv
# Testing
pytest
pytest-flask
# web framework
flask
# Database
alembic # migrations
flask-sqlalchemy # orm
sqlalchemy # orm
sqlite # driver
sqlite-utils # utilities
]))
];
}

13
tests/README.md Normal file
View File

@ -0,0 +1,13 @@
# Testing
Bugs and regressions don't stand a chance.
## Templates
[Templates](./templates) used for testing.
## Development server
The [script](./dev-server.py) is used to run a development server on the local
system for testing.

0
tests/__init__.py Normal file
View File

3
tests/config.py Normal file
View File

@ -0,0 +1,3 @@
class TestConfig():
pass

19
tests/conftest.py Normal file
View File

@ -0,0 +1,19 @@
import pytest
from flask import Flask
from accounts import accounts
from .config import TestConfig
@pytest.fixture(scope="module")
def accounts_app():
accounts_app = Flask(__name__, template_folder='templates')
accounts_app.register_blueprint(accounts)
accounts_app.config.from_object(TestConfig)
yield accounts_app
@pytest.fixture(scope="module")
def client(accounts_app):
return accounts_app.test_client()

View File

@ -0,0 +1,4 @@
# Mock application templates
Jinja templates for testing can be found in this directory.

24
tests/templates/base.html Normal file
View File

@ -0,0 +1,24 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ title }}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body class="bg-white">
{% include "header.html" %}
<main>
<div class="container">
{% block content %}
{% endblock %}
</div>
</main>
{% include "footer.html" %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body>
</html>

View File

@ -0,0 +1,12 @@
<footer class="footer mt-5 bg-tertiary">
<div class="container">
<nav class="navbar navbar-expand-sm text-light">
<div class="container">
<p class="col-md-4 mb-0 text-muted">
© {{ current_year }} Andrew Bryant
</p>
</div>
</nav>
</div>
</footer>

View File

@ -0,0 +1,17 @@
<header>
<nav class="navbar navbar-expand-sm sticky-top bg-light" data-bs-theme="light">
<div class="container">
<button class="navbar-toggler" type="button"
data-bs-toggle="collapse"
data-bs-target="#menu-bar-items"
aria-controls="menu-bar-items"
aria-expanded="false"
aria-label="Toggle menu bar">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="menu-bar-items">
</div>
</div>
</nav>
</header>

12
tests/test_login.py Normal file
View File

@ -0,0 +1,12 @@
import pytest
def test_login(client):
response = client.get('/accounts/login')
assert response.status_code == 200
def test_authenticate(client):
response = client.post('/accounts/login')
assert response.status_code == 201

View File

@ -0,0 +1,12 @@
import pytest
def test_signup(client):
response = client.get('/accounts/register')
assert response.status_code == 200
def test_registration(client):
response = client.post('/accounts/register')
assert response.status_code == 201