Initial commit
This commit is contained in:
commit
994bad056b
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
.env
|
||||||
|
.flaskenv
|
||||||
|
|
||||||
11
Makefile
Normal file
11
Makefile
Normal 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
41
README.md
Normal 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
9
accounts/__init__.py
Normal 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
|
||||||
|
|
||||||
10
accounts/templates/login.html
Normal file
10
accounts/templates/login.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% set title %}Account Login{% endset %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
Login here
|
||||||
|
---------------
|
||||||
|
Soon to come ;)
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
10
accounts/templates/registration.html
Normal file
10
accounts/templates/registration.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% set title %}Account Registration{% endset %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
Register for an account
|
||||||
|
-----------------------
|
||||||
|
Soon to come ;)
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
3
accounts/views/__init__.py
Normal file
3
accounts/views/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from accounts.views import login
|
||||||
|
from accounts.views import register
|
||||||
|
|
||||||
13
accounts/views/login.py
Normal file
13
accounts/views/login.py
Normal 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
|
||||||
|
|
||||||
14
accounts/views/register.py
Normal file
14
accounts/views/register.py
Normal 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
16
dev-server.py
Executable 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
30
shell.nix
Normal 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
13
tests/README.md
Normal 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
0
tests/__init__.py
Normal file
3
tests/config.py
Normal file
3
tests/config.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class TestConfig():
|
||||||
|
pass
|
||||||
|
|
||||||
19
tests/conftest.py
Normal file
19
tests/conftest.py
Normal 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()
|
||||||
|
|
||||||
4
tests/templates/README.md
Normal file
4
tests/templates/README.md
Normal 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
24
tests/templates/base.html
Normal 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>
|
||||||
|
|
||||||
12
tests/templates/footer.html
Normal file
12
tests/templates/footer.html
Normal 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>
|
||||||
|
|
||||||
17
tests/templates/header.html
Normal file
17
tests/templates/header.html
Normal 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
12
tests/test_login.py
Normal 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
|
||||||
|
|
||||||
12
tests/test_registration.py
Normal file
12
tests/test_registration.py
Normal 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
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user