Last active
June 30, 2019 15:44
-
-
Save cldershem/6515886 to your computer and use it in GitHub Desktop.
going from flask-login to flask-security. I'm not clear on how to not use flask-principal. since i have to change so many different things over, i'd like to do this one piece at a time. i may end up using flask-principal in the long run..but if i don't i'd like to get this running without it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from flask import Flask | |
from flask.ext.mongoengine import MongoEngine | |
#from flask.ext.login import LoginManager | |
from flask.ext.bcrypt import Bcrypt | |
from flask_debugtoolbar import DebugToolbarExtension | |
from flask.ext.mail import Mail | |
app = Flask(__name__) | |
app.config.from_object('config') | |
db = MongoEngine(app) | |
bcrypt = Bcrypt(app) | |
toolbar = DebugToolbarExtension(app) | |
mail = Mail(app) | |
#lm = LoginManager(app) | |
#lm.login_view = "users.login" | |
from flask.ext.security import Security, MongoEngineUserDatastore | |
from app.models import User | |
user_datastore = MongoEngineUserDatastore(db, User, User.Roles) | |
security = Security(app, user_datastore) | |
#if not app.debug: | |
from app import routes, models, admin # nopep8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from flask import url_for | |
from app import db, bcrypt | |
from app.constants import DATE_TIME_NOW | |
from flask.ext.security import UserMixin, RoleMixin | |
class User(db.Document, UserMixin): | |
class Roles(db.EmbeddedDocument, RoleMixin): | |
can_login = db.BooleanField(default=False) | |
can_comment = db.BooleanField(default=True) | |
can_post = db.BooleanField(default=True) | |
is_admin = db.BooleanField(default=False) | |
created_at = db.DateTimeField(required=True, default=DATE_TIME_NOW) | |
last_seen = db.DateTimeField(required=True, default=DATE_TIME_NOW) | |
firstname = db.StringField(required=True, max_length=64) | |
lastname = db.StringField(required=True, max_length=100) | |
email = db.StringField(max_length=120, unique=True) | |
pwdhash = db.StringField(required=True) | |
confirmed = db.DateTimeField(default=None) | |
roles = db.EmbeddedDocumentField(Roles, default=Roles) | |
def set_password(self, password): | |
self.pwdhash = bcrypt.generate_password_hash(password) | |
def check_password(self, password): | |
return bcrypt.check_password_hash(self.pwdhash, password) | |
def is_authenticated(self): | |
return True | |
def activate_user(self): | |
self.confirmed = DATE_TIME_NOW | |
self.roles.can_login = True | |
def is_active(self): | |
return True | |
def is_anonymous(self): | |
return False | |
def get_id(self): | |
return self.email | |
def __repr__(self): | |
return '<User %r, %r>' % (self.firstname, self.email) | |
def __unicode__(self): | |
return self.email | |
class Comment(db.EmbeddedDocument): | |
created_at = db.DateTimeField(default=DATE_TIME_NOW, required=True) | |
body = db.StringField(required=True) | |
author = db.ReferenceField(User) | |
def __repr__(self): | |
return '<Post %r>' % (self.author) | |
class Post(db.Document): | |
created_at = db.DateTimeField(default=DATE_TIME_NOW, required=True) | |
edited_on = db.ListField(db.DateTimeField(default=DATE_TIME_NOW)) | |
title = db.StringField(max_length=255, required=True) | |
slug = db.StringField(max_length=255, required=True) | |
author = db.ReferenceField(User) | |
body = db.StringField(required=True) | |
tags = db.ListField(db.StringField(max_length=50)) | |
comments = db.ListField(db.EmbeddedDocumentField(Comment)) | |
def get_absolute_url(self): | |
return url_for('post', kwargs={"slug": self.slug}) | |
def __unicode__(self): | |
return self.title | |
meta = {'allow_inheritance': True, | |
'indexes': ['-created_at', 'slug'], | |
'ordering': ['-created_at']} | |
def __repr__(self): | |
return '<Post %r, -%r>' % (self.slug, self.author) | |
class Page(db.Document): | |
created_at = db.DateTimeField(default=DATE_TIME_NOW, required=True) | |
edited_on = db.ListField(db.DateTimeField(default=DATE_TIME_NOW)) | |
title = db.StringField(required=True) | |
slug = db.StringField(required=True) | |
content = db.StringField(required=True) | |
author = db.ReferenceField(User) | |
meta = {'allow_inheritance': True, | |
'indexes': ['-created_at', 'title'], | |
'ordering': ['-created_at']} | |
def __repr__(self): | |
return '<Page %r>' % (self.title) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Flask==0.10.1 | |
Flask-Admin==1.0.6 | |
Flask-Bcrypt==0.5.2 | |
Flask-DebugToolbar==0.8.0 | |
Flask-DebugToolbar-Mongo==0.1 | |
Flask-Login==0.2.7 | |
Flask-Mail==0.9.0 | |
Flask-OAuth==0.12 | |
Flask-Principal==0.4.0 | |
Flask-Script==0.6.2 | |
Flask-Security==1.6.9 | |
Flask-Social==1.6.1 | |
Flask-WTF==0.9.1 | |
Jinja2==2.7.1 | |
MarkupSafe==0.18 | |
Tempita==0.5.1 | |
WTForms==1.0.4 | |
Werkzeug==0.9.3 | |
amqp==1.0.13 | |
anyjson==0.3.3 | |
argparse==1.2.1 | |
billiard==2.7.3.32 | |
blinker==1.3 | |
celery==3.0.23 | |
celery-with-mongodb==3.0 | |
decorator==3.4.0 | |
facebook-sdk==0.4.0 | |
flake8==2.0 | |
flask-mongoengine==0.7.0 | |
google-api-python-client==1.2 | |
httplib2==0.8 | |
itsdangerous==0.23 | |
kombu==2.5.14 | |
mccabe==0.2.1 | |
mongoengine==0.8.3 | |
oauth2==1.5.211 | |
oauth2client==1.2 | |
passlib==1.6.1 | |
pep8==1.4.6 | |
py-bcrypt==0.4 | |
pyflakes==0.7.3 | |
pymongo==2.6.1 | |
python-dateutil==2.1 | |
six==1.4.1 | |
uWSGI==1.9.14 | |
wsgiref==0.1.2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Traceback (most recent call last): | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__ | |
return self.wsgi_app(environ, start_response) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app | |
response = self.make_response(self.handle_exception(e)) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception | |
reraise(exc_type, exc_value, tb) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app | |
response = self.full_dispatch_request() | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request | |
rv = self.handle_user_exception(e) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception | |
reraise(exc_type, exc_value, tb) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request | |
rv = self.dispatch_request() | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_debugtoolbar/__init__.py", line 104, in dispatch_request | |
return view_func(**req.view_args) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/app/decorators.py", line 25, in wrapper | |
return func(*args, **kwargs) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/app/users/views.py", line 51, in login | |
login_user(user) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_security/utils.py", line 64, in login_user | |
identity=Identity(user.id)) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/blinker/base.py", line 267, in send | |
for receiver in self.receivers_for(sender)] | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_principal.py", line 469, in _on_identity_changed | |
self.set_identity(identity) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_principal.py", line 418, in set_identity | |
self._set_thread_identity(identity) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_principal.py", line 463, in _set_thread_identity | |
identity=identity) | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/blinker/base.py", line 267, in send | |
for receiver in self.receivers_for(sender)] | |
File "/home/cldershem/Documents/Development/homelessgaffer.com/hg-Python/venv/lib/python2.7/site-packages/flask_security/core.py", line 172, in _on_identity_loaded | |
identity.provides.add(RoleNeed(role.name)) | |
AttributeError: 'str' object has no attribute 'name' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from flask import (Blueprint, render_template, url_for, request, | |
redirect, flash, g, abort) | |
#from app import lm | |
from app.forms import (LoginForm, RegisterUser, | |
ForgotPasswordForm, ResetPasswordForm) | |
from app.models import (User) | |
#from flask.ext.login import (login_user, logout_user, | |
# current_user, login_required) | |
from app.utils import (get_activation_link, check_activation_link, | |
get_password_reset_link, check_password_reset_link) | |
from app.constants import DATE_TIME_NOW | |
from app.emails import email_confirmation, email_password_reset | |
from app.decorators import anon_required | |
#from app import security | |
from flask.ext.security import (login_required, login_user, | |
logout_user, current_user) | |
mod = Blueprint('users', __name__, url_prefix='/user') | |
#@lm.user_loader | |
#def load_user(id): | |
# user = User.objects.get(email=id) | |
# return user | |
@mod.before_request | |
def before_request(): | |
g.user = current_user | |
@mod.route('/login', methods=['GET', 'POST']) | |
@anon_required | |
def login(): | |
form = LoginForm() | |
page = "login" | |
if request.method == 'POST': | |
if form.validate() is False: | |
return render_template('users/login.html', | |
form=form, | |
page=page) | |
else: | |
user = User.objects.get(email=form.email.data.lower()) | |
#if user and user.roles.can_login is True: | |
#add remember_me | |
user.last_seen = DATE_TIME_NOW | |
user.save() | |
login_user(user) | |
return redirect(request.args.get('next') or | |
url_for('.profile', | |
user=current_user.email) | |
) | |
#else: | |
# flash("Please confirm your email address.") | |
# return render_template('users/login.html', | |
# form=form, | |
# page=page) | |
elif request.method == 'GET': | |
return render_template('users/login.html', | |
form=form, | |
page=page) | |
def after_login(resp): | |
pass | |
@mod.route('/logout') | |
@login_required | |
def logout(): | |
logout_user() | |
return redirect(url_for('index')) | |
@mod.route('/register', methods=['GET', 'POST']) | |
@anon_required | |
def register(): | |
form = RegisterUser() | |
page = "register" | |
if request.method == 'POST': | |
if form.validate() is False: | |
return render_template('users/register.html', | |
form=form, | |
page=page) | |
else: | |
newUser = User(firstname=form.firstname.data.title(), | |
lastname=form.lastname.data.title(), | |
email=form.email.data.lower()) | |
newUser.set_password(form.password.data) | |
newUser.save() | |
payload = get_activation_link(newUser) | |
email_confirmation(newUser, payload) | |
flash("Please confirm your email address.") | |
return redirect(url_for('index')) | |
elif request.method == 'GET': | |
return render_template('users/register.html', | |
form=form, | |
page=page) | |
@mod.route('/activate/<payload>') | |
@anon_required | |
def activateUser(payload): | |
user_email = check_activation_link(payload) | |
if not user_email: | |
return abort(404) | |
user = User.objects.get(email=user_email) | |
if user: | |
if user.confirmed is None: | |
user.activate_user() | |
user.save() | |
flash('Your account has been activated.') | |
else: | |
flash('Your account was already active.') | |
return redirect(url_for('.login')) | |
else: | |
return abort(404) | |
@mod.route('/forgotpassword', methods=['GET', 'POST']) | |
@anon_required | |
def forgotPassword(): | |
form = ForgotPasswordForm() | |
page = "forgot password" | |
if request.method == 'POST': | |
if not form.validate(): | |
return render_template('users/forgotPassword.html', | |
form=form, | |
page=page) | |
else: | |
try: | |
user = User.objects.get(email=form.email.data) | |
except: | |
flash("That email does not exist, please try another.") | |
return render_template('users/forgotPassword.html', | |
form=form, | |
page=page) | |
payload = get_password_reset_link(user) | |
email_password_reset(user, payload) | |
flash("Password reset email has been sent. \ | |
Link is good for 24 hours.") | |
return redirect(url_for('index')) | |
elif request.method == 'GET': | |
return render_template('users/forgotPassword.html', | |
form=form, | |
page=page) | |
@mod.route('/resetpassword/<payload>', methods=['GET', 'POST']) | |
@anon_required | |
def reset_password(payload): | |
form = ResetPasswordForm() | |
user_email = check_password_reset_link(payload) | |
page = "reset password" | |
if not user_email: | |
flash("Token incorrect or has expired. Please try again.") | |
return redirect(url_for('.forgotPassword')) | |
if request.method == 'POST': | |
if not form.validate(): | |
return render_template('users/resetPassword.html', | |
form=form, | |
page=page) | |
else: | |
user = User.objects.get(email=user_email) | |
user.set_password(form.password.data) | |
user.save() | |
#email password reset | |
flash("Password has been reset, please login") | |
return redirect(url_for('.login')) | |
elif request.method == 'GET': | |
return render_template('users/resetPassword.html', | |
form=form, | |
page=page) | |
@mod.route('/profile/<user>') | |
def profile(user): | |
last_seen = User.objects.get(email=user).last_seen | |
return render_template('users/profile.html', | |
user=user, | |
last_seen=last_seen, | |
page=user) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment