Commit ab94e3df0bed4f5bd980bf8231a6990a6369beac
Exists in
master
and in
33 other branches
Merge branch 'settings_py'
Showing
13 changed files
with
295 additions
and
139 deletions
Show diff stats
.gitignore
colab/plugins/context_processors.py
| @@ -2,10 +2,10 @@ | @@ -2,10 +2,10 @@ | ||
| 2 | from django.conf import settings | 2 | from django.conf import settings |
| 3 | 3 | ||
| 4 | 4 | ||
| 5 | -def proxied_apps(request): | ||
| 6 | - proxied_apps = {} | 5 | +def colab_apps(request): |
| 6 | + colab_apps = {} | ||
| 7 | 7 | ||
| 8 | for app_name, app in settings.COLAB_APPS.items(): | 8 | for app_name, app in settings.COLAB_APPS.items(): |
| 9 | - proxied_apps[app_name] = app | 9 | + colab_apps[app_name] = app |
| 10 | 10 | ||
| 11 | - return {'proxy': proxied_apps} | 11 | + return {'plugins': colab_apps} |
colab/plugins/templates/plugins/menu_template.html
| 1 | {% for title, links in menu_links.items %} | 1 | {% for title, links in menu_links.items %} |
| 2 | {% if links|length == 1 %} | 2 | {% if links|length == 1 %} |
| 3 | - {% for text, link in links %} | 3 | + {% for colab_url in links %} |
| 4 | <li> | 4 | <li> |
| 5 | - <a href="{{ link }}">{{ title }}</a> | 5 | + <a href="{{ colab_url.url }}">{{ title }}</a> |
| 6 | </li> | 6 | </li> |
| 7 | {% endfor %} | 7 | {% endfor %} |
| 8 | {% else %} | 8 | {% else %} |
| 9 | <li class="dropdown"> | 9 | <li class="dropdown"> |
| 10 | <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ title }} <b class="caret"></b></a> | 10 | <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ title }} <b class="caret"></b></a> |
| 11 | <ul class="dropdown-menu"> | 11 | <ul class="dropdown-menu"> |
| 12 | - {% for text, link in links %} | ||
| 13 | - <li><a href="{{ link }}">{{ text }}</a></li> | 12 | + {% for colab_url in links %} |
| 13 | + <li><a href="{{ colab_url.url }}">{{ colab_url.display }}</a></li> | ||
| 14 | {% endfor %} | 14 | {% endfor %} |
| 15 | </ul> | 15 | </ul> |
| 16 | </li> | 16 | </li> |
colab/plugins/templatetags/plugins.py
| @@ -3,45 +3,48 @@ from collections import OrderedDict | @@ -3,45 +3,48 @@ from collections import OrderedDict | ||
| 3 | from django import template | 3 | from django import template |
| 4 | from django.core.cache import cache | 4 | from django.core.cache import cache |
| 5 | from django.template.loader import render_to_string | 5 | from django.template.loader import render_to_string |
| 6 | -from django.utils.translation import ugettext_lazy as _ | 6 | +from django.utils.translation import get_language |
| 7 | 7 | ||
| 8 | register = template.Library() | 8 | register = template.Library() |
| 9 | 9 | ||
| 10 | 10 | ||
| 11 | @register.simple_tag(takes_context=True) | 11 | @register.simple_tag(takes_context=True) |
| 12 | def plugins_menu(context): | 12 | def plugins_menu(context): |
| 13 | + | ||
| 13 | if context['user'].is_authenticated(): | 14 | if context['user'].is_authenticated(): |
| 14 | cache_key = 'colab-proxy-menu-authenticated' | 15 | cache_key = 'colab-proxy-menu-authenticated' |
| 15 | else: | 16 | else: |
| 16 | cache_key = 'colab-proxy-menu-anonymous' | 17 | cache_key = 'colab-proxy-menu-anonymous' |
| 17 | 18 | ||
| 19 | + lang = get_language() | ||
| 20 | + cache_key += '-{}'.format(lang) | ||
| 21 | + | ||
| 18 | menu_from_cache = cache.get(cache_key) | 22 | menu_from_cache = cache.get(cache_key) |
| 19 | 23 | ||
| 20 | if menu_from_cache: | 24 | if menu_from_cache: |
| 21 | return menu_from_cache | 25 | return menu_from_cache |
| 22 | 26 | ||
| 23 | menu_links = OrderedDict() | 27 | menu_links = OrderedDict() |
| 24 | - proxied_apps = context.get('proxy', {}) | 28 | + colab_apps = context.get('plugins', {}) |
| 25 | 29 | ||
| 26 | - for app_name, app in proxied_apps.items(): | ||
| 27 | - if not app.get('menu'): | 30 | + for app_name, app in colab_apps.items(): |
| 31 | + if not app.get('menu_urls'): | ||
| 28 | continue | 32 | continue |
| 29 | 33 | ||
| 30 | - menu = app.get('menu') | ||
| 31 | - title = menu.get('title', app_name) | ||
| 32 | - links = menu.get('links', tuple()).items() | ||
| 33 | - if context['user'].is_active: | ||
| 34 | - links += menu.get('auth_links', tuple()).items() | ||
| 35 | - | ||
| 36 | - if not links: | ||
| 37 | - continue | 34 | + menu = app.get('menu_urls') |
| 35 | + title = app.get('menu_title', app_name) | ||
| 38 | 36 | ||
| 39 | if title not in menu_links: | 37 | if title not in menu_links: |
| 40 | - menu_links[_(title)] = [] | 38 | + menu_links[title] = [] |
| 39 | + | ||
| 40 | + for colab_url in menu: | ||
| 41 | + if not context['user'].is_active and colab_url.auth: | ||
| 42 | + continue | ||
| 43 | + | ||
| 44 | + menu_links[title].append(colab_url) | ||
| 41 | 45 | ||
| 42 | - for text, link in links: | ||
| 43 | - url = link | ||
| 44 | - menu_links[_(title)].append((_(text), url)) | 46 | + if not menu_links[title]: |
| 47 | + del menu_links[title] | ||
| 45 | 48 | ||
| 46 | menu = render_to_string('plugins/menu_template.html', | 49 | menu = render_to_string('plugins/menu_template.html', |
| 47 | {'menu_links': menu_links}) | 50 | {'menu_links': menu_links}) |
colab/plugins/urls.py
| @@ -14,8 +14,8 @@ for app_name, app in settings.COLAB_APPS.items(): | @@ -14,8 +14,8 @@ for app_name, app in settings.COLAB_APPS.items(): | ||
| 14 | urls = app.get('urls') | 14 | urls = app.get('urls') |
| 15 | if not urls.get('include'): | 15 | if not urls.get('include'): |
| 16 | raise ImproperlyConfigured(undef_url_include_msg) | 16 | raise ImproperlyConfigured(undef_url_include_msg) |
| 17 | - print urls['include'] | ||
| 18 | urlpatterns += patterns('', | 17 | urlpatterns += patterns('', |
| 19 | url(urls.get('prefix', r''), include(urls['include'], | 18 | url(urls.get('prefix', r''), include(urls['include'], |
| 20 | namespace=urls.get('namespace'))), | 19 | namespace=urls.get('namespace'))), |
| 21 | - ) | ||
| 22 | \ No newline at end of file | 20 | \ No newline at end of file |
| 21 | + ) | ||
| 22 | + |
| @@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
| 1 | +from django.core.urlresolvers import reverse_lazy | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +class ColabUrl(object): | ||
| 5 | + def __init__(self, display, url, auth): | ||
| 6 | + self.display = display | ||
| 7 | + self.url = url | ||
| 8 | + self.auth = auth | ||
| 9 | + | ||
| 10 | + | ||
| 11 | +def colab_url_factory(namespace): | ||
| 12 | + | ||
| 13 | + def url(display, viewname, namespace=namespace, args=tuple(), | ||
| 14 | + kwargs={}, auth=False): | ||
| 15 | + | ||
| 16 | + if namespace: | ||
| 17 | + rev_viewname = ':'.join((namespace, viewname)) | ||
| 18 | + else: | ||
| 19 | + rev_viewname = viewname | ||
| 20 | + | ||
| 21 | + url = reverse_lazy(rev_viewname, args=args, kwargs=kwargs) | ||
| 22 | + | ||
| 23 | + return ColabUrl(display, url, auth) | ||
| 24 | + | ||
| 25 | + return url |
colab/settings.py
| @@ -194,7 +194,7 @@ TEMPLATE_CONTEXT_PROCESSORS = ( | @@ -194,7 +194,7 @@ TEMPLATE_CONTEXT_PROCESSORS = ( | ||
| 194 | 'django.core.context_processors.request', | 194 | 'django.core.context_processors.request', |
| 195 | 'django_mobile.context_processors.is_mobile', | 195 | 'django_mobile.context_processors.is_mobile', |
| 196 | 'colab.super_archives.context_processors.mailarchive', | 196 | 'colab.super_archives.context_processors.mailarchive', |
| 197 | - 'colab.plugins.context_processors.proxied_apps', | 197 | + 'colab.plugins.context_processors.colab_apps', |
| 198 | 'colab.home.context_processors.robots', | 198 | 'colab.home.context_processors.robots', |
| 199 | 'colab.home.context_processors.ribbon', | 199 | 'colab.home.context_processors.ribbon', |
| 200 | 'colab.home.context_processors.google_analytics', | 200 | 'colab.home.context_processors.google_analytics', |
| @@ -280,8 +280,13 @@ CONVERSEJS_SHOW_ONLY_ONLINE_USERS = True | @@ -280,8 +280,13 @@ CONVERSEJS_SHOW_ONLY_ONLINE_USERS = True | ||
| 280 | TASTYPIE_DEFAULT_FORMATS = ['json', ] | 280 | TASTYPIE_DEFAULT_FORMATS = ['json', ] |
| 281 | 281 | ||
| 282 | from .utils.conf import load_yaml_settings | 282 | from .utils.conf import load_yaml_settings |
| 283 | +from .utils.conf import load_py_settings | ||
| 284 | +from .utils.conf import load_colab_apps | ||
| 285 | + | ||
| 283 | locals().update(load_yaml_settings()) | 286 | locals().update(load_yaml_settings()) |
| 284 | 287 | ||
| 288 | +locals().update(load_py_settings()) | ||
| 289 | + | ||
| 285 | if locals().get('RAVEN_DSN', False): | 290 | if locals().get('RAVEN_DSN', False): |
| 286 | RAVEN_CONFIG = { | 291 | RAVEN_CONFIG = { |
| 287 | 'dsn': RAVEN_DSN + '?timeout=30', # noqa | 292 | 'dsn': RAVEN_DSN + '?timeout=30', # noqa |
| @@ -291,6 +296,8 @@ if locals().get('RAVEN_DSN', False): | @@ -291,6 +296,8 @@ if locals().get('RAVEN_DSN', False): | ||
| 291 | BROWSERID_ENABLED = locals().get('BROWSERID_ENABLED') or False | 296 | BROWSERID_ENABLED = locals().get('BROWSERID_ENABLED') or False |
| 292 | SOCIAL_NETWORK_ENABLED = locals().get('SOCIAL_NETWORK_ENABLED') or False | 297 | SOCIAL_NETWORK_ENABLED = locals().get('SOCIAL_NETWORK_ENABLED') or False |
| 293 | 298 | ||
| 299 | +locals().update(load_colab_apps()) | ||
| 300 | + | ||
| 294 | COLAB_APPS = locals().get('COLAB_APPS') or {} | 301 | COLAB_APPS = locals().get('COLAB_APPS') or {} |
| 295 | PROXIED_APPS = {} | 302 | PROXIED_APPS = {} |
| 296 | 303 |
colab/utils/conf.py
| 1 | 1 | ||
| 2 | import os | 2 | import os |
| 3 | +import sys | ||
| 4 | + | ||
| 5 | +import warnings | ||
| 6 | + | ||
| 3 | import yaml | 7 | import yaml |
| 4 | 8 | ||
| 5 | import yamlordereddictloader | 9 | import yamlordereddictloader |
| 6 | 10 | ||
| 7 | from django.core.exceptions import ImproperlyConfigured | 11 | from django.core.exceptions import ImproperlyConfigured |
| 8 | 12 | ||
| 13 | +import importlib | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +USING_YAML_SETTINGS = False | ||
| 17 | + | ||
| 9 | 18 | ||
| 10 | class InaccessibleYAMLSettings(ImproperlyConfigured): | 19 | class InaccessibleYAMLSettings(ImproperlyConfigured): |
| 11 | """Settings YAML is Inaccessible. | 20 | """Settings YAML is Inaccessible. |
| @@ -29,22 +38,144 @@ def _load_yaml_file(yaml_path): | @@ -29,22 +38,144 @@ def _load_yaml_file(yaml_path): | ||
| 29 | 38 | ||
| 30 | def load_yaml_settings(): | 39 | def load_yaml_settings(): |
| 31 | settings_dir = '/etc/colab/settings.d' | 40 | settings_dir = '/etc/colab/settings.d' |
| 32 | - yaml_path = os.getenv('COLAB_SETTINGS', '/etc/colab/settings.yaml') | 41 | + yaml_path = os.getenv('COLAB_YAML_SETTINGS', '/etc/colab/settings.yaml') |
| 33 | 42 | ||
| 34 | - if not os.path.exists(yaml_path): | ||
| 35 | - msg = "The yaml file {} does not exist".format(yaml_path) | ||
| 36 | - raise InaccessibleYAMLSettings(msg) | 43 | + if os.path.exists(yaml_path): |
| 44 | + global USING_YAML_SETTINGS | ||
| 45 | + USING_YAML_SETTINGS = True | ||
| 46 | + warnings.warn("YAML Settings file is deprecated. Use Py file instead.") | ||
| 47 | + else: | ||
| 48 | + return {} | ||
| 37 | 49 | ||
| 38 | yaml_settings = _load_yaml_file(yaml_path) | 50 | yaml_settings = _load_yaml_file(yaml_path) |
| 39 | 51 | ||
| 52 | + parse_yml_menus(yaml_settings) | ||
| 53 | + | ||
| 40 | # Try to read settings from settings.d | 54 | # Try to read settings from settings.d |
| 41 | if os.path.exists(settings_dir): | 55 | if os.path.exists(settings_dir): |
| 42 | for file_name in os.listdir(settings_dir): | 56 | for file_name in os.listdir(settings_dir): |
| 43 | if file_name.endswith('.yaml') or file_name.endswith('yml'): | 57 | if file_name.endswith('.yaml') or file_name.endswith('yml'): |
| 44 | file_path = os.path.join(settings_dir, file_name) | 58 | file_path = os.path.join(settings_dir, file_name) |
| 45 | yaml_settings_d = _load_yaml_file(file_path) | 59 | yaml_settings_d = _load_yaml_file(file_path) |
| 60 | + | ||
| 61 | + parse_yml_menus(yaml_settings_d) | ||
| 62 | + | ||
| 46 | yaml_settings.update(yaml_settings_d) | 63 | yaml_settings.update(yaml_settings_d) |
| 47 | 64 | ||
| 48 | return yaml_settings or {} | 65 | return yaml_settings or {} |
| 49 | 66 | ||
| 50 | -yaml_settings = load_yaml_settings() | 67 | + |
| 68 | +class InaccessiblePySettings(ImproperlyConfigured): | ||
| 69 | + """Settings.py is Inaccessible. | ||
| 70 | + | ||
| 71 | + Check if the file exists and if you have read permissions.""" | ||
| 72 | + | ||
| 73 | + | ||
| 74 | +def _load_py_file(py_path, path): | ||
| 75 | + original_path = sys.path | ||
| 76 | + | ||
| 77 | + sys.path = [path] | ||
| 78 | + try: | ||
| 79 | + py_settings = importlib.import_module(py_path) | ||
| 80 | + | ||
| 81 | + except IOError: | ||
| 82 | + msg = ('Could not open settings file {}. Please ' | ||
| 83 | + 'check if the file exists and if user ' | ||
| 84 | + 'has read rights.').format(py_path) | ||
| 85 | + raise InaccessiblePySettings(msg) | ||
| 86 | + | ||
| 87 | + except SyntaxError as excpt: | ||
| 88 | + msg = ('Syntax Error: {}'.format(excpt)) | ||
| 89 | + raise InaccessiblePySettings(msg) | ||
| 90 | + | ||
| 91 | + finally: | ||
| 92 | + sys.path = original_path | ||
| 93 | + | ||
| 94 | + py_setting = {var: getattr(py_settings, var) for var in dir(py_settings) | ||
| 95 | + if not var.startswith('__')} | ||
| 96 | + | ||
| 97 | + return py_setting | ||
| 98 | + | ||
| 99 | + | ||
| 100 | +def load_py_settings(): | ||
| 101 | + settings_dir = '/etc/colab/settings.d' | ||
| 102 | + settings_file = os.getenv('COLAB_SETTINGS', '/etc/colab/settings.py') | ||
| 103 | + settings_module = settings_file.split('.')[-2].split('/')[-1] | ||
| 104 | + py_path = "/".join(settings_file.split('/')[:-1]) | ||
| 105 | + | ||
| 106 | + global USING_YAML_SETTINGS | ||
| 107 | + if not os.path.exists(py_path) and not USING_YAML_SETTINGS: | ||
| 108 | + msg = "The py file {} does not exist".format(py_path) | ||
| 109 | + raise InaccessiblePySettings(msg) | ||
| 110 | + elif USING_YAML_SETTINGS: | ||
| 111 | + return {} | ||
| 112 | + | ||
| 113 | + py_settings = _load_py_file(settings_module, py_path) | ||
| 114 | + | ||
| 115 | + # Try to read settings from settings.d | ||
| 116 | + | ||
| 117 | + if os.path.exists(settings_dir): | ||
| 118 | + return py_settings | ||
| 119 | + for file_name in os.listdir(settings_dir): | ||
| 120 | + if file_name.endswith('.py'): | ||
| 121 | + file_module = file_name.split('.')[0] | ||
| 122 | + py_settings_d = _load_py_file(file_module, settings_dir) | ||
| 123 | + py_settings.update(py_settings_d) | ||
| 124 | + | ||
| 125 | + return py_settings | ||
| 126 | + | ||
| 127 | + | ||
| 128 | +def load_colab_apps(): | ||
| 129 | + plugins_dir = os.getenv('COLAB_PLUGINS', '/etc/colab/plugins.d/') | ||
| 130 | + | ||
| 131 | + global USING_YAML_SETTINGS | ||
| 132 | + if USING_YAML_SETTINGS: | ||
| 133 | + return {} | ||
| 134 | + | ||
| 135 | + COLAB_APPS = {} | ||
| 136 | + | ||
| 137 | + # Try to read settings from plugins.d | ||
| 138 | + if os.path.exists(plugins_dir): | ||
| 139 | + for file_name in os.listdir(plugins_dir): | ||
| 140 | + if file_name.endswith('.py'): | ||
| 141 | + file_module = file_name.split('.')[0] | ||
| 142 | + py_settings_d = _load_py_file(file_module, plugins_dir) | ||
| 143 | + fields = ['verbose_name', 'upstream', 'urls', | ||
| 144 | + 'menu_urls', 'middlewares', 'dependencies', | ||
| 145 | + 'context_processors'] | ||
| 146 | + | ||
| 147 | + app_name = py_settings_d.get('name') | ||
| 148 | + if not app_name: | ||
| 149 | + warnings.warn("Plugin missing name variable") | ||
| 150 | + continue | ||
| 151 | + | ||
| 152 | + COLAB_APPS[app_name] = {} | ||
| 153 | + COLAB_APPS[app_name]['menu_title'] = \ | ||
| 154 | + py_settings_d.get('menu_title') | ||
| 155 | + | ||
| 156 | + for key in fields: | ||
| 157 | + value = py_settings_d.get(key) | ||
| 158 | + if value: | ||
| 159 | + COLAB_APPS[app_name][key] = value | ||
| 160 | + | ||
| 161 | + return {'COLAB_APPS': COLAB_APPS} | ||
| 162 | + | ||
| 163 | + | ||
| 164 | +def parse_yml_menus(yaml_settings): | ||
| 165 | + if 'COLAB_APPS' in yaml_settings: | ||
| 166 | + for key, plugin in yaml_settings['COLAB_APPS'].items(): | ||
| 167 | + if 'menu' in plugin: | ||
| 168 | + parse_yml_tuples(yaml_settings['COLAB_APPS'][key]['menu']) | ||
| 169 | + | ||
| 170 | + | ||
| 171 | +def parse_yml_tuples(menu): | ||
| 172 | + dict_links = menu['links'] | ||
| 173 | + dict_auth_links = menu['auth_links'] | ||
| 174 | + menu['links'] = tuple() | ||
| 175 | + menu['auth_links'] = tuple() | ||
| 176 | + | ||
| 177 | + for key, value in dict_links.items(): | ||
| 178 | + menu['links'] += ((key, value),) | ||
| 179 | + | ||
| 180 | + for key, value in dict_auth_links.items(): | ||
| 181 | + menu['auth_links'] += ((key, value),) |
docs/source/user.rst
| @@ -14,41 +14,33 @@ Install | @@ -14,41 +14,33 @@ Install | ||
| 14 | 14 | ||
| 15 | Plugins | 15 | Plugins |
| 16 | ------- | 16 | ------- |
| 17 | -.. attribute:: COLAB_APPS | 17 | +.. attribute:: name |
| 18 | 18 | ||
| 19 | - :default: None | 19 | +Declares the absolute name of the plugin app as a python import path. Example: |
| 20 | +directory.something.someplugin | ||
| 21 | + | ||
| 22 | +.. attribute:: verbose_name | ||
| 20 | 23 | ||
| 21 | - Describes the activated plugins and its configurations. It's necessary to describe | ||
| 22 | - for each app its name as the variable. The apps described here can be devided into | ||
| 23 | - two categories, that beeing, colab proxy apps and third-party apps. | ||
| 24 | - The upstream variable is only needed to colab proxy apps. | 24 | +Delclare the description name of the plugin. |
| 25 | 25 | ||
| 26 | .. attribute:: upstream | 26 | .. attribute:: upstream |
| 27 | 27 | ||
| 28 | -Declares the upstream server url of the proxy. Only declare if the plugin is a proxy. | 28 | +Declares the upstream server url of the proxy. Only declare if the plugin is a |
| 29 | +proxy. | ||
| 29 | 30 | ||
| 30 | -dependecies | ||
| 31 | -+++++++++++ | 31 | +.. attribute:: middlewares |
| 32 | 32 | ||
| 33 | - A list of the plugin dependecies that will be added to INSTALLED_APPS. | ||
| 34 | - This doesn't automatically install the python dependecies, only add to django apps. | 33 | +Declares the middlewares of the plugin in a list format. |
| 35 | 34 | ||
| 35 | +.. attribute:: context_processors | ||
| 36 | 36 | ||
| 37 | -menu | ||
| 38 | -++++ | 37 | +Declares the context processors of the plugin in a list format too. |
| 39 | 38 | ||
| 40 | -.. attribute:: title | 39 | +.. attribute:: dependency |
| 41 | 40 | ||
| 42 | - Declares the menu title. | ||
| 43 | -.. attribute:: links | ||
| 44 | - | ||
| 45 | - Declares the menu items and its links. | ||
| 46 | -.. attribute:: auth_links | ||
| 47 | - | ||
| 48 | - Declares the menu items and its links when the user authenticated. | ||
| 49 | -.. attribute:: dependecies | ||
| 50 | - | ||
| 51 | -Declares a list of the plugin dependecies. | 41 | +Declares the additional installed apps that this plugin depends on. |
| 42 | +This doesn't automatically install the python dependecies, only add to django | ||
| 43 | +apps. | ||
| 52 | 44 | ||
| 53 | urls | 45 | urls |
| 54 | ++++ | 46 | ++++ |
| @@ -63,16 +55,35 @@ urls | @@ -63,16 +55,35 @@ urls | ||
| 63 | 55 | ||
| 64 | Declares the namespace for the url. | 56 | Declares the namespace for the url. |
| 65 | 57 | ||
| 66 | -context_processors | ||
| 67 | -++++++++++++++++++ | 58 | +menu |
| 59 | +++++ | ||
| 68 | 60 | ||
| 69 | - Declares the plugin context processors. | 61 | +These variables defines the menu title and links of the plugin. |
| 70 | 62 | ||
| 71 | -middlewares | ||
| 72 | -+++++++++++ | 63 | +.. attribute:: menu_title |
| 64 | + | ||
| 65 | + Declares the menu title. | ||
| 66 | +.. attribute:: menu_links | ||
| 67 | + | ||
| 68 | + Declares the menu items and its links. | ||
| 69 | + This should be a tuple object with several colab_url elements. | ||
| 70 | + The colab_url_factory creates a factory for your links along with your | ||
| 71 | + namespace. | ||
| 72 | + The auth parameter indicates wether the link should only be displayed when | ||
| 73 | + the user is logged in. | ||
| 74 | + | ||
| 75 | +Example: | ||
| 76 | + | ||
| 77 | +.. code-block:: python | ||
| 73 | 78 | ||
| 74 | - Declares the plugin middlewares. | 79 | + from colab.plugins.utils.menu import colab_url_factory |
| 75 | 80 | ||
| 81 | + url = colab_url_factory('plugin_app_name') | ||
| 82 | + | ||
| 83 | + menu_urls = ( | ||
| 84 | + url(display=_('Profile'), viewname='profile', kwargs={'path': '/profile/'}, auth=True), | ||
| 85 | + url(display=_('Profile Two'), viewname='profile2', kwargs={'path': '/profile/2'}, auth=True), | ||
| 86 | + ) | ||
| 76 | 87 | ||
| 77 | Extra Template Folders | 88 | Extra Template Folders |
| 78 | ++++++++++++++++++++++ | 89 | ++++++++++++++++++++++ |
| @@ -113,12 +124,12 @@ SVN | @@ -113,12 +124,12 @@ SVN | ||
| 113 | .. TODO | 124 | .. TODO |
| 114 | 125 | ||
| 115 | Social Networks | 126 | Social Networks |
| 116 | -++++ | 127 | ++++++++++++++++ |
| 117 | .. attribute:: SOCIAL_NETWORK_ENABLED | 128 | .. attribute:: SOCIAL_NETWORK_ENABLED |
| 118 | 129 | ||
| 119 | :default: False | 130 | :default: False |
| 120 | 131 | ||
| 121 | - When this variable is True, the social networks fields, like Facebook and | 132 | + When this variable is True, the social networks fields, like Facebook and |
| 122 | Twitter, are added in user profile. By default, this fields are disabled. | 133 | Twitter, are added in user profile. By default, this fields are disabled. |
| 123 | 134 | ||
| 124 | Auth | 135 | Auth |
| @@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
| 1 | +SECRET_KEY = 'ddddddddddddddddddddddddddddddddddddddddddddddddddddddaddddddddd' | ||
| 2 | + | ||
| 3 | +DATABASES = { | ||
| 4 | + 'default': { | ||
| 5 | + 'ENGINE': 'django.db.backends.postgresql_psycopg2', | ||
| 6 | + 'HOST': 'localhost', | ||
| 7 | + 'NAME': 'colab', | ||
| 8 | + 'USER': 'colab', | ||
| 9 | + 'PASSWORD': 'colab', | ||
| 10 | + } | ||
| 11 | +} |
| @@ -0,0 +1,39 @@ | @@ -0,0 +1,39 @@ | ||
| 1 | +from django.utils.translation import ugettext_lazy as _ | ||
| 2 | + | ||
| 3 | +name = 'colab.plugins.gitlab' | ||
| 4 | +verbose_name = 'Gitlab Proxy' | ||
| 5 | + | ||
| 6 | +upstream = 'localhost' | ||
| 7 | +#middlewares = [] | ||
| 8 | + | ||
| 9 | +menu = { | ||
| 10 | +'title': _('Code'), | ||
| 11 | +'links': ( | ||
| 12 | + (_('Public Projects'), 'public/projects'), | ||
| 13 | +), | ||
| 14 | +'auth_links': ( | ||
| 15 | + (_('Profile'), 'profile'), | ||
| 16 | + (_('New Project'), 'projects/new'), | ||
| 17 | + (_('Projects'), 'dashboard/projects'), | ||
| 18 | + (_('Groups'), 'profile/groups'), | ||
| 19 | + (_('Issues'), 'dashboard/issues'), | ||
| 20 | + (_('Merge Requests'), 'dashboard/merge_requests'), | ||
| 21 | + | ||
| 22 | +), | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +# dpaste: | ||
| 27 | +# dependencies: | ||
| 28 | +# - 'mptt' | ||
| 29 | +# urls: | ||
| 30 | +# include: 'dpaste.urls.dpaste' | ||
| 31 | +# prefix: '^paste/' | ||
| 32 | +# namespace: 'dpaste' | ||
| 33 | +# menu: | ||
| 34 | +# title: 'Dpaste' | ||
| 35 | +# links: | ||
| 36 | +# Public Projects: '/paste' | ||
| 37 | +# auth_links: | ||
| 38 | +# Profile: '/projects' | ||
| 39 | +# New Project: '/projects/new' |
tests/run.py
| @@ -4,7 +4,9 @@ import os | @@ -4,7 +4,9 @@ import os | ||
| 4 | import sys | 4 | import sys |
| 5 | 5 | ||
| 6 | os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.settings' | 6 | os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.settings' |
| 7 | -os.environ['COLAB_SETTINGS'] = 'tests/settings.yaml' | 7 | +os.environ['COLAB_SETTINGS'] = 'tests/config_settings.py' |
| 8 | +os.environ['COLAB_YAML_SETTINGS'] = 'tests/settings.yaml' | ||
| 9 | +os.environ['COLAB_PLUGINS'] = 'tests/plugins.d' | ||
| 8 | os.environ['COVERAGE_PROCESS_START'] = '.coveragerc' | 10 | os.environ['COVERAGE_PROCESS_START'] = '.coveragerc' |
| 9 | os.environ['REUSE_DB'] = '0' | 11 | os.environ['REUSE_DB'] = '0' |
| 10 | 12 |
tests/settings.yaml
| @@ -1,73 +0,0 @@ | @@ -1,73 +0,0 @@ | ||
| 1 | - | ||
| 2 | - | ||
| 3 | -## Set to false in production | ||
| 4 | -DEBUG: true | ||
| 5 | -TEMPLATE_DEBUG: true | ||
| 6 | - | ||
| 7 | -## System admins | ||
| 8 | -ADMINS: &admin | ||
| 9 | - - | ||
| 10 | - - John Foo | ||
| 11 | - - john@example.com | ||
| 12 | - - | ||
| 13 | - - Mary Bar | ||
| 14 | - - mary@example.com | ||
| 15 | - | ||
| 16 | -MANAGERS: *admin | ||
| 17 | - | ||
| 18 | -COLAB_FROM_ADDRESS: '"Colab" <noreply@example.com>' | ||
| 19 | -SERVER_EMAIL: '"Colab" <noreply@example.com>' | ||
| 20 | - | ||
| 21 | -EMAIL_HOST: localhost | ||
| 22 | -EMAIL_PORT: 25 | ||
| 23 | -EMAIL_SUBJECT_PREFIX: '[colab]' | ||
| 24 | - | ||
| 25 | -SECRET_KEY: 'hu8-)szdcjjsz%f02gt$5djbluxc$v0a%01l)di6oi)np7%8lu' | ||
| 26 | - | ||
| 27 | -# Must use it without trailing slash | ||
| 28 | -SITE_URL: 'http://localhost:8000' | ||
| 29 | -BROWSERID_AUDIENCES: | ||
| 30 | - - http://localhost:8000 | ||
| 31 | -# - http://example.com | ||
| 32 | -# - https://example.org | ||
| 33 | -# - http://example.net | ||
| 34 | - | ||
| 35 | -ALLOWED_HOSTS: | ||
| 36 | - - localhost | ||
| 37 | -# - example.com | ||
| 38 | -# - example.org | ||
| 39 | -# - example.net | ||
| 40 | - | ||
| 41 | -### Uncomment to enable Broswer ID protocol for authentication | ||
| 42 | -# BROWSERID_ENABLED: True | ||
| 43 | - | ||
| 44 | -### Uncomment to enable Converse.js | ||
| 45 | -# CONVERSEJS_ENABLED: True | ||
| 46 | - | ||
| 47 | -### Uncomment to enable auto-registration | ||
| 48 | -# CONVERSEJS_AUTO_REGISTER: 'xmpp.example.com' | ||
| 49 | - | ||
| 50 | -## Database settings | ||
| 51 | -DATABASES: | ||
| 52 | - default: | ||
| 53 | - ENGINE: django.db.backends.postgresql_psycopg2 | ||
| 54 | - HOST: localhost | ||
| 55 | - NAME: colab | ||
| 56 | - USER: colab | ||
| 57 | - PASSWORD: colab | ||
| 58 | - | ||
| 59 | -## Disable indexing | ||
| 60 | -ROBOTS_NOINDEX: false | ||
| 61 | - | ||
| 62 | -### Log errors to Sentry instance | ||
| 63 | -# RAVEN_DSN: 'http://public:secret@example.com/1' | ||
| 64 | - | ||
| 65 | -### Colab proxied apps | ||
| 66 | -COLAB_APPS: | ||
| 67 | - colab.plugins.gitlab: | ||
| 68 | - upstream: 'http://localhost:8090/gitlab/' | ||
| 69 | - private_token: '' | ||
| 70 | -# colab.plugins.trac: | ||
| 71 | -# upstream: 'http://localhost:5000/trac/' | ||
| 72 | - | ||
| 73 | - |