initial application skeleton
This commit is contained in:
parent
b77dea31a9
commit
d13dbf8178
|
@ -0,0 +1,5 @@
|
|||
*.pyc
|
||||
local_settings.py
|
||||
/db.sqlite3
|
||||
/dist
|
||||
/chrono.egg-info
|
|
@ -0,0 +1,11 @@
|
|||
# locales
|
||||
recursive-include chrono/locale *.po *.mo
|
||||
|
||||
# static
|
||||
|
||||
# templates
|
||||
recursive-include combo/manager/templates *.html
|
||||
|
||||
include COPYING README
|
||||
include MANIFEST.in
|
||||
include VERSION
|
|
@ -0,0 +1,22 @@
|
|||
{% extends "gadjo/base.html" %}
|
||||
{% load staticfiles i18n %}
|
||||
|
||||
{% block page-title %}
|
||||
{% trans 'Agendas' as default_site_title %}
|
||||
{% firstof site_title default_site_title %}
|
||||
{% endblock %}
|
||||
{% block site-title %}
|
||||
{% trans 'Agendas' as default_site_title %}
|
||||
{% firstof site_title default_site_title %}
|
||||
{% endblock %}
|
||||
{% block footer %}Chrono — Copyright © Entr'ouvert{% endblock %}
|
||||
|
||||
{% block homepage-url %}
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'chrono-manager-homepage' %}">{% trans 'Agendas' %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block logout-url %}{% url 'auth_logout' %}{% endblock %}
|
|
@ -0,0 +1,22 @@
|
|||
{% extends "chrono/manager_base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans 'Agendas' %}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% if object_list %}
|
||||
<div class="objects-list">
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="big-msg-info">
|
||||
{% blocktrans %}
|
||||
This site doesn't have any agenda yet. Click on the "New" button in the top
|
||||
right of the page to add a first one.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,10 @@
|
|||
{% extends "chrono/manager_base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="{% trans 'Log in' %}" />
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -0,0 +1,24 @@
|
|||
# chrono - agendas system
|
||||
# Copyright (C) 2016 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = patterns('chrono.views',
|
||||
url(r'^$', views.homepage, name='chrono-manager-homepage'),
|
||||
url(r'^menu.json$', views.menu_json),
|
||||
)
|
|
@ -0,0 +1,44 @@
|
|||
# chrono - agendas system
|
||||
# Copyright (C) 2016 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.encoding import force_text
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
|
||||
class HomepageView(TemplateView):
|
||||
template_name = 'chrono/manager_home.html'
|
||||
|
||||
homepage = HomepageView.as_view()
|
||||
|
||||
|
||||
def menu_json(request):
|
||||
response = HttpResponse(content_type='application/json')
|
||||
label = _('Agendas')
|
||||
json_str = json.dumps([{'label': force_text(label),
|
||||
'slug': 'calendar',
|
||||
'url': request.build_absolute_uri(reverse('chrono-manager-homepage'))
|
||||
}])
|
||||
for variable in ('jsonpCallback', 'callback'):
|
||||
if variable in request.GET:
|
||||
json_str = '%s(%s);' % (request.GET[variable], json_str)
|
||||
break
|
||||
response.write(json_str)
|
||||
return response
|
|
@ -0,0 +1,146 @@
|
|||
# chrono - agendas system
|
||||
# Copyright (C) 2016 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Django settings file; it loads the default settings, and local settings
|
||||
(from a local_settings.py file, or a configuration file set in the
|
||||
COMBO_SETTINGS_FILE environment variable).
|
||||
|
||||
The local settings file should exist, at least to set a suitable SECRET_KEY,
|
||||
and to disable DEBUG mode in production.
|
||||
"""
|
||||
|
||||
import os
|
||||
from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS, STATICFILES_FINDERS
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = '1am-@xw1d%#+1f+4$ws4e3*k9+z&f4f9i#di4pt4@_%829(%bl'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
TEMPLATE_DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'gadjo',
|
||||
'chrono.manager',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
)
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS += (
|
||||
'django.core.context_processors.request',
|
||||
)
|
||||
|
||||
# Serve xstatic files, required for gadjo
|
||||
STATICFILES_FINDERS = tuple(STATICFILES_FINDERS) + ('gadjo.finders.XStaticFinder',)
|
||||
|
||||
ROOT_URLCONF = 'chrono.urls'
|
||||
|
||||
WSGI_APPLICATION = 'chrono.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.7/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'fr-fr'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
LOCALE_PATHS = (os.path.join(BASE_DIR, 'chrono', 'locale'), )
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.7/howto/static-files/
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
MEDIA_URL = '/media/'
|
||||
|
||||
# Authentication settings
|
||||
try:
|
||||
import mellon
|
||||
except ImportError:
|
||||
mellon = None
|
||||
|
||||
if mellon is not None:
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'mellon.backends.SAMLBackend',
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
)
|
||||
|
||||
LOGIN_URL = '/login/'
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
LOGOUT_URL = '/logout/'
|
||||
|
||||
MELLON_ATTRIBUTE_MAPPING = {
|
||||
'email': '{attributes[email][0]}',
|
||||
'first_name': '{attributes[first_name][0]}',
|
||||
'last_name': '{attributes[last_name][0]}',
|
||||
}
|
||||
|
||||
MELLON_SUPERUSER_MAPPING = {
|
||||
'is_superuser': 'true',
|
||||
}
|
||||
|
||||
MELLON_USERNAME_TEMPLATE = '{attributes[name_id_content]}'
|
||||
|
||||
MELLON_IDENTITY_PROVIDERS = []
|
||||
|
||||
local_settings_file = os.environ.get('CHRONO_SETTINGS_FILE',
|
||||
os.path.join(os.path.dirname(__file__), 'local_settings.py'))
|
||||
if os.path.exists(local_settings_file):
|
||||
execfile(local_settings_file)
|
|
@ -0,0 +1,42 @@
|
|||
# chrono - agendas system
|
||||
# Copyright (C) 2016 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import patterns, include, url
|
||||
|
||||
from .urls_utils import decorated_includes, manager_required
|
||||
|
||||
from .views import homepage, login, logout
|
||||
from .manager.urls import urlpatterns as chrono_manager_urls
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', homepage, name='home'),
|
||||
url(r'^manage/', decorated_includes(manager_required,
|
||||
include(chrono_manager_urls))),
|
||||
url(r'^logout/$', logout, name='auth_logout'),
|
||||
url(r'^login/$', login, name='auth_login'),
|
||||
)
|
||||
|
||||
if 'mellon' in settings.INSTALLED_APPS:
|
||||
urlpatterns += patterns('', url(r'^accounts/mellon/', include('mellon.urls')))
|
||||
|
||||
# static and media files
|
||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||
urlpatterns += staticfiles_urlpatterns()
|
||||
|
||||
from django.conf.urls.static import static
|
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
|
@ -0,0 +1,62 @@
|
|||
# chrono - agendas system
|
||||
# Copyright (C) 2016 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Decorating URL includes, <https://djangosnippets.org/snippets/2532/>
|
||||
|
||||
from django.contrib.auth.decorators import user_passes_test
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
|
||||
|
||||
class DecoratedURLPattern(RegexURLPattern):
|
||||
def resolve(self, *args, **kwargs):
|
||||
result = super(DecoratedURLPattern, self).resolve(*args, **kwargs)
|
||||
if result:
|
||||
result.func = self._decorate_with(result.func)
|
||||
return result
|
||||
|
||||
class DecoratedRegexURLResolver(RegexURLResolver):
|
||||
def resolve(self, *args, **kwargs):
|
||||
result = super(DecoratedRegexURLResolver, self).resolve(*args, **kwargs)
|
||||
if result:
|
||||
result.func = self._decorate_with(result.func)
|
||||
return result
|
||||
|
||||
def decorated_includes(func, includes, *args, **kwargs):
|
||||
urlconf_module, app_name, namespace = includes
|
||||
|
||||
for item in urlconf_module:
|
||||
if isinstance(item, RegexURLPattern):
|
||||
item.__class__ = DecoratedURLPattern
|
||||
item._decorate_with = func
|
||||
|
||||
elif isinstance(item, RegexURLResolver):
|
||||
item.__class__ = DecoratedRegexURLResolver
|
||||
item._decorate_with = func
|
||||
|
||||
return urlconf_module, app_name, namespace
|
||||
|
||||
def manager_required(function=None, login_url=None):
|
||||
def check_manager(user):
|
||||
if user and user.is_staff:
|
||||
return True
|
||||
if user and not user.is_anonymous():
|
||||
raise PermissionDenied()
|
||||
# As the last resort, show the login form
|
||||
return False
|
||||
actual_decorator = user_passes_test(check_manager, login_url=login_url)
|
||||
if function:
|
||||
return actual_decorator(function)
|
||||
return actual_decorator
|
|
@ -0,0 +1,49 @@
|
|||
# chrono - agendas system
|
||||
# Copyright (C) 2016 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import urllib
|
||||
|
||||
from django.contrib.auth import logout as auth_logout
|
||||
from django.contrib.auth import views as auth_views
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import resolve_url
|
||||
|
||||
try:
|
||||
from mellon.utils import get_idps
|
||||
except ImportError:
|
||||
get_idps = lambda: []
|
||||
|
||||
|
||||
def login(request, *args, **kwargs):
|
||||
if any(get_idps()):
|
||||
if not 'next' in request.GET:
|
||||
return HttpResponseRedirect(resolve_url('mellon_login'))
|
||||
return HttpResponseRedirect(resolve_url('mellon_login') + '?next='
|
||||
+ urllib.quote(request.GET.get('next')))
|
||||
return auth_views.login(request, *args, **kwargs)
|
||||
|
||||
def logout(request, next_page=None):
|
||||
if any(get_idps()):
|
||||
return HttpResponseRedirect(resolve_url('mellon_logout'))
|
||||
auth_logout(request)
|
||||
if next_page is not None:
|
||||
next_page = resolve_url(next_page)
|
||||
else:
|
||||
next_page = '/'
|
||||
return HttpResponseRedirect(next_page)
|
||||
|
||||
def homepage(request, *args, **kwargs):
|
||||
return HttpResponseRedirect(resolve_url('chrono-manager-homepage'))
|
|
@ -0,0 +1,14 @@
|
|||
"""
|
||||
WSGI config for chrono project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chrono.settings")
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
application = get_wsgi_application()
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chrono.settings")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
|
@ -0,0 +1,115 @@
|
|||
#! /usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from setuptools.command.install_lib import install_lib as _install_lib
|
||||
from distutils.command.build import build as _build
|
||||
from distutils.command.sdist import sdist
|
||||
from distutils.cmd import Command
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
class eo_sdist(sdist):
|
||||
def run(self):
|
||||
if os.path.exists('VERSION'):
|
||||
os.remove('VERSION')
|
||||
version = get_version()
|
||||
version_file = open('VERSION', 'w')
|
||||
version_file.write(version)
|
||||
version_file.close()
|
||||
sdist.run(self)
|
||||
if os.path.exists('VERSION'):
|
||||
os.remove('VERSION')
|
||||
|
||||
def get_version():
|
||||
if os.path.exists('VERSION'):
|
||||
version_file = open('VERSION', 'r')
|
||||
version = version_file.read()
|
||||
version_file.close()
|
||||
return version
|
||||
if os.path.exists('.git'):
|
||||
p = subprocess.Popen(['git', 'describe', '--dirty', '--match=v*'], stdout=subprocess.PIPE)
|
||||
result = p.communicate()[0]
|
||||
if p.returncode == 0:
|
||||
version = result.split()[0][1:]
|
||||
version = version.replace('-', '.')
|
||||
return version
|
||||
return '0'
|
||||
|
||||
def data_tree(destdir, sourcedir):
|
||||
extensions = ['.css', '.png', '.jpeg', '.jpg', '.gif', '.xml', '.html', '.js']
|
||||
r = []
|
||||
for root, dirs, files in os.walk(sourcedir):
|
||||
l = [os.path.join(root, x) for x in files if os.path.splitext(x)[1] in extensions]
|
||||
r.append((root.replace(sourcedir, destdir, 1), l))
|
||||
return r
|
||||
|
||||
class compile_translations(Command):
|
||||
description = 'compile message catalogs to MO files via django compilemessages'
|
||||
user_options = []
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
from django.core.management import call_command
|
||||
for path, dirs, files in os.walk('chrono'):
|
||||
if 'locale' not in dirs:
|
||||
continue
|
||||
curdir = os.getcwd()
|
||||
os.chdir(os.path.realpath(path))
|
||||
call_command('compilemessages')
|
||||
os.chdir(curdir)
|
||||
except ImportError:
|
||||
sys.stderr.write('!!! Please install Django >= 1.4 to build translations\n')
|
||||
|
||||
|
||||
class build(_build):
|
||||
sub_commands = [('compile_translations', None)] + _build.sub_commands
|
||||
|
||||
|
||||
class install_lib(_install_lib):
|
||||
def run(self):
|
||||
self.run_command('compile_translations')
|
||||
_install_lib.run(self)
|
||||
|
||||
|
||||
setup(
|
||||
name='chrono',
|
||||
version=get_version(),
|
||||
description='Agendas System',
|
||||
author='Frederic Peters',
|
||||
author_email='fpeters@entrouvert.com',
|
||||
packages=find_packages(),
|
||||
include_package_data=True,
|
||||
scripts=('manage.py',),
|
||||
url='https://dev.entrouvert.org/projects/chrono/',
|
||||
classifiers=[
|
||||
'Development Status :: 2 - Pre-Alpha',
|
||||
'Environment :: Web Environment',
|
||||
'Framework :: Django',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
],
|
||||
install_requires=['django>=1.7, <1.8',
|
||||
'gadjo',
|
||||
],
|
||||
zip_safe=False,
|
||||
cmdclass={
|
||||
'build': build,
|
||||
'compile_translations': compile_translations,
|
||||
'install_lib': install_lib,
|
||||
'sdist': eo_sdist,
|
||||
},
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
LANGUAGE_CODE = 'en-us'
|
|
@ -0,0 +1,40 @@
|
|||
from django.contrib.auth.models import User
|
||||
import pytest
|
||||
from webtest import TestApp
|
||||
|
||||
from chrono.wsgi import application
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
@pytest.fixture
|
||||
def admin_user():
|
||||
try:
|
||||
user = User.objects.get(username='admin')
|
||||
except User.DoesNotExist:
|
||||
user = User.objects.create_superuser('admin', email=None, password='admin')
|
||||
return user
|
||||
|
||||
def login(app, username='admin', password='admin'):
|
||||
login_page = app.get('/login/')
|
||||
login_form = login_page.forms[0]
|
||||
login_form['username'] = username
|
||||
login_form['password'] = password
|
||||
resp = login_form.submit()
|
||||
assert resp.status_int == 302
|
||||
return app
|
||||
|
||||
def test_unlogged_access():
|
||||
# connect while not being logged in
|
||||
app = TestApp(application)
|
||||
assert app.get('/manage/', status=302).location == 'http://localhost:80/login/?next=/manage/'
|
||||
|
||||
def test_access(admin_user):
|
||||
app = login(TestApp(application))
|
||||
resp = app.get('/manage/', status=200)
|
||||
assert '<h2>Agendas</h2>' in resp.body
|
||||
assert "This site doesn't have any agenda yet." in resp.body
|
||||
|
||||
def test_logout(admin_user):
|
||||
app = login(TestApp(application))
|
||||
app.get('/logout/')
|
||||
assert app.get('/manage/', status=302).location == 'http://localhost:80/login/?next=/manage/'
|
Loading…
Reference in New Issue