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 realms import config, app, manager
from flask.ext.script import Server
manager.add_command("runserver", Server(host="0.0.0.0", port=5000))
from realms import config, app, cli, db
from werkzeug.serving import run_with_reloader
import click
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():
""" Run production server
"""
Run production ready server
"""
print "Server started. Env: %s Port: %s" % (config.ENV, config.PORT)
click.echo("Server started. Env: %s Port: %s" % (config.ENV, config.PORT))
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__':
manager.run()
cli()

View file

@ -1,6 +1,6 @@
# Monkey patch stdlib.
import gevent.monkey
gevent.monkey.patch_all(aggressive=False)
gevent.monkey.patch_all(aggressive=False, subprocess=True)
# Set default encoding to UTF-8
import sys
@ -14,9 +14,9 @@ import sys
import json
import httplib
import traceback
import click
from flask import Flask, request, render_template, url_for, redirect, g
from flask.ext.cache import Cache
from flask.ext.script import Manager
from flask.ext.login import LoginManager, current_user
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.assets import Environment, Bundle
@ -67,9 +67,9 @@ class Application(Flask):
if hasattr(sources, 'views'):
self.register_blueprint(sources.views.blueprint)
# Flask-Script
# Click
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))
@ -142,40 +142,39 @@ def error_handler(e):
return response, status_code
def create_app():
app = Application(__name__)
app.config.from_object('realms.config')
app.url_map.converters['regex'] = RegexConverter
app.url_map.strict_slashes = False
for status_code in httplib.responses:
if status_code >= 400:
app.register_error_handler(status_code, error_handler)
app = Application(__name__)
app.config.from_object('realms.config')
app.url_map.converters['regex'] = RegexConverter
app.url_map.strict_slashes = False
@app.before_request
def init_g():
g.assets = dict(css=['main.css'], js=['main.js'])
for status_code in httplib.responses:
if status_code >= 400:
app.register_error_handler(status_code, error_handler)
@app.template_filter('datetime')
def _jinja2_filter_datetime(ts):
return time.strftime('%b %d, %Y %I:%M %p', time.localtime(ts))
@app.before_request
def init_g():
g.assets = dict(css=['main.css'], js=['main.js'])
@app.errorhandler(404)
def page_not_found(e):
return render_template('errors/404.html'), 404
@app.template_filter('datetime')
def _jinja2_filter_datetime(ts):
return time.strftime('%b %d, %Y %I:%M %p', time.localtime(ts))
if config.RELATIVE_PATH:
@app.route("/")
def root():
return redirect(url_for(config.ROOT_ENDPOINT))
@app.errorhandler(404)
def page_not_found(e):
return render_template('errors/404.html'), 404
return app
if config.RELATIVE_PATH:
@app.route("/")
def root():
return redirect(url_for(config.ROOT_ENDPOINT))
app = create_app()
@click.group()
def cli():
pass
# Init plugins here if possible
manager = Manager(app)
login_manager = LoginManager(app)
login_manager.login_view = 'auth.login'
@ -204,7 +203,7 @@ assets.register('main.css',
app.discover()
# Should be called explicitly during install?
# This will be removed at some point
db.create_all()

View file

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

View file

@ -2,6 +2,8 @@ import re
import os
import hashlib
import json
import string
import random
class AttrDict(dict):
@ -10,6 +12,10 @@ class AttrDict(dict):
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):
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 realms import config
class RegistrationForm(Form):
username = StringField('Username', [validators.Length(min=4, max=25)])
email = StringField('Email Address', [validators.Length(min=6, max=35)])

View file

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

View file

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

View file

@ -59,8 +59,10 @@
</ul>
</li>
{% 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>
{% endif %}
{% endif %}
</ul>
</div><!--/.nav-collapse -->

View file

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