From 11eec8a365b2ce17a6b7a562c8888b140f30458c Mon Sep 17 00:00:00 2001
From: Alex Couper
Date: Fri, 31 May 2013 12:11:10 +0100
Subject: [PATCH 01/20] Add initial users app.
Taken largely from: https://github.com/mitsuhiko/flask/wiki/Large-app-how-to
---
config/settings.py | 20 +++++-
deploystream/__init__.py | 5 ++
deploystream/apps/users/__init__.py | 0
deploystream/apps/users/constants.py | 19 ++++++
deploystream/apps/users/decorators.py | 13 ++++
deploystream/apps/users/forms.py | 21 +++++++
deploystream/apps/users/models.py | 27 ++++++++
deploystream/apps/users/views.py | 73 ++++++++++++++++++++++
deploystream/templates/base-angular.html | 10 +++
deploystream/templates/base.html | 7 ---
deploystream/templates/forms/macros.html | 12 ++++
deploystream/templates/index-async.html | 2 +-
deploystream/templates/index.html | 11 +++-
deploystream/templates/users/login.html | 11 ++++
deploystream/templates/users/profile.html | 4 ++
deploystream/templates/users/register.html | 16 +++++
scripts/shell.py | 9 +++
17 files changed, 249 insertions(+), 11 deletions(-)
create mode 100644 deploystream/apps/users/__init__.py
create mode 100644 deploystream/apps/users/constants.py
create mode 100644 deploystream/apps/users/decorators.py
create mode 100644 deploystream/apps/users/forms.py
create mode 100644 deploystream/apps/users/models.py
create mode 100644 deploystream/apps/users/views.py
create mode 100644 deploystream/templates/base-angular.html
create mode 100644 deploystream/templates/forms/macros.html
create mode 100644 deploystream/templates/users/login.html
create mode 100644 deploystream/templates/users/profile.html
create mode 100644 deploystream/templates/users/register.html
create mode 100644 scripts/shell.py
diff --git a/config/settings.py b/config/settings.py
index 33843ed..78e88fe 100644
--- a/config/settings.py
+++ b/config/settings.py
@@ -1,12 +1,28 @@
from os import path, environ
import traceback
+_basedir = path.abspath(path.dirname(__file__))
-APP_PACKAGE = path.basename(path.dirname(__file__))
+APP_PACKAGE = path.basename(_basedir)
+
+# Default settings, overridden by the python file pointed to by CONFIG variable
+SQLALCHEMY_DATABASE_URI = 'sqlite:///' + path.join(_basedir, 'app.db')
+DATABASE_CONNECT_OPTIONS = {}
+
+# THREADS_PER_PAGE = 8
+
+# CSRF_ENABLED = True
+# CSRF_SESSION_KEY = "somethingimpossibletoguess"
+
+RECAPTCHA_USE_SSL = False
+RECAPTCHA_PUBLIC_KEY = 'blahblahblahblahblahblahblahblahblah'
+RECAPTCHA_PRIVATE_KEY = 'blahblahblahblahblahblahprivate'
+RECAPTCHA_OPTIONS = {'theme': 'white'}
+
+GITHUB_CONFIG = GIT_CONFIG = SPRINTLY_CONFIG = JIRA_CONFIG = None
# The following is the programmatic equivalent of
# from deploystream.local_settings_ import *
-GITHUB_CONFIG = GIT_CONFIG = SPRINTLY_CONFIG = JIRA_CONFIG = None
try:
CONFIG = environ.get('CONFIG', 'sample')
diff --git a/deploystream/__init__.py b/deploystream/__init__.py
index 263a040..cafa438 100644
--- a/deploystream/__init__.py
+++ b/deploystream/__init__.py
@@ -3,6 +3,7 @@
from os import environ
from os.path import join, dirname
from flask import Flask
+from flask.ext.sqlalchemy import SQLAlchemy
APP_DIR = dirname(__file__)
CONFIG_DIR = join(dirname(APP_DIR), 'config')
@@ -51,6 +52,7 @@
# something that is actually a secret
app.secret_key = 'mysecret'
+db = SQLAlchemy(app)
# Initialise the providers.
from providers import init_providers
classes = init_providers(app.config['PROVIDERS'])
@@ -62,3 +64,6 @@
# Import any views we want to register here at the bottom of the file:
import deploystream.views # NOQA
import deploystream.apps.feature.views # NOQA
+
+from deploystream.apps.users.views import mod as usersModule
+app.register_blueprint(usersModule)
diff --git a/deploystream/apps/users/__init__.py b/deploystream/apps/users/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/deploystream/apps/users/constants.py b/deploystream/apps/users/constants.py
new file mode 100644
index 0000000..ab54a21
--- /dev/null
+++ b/deploystream/apps/users/constants.py
@@ -0,0 +1,19 @@
+# User role
+ADMIN = 0
+STAFF = 1
+USER = 2
+ROLE = {
+ ADMIN: 'admin',
+ STAFF: 'staff',
+ USER: 'user',
+}
+
+# user status
+INACTIVE = 0
+NEW = 1
+ACTIVE = 2
+STATUS = {
+ INACTIVE: 'inactive',
+ NEW: 'new',
+ ACTIVE: 'active',
+}
diff --git a/deploystream/apps/users/decorators.py b/deploystream/apps/users/decorators.py
new file mode 100644
index 0000000..aa0e4e1
--- /dev/null
+++ b/deploystream/apps/users/decorators.py
@@ -0,0 +1,13 @@
+from functools import wraps
+
+from flask import g, flash, redirect, url_for, request
+
+
+def requires_login(f):
+ @wraps(f)
+ def decorated_function(*args, **kwargs):
+ if g.user is None:
+ flash(u'You need to be signed in for this page.')
+ return redirect(url_for('users.login', next=request.path))
+ return f(*args, **kwargs)
+ return decorated_function
diff --git a/deploystream/apps/users/forms.py b/deploystream/apps/users/forms.py
new file mode 100644
index 0000000..71743d1
--- /dev/null
+++ b/deploystream/apps/users/forms.py
@@ -0,0 +1,21 @@
+from flask.ext.wtf import (
+ Form, TextField, PasswordField, BooleanField, RecaptchaField
+)
+from flask.ext.wtf import Required, Email, EqualTo
+
+
+class LoginForm(Form):
+ email = TextField('Email address', [Required(), Email()])
+ password = PasswordField('Password', [Required()])
+
+
+class RegisterForm(Form):
+ name = TextField('NickName', [Required()])
+ email = TextField('Email address', [Required(), Email()])
+ password = PasswordField('Password', [Required()])
+ confirm = PasswordField('Repeat Password', [
+ Required(),
+ EqualTo('password', message='Passwords must match')
+ ])
+ accept_tos = BooleanField('I accept the TOS', [Required()])
+ #recaptcha = RecaptchaField()
diff --git a/deploystream/apps/users/models.py b/deploystream/apps/users/models.py
new file mode 100644
index 0000000..8ea66bd
--- /dev/null
+++ b/deploystream/apps/users/models.py
@@ -0,0 +1,27 @@
+from deploystream import db
+from deploystream.apps.users import constants as USER
+
+
+class User(db.Model):
+
+ __tablename__ = 'users_user'
+ id = db.Column(db.Integer, primary_key=True)
+ name = db.Column(db.String(50), unique=True)
+ email = db.Column(db.String(120), unique=True)
+ password = db.Column(db.String(20))
+ role = db.Column(db.SmallInteger, default=USER.USER)
+ status = db.Column(db.SmallInteger, default=USER.NEW)
+
+ def __init__(self, name=None, email=None, password=None):
+ self.name = name
+ self.email = email
+ self.password = password
+
+ def getStatus(self):
+ return USER.STATUS[self.status]
+
+ def getRole(self):
+ return USER.ROLE[self.role]
+
+ def __repr__(self):
+ return '' % (self.name)
diff --git a/deploystream/apps/users/views.py b/deploystream/apps/users/views.py
new file mode 100644
index 0000000..c7ba9cf
--- /dev/null
+++ b/deploystream/apps/users/views.py
@@ -0,0 +1,73 @@
+from flask import (Blueprint, request, render_template, flash, g, session,
+ redirect, url_for)
+from werkzeug import check_password_hash, generate_password_hash
+
+from deploystream import db
+from deploystream.apps.users.forms import RegisterForm, LoginForm
+from deploystream.apps.users.models import User
+from deploystream.apps.users.decorators import requires_login
+
+mod = Blueprint('users', __name__, url_prefix='/users')
+
+
+@mod.route('/me/')
+@requires_login
+def home():
+ return render_template("users/profile.html", user=g.user)
+
+
+@mod.before_request
+def before_request():
+ """
+ pull user's profile from the database before every request are treated
+ """
+ g.user = None
+ if 'user_id' in session:
+ g.user = User.query.get(session['user_id'])
+
+
+@mod.route('/login/', methods=['GET', 'POST'])
+def login():
+ """
+ Login form
+ """
+ form = LoginForm(request.form)
+ # make sure data are valid, but doesn't validate password is right
+ if form.validate_on_submit():
+ user = User.query.filter_by(email=form.email.data).first()
+ # we use werzeug to validate user's password
+ if user and check_password_hash(user.password, form.password.data):
+ # the session can't be modified as it's signed,
+ # it's a safe place to store the user id
+ session['user_id'] = user.id
+ flash('Welcome %s' % user.name)
+ return redirect(url_for('users.home'))
+ flash('Wrong email or password', 'error-message')
+ return render_template("users/login.html", form=form)
+
+
+@mod.route('/register/', methods=['GET', 'POST'])
+def register():
+ """
+ Registration Form
+ """
+ form = RegisterForm(request.form)
+ if form.validate_on_submit():
+ print "VALID"
+ # create an user instance not yet stored in the database
+ user = User(form.name.data, form.email.data, \
+ generate_password_hash(form.password.data))
+ # Insert the record in our database and commit it
+ db.session.add(user)
+ db.session.commit()
+
+ # Log the user in, as he now has an id
+ session['user_id'] = user.id
+
+ # flash will display a message to the user
+ flash('Thanks for registering')
+ # redirect user to the 'home' method of the user module.
+ return redirect(url_for('users.home'))
+ else:
+ print form.__dict__
+ return render_template("users/register.html", form=form)
diff --git a/deploystream/templates/base-angular.html b/deploystream/templates/base-angular.html
new file mode 100644
index 0000000..14535f0
--- /dev/null
+++ b/deploystream/templates/base-angular.html
@@ -0,0 +1,10 @@
+{% extends "base.html" %}
+
+{% block extrahead %}
+
+{% endblock %}
diff --git a/deploystream/templates/base.html b/deploystream/templates/base.html
index e36bb90..24fe0f6 100644
--- a/deploystream/templates/base.html
+++ b/deploystream/templates/base.html
@@ -6,13 +6,6 @@
DeployStream {% block extratitle %}{% endblock %}
-
-
diff --git a/deploystream/templates/forms/macros.html b/deploystream/templates/forms/macros.html
new file mode 100644
index 0000000..9496292
--- /dev/null
+++ b/deploystream/templates/forms/macros.html
@@ -0,0 +1,12 @@
+{% macro render_field(field) %}
+
+{% endmacro %}
diff --git a/deploystream/templates/index-async.html b/deploystream/templates/index-async.html
index f8ac747..5e8fa8f 100644
--- a/deploystream/templates/index-async.html
+++ b/deploystream/templates/index-async.html
@@ -1,4 +1,4 @@
-{% extends "base.html" %}
+{% extends "base-angular.html" %}
{% block scripts %}
diff --git a/deploystream/templates/users/login.html b/deploystream/templates/users/login.html
new file mode 100644
index 0000000..f68bbc2
--- /dev/null
+++ b/deploystream/templates/users/login.html
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+{% block content %}
+ {% from "forms/macros.html" import render_field %}
+
+ Register
+{% endblock %}
diff --git a/deploystream/templates/users/profile.html b/deploystream/templates/users/profile.html
new file mode 100644
index 0000000..11e2df1
--- /dev/null
+++ b/deploystream/templates/users/profile.html
@@ -0,0 +1,4 @@
+{% extends "base.html" %}
+{% block content %}
+ {{ user.name }}
+{% endblock %}
diff --git a/deploystream/templates/users/register.html b/deploystream/templates/users/register.html
new file mode 100644
index 0000000..4587062
--- /dev/null
+++ b/deploystream/templates/users/register.html
@@ -0,0 +1,16 @@
+{% extends "base.html" %}
+{% block content %}
+ {% from "forms/macros.html" import render_field %}
+
+ Login
+{% endblock %}
diff --git a/scripts/shell.py b/scripts/shell.py
new file mode 100644
index 0000000..156a0d0
--- /dev/null
+++ b/scripts/shell.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+import os
+import readline
+from pprint import pprint
+
+from flask import *
+from deploystream import *
+
+os.environ['PYTHONINSPECT'] = 'True'
From f93dc78287f502de3dc27c0a76249a8d321c42dd Mon Sep 17 00:00:00 2001
From: Alex Couper
Date: Fri, 31 May 2013 12:14:44 +0100
Subject: [PATCH 02/20] Add script for creating the DB
---
scripts/create_db.py | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 scripts/create_db.py
diff --git a/scripts/create_db.py b/scripts/create_db.py
new file mode 100644
index 0000000..f6d7cca
--- /dev/null
+++ b/scripts/create_db.py
@@ -0,0 +1,3 @@
+from deploystream import db
+
+db.create_all()
From e60dce42b7d98e265bb06ccf29fb5a813797ef3e Mon Sep 17 00:00:00 2001
From: Alex Couper
Date: Fri, 31 May 2013 16:08:57 +0100
Subject: [PATCH 03/20] Allow sign in with github or directly with the site.
---
deploystream/apps/oauth/views.py | 27 ++++++++++++++++++-----
deploystream/apps/users/lib.py | 3 +++
deploystream/apps/users/models.py | 14 +++++++++++-
deploystream/apps/users/views.py | 22 +++++++++---------
deploystream/static/partials/home.html | 2 +-
deploystream/templates/forms/macros.html | 6 ++---
deploystream/templates/navbar.html | 9 ++++++--
deploystream/templates/users/login.html | 6 ++++-
requirements/runtime.txt | 2 ++
tests/test_providers/test_git_provider.py | 7 +++++-
10 files changed, 72 insertions(+), 26 deletions(-)
create mode 100644 deploystream/apps/users/lib.py
diff --git a/deploystream/apps/oauth/views.py b/deploystream/apps/oauth/views.py
index 5a31280..1ec292d 100644
--- a/deploystream/apps/oauth/views.py
+++ b/deploystream/apps/oauth/views.py
@@ -1,8 +1,10 @@
from flask import session, redirect, flash, request, url_for
from flask_oauth import OAuth
-from deploystream import app
+from deploystream import app, db
from deploystream.apps.oauth import get_token, set_token
+from deploystream.apps.users.models import User, OAuth as UserOAuth
+from deploystream.apps.users.lib import load_user_to_session
from deploystream.providers.interfaces import class_implements, IOAuthProvider
@@ -63,14 +65,29 @@ def oauth_authorized(resp):
set_token(session, oauth_name, resp['access_token'])
if request.args.get('islogin'):
- user = OAUTH_OBJECTS[oauth_name].get('/user')
- username = user.data['login']
- session['username'] = username
+ remote_user = OAUTH_OBJECTS[oauth_name].get('/user')
+ remote_user_id = remote_user.data['id']
+ # Save user if doesn't already exist.
+ oauth_obj = UserOAuth.query.filter_by(service_user_id=remote_user_id,
+ service=oauth_name).first()
+ if not oauth_obj:
+ # Create a user and an OAuth linked to it.
+ user = User(name=remote_user.data['login'])
+ oauth = UserOAuth(service_user_id=remote_user_id,
+ service=oauth_name)
+ oauth.user = user
+ db.session.add(user)
+ db.session.add(oauth)
+ db.session.commit()
+ else:
+ user = oauth_obj.user
+
+ load_user_to_session(session, user)
return redirect(next_url)
-@app.route('/login')
+@app.route('/github-login')
def login():
"Handler for calls to login via github."
return start_token_processing('github', islogin=True)
diff --git a/deploystream/apps/users/lib.py b/deploystream/apps/users/lib.py
new file mode 100644
index 0000000..7ba0af4
--- /dev/null
+++ b/deploystream/apps/users/lib.py
@@ -0,0 +1,3 @@
+def load_user_to_session(session, user):
+ session['user_id'] = user.id
+ session['user_name'] = user.name
diff --git a/deploystream/apps/users/models.py b/deploystream/apps/users/models.py
index 8ea66bd..60391b2 100644
--- a/deploystream/apps/users/models.py
+++ b/deploystream/apps/users/models.py
@@ -6,11 +6,12 @@ class User(db.Model):
__tablename__ = 'users_user'
id = db.Column(db.Integer, primary_key=True)
- name = db.Column(db.String(50), unique=True)
+ name = db.Column(db.String(50))
email = db.Column(db.String(120), unique=True)
password = db.Column(db.String(20))
role = db.Column(db.SmallInteger, default=USER.USER)
status = db.Column(db.SmallInteger, default=USER.NEW)
+ oauth_keys = db.relationship('OAuth', backref='user')
def __init__(self, name=None, email=None, password=None):
self.name = name
@@ -25,3 +26,14 @@ def getRole(self):
def __repr__(self):
return '' % (self.name)
+
+
+class OAuth(db.Model):
+
+ __tablename__ = 'users_oauth'
+ id = db.Column(db.Integer, primary_key=True)
+ user_id = db.Column(db.Integer, db.ForeignKey('users_user.id'))
+ service = db.Column(db.String(20))
+ service_user_id = db.Column(db.String(120))
+
+ db.UniqueConstraint('service', 'service_user_id', name='service_user')
diff --git a/deploystream/apps/users/views.py b/deploystream/apps/users/views.py
index c7ba9cf..5853850 100644
--- a/deploystream/apps/users/views.py
+++ b/deploystream/apps/users/views.py
@@ -3,9 +3,10 @@
from werkzeug import check_password_hash, generate_password_hash
from deploystream import db
-from deploystream.apps.users.forms import RegisterForm, LoginForm
-from deploystream.apps.users.models import User
-from deploystream.apps.users.decorators import requires_login
+from .forms import RegisterForm, LoginForm
+from .models import User
+from .lib import load_user_to_session
+from .decorators import requires_login
mod = Blueprint('users', __name__, url_prefix='/users')
@@ -37,9 +38,8 @@ def login():
user = User.query.filter_by(email=form.email.data).first()
# we use werzeug to validate user's password
if user and check_password_hash(user.password, form.password.data):
- # the session can't be modified as it's signed,
- # it's a safe place to store the user id
- session['user_id'] = user.id
+ load_user_to_session(session, user)
+
flash('Welcome %s' % user.name)
return redirect(url_for('users.home'))
flash('Wrong email or password', 'error-message')
@@ -53,10 +53,9 @@ def register():
"""
form = RegisterForm(request.form)
if form.validate_on_submit():
- print "VALID"
- # create an user instance not yet stored in the database
- user = User(form.name.data, form.email.data, \
- generate_password_hash(form.password.data))
+ # create a user instance not yet stored in the database
+ user = User(form.name.data, form.email.data,
+ generate_password_hash(form.password.data))
# Insert the record in our database and commit it
db.session.add(user)
db.session.commit()
@@ -68,6 +67,5 @@ def register():
flash('Thanks for registering')
# redirect user to the 'home' method of the user module.
return redirect(url_for('users.home'))
- else:
- print form.__dict__
+
return render_template("users/register.html", form=form)
diff --git a/deploystream/static/partials/home.html b/deploystream/static/partials/home.html
index 4248b82..dce9602 100644
--- a/deploystream/static/partials/home.html
+++ b/deploystream/static/partials/home.html
@@ -10,7 +10,7 @@ Welcome to Ployst!
from various tools.
-
+
Sign in via Github
diff --git a/deploystream/templates/forms/macros.html b/deploystream/templates/forms/macros.html
index 9496292..5d3f1e0 100644
--- a/deploystream/templates/forms/macros.html
+++ b/deploystream/templates/forms/macros.html
@@ -1,8 +1,8 @@
{% macro render_field(field) %}
-
diff --git a/deploystream/templates/users/login.html b/deploystream/templates/users/login.html
index f68bbc2..21ee7b5 100644
--- a/deploystream/templates/users/login.html
+++ b/deploystream/templates/users/login.html
@@ -1,7 +1,11 @@
{% extends "base.html" %}
+
{% block content %}
{% from "forms/macros.html" import render_field %}
-
Login
diff --git a/tests/test_users/__init__.py b/tests/test_users/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_users/test_views.py b/tests/test_users/test_views.py
new file mode 100644
index 0000000..156de3d
--- /dev/null
+++ b/tests/test_users/test_views.py
@@ -0,0 +1,40 @@
+from nose.tools import assert_true, assert_equal, assert_false
+
+import deploystream
+
+
+class TestRegister(object):
+
+ def setup(self):
+ self.client = deploystream.app.test_client()
+
+ def send_register_post(self, email, password='123',
+ confirm_password='123'):
+ return self.client.post('/users/register',
+ {'name': 'testuser', 'email': email, 'password': password,
+ 'confirm': confirm_password, 'accept_tos': True})
+
+ def test_adds_user_to_the_database(self):
+ response = self.send_register_post('test@test.com')
+
+ assert_equal(response.status_code, 302)
+ assert_true("/users/me" in response.location)
+ assert_false("NEED TO CHECK IN THE DB FOR THE OBJECT HERE")
+
+ def test_incomplete_when_email_already_exists(self):
+ response = self.send_register_post('test@test.com')
+ assert_true("/users/me" in response.location)
+
+ response = self.send_register_post('test@test.com')
+ assert_true("This user already exists" in response.data)
+
+ def test_incomplete_when_passwords_do_not_match(self):
+ response = self.send_register_post('test@test.com', '123', '111')
+
+ assert_true("Passwords must match" in response.data)
+
+
+class TestLogin(object):
+
+ def test_login_to_existing_user_account():
+ raise NotImplementedError()
From f05976b8e8da1ebd68a406003fd5f8ffed4c6dc2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carles=20Barrob=C3=A9s?=
Date: Sat, 1 Jun 2013 14:38:02 +0100
Subject: [PATCH 06/20] Add bootstrap styles for forms
---
deploystream/static/less/bootstrap-modules.less | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/deploystream/static/less/bootstrap-modules.less b/deploystream/static/less/bootstrap-modules.less
index 798c5e0..8afb5bf 100644
--- a/deploystream/static/less/bootstrap-modules.less
+++ b/deploystream/static/less/bootstrap-modules.less
@@ -13,7 +13,7 @@
// Base CSS
@import "bootstrap/type.less";
@import "bootstrap/code.less";
-// @import "bootstrap/forms.less";
+@import "bootstrap/forms.less";
@import "bootstrap/tables.less";
// Components: common
From 5744d5d1ec826f29b58bcfeb9c617d567b2fadc3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carles=20Barrob=C3=A9s?=
Date: Sat, 1 Jun 2013 14:38:35 +0100
Subject: [PATCH 07/20] Make create_db script executable
---
scripts/create_db.py | 1 +
1 file changed, 1 insertion(+)
mode change 100644 => 100755 scripts/create_db.py
diff --git a/scripts/create_db.py b/scripts/create_db.py
old mode 100644
new mode 100755
index f6d7cca..93e8470
--- a/scripts/create_db.py
+++ b/scripts/create_db.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
from deploystream import db
db.create_all()
From 22fa34bc4e14408f6ca424cdf897889f9bcbd31a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carles=20Barrob=C3=A9s?=
Date: Sat, 1 Jun 2013 15:10:41 +0100
Subject: [PATCH 08/20] Improved bootstrap form layout
---
deploystream/templates/forms/macros.html | 18 ++++++++++--------
deploystream/templates/users/login.html | 16 +++++++++++-----
deploystream/templates/users/register.html | 15 ++++++++++++---
3 files changed, 33 insertions(+), 16 deletions(-)
diff --git a/deploystream/templates/forms/macros.html b/deploystream/templates/forms/macros.html
index 5d3f1e0..af8b188 100644
--- a/deploystream/templates/forms/macros.html
+++ b/deploystream/templates/forms/macros.html
@@ -1,12 +1,14 @@
{% macro render_field(field) %}
{% endmacro %}
diff --git a/deploystream/templates/users/login.html b/deploystream/templates/users/login.html
index 21ee7b5..0a3dd6b 100644
--- a/deploystream/templates/users/login.html
+++ b/deploystream/templates/users/login.html
@@ -1,15 +1,21 @@
{% extends "base.html" %}
{% block content %}
+
{% from "forms/macros.html" import render_field %}
- Register
{% endblock %}
diff --git a/deploystream/templates/users/register.html b/deploystream/templates/users/register.html
index 2be4926..c6c6ef8 100644
--- a/deploystream/templates/users/register.html
+++ b/deploystream/templates/users/register.html
@@ -1,14 +1,23 @@
{% extends "base.html" %}
{% block content %}
+
{% from "forms/macros.html" import render_field %}
-
- Login
{% endblock %}
From f2eb401d0997dab7adb3ddd6196a2b4b0a5fa74a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carles=20Barrob=C3=A9s?=
Date: Sun, 2 Jun 2013 00:43:45 +0100
Subject: [PATCH 09/20] Change the approach to login by using a popover
---
deploystream/apps/users/views.py | 6 ++++-
deploystream/templates/base.html | 25 ++++++++++++++++----
deploystream/templates/navbar.html | 4 +++-
deploystream/templates/users/login_ajax.html | 9 +++++++
4 files changed, 38 insertions(+), 6 deletions(-)
create mode 100644 deploystream/templates/users/login_ajax.html
diff --git a/deploystream/apps/users/views.py b/deploystream/apps/users/views.py
index 5853850..8e8d731 100644
--- a/deploystream/apps/users/views.py
+++ b/deploystream/apps/users/views.py
@@ -43,7 +43,11 @@ def login():
flash('Welcome %s' % user.name)
return redirect(url_for('users.home'))
flash('Wrong email or password', 'error-message')
- return render_template("users/login.html", form=form)
+ if request.method == 'POST':
+ suffix = ".html"
+ else:
+ suffix = "_ajax.html"
+ return render_template("users/login" + suffix, form=form)
@mod.route('/register/', methods=['GET', 'POST'])
diff --git a/deploystream/templates/base.html b/deploystream/templates/base.html
index 24fe0f6..bb39707 100644
--- a/deploystream/templates/base.html
+++ b/deploystream/templates/base.html
@@ -11,6 +11,11 @@
+
+
+
+
+
{% block extrahead %}
{% endblock %}
{% endblock %}
@@ -36,10 +41,22 @@
-
-
-
-
+
{% block scripts %}{% endblock %}