many things have occured
Этот коммит содержится в:
		
							родитель
							
								
									02b6b7d592
								
							
						
					
					
						коммит
						db70df22a2
					
				
					 23 изменённых файлов: 281 добавлений и 167 удалений
				
			
		
							
								
								
									
										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
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										38
									
								
								realms/config/__init__.py
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -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
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										0
									
								
								realms/modules/__init__.py
									
										
									
									
									
										Обычный файл
									
								
							
							
								
								
									
										0
									
								
								realms/modules/auth/__init__.py
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										0
									
								
								realms/modules/auth/__init__.py
									
										
									
									
									
										Обычный файл
									
								
							
							
								
								
									
										35
									
								
								realms/modules/auth/views.py
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										35
									
								
								realms/modules/auth/views.py
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -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
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										0
									
								
								realms/modules/wiki/__init__.py
									
										
									
									
									
										Обычный файл
									
								
							
							
								
								
									
										5
									
								
								realms/modules/wiki/tests.py
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										5
									
								
								realms/modules/wiki/tests.py
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -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
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										122
									
								
								realms/modules/wiki/views.py
									
										
									
									
									
										Обычный файл
									
								
							|  | @ -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 | ||||||
|  |  | ||||||
		Загрузка…
	
	Создание таблицы
		Добавить ссылку
		
	
		Сослаться в новой задаче