Browse Source

implement login

feature_tests
Burathar 4 years ago
parent
commit
1de0ef561d
  1. 3
      app/__init__.py
  2. 22
      app/forms.py
  3. 28
      app/models.py
  4. 38
      app/routes.py
  5. 19
      app/templates/base.html
  6. 36
      app/templates/index.html
  7. 14
      app/templates/login.html
  8. 11
      app/templates/register.html
  9. 28
      migrations/versions/01c009738a1f_update_to_1_3.py

3
app/__init__.py

@ -3,11 +3,14 @@ from flask_bootstrap import Bootstrap @@ -3,11 +3,14 @@ from flask_bootstrap import Bootstrap
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager
app = Flask(__name__)
app.config.from_object(Config)
bootstrap = Bootstrap(app)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
login = LoginManager(app)
login.login_view = 'login'
from app import routes, models

22
app/forms.py

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField, TextAreaField
from wtforms.validators import DataRequired, EqualTo, ValidationError, Length
from app.models import Player
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Remember Me', default=True)
submit = SubmitField('Sign In')
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(min=0, max=64)])
password = PasswordField('Password', validators=[DataRequired(), Length(min=0, max=128)])
password2 = PasswordField(
'Repeat Password', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('Register')
def validate_username(self, username):
player = Player.query.filter_by(name=username.data).first()
if player is not None:
raise ValidationError('Please use a different username.')

28
app/models.py

@ -1,5 +1,8 @@ @@ -1,5 +1,8 @@
from app import app, db
from werkzeug.security import generate_password_hash, check_password_hash
from app import app, db, login
from sqlalchemy.sql import func
from secrets import token_hex
from flask_login import UserMixin
game_player = db.Table('game_player',
db.Column('game_id', db.Integer, db.ForeignKey('game.id'), nullable=False),
@ -9,9 +12,9 @@ game_player = db.Table('game_player', @@ -9,9 +12,9 @@ game_player = db.Table('game_player',
)
player_found_objective = db.Table('player_found_objective',
db.Column('game_id', db.Integer, db.ForeignKey('game.id'), nullable=False),
db.Column('player_id', db.Integer, db.ForeignKey('player.id'), nullable=False),
db.PrimaryKeyConstraint('game_id', 'player_id'),
db.Column('objective_id', db.Integer, db.ForeignKey('objective.id'), nullable=False, server_default='-1'),
db.Column('player_id', db.Integer, db.ForeignKey('player.id'), nullable=False, server_default='-1'),
db.PrimaryKeyConstraint('objective_id', 'player_id'),
db.Column('timestamp', db.DateTime, server_default=func.now(), nullable=False)
)
@ -49,11 +52,11 @@ class Game(db.Model): @@ -49,11 +52,11 @@ class Game(db.Model):
lazy='select',
backref=db.backref('game', lazy='joined'))
class Player(db.Model):
class Player(UserMixin, db.Model):
__tablename__ = 'player'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True, nullable=False)
auth_hash = db.Column(db.String(128), unique=True, nullable=True)
auth_hash = db.Column(db.String(32), unique=True, nullable=True)
password_hash = db.Column(db.String(128))
games = db.relationship(
'Game',
@ -78,6 +81,19 @@ class Player(db.Model): @@ -78,6 +81,19 @@ class Player(db.Model):
secondary=notification_player,
back_populates='recipients')
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def set_auth_hash(self):
self.auth_hash = token_hex(16)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
@login.user_loader
def load_user(id):
return Player.query.get(int(id))
class Objective(db.Model):
__tablename__ = 'objective'
id = db.Column(db.Integer, primary_key=True)

38
app/routes.py

@ -1,11 +1,45 @@ @@ -1,11 +1,45 @@
from flask import render_template, flash, redirect, url_for, request
from flask_login import login_user, logout_user, current_user, login_required
from app import app, db
#from app.forms import -
from app.models import Player, Game
from app.forms import LoginForm, RegistrationForm
@app.route('/', methods=['GET'])
@app.route('/index', methods=['GET'])
@login_required
def index():
message="Hello, World"
return render_template("index.html", title='Home', message=message)
#@app.route('/game/<game_name>/leader')
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = LoginForm()
if form.validate_on_submit():
player = Player.query.filter_by(name=form.username.data).first()
if player is None or not player.check_password(form.password.data):
flash('Invalid username or password')
return redirect(url_for('login'))
login_user(player, remember=form.remember_me.data)
return redirect(url_for('index'))
return render_template('login.html', title='Sign In', form=form)
@app.route('/logout')
def logout():
logout_user()
return redirect(url_for('index'))
@app.route('/register', methods=['GET', 'POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = RegistrationForm()
if form.validate_on_submit():
player = Player(name=form.username.data)
player.set_password(form.password.data)
db.session.add(player)
db.session.commit()
flash('Congratulations, you are now a registered user!')
return redirect(url_for('login'))
return render_template('register.html', title='Register', form=form)

19
app/templates/base.html

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
{% extends 'bootstrap/base.html' %}
{% block title %}
{% if title %}{{ title }} - Microblog{% else %}Welcome to Microblog{% endif %}
{% if title %}{{ title }} - The Hunt{% else %}Welcome to The Hunt{% endif %}
{% endblock %}
{% block navbar %}
@ -14,14 +14,18 @@ @@ -14,14 +14,18 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{{ url_for('index') }}">Microblog</a>
<a class="navbar-brand" href="{{ url_for('index') }}">The Hunt</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="{{ url_for('index') }}">Home</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><p>Logout</p></li>
{% if current_user.is_anonymous %}
<li><a href="{{ url_for('login') }}">Login</a></li>
{% else %}
<li><a href="{{ url_for('logout') }}">Logout</a></li>
{% endif %}
</ul>
</div>
</div>
@ -30,6 +34,15 @@ @@ -30,6 +34,15 @@
{% block content %}
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-info" role="alert">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{# application content needs to be provided in the app_content block #}
{% block app_content %}{% endblock %}
</div>
{% endblock %}

36
app/templates/index.html

@ -1,8 +1,40 @@ @@ -1,8 +1,40 @@
{% extends 'base.html' %}
{% block app_content %}
<h1>Welcome!</h1>
<h1>Hi, {{ current_user.name }}!</h1>
<h2>{{ message }}</h2>
<h2>My games:</h2>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">State</th>
<th scope="col">Start Time</th>
<th scope="col">End Time</th>
<th scope="col">My Role</th>
</tr>
</thead>
<tbody>
<tr>
<td>Gamename</td>
<td>Running</td>
<td>yesterday</td>
<td>tomorrow</td>
<td>bitch</td>
</tr>
{% for game in current_user.games %}
<tr>
<td>{{ game.name }}</td>
<td>{{ game.state }}</td>
<td>{{ game.start_time }}</td>
<td>{{ game.end_time }}</td>
<td>bitch</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

14
app/templates/login.html

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<h1>Sign In</h1>
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
</div>
<br>
<p>New User? <a href="{{ url_for('register') }}">Click to Register!</a></p>
{% endblock %}

11
app/templates/register.html

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<h1>Register</h1>
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
</div>
{% endblock %}

28
migrations/versions/b98d6f905471_update_up_to_1_3.py → migrations/versions/01c009738a1f_update_to_1_3.py

@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
"""update up to 1.3
"""update to 1.3
Revision ID: b98d6f905471
Revision ID: 01c009738a1f
Revises:
Create Date: 2020-07-03 11:23:06.765509
Create Date: 2020-07-03 13:12:00.463246
"""
from alembic import op
@ -10,7 +10,7 @@ import sqlalchemy as sa @@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'b98d6f905471'
revision = '01c009738a1f'
down_revision = None
branch_labels = None
depends_on = None
@ -30,7 +30,7 @@ def upgrade(): @@ -30,7 +30,7 @@ def upgrade():
op.create_table('player',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=64), nullable=False),
sa.Column('auth_hash', sa.String(length=128), nullable=True),
sa.Column('auth_hash', sa.String(length=32), nullable=True),
sa.Column('password_hash', sa.String(length=128), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('auth_hash'),
@ -82,14 +82,6 @@ def upgrade(): @@ -82,14 +82,6 @@ def upgrade():
sa.ForeignKeyConstraint(['caught_player_id'], ['player.id'], ),
sa.UniqueConstraint('photo_reference')
)
op.create_table('player_found_objective',
sa.Column('game_id', sa.Integer(), nullable=False),
sa.Column('player_id', sa.Integer(), nullable=False),
sa.Column('timestamp', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
sa.ForeignKeyConstraint(['game_id'], ['game.id'], ),
sa.ForeignKeyConstraint(['player_id'], ['player.id'], ),
sa.PrimaryKeyConstraint('game_id', 'player_id')
)
op.create_table('notification_player',
sa.Column('notification_id', sa.Integer(), nullable=False),
sa.Column('player_id', sa.Integer(), nullable=False),
@ -98,13 +90,21 @@ def upgrade(): @@ -98,13 +90,21 @@ def upgrade():
sa.ForeignKeyConstraint(['player_id'], ['player.id'], ),
sa.PrimaryKeyConstraint('notification_id', 'player_id')
)
op.create_table('player_found_objective',
sa.Column('objective_id', sa.Integer(), server_default='-1', nullable=False),
sa.Column('player_id', sa.Integer(), server_default='-1', nullable=False),
sa.Column('timestamp', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
sa.ForeignKeyConstraint(['objective_id'], ['objective.id'], ),
sa.ForeignKeyConstraint(['player_id'], ['player.id'], ),
sa.PrimaryKeyConstraint('objective_id', 'player_id')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('notification_player')
op.drop_table('player_found_objective')
op.drop_table('notification_player')
op.drop_table('player_caught_player')
op.drop_table('objective')
op.drop_table('notification')
Loading…
Cancel
Save