From 2d6f368ff1628dbfea39963ccc8b7e2465504c53 Mon Sep 17 00:00:00 2001 From: Matthew Scragg Date: Thu, 30 Oct 2014 17:59:19 -0500 Subject: [PATCH] fix #32 --- realms/__init__.py | 13 +------------ realms/commands.py | 6 ++++-- realms/config/__init__.py | 6 +++--- realms/lib/model.py | 21 ++++++++++++++++----- realms/modules/auth/__init__.py | 12 ++++++++++++ realms/modules/auth/models.py | 9 +++------ realms/modules/wiki/tests.py | 22 +++++++++++++++++----- realms/modules/wiki/views.py | 6 ++++++ realms/version.py | 2 +- 9 files changed, 63 insertions(+), 34 deletions(-) diff --git a/realms/__init__.py b/realms/__init__.py index 6bfa461..08de16f 100644 --- a/realms/__init__.py +++ b/realms/__init__.py @@ -96,16 +96,6 @@ class Application(Flask): return super(Application, self).make_response(tuple(rv)) -class MySQLAlchemy(SQLAlchemy): - - def make_declarative_base(self): - """Creates the declarative base.""" - base = declarative_base(cls=Model, name='Model', - metaclass=HookModelMeta) - base.query = _QueryProperty(self) - return base - - class Assets(Environment): default_filters = {'js': 'rjsmin', 'css': 'cleancss'} default_output = {'js': 'assets/%(version)s.js', 'css': 'assets/%(version)s.css'} @@ -203,9 +193,8 @@ def create_app(config=None): # Init plugins here if possible login_manager = LoginManager() -login_manager.login_view = 'auth.login' -db = MySQLAlchemy() +db = SQLAlchemy() cache = Cache() assets = Assets() diff --git a/realms/commands.py b/realms/commands.py index c7a2678..24781b4 100644 --- a/realms/commands.py +++ b/realms/commands.py @@ -338,7 +338,8 @@ def create_db(): """ Creates DB tables """ green("Creating all tables") - db.create_all() + with app.app_context(): + db.create_all() @cli.command() @@ -347,7 +348,8 @@ def drop_db(): """ Drops DB tables """ yellow("Dropping all tables") - db.drop_all() + with app.app_context(): + db.create_all() @cli.command() diff --git a/realms/config/__init__.py b/realms/config/__init__.py index 7995a3e..8f8eedb 100644 --- a/realms/config/__init__.py +++ b/realms/config/__init__.py @@ -114,9 +114,6 @@ WIKI_HOME = 'home' ALLOW_ANON = True REGISTRATION_ENABLED = True -# Used by Flask-Login -LOGIN_DISABLED = ALLOW_ANON - # None, firepad, and/or togetherjs COLLABORATION = 'togetherjs' @@ -130,6 +127,9 @@ ROOT_ENDPOINT = 'wiki.page' globals().update(read()) +# Used by Flask-Login +LOGIN_DISABLED = ALLOW_ANON + # Depreciated variable name LOCKED = WIKI_LOCKED_PAGES[:] diff --git a/realms/lib/model.py b/realms/lib/model.py index ac3d5cb..a811d18 100644 --- a/realms/lib/model.py +++ b/realms/lib/model.py @@ -1,12 +1,14 @@ import json -from sqlalchemy import not_ +from sqlalchemy import not_, and_ +from sqlalchemy.ext.declarative import declarative_base from datetime import datetime -from flask.ext.sqlalchemy import SQLAlchemy +from realms import db +from .hook import HookModelMeta, HookMixin -db = SQLAlchemy() +Base = declarative_base(metaclass=HookModelMeta, cls=HookMixin) -class Model(db.Model): +class Model(Base): """Base SQLAlchemy Model for automatic serialization and deserialization of columns and nested relationships. @@ -54,6 +56,11 @@ class Model(db.Model): kwargs['_force'] = True self._set_columns(**kwargs) + def filter_by(self, **kwargs): + clauses = [key == value + for key, value in kwargs.items()] + return self.filter(and_(*clauses)) + def _set_columns(self, **kwargs): force = kwargs.get('_force') @@ -283,6 +290,10 @@ class Model(db.Model): db.session.delete(self) db.session.commit() + @classmethod + def query(cls): + return db.session.query(cls) + @classmethod def get_by_id(cls, id_): - return cls.query.filter_by(id=id_).first() \ No newline at end of file + return cls.query().filter_by(id=id_).first() \ No newline at end of file diff --git a/realms/modules/auth/__init__.py b/realms/modules/auth/__init__.py index e69de29..8487cd9 100644 --- a/realms/modules/auth/__init__.py +++ b/realms/modules/auth/__init__.py @@ -0,0 +1,12 @@ +from realms import login_manager +from flask import request, flash, redirect +from flask.ext.login import login_url + + +@login_manager.unauthorized_handler +def unauthorized(): + if request.method == 'GET': + flash('Please log in to access this page') + return redirect(login_url('auth.login', request.url)) + else: + return dict(error=True, message="Please log in for access."), 403 diff --git a/realms/modules/auth/models.py b/realms/modules/auth/models.py index 16be5c3..5b5a3fe 100644 --- a/realms/modules/auth/models.py +++ b/realms/modules/auth/models.py @@ -71,22 +71,19 @@ class User(Model, UserMixin): @staticmethod def get_by_username(username): - return User.query.filter_by(username=username).first() + return User.query().filter_by(username=username).first() @staticmethod def get_by_email(email): - return User.query.filter_by(email=email).first() + return User.query().filter_by(email=email).first() @staticmethod def signer(salt): - """ - Signed with app secret salted with sha256 of password hash of user (client secret) - """ return URLSafeSerializer(current_app.config['SECRET_KEY'] + salt) @staticmethod def auth(email, password): - user = User.query.filter_by(email=email).first() + user = User.get_by_email(email) if not user: # User doesn't exist diff --git a/realms/modules/wiki/tests.py b/realms/modules/wiki/tests.py index daaa723..1cf3f5d 100644 --- a/realms/modules/wiki/tests.py +++ b/realms/modules/wiki/tests.py @@ -6,7 +6,11 @@ from realms.lib.test import BaseTest class WikiBaseTest(BaseTest): - def write_page(self, name, message=None, content=None): + def update_page(self, name, message=None, content=None): + return self.client.post(url_for('wiki.page_write', name=name), + data=dict(message=message, content=content)) + + def create_page(self, name, message=None, content=None): return self.client.post(url_for('wiki.page_write', name=name), data=dict(message=message, content=content)) @@ -22,7 +26,7 @@ class UtilTest(WikiBaseTest): class WikiTest(WikiBaseTest): def test_routes(self): self.assert_200(self.client.get(url_for("wiki.create"))) - self.write_page('test', message='test message', content='testing') + self.create_page('test', message='test message', content='testing') for route in ['page', 'edit', 'history']: rv = self.client.get(url_for("wiki.%s" % route, name='test')) @@ -31,7 +35,7 @@ class WikiTest(WikiBaseTest): self.assert_200(self.client.get(url_for('wiki.index'))) def test_write_page(self): - self.assert_200(self.write_page('test', message='test message', content='testing')) + self.assert_200(self.create_page('test', message='test message', content='testing')) rv = self.client.get(url_for('wiki.page', name='test')) self.assert_200(rv) @@ -54,8 +58,8 @@ class WikiTest(WikiBaseTest): self.assert_status(rv, 302) def test_revert(self): - rv1 = self.write_page('test', message='test message', content='testing_old') - self.write_page('test', message='test message', content='testing_new') + rv1 = self.create_page('test', message='test message', content='testing_old') + self.update_page('test', message='test message', content='testing_new') data = json.loads(rv1.data) self.client.post(url_for('wiki.revert'), data=dict(name='test', commit=data['sha'])) self.client.get(url_for('wiki.page', name='test')) @@ -66,6 +70,14 @@ class WikiTest(WikiBaseTest): self.assert_403(self.client.post(url_for('wiki.revert'), data=dict(name='test', commit=data['sha']))) self.app.config['WIKI_LOCKED_PAGES'] = [] + def test_anon(self): + rv1 = self.create_page('test', message='test message', content='testing_old') + self.update_page('test', message='test message', content='testing_new') + data = json.loads(rv1.data) + self.app.config['ALLOW_ANON'] = False + self.assert_403(self.update_page('test', message='test message', content='testing_again')) + self.assert_403(self.client.post(url_for('wiki.revert'), data=dict(name='test', commit=data['sha']))) + class RelativePathTest(WikiTest): def configure(self): diff --git a/realms/modules/wiki/views.py b/realms/modules/wiki/views.py index d6f0329..fe00b87 100644 --- a/realms/modules/wiki/views.py +++ b/realms/modules/wiki/views.py @@ -32,6 +32,9 @@ def revert(): commit = request.form.get('commit') message = request.form.get('message', "Reverting %s" % cname) + if not current_app.config.get('ALLOW_ANON') and current_user.is_anonymous: + return dict(error=True, message="Anonymous posting not allowed"), 403 + if cname in current_app.config.get('WIKI_LOCKED_PAGES'): return dict(error=True, message="Page is locked"), 403 @@ -104,6 +107,9 @@ def page_write(name): if not cname: return dict(error=True, message="Invalid name") + if not current_app.config.get('ALLOW_ANON') and current_user.is_anonymous: + return dict(error=True, message="Anonymous posting not allowed"), 403 + if request.method == 'POST': # Create if cname in current_app.config.get('WIKI_LOCKED_PAGES'): diff --git a/realms/version.py b/realms/version.py index 4dde6e7..3514ea2 100644 --- a/realms/version.py +++ b/realms/version.py @@ -1 +1 @@ -__version__ = '0.4.4' \ No newline at end of file +__version__ = '0.4.5' \ No newline at end of file