Profile edit and password change views. Better login/logout templates. Some polish...
authorŁukasz Rekucki <lrekucki@gmail.com>
Sat, 17 Apr 2010 21:59:47 +0000 (23:59 +0200)
committerŁukasz Rekucki <lrekucki@gmail.com>
Sun, 18 Apr 2010 10:54:14 +0000 (12:54 +0200)
24 files changed:
provider/cas_provider/models.py
provider/cas_provider/views.py
provider/setup.py
src/accounts/__init__.py [new file with mode: 0644]
src/accounts/forms.py [new file with mode: 0644]
src/accounts/locale/pl_PL/LC_MESSAGES/django.mo [new file with mode: 0644]
src/accounts/locale/pl_PL/LC_MESSAGES/django.po [new file with mode: 0644]
src/accounts/models.py [new file with mode: 0644]
src/accounts/templates/account/profile.html [new file with mode: 0644]
src/accounts/templatetags/__init__.py [new file with mode: 0644]
src/accounts/templatetags/gravatar.py [new file with mode: 0644]
src/accounts/tests.py [new file with mode: 0644]
src/accounts/urls.py [new file with mode: 0644]
src/accounts/views.py [new file with mode: 0644]
src/cas/manage.py [changed mode: 0644->0755]
src/cas/media/static/css/main.css [new file with mode: 0644]
src/cas/media/static/redmine_logo.png [new file with mode: 0644]
src/cas/settings.py
src/cas/templates/base.html [new file with mode: 0644]
src/cas/templates/cas/login.html
src/cas/templates/cas/logout.html
src/cas/templates/cas_base.html [deleted file]
src/cas/templates/horizontal_footer.html [new file with mode: 0644]
src/cas/urls.py

index 5d09912..6e7ebaf 100644 (file)
@@ -10,14 +10,14 @@ class ServiceTicket(models.Model):
     service = models.URLField(verify_exists=False)
     ticket = models.CharField(max_length=256)
     created = models.DateTimeField(auto_now=True)
     service = models.URLField(verify_exists=False)
     ticket = models.CharField(max_length=256)
     created = models.DateTimeField(auto_now=True)
-    
+
     def __unicode__(self):
         return "%s (%s) - %s" % (self.user.username, self.service, self.created)
     def __unicode__(self):
         return "%s (%s) - %s" % (self.user.username, self.service, self.created)
-        
+
 class LoginTicket(models.Model):
     ticket = models.CharField(max_length=32)
     created = models.DateTimeField(auto_now=True)
 class LoginTicket(models.Model):
     ticket = models.CharField(max_length=32)
     created = models.DateTimeField(auto_now=True)
-    
+
     def __unicode__(self):
         return "%s - %s" % (self.ticket, self.created)
 
     def __unicode__(self):
         return "%s - %s" % (self.ticket, self.created)
 
@@ -30,7 +30,7 @@ def auth_success_response(user):
     if settings.CAS_CUSTOM_ATTRIBUTES_CALLBACK:
         callback = get_callable(settings.CAS_CUSTOM_ATTRIBUTES_CALLBACK)
         attrs = callback(user)
     if settings.CAS_CUSTOM_ATTRIBUTES_CALLBACK:
         callback = get_callable(settings.CAS_CUSTOM_ATTRIBUTES_CALLBACK)
         attrs = callback(user)
-    
+
     response = ElementRoot(CAS + 'serviceResponse')
     auth_success = etree.SubElement(response, CAS + 'authenticationSuccess')
     username = etree.SubElement(auth_success, CAS + 'user')
     response = ElementRoot(CAS + 'serviceResponse')
     auth_success = etree.SubElement(response, CAS + 'authenticationSuccess')
     username = etree.SubElement(auth_success, CAS + 'user')
index 2733eb3..e2466b8 100644 (file)
@@ -4,6 +4,7 @@ from django.template import RequestContext
 from django.contrib.auth.models import User
 from django.contrib.auth import authenticate
 from django.contrib.auth import login as auth_login, logout as auth_logout
 from django.contrib.auth.models import User
 from django.contrib.auth import authenticate
 from django.contrib.auth import login as auth_login, logout as auth_logout
+from django.utils.translation import ugettext_lazy as _
 
 from cas_provider.forms import LoginForm
 from cas_provider.models import ServiceTicket, LoginTicket, auth_success_response
 
 from cas_provider.forms import LoginForm
 from cas_provider.models import ServiceTicket, LoginTicket, auth_success_response
@@ -15,14 +16,13 @@ try:
     from urlparse import parse_qs as url_parse_qs
 except ImportError:
     from cgi import parse_qs as url_parse_qs
     from urlparse import parse_qs as url_parse_qs
 except ImportError:
     from cgi import parse_qs as url_parse_qs
-     
 
 import logging
 
 import logging
-logger = logging.getLogger("fnp.cas.provider")
+logger = logging.getLogger("cas.provider")
 
 __all__ = ['login', 'validate', 'service_validate', 'logout']
 
 
 __all__ = ['login', 'validate', 'service_validate', 'logout']
 
-def _add_query_param(url, param, value):    
+def _add_query_param(url, param, value):
     parsed = urlparse.urlparse(url)
     query = url_parse_qs(parsed.query)
     query[param] = [unicode(value, 'utf-8')]
     parsed = urlparse.urlparse(url)
     query = url_parse_qs(parsed.query)
     query[param] = [unicode(value, 'utf-8')]
@@ -33,12 +33,10 @@ def _add_query_param(url, param, value):
     return parsed.geturl()
 
 
     return parsed.geturl()
 
 
-def login(request, template_name = 'cas/login.html', success_redirect = '/accounts/'):
+def login(request, template_name='cas/login.html', success_redirect='/accounts/'):
     service = request.GET.get('service', None)
     service = request.GET.get('service', None)
-    
+
     if request.user.is_authenticated():
     if request.user.is_authenticated():
-        logger.info("User %s passed auth, service is %s", request.user, service)
-        
         if service is not None:
             ticket = create_service_ticket(request.user, service)
             target = _add_query_param(service, 'ticket', ticket.ticket)
         if service is not None:
             ticket = create_service_ticket(request.user, service)
             target = _add_query_param(service, 'ticket', ticket.ticket)
@@ -47,53 +45,46 @@ def login(request, template_name = 'cas/login.html', success_redirect = '/accoun
         else:
             logger.info("Redirecting to default: %s", success_redirect)
             return HttpResponseRedirect(success_redirect)
         else:
             logger.info("Redirecting to default: %s", success_redirect)
             return HttpResponseRedirect(success_redirect)
-    
+
     errors = []
     if request.method == 'POST':
         username = request.POST.get('username', None)
         password = request.POST.get('password', None)
         service = request.POST.get('service', None)
         lt = request.POST.get('lt', None)
     errors = []
     if request.method == 'POST':
         username = request.POST.get('username', None)
         password = request.POST.get('password', None)
         service = request.POST.get('service', None)
         lt = request.POST.get('lt', None)
-        
+
         logger.debug("User %s logging in", username)
         logger.debug("User %s logging in", username)
-        logger.info("Login submit: serivce = %s, Lticket=%s",service, lt)                      
 
         try:
 
         try:
-            login_ticket = LoginTicket.objects.get(ticket = lt)
+            login_ticket = LoginTicket.objects.get(ticket=lt)
         except:
         except:
-            errors.append('Login ticket expired. Please try again.')
+            errors.append(_(u'Login ticket expired. Please try again.'))
         else:
             login_ticket.delete()
         else:
             login_ticket.delete()
-            logger.debug("Auth")
-            user = authenticate(username = username, password = password)
+            user = authenticate(username=username, password=password)
             if user is not None:
                 if user.is_active:
             if user is not None:
                 if user.is_active:
-                    logger.debug("AuthLogin")
                     auth_login(request, user)
                     auth_login(request, user)
-                    if service is not None:                        
+                    if service is not None:
                         ticket = create_service_ticket(user, service)
                         ticket = create_service_ticket(user, service)
-                        logger.info("Service=%s, ticket=%s", service, ticket)
                         target = _add_query_param(service, 'ticket', ticket.ticket)
                         target = _add_query_param(service, 'ticket', ticket.ticket)
-                        logger.info("Redirecting to %s", target)
                         return HttpResponseRedirect(target)
                     else:
                         return HttpResponseRedirect(target)
                     else:
-                        logger.info("Redirecting to default: %s", success_redirect)
                         return HttpResponseRedirect(success_redirect)
                 else:
                         return HttpResponseRedirect(success_redirect)
                 else:
-                    errors.append('This account is disabled.')
+                    errors.append(_(u'This account is disabled.'))
             else:
             else:
-                    errors.append('Incorrect username and/or password.')
-    
-    logger.debug("LOGIN GET, service = %s", service)
+                    errors.append(_(u'Incorrect username and/or password.'))
+
     form = LoginForm(service)
     form = LoginForm(service)
-    return render_to_response(template_name, {'form': form, 'errors': errors}, context_instance = RequestContext(request))
+    return render_to_response(template_name, {'form': form, 'errors': errors}, context_instance=RequestContext(request))
 
 def validate(request):
     service = request.GET.get('service', None)
     ticket_string = request.GET.get('ticket', None)
     if service is not None and ticket_string is not None:
         try:
 
 def validate(request):
     service = request.GET.get('service', None)
     ticket_string = request.GET.get('ticket', None)
     if service is not None and ticket_string is not None:
         try:
-            ticket = ServiceTicket.objects.get(ticket = ticket_string)
+            ticket = ServiceTicket.objects.get(ticket=ticket_string)
             username = ticket.user.username
             ticket.delete()
             return HttpResponse("yes\n%s\n" % username)
             username = ticket.user.username
             ticket.delete()
             return HttpResponse("yes\n%s\n" % username)
@@ -105,24 +96,24 @@ def service_validate(request):
     service = request.GET.get('service', None)
     ticket_string = request.GET.get('ticket', None)
     if service is None or ticket_string is None:
     service = request.GET.get('service', None)
     ticket_string = request.GET.get('ticket', None)
     if service is None or ticket_string is None:
-        return HttpResponse('''<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
+        return HttpResponse(r'''<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
             <cas:authenticationFailure code="INVALID_REQUEST">
                 Not all required parameters were sent.
             </cas:authenticationFailure>
             <cas:authenticationFailure code="INVALID_REQUEST">
                 Not all required parameters were sent.
             </cas:authenticationFailure>
-        </cas:serviceResponse>''', mimetype = 'text/xml')
+        </cas:serviceResponse>''', mimetype='application/xml')
 
     try:
 
     try:
-        ticket = ServiceTicket.objects.get(ticket = ticket_string)
+        ticket = ServiceTicket.objects.get(ticket=ticket_string)
         ticket.delete()
         ticket.delete()
-        return HttpResponse(auth_success_response(ticket.user), mimetype = 'text/xml')
+        return HttpResponse(auth_success_response(ticket.user), mimetype='text/xml')
     except ServiceTicket.DoesNotExist:
     except ServiceTicket.DoesNotExist:
-        return HttpResponse('''<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
+        return HttpResponse(r'''<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
             <cas:authenticationFailure code="INVALID_TICKET">
                 The provided ticket is invalid.
             </cas:authenticationFailure>
             <cas:authenticationFailure code="INVALID_TICKET">
                 The provided ticket is invalid.
             </cas:authenticationFailure>
-        </cas:serviceResponse>''', mimetype = 'text/xml')
+        </cas:serviceResponse>''', mimetype='application/xml')
 
 
-def logout(request, template_name = 'cas/logout.html'):
+def logout(request, template_name='cas/logout.html'):
     url = request.GET.get('url', None)
     auth_logout(request)
     url = request.GET.get('url', None)
     auth_logout(request)
-    return render_to_response(template_name, {'url': url}, context_instance = RequestContext(request))
+    return render_to_response(template_name, {'url': url}, context_instance=RequestContext(request))
index 489f8d2..8a67235 100644 (file)
@@ -1,5 +1,5 @@
 from setuptools import setup, find_packages
 from setuptools import setup, find_packages
+
 setup(
     name='django-cas-provider',
     version='0.2',
 setup(
     name='django-cas-provider',
     version='0.2',
diff --git a/src/accounts/__init__.py b/src/accounts/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/accounts/forms.py b/src/accounts/forms.py
new file mode 100644 (file)
index 0000000..5dcb842
--- /dev/null
@@ -0,0 +1,26 @@
+from django import forms
+from django.contrib.auth.models import User as DjangoUser
+from django.utils.translation import ugettext_lazy as _
+
+class UserBasicForm(forms.ModelForm):
+
+    class Meta:
+        model = DjangoUser
+        fields = ('first_name', 'last_name', 'email',)
+
+
+class UserPasswordForm(forms.Form):
+
+    new_password = forms.CharField(widget=forms.PasswordInput(),
+                        label=_("Your new password"))
+    verifier = forms.CharField(widget=forms.PasswordInput(),
+                        label=_("Repeated password"))
+
+    def clean(self):
+        if 'verifier' not in self.cleaned_data or 'new_password' not in self.cleaned_data:
+            return self.cleaned_data
+
+        if self.cleaned_data['verifier'] != self.cleaned_data['new_password']:
+            raise forms.ValidationError(_("Passwords do not match!"))
+
+        return self.cleaned_data
diff --git a/src/accounts/locale/pl_PL/LC_MESSAGES/django.mo b/src/accounts/locale/pl_PL/LC_MESSAGES/django.mo
new file mode 100644 (file)
index 0000000..59955ae
Binary files /dev/null and b/src/accounts/locale/pl_PL/LC_MESSAGES/django.mo differ
diff --git a/src/accounts/locale/pl_PL/LC_MESSAGES/django.po b/src/accounts/locale/pl_PL/LC_MESSAGES/django.po
new file mode 100644 (file)
index 0000000..8bb2e63
--- /dev/null
@@ -0,0 +1,49 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-18 10:48+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: forms.py:15
+msgid "Your new password"
+msgstr "Twoje nowe hasło"
+
+#: forms.py:17
+msgid "Repeated password"
+msgstr "Powtórzone hasło"
+
+#: forms.py:24
+msgid "Passwords do not match!"
+msgstr "Hasło i powtórzenie się nie zgadzają!"
+
+#: templates/account/profile.html:12
+msgid "Your profile"
+msgstr "Twój profil"
+
+#: templates/account/profile.html:16
+msgid "Change profile"
+msgstr "Zmień profil"
+
+#: templates/account/profile.html:20
+msgid "Password change"
+msgstr "Zmiana hasła"
+
+#: templates/account/profile.html:24
+msgid "Change password"
+msgstr "Zmień hasło"
+
+#: templates/account/profile.html:30
+msgid "Availble services"
+msgstr "Dostępne usługi"
diff --git a/src/accounts/models.py b/src/accounts/models.py
new file mode 100644 (file)
index 0000000..71a8362
--- /dev/null
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/src/accounts/templates/account/profile.html b/src/accounts/templates/account/profile.html
new file mode 100644 (file)
index 0000000..15e5eaf
--- /dev/null
@@ -0,0 +1,41 @@
+{% extends "base.html" %}
+{% load gravatar i18n %}
+
+{% block content %}
+       <div class="user_avatar">
+               <img src="{% gravatar request.user.email 120 %}">
+               <p><a href="{% url cas_provider.views.logout %}">{% trans "Logout" %}</a></p>
+       </div>
+
+       <div id="details">
+               {% if messages %}
+                       <p>{% for message in messages %}<span class="message">{{ message }}</span>{% endfor %}</p>
+       {% endif %}
+
+               <h2>{% trans "Your profile" %}</h2>
+    <form method="post" action="/accounts/change_profile">
+       <table>
+               {{ basic_form.as_table }}
+                       <tr><td colspan="2"><button type="submit">{% trans "Change profile" %}</button></td></tr>
+               </table>
+       </form>
+
+       <h2>{% trans "Password change" %}</h2>
+       <form method="post" action="/accounts/change_password">
+       <table>
+               {{ pass_form.as_table }}
+               <tr><td colspan="2"><button type="submit">{% trans "Change password" %}</button></td></tr>
+               </table>
+       </form>
+       </div>
+
+       <div id="services-list">
+               <h2>{% trans "Availble services" %}</h2>
+               <a href="http://redakcja.nowoczesnapolska.org.pl/">
+                       <img src="http://www.nowoczesnapolska.org.pl/wordpress/wp-content/uploads/2008/11/wl-logo-white.png">
+               </a>
+               <a href="http://redmine.nowoczesnapolska.org.pl/">
+                       <img src="{{ MEDIA_URL }}static/redmine_logo.png">
+               </a>
+       </div>
+{% endblock %}
\ No newline at end of file
diff --git a/src/accounts/templatetags/__init__.py b/src/accounts/templatetags/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/accounts/templatetags/gravatar.py b/src/accounts/templatetags/gravatar.py
new file mode 100644 (file)
index 0000000..a6db9aa
--- /dev/null
@@ -0,0 +1,44 @@
+from django import template
+from django.template.defaultfilters import stringfilter
+import hashlib
+import urllib
+
+register = template.Library()
+
+DEFAULTS = dict(size=80, rating='g', default='monsterid')
+
+class GravatarNode(template.Node):
+
+    def __init__(self, email, size):
+        self.email = template.Variable(email)
+        self.size = size
+
+    def render(self, context):
+        try:
+            email = self.email.resolve(context)
+        except template.VariableDoesNotExist:
+            return ''
+
+        gravatar_url = "http://www.gravatar.com/avatar/" + hashlib.md5(email).hexdigest() + "?"
+        gravatar_url += urllib.urlencode({'default': 'wavatar', 'size': str(self.size)})
+
+        return gravatar_url
+
+@register.tag
+def gravatar(parser, token):
+    try:
+        _tag_name, email, size = token.split_contents()
+    except ValueError:
+        raise template.TemplateSyntaxError, "%r tag requires two args" % token.contents.split()[0]
+
+    return GravatarNode(email, int(size))
+
+
+
+
+@register.filter(name='md5')
+@stringfilter
+def md5_hash(value):
+    h = hashlib.md5()
+    h.update(value)
+    return h.hexdigest()
diff --git a/src/accounts/tests.py b/src/accounts/tests.py
new file mode 100644 (file)
index 0000000..2247054
--- /dev/null
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
diff --git a/src/accounts/urls.py b/src/accounts/urls.py
new file mode 100644 (file)
index 0000000..86e81fa
--- /dev/null
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('accounts.views',
+    url(r'^$', 'account_profile'),
+    url(r'^change_profile$', 'account_change_basic_profile'),
+    url(r'^change_password$', 'account_change_password'),
+)
diff --git a/src/accounts/views.py b/src/accounts/views.py
new file mode 100644 (file)
index 0000000..b00dd20
--- /dev/null
@@ -0,0 +1,41 @@
+# Create your views here.
+from django import http
+from django.utils.translation import ugettext as __
+from django.views.generic.simple import direct_to_template
+from django.views.decorators.http import require_POST
+from django.contrib.auth.decorators import login_required
+from accounts.forms import UserBasicForm, UserPasswordForm
+
+@login_required
+def account_profile(request, basic_form=None, pass_form=None):
+    return direct_to_template(request, "account/profile.html", {
+        "basic_form": basic_form or UserBasicForm(instance=request.user),
+        "pass_form": pass_form or UserPasswordForm(),
+    })
+
+
+@require_POST
+@login_required
+def account_change_basic_profile(request):
+    form = UserBasicForm(request.POST, instance=request.user)
+
+    if form.is_valid():
+        form.save()
+        request.user.message_set.create(message=__("Profile has been changed."))
+        return http.HttpResponseRedirect('/accounts/')
+
+    return account_profile(request, basic_form=form)
+
+@require_POST
+@login_required
+def account_change_password(request):
+    form = UserPasswordForm(request.POST)
+
+    if form.is_valid():
+        request.user.set_password(form.cleaned_data['new_password'])
+        request.user.save()
+
+        request.user.message_set.create(message=__("Password has been changed."))
+        return http.HttpResponseRedirect('/accounts/')
+
+    return account_profile(request, pass_form=form)
old mode 100644 (file)
new mode 100755 (executable)
index 741587d..43896be
@@ -4,20 +4,20 @@ from django.core.management import execute_manager
 from os import path
 import sys
 
 from os import path
 import sys
 
-PROJECT_ROOT = path.realpath(path.dirname(__file__))  
-sys.path.insert(0, path.abspath(path.join(PROJECT_ROOT, "..", "provider")))                                 
-print sys.path
+PROJECT_ROOT = path.realpath(path.dirname(__file__))
+sys.path = [
+    path.abspath(path.join(PROJECT_ROOT, '..')),
+    path.abspath(path.join(PROJECT_ROOT, '..', '..', "provider")),
+] + sys.path
 
 try:
     import settings # Assumed to be in the same directory.
 except ImportError:
     import traceback
 
 try:
     import settings # Assumed to be in the same directory.
 except ImportError:
     import traceback
-    traceback.print_exc(file =sys.stderr)
+    traceback.print_exc(file=sys.stderr)
     sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
     sys.exit(1)
 
 if __name__ == "__main__":
     # Append lib and apps directories to PYTHONPATH
     sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
     sys.exit(1)
 
 if __name__ == "__main__":
     # Append lib and apps directories to PYTHONPATH
-    
-    
     execute_manager(settings)
     execute_manager(settings)
diff --git a/src/cas/media/static/css/main.css b/src/cas/media/static/css/main.css
new file mode 100644 (file)
index 0000000..b2c7b75
--- /dev/null
@@ -0,0 +1,58 @@
+body {
+       background-color: #eee;
+}
+
+#content_wrap {
+       background-color: #555;
+       margin: 0px 5%;
+       padding: 5px;
+}
+
+#content {
+       background-color: white;
+       border-radius: 10px;
+       margin: 5px;
+       padding: 0.2em 1em;
+       overflow: hidden;
+}
+
+#details {
+       margin: 1em;
+       float: left;
+       max-width: 75%;
+
+}
+
+#details form table th {
+       text-align: left;
+}
+
+#details form {
+       margin-bottom: 2em;
+}
+
+.user_avatar {
+       float: left;
+       margin: 1em;
+       max-width: 20%;
+       text-align: center;
+}
+
+.user_avatar img {
+       border: 1px solid black;
+}
+
+#services-list {
+       width: 250px;
+       float: right;
+       margin: 1em 2em;
+}
+
+#services-list img {
+       width: 250px;
+       margin: 1em 0em;
+}
+
+img.small_logo {
+       width: 250px;
+}
diff --git a/src/cas/media/static/redmine_logo.png b/src/cas/media/static/redmine_logo.png
new file mode 100644 (file)
index 0000000..bdfabb1
Binary files /dev/null and b/src/cas/media/static/redmine_logo.png differ
index acc5988..3ed14b0 100644 (file)
@@ -6,7 +6,9 @@ PROJECT_ROOT = path.realpath(path.dirname(__file__))
 DEBUG = True
 TEMPLATE_DEBUG = DEBUG
 
 DEBUG = True
 TEMPLATE_DEBUG = DEBUG
 
-ADMINS = []
+ADMINS = [
+    "lrekucki@gmail.com",
+]
 
 MANAGERS = ADMINS
 
 
 MANAGERS = ADMINS
 
@@ -37,13 +39,11 @@ USE_I18N = True
 # Absolute path to the directory that holds media.
 # Example: "/home/media/media.lawrence.com/"
 MEDIA_ROOT = PROJECT_ROOT + '/media/'
 # Absolute path to the directory that holds media.
 # Example: "/home/media/media.lawrence.com/"
 MEDIA_ROOT = PROJECT_ROOT + '/media/'
-STATIC_ROOT = PROJECT_ROOT + '/static/'
 
 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
 # trailing slash if there is a path component (optional in other cases).
 # Examples: "http://media.lawrence.com", "http://example.com/media/"
 MEDIA_URL = '/media/'
 
 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
 # trailing slash if there is a path component (optional in other cases).
 # Examples: "http://media.lawrence.com", "http://example.com/media/"
 MEDIA_URL = '/media/'
-STATIC_URL = '/static/'
 
 # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
 # trailing slash.
 
 # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
 # trailing slash.
@@ -61,6 +61,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
     "django.core.context_processors.auth",
     "django.core.context_processors.debug",
     "django.core.context_processors.i18n",
     "django.core.context_processors.auth",
     "django.core.context_processors.debug",
     "django.core.context_processors.i18n",
+    'django.core.context_processors.media',
     "django.core.context_processors.request",
 )
 
     "django.core.context_processors.request",
 )
 
@@ -75,7 +76,7 @@ MIDDLEWARE_CLASSES = (
 ROOT_URLCONF = 'cas.urls'
 
 TEMPLATE_DIRS = (
 ROOT_URLCONF = 'cas.urls'
 
 TEMPLATE_DIRS = (
-    PROJECT_ROOT + '/templates',    
+    PROJECT_ROOT + '/templates',
 )
 
 INSTALLED_APPS = (
 )
 
 INSTALLED_APPS = (
@@ -85,8 +86,9 @@ INSTALLED_APPS = (
     'django.contrib.sites',
     'django.contrib.admin',
     'django.contrib.admindocs',
     'django.contrib.sites',
     'django.contrib.admin',
     'django.contrib.admindocs',
-    
+
     'cas_provider',
     'cas_provider',
+    'accounts',
 )
 
 # django-cas-provider settings
 )
 
 # django-cas-provider settings
diff --git a/src/cas/templates/base.html b/src/cas/templates/base.html
new file mode 100644 (file)
index 0000000..1872c06
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+        <title>{% block title %}Fundacja Nowoczesna Polska - CAS{% block subtitle %}{% endblock subtitle %}{% endblock title%}</title>
+               <link rel="stylesheet" href="{{ MEDIA_URL }}static/css/main.css"/>
+        {% block extrahead %}
+        {% endblock %}
+    </head>
+    <body>
+    <div id="content_wrap"><div id="content">{% block content %} {% endblock %}</div></div>
+    </body>
+</html>
index e51cd8d..7a51cac 100644 (file)
@@ -1,21 +1,21 @@
-{% extends "cas_base.html" %}
+{% extends "base.html" %}
+{% load i18n %}
 
 {% block content %}
 
 {% block content %}
+
   <form action='.' method='post'>
   <form action='.' method='post'>
-    <fieldset>
-      <legend>Zaloguj się</legend>
-      {% if errors %}
-        <ul>
-            {% for error in errors %}
-                <li>{{ error|escape }}</li>
-            {% endfor %}
-        </ul>
-      {% endif %}
-      <table style="border: none;">
-        {{ form.as_table }}
-      </table>
-      <p><input type="submit" value="Login"/></p>
-    </fieldset>
+    <h1>{% trans "Login" %}</h1>
+
+       {% for error in errors %}
+           <p>{{ error }}</p>
+       {% endfor %}
+
+       <table>
+       {{ form.as_table }}
+       <tr><td><input type="submit" value="{% trans "Login me in" %}"/></td></tr>
+       </table>
+
   </form>
   </form>
+
+  {% include "horizontal_footer.html" %}
 {% endblock %}
 {% endblock %}
\ No newline at end of file
index d2a4009..ce3db21 100644 (file)
@@ -1,12 +1,21 @@
-{% extends "cas_base.html" %}
+{% extends "base.html" %}
+{% load i18n %}
+
 {% block title %}
 Logged out
 {% endblock %}
 {% block title %}
 Logged out
 {% endblock %}
+
 {% block content %}
 {% block content %}
-    <h3>Logged out</h3>
-    <p>You have successfully logged out. To ensure that you are logged out of all services, please close your browser.</p>
-    {% if url %}<p><a href="{{ url }}">Click here</a> to return to {{ url }}</p>{% endif %}
+    <h1>{% trans "Logged out" %}</h1>
+
+    <p>{% blocktrans %}You have successfully logged out. To ensure that you are logged out of all services, please close your browser.{% endblocktrans %}</p>
+
+       {% if url %}
+       <p>{% blocktrans %}You can return to service you came from: <a href="{{ url }}">{{ url }}</a>{% endblocktrans %}</p>
+       {% endif %}
+
+       {% url cas_provider.views.login as login_url %}
+    <p>{% blocktrans %}You can also <a href="{{ login_url }}">login again</a>{% endblocktrans %}</p>
+
+       {% include "horizontal_footer.html" %}
 {% endblock %}
\ No newline at end of file
 {% endblock %}
\ No newline at end of file
diff --git a/src/cas/templates/cas_base.html b/src/cas/templates/cas_base.html
deleted file mode 100644 (file)
index a49c721..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
-        <title>{% block title %}Fundacja Nowoczesna Polska - CAS{% block subtitle %}{% endblock subtitle %}{% endblock title%}</title>
-        {% block extrahead %}
-        {% endblock %}
-    </head>
-    <body id="{% block bodyid %}base{% endblock %}">
-    <div id="content">{% block content %} {% endblock %}</div>
-    </body>
-</html>
diff --git a/src/cas/templates/horizontal_footer.html b/src/cas/templates/horizontal_footer.html
new file mode 100644 (file)
index 0000000..4d6ab86
--- /dev/null
@@ -0,0 +1,9 @@
+<hr />
+<p>
+       <a href="http://redakcja.nowoczesnapolska.org.pl/" >
+               <img src="http://www.nowoczesnapolska.org.pl/wordpress/wp-content/uploads/2008/11/wl-logo-white.png" class="small_logo">
+       </a>
+       <a href="http://redmine.nowoczesnapolska.org.pl/">
+               <img src="{{ MEDIA_URL }}static/redmine_logo.png" class="small_logo">
+       </a>
+</p>
\ No newline at end of file
index f1aeca6..4a285fd 100644 (file)
@@ -1,17 +1,25 @@
 # -*- coding: utf-8 -*-
 from django.conf.urls.defaults import *
 # -*- coding: utf-8 -*-
 from django.conf.urls.defaults import *
+from django.views.generic.simple import redirect_to
 from django.contrib import admin
 from django.conf import settings
 
 admin.autodiscover()
 
 urlpatterns = patterns('',
 from django.contrib import admin
 from django.conf import settings
 
 admin.autodiscover()
 
 urlpatterns = patterns('',
+    url(r'^$', redirect_to, {'url': '/accounts/'}),
+
+    # django-cas-provider
+    url(r'^cas/', include('cas_provider.urls')),
+
     # Admin panel
     url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
     # Admin panel
     url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
-    url(r'^admin/(.*)', admin.site.root),
+    url(r'^admin/', include(admin.site.urls)),
 
 
-    # django-cas-provider
-    url(r'^', include('cas_provider.urls')),
+    url(r'^accounts/', include('accounts.urls')),
+
+    url(r'^%s(?P<path>.+)$' % settings.MEDIA_URL[1:], 'django.views.static.serve',
+        {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
 )
 
 
 )