add config option to disable registration

add command to create user
This commit is contained in:
Matthew Scragg 2014-09-13 22:47:17 -05:00
parent 17eabddd70
commit b8531a0347
10 changed files with 131 additions and 45 deletions

View file

@ -1,18 +1,43 @@
from gevent import wsgi from gevent import wsgi
from realms import config, app, manager from realms import config, app, cli, db
from flask.ext.script import Server from werkzeug.serving import run_with_reloader
import click
manager.add_command("runserver", Server(host="0.0.0.0", port=5000)) import os
@manager.command @cli.command()
@click.option('--port', default=5000)
def runserver(port):
""" Run development server
"""
click.secho("Starting development server", fg='green')
app.run(host="0.0.0.0",
port=port,
debug=True)
@cli.command()
def run(): def run():
""" Run production server
""" """
Run production ready server click.echo("Server started. Env: %s Port: %s" % (config.ENV, config.PORT))
"""
print "Server started. Env: %s Port: %s" % (config.ENV, config.PORT)
wsgi.WSGIServer(('', int(config.PORT)), app).serve_forever() wsgi.WSGIServer(('', int(config.PORT)), app).serve_forever()
@cli.command()
def create_db():
""" Creates DB tables
"""
click.echo("Creating all tables")
db.create_all()
@cli.command()
def drop_db():
""" Drops DB tables
"""
click.echo("Dropping all tables")
db.drop_all()
if __name__ == '__main__': if __name__ == '__main__':
manager.run() cli()

View file

@ -1,6 +1,6 @@
# Monkey patch stdlib. # Monkey patch stdlib.
import gevent.monkey import gevent.monkey
gevent.monkey.patch_all(aggressive=False) gevent.monkey.patch_all(aggressive=False, subprocess=True)
# Set default encoding to UTF-8 # Set default encoding to UTF-8
import sys import sys
@ -14,9 +14,9 @@ import sys
import json import json
import httplib import httplib
import traceback import traceback
import click
from flask import Flask, request, render_template, url_for, redirect, g from flask import Flask, request, render_template, url_for, redirect, g
from flask.ext.cache import Cache from flask.ext.cache import Cache
from flask.ext.script import Manager
from flask.ext.login import LoginManager, current_user from flask.ext.login import LoginManager, current_user
from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.assets import Environment, Bundle from flask.ext.assets import Environment, Bundle
@ -67,9 +67,9 @@ class Application(Flask):
if hasattr(sources, 'views'): if hasattr(sources, 'views'):
self.register_blueprint(sources.views.blueprint) self.register_blueprint(sources.views.blueprint)
# Flask-Script # Click
if hasattr(sources, 'commands'): if hasattr(sources, 'commands'):
manager.add_command(module_name, sources.commands.manager) cli.add_command(sources.commands.cli, name=module_name)
print >> sys.stderr, ' * Ready in %.2fms' % (1000.0 * (time.time() - start_time)) print >> sys.stderr, ' * Ready in %.2fms' % (1000.0 * (time.time() - start_time))
@ -142,7 +142,7 @@ def error_handler(e):
return response, status_code return response, status_code
def create_app():
app = Application(__name__) app = Application(__name__)
app.config.from_object('realms.config') app.config.from_object('realms.config')
app.url_map.converters['regex'] = RegexConverter app.url_map.converters['regex'] = RegexConverter
@ -169,13 +169,12 @@ def create_app():
def root(): def root():
return redirect(url_for(config.ROOT_ENDPOINT)) return redirect(url_for(config.ROOT_ENDPOINT))
return app
app = create_app() @click.group()
def cli():
pass
# Init plugins here if possible # Init plugins here if possible
manager = Manager(app)
login_manager = LoginManager(app) login_manager = LoginManager(app)
login_manager.login_view = 'auth.login' login_manager.login_view = 'auth.login'
@ -204,7 +203,7 @@ assets.register('main.css',
app.discover() app.discover()
# Should be called explicitly during install? # This will be removed at some point
db.create_all() db.create_all()

View file

@ -37,19 +37,31 @@ RECAPTCHA_OPTIONS = {}
SECRET_KEY = 'K3dRq1q9eN72GJDkgvyshFVwlqHHCyPI' SECRET_KEY = 'K3dRq1q9eN72GJDkgvyshFVwlqHHCyPI'
# Path on file system where wiki data will reside
WIKI_PATH = os.path.join(APP_PATH, 'wiki') WIKI_PATH = os.path.join(APP_PATH, 'wiki')
# Name of page that will act as home
WIKI_HOME = 'home' WIKI_HOME = 'home'
ALLOW_ANON = True ALLOW_ANON = True
REGISTRATION_ENABLED = True
# Used by Flask-Login
LOGIN_DISABLED = ALLOW_ANON LOGIN_DISABLED = ALLOW_ANON
# Page names that can't be modified # Page names that can't be modified
LOCKED = [] WIKI_LOCKED_PAGES = []
# Depreciated variable name
LOCKED = WIKI_LOCKED_PAGES
ROOT_ENDPOINT = 'wiki.page' ROOT_ENDPOINT = 'wiki.page'
try: try:
with open(os.path.join(APP_PATH, 'config.json')) as f: with open(os.path.join(APP_PATH, 'config.json')) as f:
__settings = json.load(f) __settings = json.load(f)
for k in ['APP_PATH', 'USER_HOME']:
if k in __settings:
del __settings[k]
globals().update(__settings) globals().update(__settings)
except IOError: except IOError:
pass pass

View file

@ -2,6 +2,8 @@ import re
import os import os
import hashlib import hashlib
import json import json
import string
import random
class AttrDict(dict): class AttrDict(dict):
@ -10,6 +12,10 @@ class AttrDict(dict):
self.__dict__ = self self.__dict__ = self
def random_string(size=6, chars=string.ascii_lowercase + string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
def to_json(data): def to_json(data):
return json.dumps(to_dict(data), separators=(',', ':')) return json.dumps(to_dict(data), separators=(',', ':'))

View file

@ -0,0 +1,35 @@
import click
from realms.lib.util import random_string
from realms.modules.auth.models import User
@click.group()
def cli():
pass
@cli.command()
@click.argument('username')
@click.argument('email')
@click.option('--password', help='Leave blank for random password')
def create_user(username, email, password):
""" Create a new user
"""
show_pass = not password
if not password:
password = random_string(12)
if User.get_by_username(username):
click.secho("Username %s already exists" % username, fg='red')
return
if User.get_by_email(email):
click.secho("Email %s already exists" % email, fg='red')
return
User.create(username, email, password)
click.secho("User %s created" % username, fg='green')
if show_pass:
click.secho("Password: %s" % password, fg='yellow')

View file

@ -2,6 +2,7 @@ from flask_wtf import Form, RecaptchaField
from wtforms import StringField, PasswordField, validators from wtforms import StringField, PasswordField, validators
from realms import config from realms import config
class RegistrationForm(Form): class RegistrationForm(Form):
username = StringField('Username', [validators.Length(min=4, max=25)]) username = StringField('Username', [validators.Length(min=4, max=25)])
email = StringField('Email Address', [validators.Length(min=6, max=35)]) email = StringField('Email Address', [validators.Length(min=6, max=35)])

View file

@ -33,6 +33,11 @@ def login():
@blueprint.route("/register", methods=['GET', 'POST']) @blueprint.route("/register", methods=['GET', 'POST'])
def register(): def register():
if not config.REGISTRATION_ENABLED:
flash("Registration is disabled")
return redirect(url_for(config.ROOT_ENDPOINT))
form = RegistrationForm() form = RegistrationForm()
if request.method == "POST": if request.method == "POST":
@ -61,6 +66,7 @@ def register():
def settings(): def settings():
return render_template("auth/settings.html") return render_template("auth/settings.html")
@blueprint.route("/logout") @blueprint.route("/logout")
def logout(): def logout():
User.logout() User.logout()

View file

@ -33,7 +33,7 @@ def revert():
commit = request.form.get('commit') commit = request.form.get('commit')
cname = to_canonical(name) cname = to_canonical(name)
if cname in config.LOCKED: if cname in config.WIKI_LOCKED_PAGES:
flash("Page is locked") flash("Page is locked")
return redirect(url_for(config.ROOT_ENDPOINT)) return redirect(url_for(config.ROOT_ENDPOINT))
@ -56,7 +56,7 @@ def edit(name):
if request.method == 'POST': if request.method == 'POST':
edit_cname = to_canonical(request.form['name']) edit_cname = to_canonical(request.form['name'])
if edit_cname in config.LOCKED: if edit_cname in config.WIKI_LOCKED_PAGES:
return redirect(url_for(config.ROOT_ENDPOINT)) return redirect(url_for(config.ROOT_ENDPOINT))
if edit_cname.lower() != cname.lower(): if edit_cname.lower() != cname.lower():
@ -91,7 +91,7 @@ def create(name):
if request.method == 'POST': if request.method == 'POST':
cname = to_canonical(request.form['name']) cname = to_canonical(request.form['name'])
if cname in config.LOCKED: if cname in config.WIKI_LOCKED_PAGES:
return redirect(url_for("wiki.create")) return redirect(url_for("wiki.create"))
if not cname: if not cname:

View file

@ -60,8 +60,10 @@
</li> </li>
{% else %} {% else %}
<li><a href="{{ url_for('auth.login') }}"><i class="icon-user"></i> &nbsp;Login</a></li> <li><a href="{{ url_for('auth.login') }}"><i class="icon-user"></i> &nbsp;Login</a></li>
{% if config.REGISTRATION_ENABLED %}
<li><a href="{{ url_for('auth.register') }}"><i class="icon-pencil"></i> &nbsp;Register</a></li> <li><a href="{{ url_for('auth.register') }}"><i class="icon-pencil"></i> &nbsp;Register</a></li>
{% endif %} {% endif %}
{% endif %}
</ul> </ul>
</div><!--/.nav-collapse --> </div><!--/.nav-collapse -->
</div> </div>

View file

@ -3,7 +3,6 @@ Flask
Flask-Assets Flask-Assets
Flask-Cache Flask-Cache
Flask-Login Flask-Login
Flask-Script
Flask-SQLAlchemy Flask-SQLAlchemy
Flask-WTF Flask-WTF
beautifulsoup4 beautifulsoup4
@ -15,3 +14,4 @@ lxml
markdown2 markdown2
simplejson simplejson
PyYAML PyYAML
click