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