many things have occured
This commit is contained in:
parent
02b6b7d592
commit
db70df22a2
3
app.py
3
app.py
|
@ -1,7 +1,8 @@
|
||||||
from gevent import monkey, pywsgi
|
from gevent import monkey, pywsgi
|
||||||
|
from realms import config, app
|
||||||
|
|
||||||
monkey.patch_all()
|
monkey.patch_all()
|
||||||
import logging
|
import logging
|
||||||
from realms import app, config
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import time
|
import time
|
||||||
from tldextract import tldextract
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
from flask import Flask, g, request, render_template, url_for, redirect, flash, session, current_app
|
from flask import Flask, request, render_template, url_for, redirect, session
|
||||||
from flask.ctx import _AppCtxGlobals
|
from flask.ctx import _AppCtxGlobals
|
||||||
|
from flask.ext.script import Manager
|
||||||
from flask.ext.login import LoginManager, login_required
|
from flask.ext.login import LoginManager, login_required
|
||||||
from flask.ext.assets import Environment, Bundle
|
from flask.ext.assets import Environment, Bundle
|
||||||
from werkzeug.routing import BaseConverter
|
from werkzeug.routing import BaseConverter
|
||||||
from werkzeug.utils import cached_property
|
from werkzeug.utils import cached_property
|
||||||
|
|
||||||
import config
|
from realms import config
|
||||||
from realms.lib.ratelimit import get_view_rate_limit, ratelimiter
|
from realms.lib.ratelimit import get_view_rate_limit, ratelimiter
|
||||||
from realms.lib.session import RedisSessionInterface
|
from realms.lib.session import RedisSessionInterface
|
||||||
from realms.lib.wiki import Wiki
|
from realms.lib.wiki import Wiki
|
||||||
|
@ -19,13 +20,26 @@ from realms.lib.services import db
|
||||||
from models import Site, User, CurrentUser
|
from models import Site, User, CurrentUser
|
||||||
|
|
||||||
|
|
||||||
|
wikis = {}
|
||||||
|
|
||||||
|
|
||||||
class AppCtxGlobals(_AppCtxGlobals):
|
class AppCtxGlobals(_AppCtxGlobals):
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def current_wiki(self):
|
||||||
|
subdomain = format_subdomain(self.current_site)
|
||||||
|
if not subdomain:
|
||||||
|
subdomain = "_"
|
||||||
|
|
||||||
|
if not wikis.get(subdomain):
|
||||||
|
wikis[subdomain] = Wiki("%s/%s" % (config.REPO_DIR, subdomain))
|
||||||
|
|
||||||
|
return wikis[subdomain]
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def current_site(self):
|
def current_site(self):
|
||||||
ext = tldextract.extract(request.host)
|
host = request.host.split(':')[0]
|
||||||
print ext
|
return host[:-len(config.DOMAIN)].rstrip('.')
|
||||||
return ext.subdomain
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def current_user(self):
|
def current_user(self):
|
||||||
|
@ -53,6 +67,41 @@ class Application(Flask):
|
||||||
|
|
||||||
return super(Application, self).__call__(environ, start_response)
|
return super(Application, self).__call__(environ, start_response)
|
||||||
|
|
||||||
|
def discover(self):
|
||||||
|
"""
|
||||||
|
Pattern taken from guildwork.com
|
||||||
|
"""
|
||||||
|
IMPORT_NAME = 'realms.modules'
|
||||||
|
FROMLIST = (
|
||||||
|
'assets',
|
||||||
|
'models',
|
||||||
|
'search',
|
||||||
|
'perms',
|
||||||
|
'broadcasts',
|
||||||
|
'commands',
|
||||||
|
'notifications',
|
||||||
|
'requests',
|
||||||
|
'tasks',
|
||||||
|
'views',
|
||||||
|
)
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
__import__(IMPORT_NAME, fromlist=FROMLIST)
|
||||||
|
|
||||||
|
for module_name in self.config['MODULES']:
|
||||||
|
sources = __import__('%s.%s' % (IMPORT_NAME, module_name), fromlist=FROMLIST)
|
||||||
|
|
||||||
|
# Blueprint
|
||||||
|
if hasattr(sources, 'views'):
|
||||||
|
self.register_blueprint(sources.views.blueprint)
|
||||||
|
|
||||||
|
# Flask-Script
|
||||||
|
if hasattr(sources, 'commands'):
|
||||||
|
manager.add_command(module_name, sources.commands.manager)
|
||||||
|
|
||||||
|
print >> sys.stderr, ' * Ready in %.2fms' % (1000.0 * (time.time() - start_time))
|
||||||
|
|
||||||
|
|
||||||
def init_db(dbname):
|
def init_db(dbname):
|
||||||
"""
|
"""
|
||||||
|
@ -77,23 +126,24 @@ def redirect_url(referrer=None):
|
||||||
|
|
||||||
|
|
||||||
def format_subdomain(s):
|
def format_subdomain(s):
|
||||||
if not config.repos['enable_subrepos']:
|
if not config.REPO_ENABLE_SUBDOMAIN:
|
||||||
return ""
|
return ""
|
||||||
s = s.lower()
|
s = s.lower()
|
||||||
s = to_canonical(s)
|
s = to_canonical(s)
|
||||||
if s in config.repos['forbidden_subrepos']:
|
if s in config.REPO_FORBIDDEN_NAMES:
|
||||||
# Not allowed
|
# Not allowed
|
||||||
s = ""
|
s = ""
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
app = Application(__name__)
|
app = Application(__name__)
|
||||||
app.config.update(config.FLASK)
|
app.config.from_object('realms.config')
|
||||||
app.debug = (config.ENV is not 'PROD')
|
|
||||||
app.secret_key = config.SECRET_KEY
|
|
||||||
app.static_path = os.sep + 'static'
|
|
||||||
app.session_interface = RedisSessionInterface()
|
app.session_interface = RedisSessionInterface()
|
||||||
app.url_map.converters['regex'] = RegexConverter
|
app.url_map.converters['regex'] = RegexConverter
|
||||||
|
app.url_map.strict_slashes = False
|
||||||
|
app.debug = True
|
||||||
|
|
||||||
|
manager = Manager(app)
|
||||||
|
|
||||||
# Flask extension objects
|
# Flask extension objects
|
||||||
login_manager = LoginManager()
|
login_manager = LoginManager()
|
||||||
|
@ -137,8 +187,6 @@ else:
|
||||||
filters='closure_js', output='packed-editor.js')
|
filters='closure_js', output='packed-editor.js')
|
||||||
assets.register('js_editor', js)
|
assets.register('js_editor', js)
|
||||||
|
|
||||||
repo_dir = config.REPO_DIR
|
|
||||||
|
|
||||||
|
|
||||||
@app.after_request
|
@app.after_request
|
||||||
def inject_x_rate_headers(response):
|
def inject_x_rate_headers(response):
|
||||||
|
@ -155,6 +203,7 @@ def inject_x_rate_headers(response):
|
||||||
def _jinja2_filter_datetime(ts):
|
def _jinja2_filter_datetime(ts):
|
||||||
return time.strftime('%b %d, %Y %I:%M %p', time.localtime(ts))
|
return time.strftime('%b %d, %Y %I:%M %p', time.localtime(ts))
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(404)
|
@app.errorhandler(404)
|
||||||
def page_not_found(e):
|
def page_not_found(e):
|
||||||
return render_template('errors/404.html'), 404
|
return render_template('errors/404.html'), 404
|
||||||
|
@ -167,160 +216,18 @@ def page_error(e):
|
||||||
|
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
@ratelimiter(limit=50, per=60)
|
|
||||||
def root():
|
def root():
|
||||||
return g.current_site
|
return redirect(url_for(config.ROOT_ENDPOINT))
|
||||||
return render('home')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/home")
|
|
||||||
def home():
|
|
||||||
return redirect(url_for('root'))
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_account/")
|
@app.route("/_account/")
|
||||||
@login_required
|
@login_required
|
||||||
def account():
|
def account():
|
||||||
return render_template('account/index.html')
|
return render_template('account/index.html')
|
||||||
|
|
||||||
|
if 'devserver' not in sys.argv or os.environ.get('WERKZEUG_RUN_MAIN'):
|
||||||
|
app.discover()
|
||||||
|
|
||||||
@app.route("/_new/", methods=['GET', 'POST'])
|
print app.url_map
|
||||||
@login_required
|
|
||||||
def new_wiki():
|
|
||||||
if request.method == 'POST':
|
|
||||||
wiki_name = to_canonical(request.form['name'])
|
|
||||||
|
|
||||||
if Wiki.is_registered(wiki_name):
|
|
||||||
flash("Site already exists")
|
|
||||||
return redirect(redirect_url())
|
|
||||||
else:
|
|
||||||
s = Site()
|
|
||||||
s.create(name=wiki_name, repo=wiki_name, founder=g.current_user.get('id'))
|
|
||||||
return redirect('http://%s.%s' % (wiki_name, config.hostname))
|
|
||||||
else:
|
|
||||||
return render_template('_new/index.html')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_logout/")
|
|
||||||
def logout():
|
|
||||||
User.logout()
|
|
||||||
return redirect(url_for('root'))
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_commit/<sha>/<name>")
|
|
||||||
def commit_sha(name, sha):
|
|
||||||
cname = to_canonical(name)
|
|
||||||
|
|
||||||
data = Wiki.get_page(cname, sha=sha)
|
|
||||||
if data:
|
|
||||||
return render_template('page/page.html', name=name, page=data, commit=sha)
|
|
||||||
else:
|
|
||||||
return redirect('/_create/'+cname)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_compare/<name>/<regex('[^.]+'):fsha><regex('\.{2,3}'):dots><regex('.+'):lsha>")
|
|
||||||
def compare(name, fsha, dots, lsha):
|
|
||||||
diff = Wiki.compare(name, fsha, lsha)
|
|
||||||
return render_template('page/compare.html', name=name, diff=diff, old=fsha, new=lsha)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_revert", methods=['POST'])
|
|
||||||
def revert():
|
|
||||||
if request.method == 'POST':
|
|
||||||
name = request.form.get('name')
|
|
||||||
commit = request.form.get('commit')
|
|
||||||
cname = to_canonical(name)
|
|
||||||
Wiki.revert_page(name, commit, message="Reverting %s" % cname, username=g.current_user.get('username'))
|
|
||||||
flash('Page reverted', 'success')
|
|
||||||
return redirect("/" + cname)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_register", methods=['GET', 'POST'])
|
|
||||||
def register():
|
|
||||||
if request.method == 'POST':
|
|
||||||
if User.register(request.form.get('username'), request.form.get('email'), request.form.get('password')):
|
|
||||||
return redirect(url_for('root'))
|
|
||||||
else:
|
|
||||||
# Login failed
|
|
||||||
return redirect(url_for('register'))
|
|
||||||
else:
|
|
||||||
return render_template('account/register.html')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_login", methods=['GET', 'POST'])
|
|
||||||
def login():
|
|
||||||
if request.method == 'POST':
|
|
||||||
if User.auth(request.form['email'], request.form['password']):
|
|
||||||
return redirect(redirect_url(referrer=url_for('root')))
|
|
||||||
else:
|
|
||||||
flash("Email or Password invalid")
|
|
||||||
return redirect("/_login")
|
|
||||||
else:
|
|
||||||
return render_template('account/login.html')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_history/<name>")
|
|
||||||
def history(name):
|
|
||||||
history = Wiki.get_history(name)
|
|
||||||
return render_template('page/history.html', name=name, history=history)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_edit/<name>", methods=['GET', 'POST'])
|
|
||||||
def edit(name):
|
|
||||||
data = Wiki.get_page(name)
|
|
||||||
cname = to_canonical(name)
|
|
||||||
if request.method == 'POST':
|
|
||||||
edit_cname = to_canonical(request.form['name'])
|
|
||||||
if edit_cname.lower() != cname.lower():
|
|
||||||
Wiki.rename_page(cname, edit_cname)
|
|
||||||
Wiki.write_page(edit_cname,
|
|
||||||
request.form['content'],
|
|
||||||
message=request.form['message'],
|
|
||||||
username=g.current_user.get('username'))
|
|
||||||
return redirect("/" + edit_cname)
|
|
||||||
else:
|
|
||||||
if data:
|
|
||||||
name = remove_ext(data['name'])
|
|
||||||
content = data['data']
|
|
||||||
return render_template('page/edit.html', name=name, content=content)
|
|
||||||
else:
|
|
||||||
return redirect('/_create/'+cname)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_delete/<name>", methods=['POST'])
|
|
||||||
@login_required
|
|
||||||
def delete(name):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/_create/", methods=['GET', 'POST'])
|
|
||||||
@app.route("/_create/<name>", methods=['GET', 'POST'])
|
|
||||||
def create(name=None):
|
|
||||||
cname = ""
|
|
||||||
if name:
|
|
||||||
cname = to_canonical(name)
|
|
||||||
if Wiki.get_page(cname):
|
|
||||||
# Page exists, edit instead
|
|
||||||
return redirect("/edit/" + cname)
|
|
||||||
if request.method == 'POST':
|
|
||||||
Wiki.write_page(request.form['name'],
|
|
||||||
request.form['content'],
|
|
||||||
message=request.form['message'],
|
|
||||||
create=True,
|
|
||||||
username=g.current_user.get('username'))
|
|
||||||
return redirect("/" + cname)
|
|
||||||
else:
|
|
||||||
return render_template('page/edit.html', name=cname, content="")
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/<name>")
|
|
||||||
def render(name):
|
|
||||||
cname = to_canonical(name)
|
|
||||||
if cname != name:
|
|
||||||
return redirect('/' + cname)
|
|
||||||
|
|
||||||
data = Wiki.get_page(cname)
|
|
||||||
if data:
|
|
||||||
return render_template('page/page.html', name=cname, page=data)
|
|
||||||
else:
|
|
||||||
return redirect('/_create/'+cname)
|
|
||||||
|
|
38
realms/config/__init__.py
Normal file
38
realms/config/__init__.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import socket
|
||||||
|
|
||||||
|
HOSTNAME = socket.gethostname()
|
||||||
|
|
||||||
|
DOMAIN = 'realms.dev'
|
||||||
|
ENV = 'DEV'
|
||||||
|
PORT = 10000
|
||||||
|
|
||||||
|
DB_URI = 'postgresql://realms:dbpassword@localhost:5432/realms'
|
||||||
|
|
||||||
|
REDIS_HOST = '127.0.0.1'
|
||||||
|
REDIS_PORT = 6379
|
||||||
|
|
||||||
|
SECRET_KEY = 'K3dRq1q9eN72GJDkgvyshFVwlqHHCyPI'
|
||||||
|
|
||||||
|
REPO_DIR = '/home/deploy/repos'
|
||||||
|
REPO_MAIN_NAME = '_'
|
||||||
|
REPO_FORBIDDEN_NAMES = ['api', 'www']
|
||||||
|
REPO_ENABLE_SUBDOMAIN = True
|
||||||
|
|
||||||
|
|
||||||
|
RECAPTCHA_PUBLIC_KEY = '6LfoxeESAAAAAGNaeWnISh0GTgDk0fBnr6Bo2Tfk'
|
||||||
|
RECAPTCHA_PRIVATE_KEY = '6LfoxeESAAAAABFzdCs0hNIIyeb42mofV-Ndd2_2'
|
||||||
|
RECAPTCHA_OPTIONS = {'theme': 'clean'}
|
||||||
|
|
||||||
|
ROOT_ENDPOINT = 'wiki.page'
|
||||||
|
WIKI_HOME = 'home'
|
||||||
|
|
||||||
|
MODULES = [
|
||||||
|
'wiki',
|
||||||
|
'auth'
|
||||||
|
]
|
||||||
|
|
||||||
|
if ENV is 'PROD':
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
DEBUG = True
|
||||||
|
ASSETS_DEBUG = True
|
|
@ -1,8 +1,9 @@
|
||||||
import redis
|
import redis
|
||||||
from realms import config
|
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
|
|
||||||
# Default DB connection
|
# Default DB connection
|
||||||
|
from realms import config
|
||||||
|
|
||||||
db = create_engine(config.DB_URI, encoding='utf8', echo=True)
|
db = create_engine(config.DB_URI, encoding='utf8', echo=True)
|
||||||
|
|
||||||
# Default Cache connection
|
# Default Cache connection
|
||||||
|
|
|
@ -59,11 +59,12 @@ def to_dict(cur, first=False):
|
||||||
else:
|
else:
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def validate_captcha():
|
def validate_captcha():
|
||||||
response = captcha.submit(
|
response = captcha.submit(
|
||||||
request.form['recaptcha_challenge_field'],
|
request.form['recaptcha_challenge_field'],
|
||||||
request.form['recaptcha_response_field'],
|
request.form['recaptcha_response_field'],
|
||||||
config.flask['RECAPTCHA_PRIVATE_KEY'],
|
config.RECAPTCHA_PRIVATE_KEY,
|
||||||
request.remote_addr)
|
request.remote_addr)
|
||||||
return response.is_valid
|
return response.is_valid
|
||||||
|
|
||||||
|
@ -125,4 +126,4 @@ def to_canonical(s):
|
||||||
|
|
||||||
|
|
||||||
def gravatar_url(email):
|
def gravatar_url(email):
|
||||||
return "https://www.gravatar.com/avatar/" + hashlib.md5(email).hexdigest()
|
return "//www.gravatar.com/avatar/" + hashlib.md5(email).hexdigest()
|
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import lxml.html
|
import lxml.html
|
||||||
|
from lxml.html.clean import Cleaner
|
||||||
import ghdiff
|
import ghdiff
|
||||||
import gittle.utils
|
import gittle.utils
|
||||||
from gittle import Gittle
|
from gittle import Gittle
|
||||||
|
@ -92,7 +93,9 @@ class Wiki():
|
||||||
|
|
||||||
tree = lxml.html.fromstring(content)
|
tree = lxml.html.fromstring(content)
|
||||||
|
|
||||||
cleaner = lxml.html.Cleaner(remove_unknown_tags=False, kill_tags=set(['style']), safe_attrs_only=False)
|
cleaner = Cleaner(remove_unknown_tags=False,
|
||||||
|
kill_tags=set(['style']),
|
||||||
|
safe_attrs_only=False)
|
||||||
tree = cleaner.clean_html(tree)
|
tree = cleaner.clean_html(tree)
|
||||||
|
|
||||||
content = lxml.html.tostring(tree, encoding='utf-8', method='html')
|
content = lxml.html.tostring(tree, encoding='utf-8', method='html')
|
||||||
|
|
0
realms/modules/__init__.py
Normal file
0
realms/modules/__init__.py
Normal file
0
realms/modules/auth/__init__.py
Normal file
0
realms/modules/auth/__init__.py
Normal file
35
realms/modules/auth/views.py
Normal file
35
realms/modules/auth/views.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
from flask import render_template, redirect, request, url_for, flash, Blueprint
|
||||||
|
from realms import redirect_url
|
||||||
|
from realms.models import User
|
||||||
|
|
||||||
|
blueprint = Blueprint('auth', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/logout/")
|
||||||
|
def logout():
|
||||||
|
User.logout()
|
||||||
|
return redirect(url_for('root'))
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/register/", methods=['GET', 'POST'])
|
||||||
|
def register():
|
||||||
|
if request.method == 'POST':
|
||||||
|
if User.register(request.form.get('username'), request.form.get('email'), request.form.get('password')):
|
||||||
|
return redirect(url_for('root'))
|
||||||
|
else:
|
||||||
|
# Login failed
|
||||||
|
return redirect(url_for('.register'))
|
||||||
|
else:
|
||||||
|
return render_template('auth/register.html')
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/login/", methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
if request.method == 'POST':
|
||||||
|
if User.auth(request.form['email'], request.form['password']):
|
||||||
|
return redirect(redirect_url(referrer=url_for('root')))
|
||||||
|
else:
|
||||||
|
flash("Email or Password invalid")
|
||||||
|
return redirect(url_for(".login"))
|
||||||
|
else:
|
||||||
|
return render_template('auth/login.html')
|
0
realms/modules/wiki/__init__.py
Normal file
0
realms/modules/wiki/__init__.py
Normal file
5
realms/modules/wiki/tests.py
Normal file
5
realms/modules/wiki/tests.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import realms
|
||||||
|
|
||||||
|
c = realms.app.test_client()
|
||||||
|
print c.get('/wiki/_create')
|
||||||
|
print c.get('/wiki/_create/blah')
|
122
realms/modules/wiki/views.py
Normal file
122
realms/modules/wiki/views.py
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
from flask import g, render_template, request, redirect, Blueprint, flash, url_for
|
||||||
|
from flask.ext.login import login_required
|
||||||
|
from realms import app, redirect_url, config
|
||||||
|
from realms.lib.util import to_canonical, remove_ext
|
||||||
|
from realms.lib.wiki import Wiki
|
||||||
|
from realms.models import Site
|
||||||
|
|
||||||
|
blueprint = Blueprint('wiki', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/wiki/_new/", methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def new_wiki():
|
||||||
|
if request.method == 'POST':
|
||||||
|
wiki_name = to_canonical(request.form['name'])
|
||||||
|
|
||||||
|
if Wiki.is_registered(wiki_name):
|
||||||
|
flash("Site already exists")
|
||||||
|
return redirect(redirect_url())
|
||||||
|
else:
|
||||||
|
s = Site()
|
||||||
|
s.create(name=wiki_name, repo=wiki_name, founder=g.current_user.get('id'))
|
||||||
|
return redirect('http://%s.%s' % (wiki_name, config.HOSTNAME))
|
||||||
|
else:
|
||||||
|
return render_template('wiki/new.html')
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/wiki/_commit/<sha>/<name>")
|
||||||
|
def commit_sha(name, sha):
|
||||||
|
cname = to_canonical(name)
|
||||||
|
|
||||||
|
data = g.current_wiki.get_page(cname, sha=sha)
|
||||||
|
if data:
|
||||||
|
return render_template('wiki/page.html', name=name, page=data, commit=sha)
|
||||||
|
else:
|
||||||
|
return redirect(url_for('.create', name=cname))
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/wiki/_compare/<name>/<regex('[^.]+'):fsha><regex('\.{2,3}'):dots><regex('.+'):lsha>")
|
||||||
|
def compare(name, fsha, dots, lsha):
|
||||||
|
diff = g.current_wiki.compare(name, fsha, lsha)
|
||||||
|
return render_template('wiki/compare.html', name=name, diff=diff, old=fsha, new=lsha)
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/wiki/_revert", methods=['POST'])
|
||||||
|
def revert():
|
||||||
|
if request.method == 'POST':
|
||||||
|
name = request.form.get('name')
|
||||||
|
commit = request.form.get('commit')
|
||||||
|
cname = to_canonical(name)
|
||||||
|
g.current_wiki.revert_page(name, commit, message="Reverting %s" % cname, username=g.current_user.get('username'))
|
||||||
|
flash('Page reverted', 'success')
|
||||||
|
return redirect(url_for('.page', name=cname))
|
||||||
|
|
||||||
|
@blueprint.route("/wiki/_history/<name>")
|
||||||
|
def history(name):
|
||||||
|
history = g.current_wiki.get_history(name)
|
||||||
|
return render_template('wiki/history.html', name=name, history=history)
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/wiki/_edit/<name>", methods=['GET', 'POST'])
|
||||||
|
def edit(name):
|
||||||
|
data = g.current_wiki.get_page(name)
|
||||||
|
cname = to_canonical(name)
|
||||||
|
if request.method == 'POST':
|
||||||
|
edit_cname = to_canonical(request.form['name'])
|
||||||
|
if edit_cname.lower() != cname.lower():
|
||||||
|
g.current_wiki.rename_page(cname, edit_cname)
|
||||||
|
g.current_wiki.write_page(edit_cname,
|
||||||
|
request.form['content'],
|
||||||
|
message=request.form['message'],
|
||||||
|
username=g.current_user.get('username'))
|
||||||
|
return redirect(url_for('.page', name=edit_cname))
|
||||||
|
else:
|
||||||
|
if data:
|
||||||
|
name = remove_ext(data['name'])
|
||||||
|
content = data['data']
|
||||||
|
return render_template('wiki/edit.html', name=name, content=content)
|
||||||
|
else:
|
||||||
|
return redirect(url_for('.create', name=cname))
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/wiki/_delete/<name>", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def delete(name):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/wiki/_create/", defaults={'name': None}, methods=['GET', 'POST'])
|
||||||
|
@blueprint.route("/wiki/_create/<name>", methods=['GET', 'POST'])
|
||||||
|
def create(name):
|
||||||
|
cname = ""
|
||||||
|
if name:
|
||||||
|
cname = to_canonical(name)
|
||||||
|
if g.current_wiki.get_page(cname):
|
||||||
|
# Page exists, edit instead
|
||||||
|
return redirect(url_for('.edit', name=cname))
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
g.current_wiki.write_page(request.form['name'],
|
||||||
|
request.form['content'],
|
||||||
|
message=request.form['message'],
|
||||||
|
create=True,
|
||||||
|
username=g.current_user.get('username'))
|
||||||
|
return redirect(url_for('.page', name=cname))
|
||||||
|
else:
|
||||||
|
return render_template('wiki/edit.html', name=cname, content="")
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/wiki/", defaults={'name': 'home'})
|
||||||
|
@blueprint.route("/wiki/<name>")
|
||||||
|
def page(name):
|
||||||
|
cname = to_canonical(name)
|
||||||
|
if cname != name:
|
||||||
|
return redirect(url_for('.page', name=cname))
|
||||||
|
|
||||||
|
data = g.current_wiki.get_page(cname)
|
||||||
|
|
||||||
|
if data:
|
||||||
|
return render_template('wiki/page.html', name=cname, page=data)
|
||||||
|
else:
|
||||||
|
return redirect(url_for('.create', name=cname))
|
|
@ -7,7 +7,7 @@
|
||||||
<meta name="author" content="">
|
<meta name="author" content="">
|
||||||
|
|
||||||
<title>Realms</title>
|
<title>Realms</title>
|
||||||
|
<link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.ico') }}">
|
||||||
<link href="/static/css/bootstrap/spacelab.css" rel="stylesheet">
|
<link href="/static/css/bootstrap/spacelab.css" rel="stylesheet">
|
||||||
<link href="/static/css/font-awesome.min.css" rel="stylesheet">
|
<link href="/static/css/font-awesome.min.css" rel="stylesheet">
|
||||||
<link href="/static/vendor/highlightjs/styles/github.css" rel="stylesheet">
|
<link href="/static/vendor/highlightjs/styles/github.css" rel="stylesheet">
|
||||||
|
|
|
@ -2,6 +2,7 @@ Flask==0.10.1
|
||||||
Flask-Assets==0.8
|
Flask-Assets==0.8
|
||||||
Flask-Bcrypt==0.5.2
|
Flask-Bcrypt==0.5.2
|
||||||
Flask-Login==0.2.7
|
Flask-Login==0.2.7
|
||||||
|
Flask-Script==0.6.3
|
||||||
beautifulsoup4==4.3.2
|
beautifulsoup4==4.3.2
|
||||||
boto==2.17.0
|
boto==2.17.0
|
||||||
closure==20121212
|
closure==20121212
|
||||||
|
|
Loading…
Reference in a new issue