Commit a2e34e57bdc5a61f9f47a4098b962d7e3245a8d3

Authored by Sergio Oliveira
2 parents e2a52f55 e2e2afd0

Merge remote-tracking branch 'origin/remove-core-deps'

Showing 67 changed files with 125 additions and 1686 deletions   Show diff stats
colab/accounts/auth.py
... ... @@ -1,7 +0,0 @@
1   -
2   -from django_browserid.auth import BrowserIDBackend
3   -
4   -
5   -class ColabBrowserIDBackend(BrowserIDBackend):
6   - def filter_users_by_email(self, email):
7   - return self.User.objects.filter(emails__address=email)
colab/accounts/forms.py
... ... @@ -16,8 +16,6 @@ from django.utils.text import capfirst
16 16 from django.utils.translation import ugettext_lazy as _
17 17 from django.utils.safestring import mark_safe
18 18  
19   -from conversejs.models import XMPPAccount
20   -
21 19  
22 20 from .utils.validators import validate_social_account
23 21 from .utils import mailman
... ... @@ -152,42 +150,6 @@ class ListsForm(forms.Form):
152 150 choices=LISTS_NAMES)
153 151  
154 152  
155   -class ChangeXMPPPasswordForm(forms.ModelForm):
156   - password1 = forms.CharField(label=_("Password"),
157   - widget=forms.PasswordInput)
158   - password2 = forms.CharField(label=_("Password confirmation"),
159   - widget=forms.PasswordInput,
160   - help_text=_(("Enter the same password as above"
161   - ", for verification.")))
162   -
163   - class Meta:
164   - model = XMPPAccount
165   - fields = ('password1', 'password2')
166   -
167   - def __init__(self, *args, **kwargs):
168   - super(ChangeXMPPPasswordForm, self).__init__(*args, **kwargs)
169   -
170   - for field_name, field in self.fields.items():
171   - # Adds form-control class to all form fields
172   - field.widget.attrs.update({'class': 'form-control'})
173   -
174   - def clean_password2(self):
175   - password1 = self.cleaned_data.get("password1")
176   - password2 = self.cleaned_data.get("password2")
177   - if password1 and password2 and password1 != password2:
178   - raise forms.ValidationError(
179   - _("Password mismatch"),
180   - code='password_mismatch',
181   - )
182   - return password2
183   -
184   - def save(self, commit=True):
185   - self.instance.password = self.cleaned_data['password2']
186   - if commit:
187   - self.instance.save()
188   - return self.instance
189   -
190   -
191 153 class UserCreationForm(UserForm):
192 154 """
193 155 A form that creates a user, with no privileges, from the given username and
... ...
colab/accounts/middleware.py
... ... @@ -1,24 +0,0 @@
1   -
2   -from django.shortcuts import redirect
3   -from django.conf import settings
4   -
5   -VIEW_NAMES_ALLOWED = ('signup', 'Logout')
6   -
7   -
8   -class UserRegisterMiddleware(object):
9   -
10   - def process_view(self, request, view_func, view_args, view_kwargs):
11   - if not settings.BROWSERID_ENABLED:
12   - return
13   -
14   - if request.is_ajax():
15   - return
16   -
17   - if not request.user.is_authenticated():
18   - return
19   -
20   - if not request.user.needs_update:
21   - return
22   -
23   - if view_func.__name__ not in VIEW_NAMES_ALLOWED:
24   - return redirect('signup')
colab/accounts/models.py
... ... @@ -47,13 +47,6 @@ class User(AbstractUser):
47 47  
48 48 objects = ColabUserManager()
49 49  
50   - def check_password(self, raw_password):
51   -
52   - if self.xmpp.exists() and raw_password == self.xmpp.first().password:
53   - return True
54   -
55   - return super(User, self).check_password(raw_password)
56   -
57 50 def get_absolute_url(self):
58 51 return reverse('user_profile', kwargs={'username': self.username})
59 52  
... ...
colab/accounts/search_indexes.py
1 1 # -*- coding: utf-8 -*-
2 2  
3 3 from haystack import indexes
4   -# from django.db.models import Count
5   -
6   -from colab.badger.utils import get_users_counters
7 4 from .models import User
8 5  
9 6  
... ... @@ -26,30 +23,13 @@ class UserIndex(indexes.SearchIndex, indexes.Indexable):
26 23 stored=False)
27 24 webpage = indexes.CharField(model_attr='webpage', null=True, stored=False)
28 25 message_count = indexes.IntegerField(stored=False)
29   - # changeset_count = indexes.IntegerField(stored=False)
30   - # ticket_count = indexes.IntegerField(stored=False)
31   - # wiki_count = indexes.IntegerField(stored=False)
32   - contribution_count = indexes.IntegerField(stored=False)
33 26  
34 27 def get_model(self):
35 28 return User
36 29  
37   - @property
38   - def badge_counters(self):
39   - if not hasattr(self, '_badge_counters'):
40   - self._badge_counters = get_users_counters()
41   - return self._badge_counters
42   -
43 30 def prepare(self, obj):
44 31 prepared_data = super(UserIndex, self).prepare(obj)
45 32  
46   - prepared_data['contribution_count'] = sum((
47   - self.prepared_data['message_count'],
48   - # self.prepared_data['changeset_count'],
49   - # self.prepared_data['ticket_count'],
50   - # self.prepared_data['wiki_count']
51   - ))
52   -
53 33 return prepared_data
54 34  
55 35 def prepare_description(self, obj):
... ... @@ -63,17 +43,5 @@ class UserIndex(indexes.SearchIndex, indexes.Indexable):
63 43 def prepare_type(self, obj):
64 44 return u'user'
65 45  
66   - def prepare_message_count(self, obj):
67   - return self.badge_counters[obj.username]['messages']
68   -
69   - # def prepare_changeset_count(self, obj):
70   - # return self.badge_counters[obj.username]['revisions']
71   -
72   - # def prepare_ticket_count(self, obj):
73   - # return self.badge_counters[obj.username]['tickets']
74   -
75   - # def prepare_wiki_count(self, obj):
76   - # return self.badge_counters[obj.username]['wikis']
77   -
78 46 def index_queryset(self, using=None):
79 47 return self.get_model().objects.filter(is_active=True)
... ...
colab/accounts/templates/accounts/change_password.html
... ... @@ -1,21 +0,0 @@
1   -{% extends "base.html" %}
2   -{% load i18n %}
3   -
4   -{% block main-content %}
5   -<form method="POST" role="form">
6   - {% csrf_token %}
7   - <div class="row">
8   - <h2>{% trans "Change XMPP Client and SVN Password" %}</h2>
9   - <div class="col-lg-4 col-md-4 col-sm-12 col-xs-12">
10   - {% for field in form %}
11   - <div class="form-group required{% if field.errors %} alert alert-danger has-error{% endif %}">
12   - <label for="{{ field.name }}" class="control-label">{{ field.label }}</label>
13   - {{ field }}
14   - {{ field.errors }}
15   - </div>
16   - {% endfor %}
17   - <button class="btn btn-primary">{% trans "Change Password" %}</button>
18   - </div>
19   - </div>
20   -</form>
21   -{% endblock %}
colab/accounts/templates/accounts/login.html
... ... @@ -1,12 +0,0 @@
1   -{% extends 'base.html' %}
2   -{% load browserid i18n %}
3   -
4   -{% block main-content %}
5   - <br><br><br>
6   - <div class="col-lg-12 text-center">
7   - <p>{% trans 'To login please click in the link below:'%}</p>
8   - {% trans 'Login' as login_text %}
9   - {% browserid_login text=login_text link_class='btn btn-primary btn-lg' %}
10   - </div>
11   - <br><br><br>
12   -{% endblock %}
colab/accounts/templates/accounts/user_update_form.html
... ... @@ -178,40 +178,19 @@ $(function() {
178 178 </div>
179 179 </div>
180 180 </div>
181   - {% if not BROWSERID_ENABLED %}
182   - <div class="col-lg-4 col-md-5 col-sm-12 col-xm-12">
183   - <div class="panel panel-default">
184   - <div class="panel-heading">
185   - <h3 class="panel-title">
186   - {% trans 'Change Password' %}
187   - </h3>
188   - </div>
189   - <div class="panel-body">
190   - <a href="{% url 'password_change' %}" class="btn btn-default btn-primary pull-right btn-block">{% trans "Change Password" %}</a>
191   - </div>
  181 + <div class="col-lg-4 col-md-5 col-sm-12 col-xm-12">
  182 + <div class="panel panel-default">
  183 + <div class="panel-heading">
  184 + <h3 class="panel-title">
  185 + {% trans 'Change Password' %}
  186 + </h3>
192 187 </div>
193   - </div>
194   - {% endif %}
195   - </div>
196   - {% if CONVERSEJS_ENABLED %}
197   - <div class="row">
198   - <div class="col-lg-12">
199   - <div class="panel panel-default">
200   - <div class="panel-heading">
201   - <h3 class="panel-title">
202   - {% trans 'Change Password' %}
203   - </h3>
204   - </div>
205   - <div class="panel-body">
206   - <div class="form-group">
207   - {% trans "This feature is available only for those who need to change the password for some reason as having an old user with the same username, forgot your password to commit, usage of other XMPP Client for connection. Usually, you won't need to change this password. Only change it if you are sure about what you are doing." %}
  188 + <div class="panel-body">
  189 + <a href="{% url 'password_change' %}" class="btn btn-default btn-primary pull-right btn-block">{% trans "Change Password" %}</a>
208 190 </div>
209   - <a href="{% url 'change_password' %}" class="btn btn-default pull-right"><span class="icon-warning-sign"></span> {% trans "Change Password" %}</a>
210 191 </div>
211 192 </div>
212   - </div>
213 193 </div>
214   - {% endif %}
215 194 <div class="row">
216 195 <div class="submit">
217 196 <button type="submit" class="btn btn-primary btn-lg btn-block">{% trans "Update" %}</button>
... ...
colab/accounts/tests/test_view_signup.py
... ... @@ -21,13 +21,6 @@ class TestSignUpView(TestCase):
21 21 "usertest@colab.com.br", "123colab4")
22 22 return user
23 23  
24   - def test_user_not_authenticated(self):
25   - with self.settings(BROWSERID_ENABLED=True):
26   - response = self.client.get("/account/register")
27   - self.assertEquals(302, response.status_code)
28   - url = "http://testserver/account/login"
29   - self.assertEquals(url, response.url)
30   -
31 24 def test_user_authenticated_and_unregistered(self):
32 25 self.client.login(username="usertestcolab", password="123colab4")
33 26 response = self.client.get("/account/register/")
... ...
colab/accounts/urls.py
... ... @@ -2,56 +2,44 @@
2 2 from django.conf import settings
3 3 from django.conf.urls import patterns, url
4 4  
5   -from .views import (UserProfileDetailView, UserProfileUpdateView, LoginView,
6   - ManageUserSubscriptionsView, ChangeXMPPPasswordView)
  5 +from .views import (UserProfileDetailView, UserProfileUpdateView,
  6 + ManageUserSubscriptionsView)
7 7  
8 8 from colab.accounts import views
9 9 from django.contrib.auth import views as auth_views
10 10  
11 11  
12   -BROWSERID_ENABLED = getattr(settings, 'BROWSERID_ENABLED', False)
  12 +urlpatterns = patterns('',
  13 + url(r'^login/?$', 'django.contrib.auth.views.login', name='login'),
13 14  
  15 + url(r'^logout/?$', 'django.contrib.auth.views.logout',
  16 + {'next_page':'home'}, name='logout'),
14 17  
15   -if not BROWSERID_ENABLED:
16   - urlpatterns = patterns('',
17   - url(r'^login/?$', 'django.contrib.auth.views.login', name='login'),
  18 + url(r'^password-reset-done/?$', 'colab.accounts.views.password_reset_done_custom',
  19 + name="password_reset_done"),
  20 + url(r'^password-reset-complete/$', 'colab.accounts.views.password_reset_complete_custom',
  21 + name="password_reset_complete"),
18 22  
19   - url(r'^logout/?$', 'django.contrib.auth.views.logout',
20   - {'next_page':'home'}, name='logout'),
  23 + url(r'^password-reset-confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
  24 + auth_views.password_reset_confirm,
  25 + {'template_name':'registration/password_reset_confirm_custom.html'},
  26 + name="password_reset_confirm"),
21 27  
22   - url(r'^password-reset-done/?$', 'colab.accounts.views.password_reset_done_custom',
23   - name="password_reset_done"),
24   - url(r'^password-reset-complete/$', 'colab.accounts.views.password_reset_complete_custom',
25   - name="password_reset_complete"),
  28 + url(r'^password-reset/?$', auth_views.password_reset,
  29 + {'template_name':'registration/password_reset_form_custom.html'},
  30 + name="password_reset"),
26 31  
27   - url(r'^password-reset-confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
28   - auth_views.password_reset_confirm,
29   - {'template_name':'registration/password_reset_confirm_custom.html'},
30   - name="password_reset_confirm"),
  32 + url(r'^change-password/?$',auth_views.password_change,
  33 + {'template_name':'registration/password_change_form_custom.html'},
  34 + name='password_change'),
31 35  
32   - url(r'^password-reset/?$', auth_views.password_reset,
33   - {'template_name':'registration/password_reset_form_custom.html'},
34   - name="password_reset"),
35   -
36   - url(r'^change-password/?$',auth_views.password_change,
37   - {'template_name':'registration/password_change_form_custom.html'},
38   - name='password_change'),
39   -
40   - url(r'^change-password-done/?$',
41   - 'colab.accounts.views.password_changed', name='password_change_done'),
42   - )
43   -else:
44   - urlpatterns = patterns('',
45   - url(r'^login/?$', LoginView.as_view(), name='login'),
46   - )
  36 + url(r'^change-password-done/?$',
  37 + 'colab.accounts.views.password_changed', name='password_change_done'),
  38 +)
47 39  
48 40 urlpatterns += patterns('',
49 41 url(r'^register/?$', 'colab.accounts.views.signup', name='signup'),
50 42  
51   -#FIXME Configure for XMPP
52   -# url(r'^change-password/$',
53   -# ChangeXMPPPasswordView.as_view(), name='change_password'),
54   -
55 43 url(r'^(?P<username>[\w@+.-]+)/?$',
56 44 UserProfileDetailView.as_view(), name='user_profile'),
57 45  
... ...
colab/accounts/views.py
... ... @@ -13,23 +13,16 @@ from django.core.exceptions import PermissionDenied
13 13 from django.views.generic import DetailView, UpdateView, TemplateView
14 14 from django.http import Http404
15 15  
16   -from conversejs import xmpp
17   -from conversejs.models import XMPPAccount
18   -
19 16 from colab.super_archives.models import (EmailAddress,
20 17 EmailAddressValidation)
21 18 from colab.search.utils import get_collaboration_data, get_visible_threads
22 19 from colab.accounts.models import User
23 20  
24 21 from .forms import (UserCreationForm, UserForm, ListsForm,
25   - UserUpdateForm, ChangeXMPPPasswordForm)
  22 + UserUpdateForm)
26 23 from .utils import mailman
27 24  
28 25  
29   -class LoginView(TemplateView):
30   - template_name = "accounts/login.html"
31   -
32   -
33 26 class UserProfileBaseMixin(object):
34 27 model = get_user_model()
35 28 slug_field = 'username'
... ... @@ -52,11 +45,6 @@ class UserProfileUpdateView(UserProfileBaseMixin, UpdateView):
52 45  
53 46 return obj
54 47  
55   - def get_context_data(self, **kwargs):
56   - context = super(UserProfileUpdateView, self).get_context_data(**kwargs)
57   - context['CONVERSEJS_ENABLED'] = getattr(settings, 'CONVERSEJS_ENABLED')
58   - return context
59   -
60 48  
61 49 class UserProfileDetailView(UserProfileBaseMixin, DetailView):
62 50 template_name = 'accounts/user_detail.html'
... ... @@ -94,37 +82,19 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView):
94 82  
95 83  
96 84 def signup(request):
97   - BROWSERID_ENABLED = getattr(settings, 'BROWSERID_ENABLED', False)
98   -
99   - if BROWSERID_ENABLED:
100   - # If the user is not authenticated, redirect to login
101   - if not request.user.is_authenticated():
102   - return redirect('login')
103 85  
104 86 if request.user.is_authenticated():
105   - # If the user doesn't need to update its main data,
106   - # redirect to its profile
107   - # It happens when user is created by browserid
108   - # and didn't set his/her main data
109 87 if not request.user.needs_update:
110 88 return redirect('user_profile', username=request.user.username)
111 89  
112   - # If the user is authenticated in Persona, but not in the Colab then he
113   - # will be redirected to the register form.
114 90 if request.method == 'GET':
115   - if BROWSERID_ENABLED:
116   - user_form = UserForm()
117   - else:
118   - user_form = UserCreationForm()
  91 + user_form = UserCreationForm()
119 92 lists_form = ListsForm()
120 93  
121 94 return render(request, 'accounts/user_create_form.html',
122 95 {'user_form': user_form, 'lists_form': lists_form})
123 96  
124   - if BROWSERID_ENABLED:
125   - user_form = UserForm(request.POST, instance=request.user)
126   - else:
127   - user_form = UserCreationForm(request.POST)
  97 + user_form = UserCreationForm(request.POST)
128 98 lists_form = ListsForm(request.POST)
129 99  
130 100 if not user_form.is_valid() or not lists_form.is_valid():
... ... @@ -134,12 +104,9 @@ def signup(request):
134 104 user = user_form.save(commit=False)
135 105 user.needs_update = False
136 106  
137   - if not BROWSERID_ENABLED:
138   - user.is_active = False
139   - user.save()
140   - EmailAddressValidation.create(user.email, user)
141   - else:
142   - user.save()
  107 + user.is_active = False
  108 + user.save()
  109 + EmailAddressValidation.create(user.email, user)
143 110  
144 111 # Check if the user's email have been used previously
145 112 # in the mainling lists to link the user to old messages
... ... @@ -208,50 +175,6 @@ class ManageUserSubscriptionsView(UserProfileBaseMixin, DetailView):
208 175 self).get_context_data(**context)
209 176  
210 177  
211   -class ChangeXMPPPasswordView(UpdateView):
212   - model = XMPPAccount
213   - form_class = ChangeXMPPPasswordForm
214   - fields = ['password', ]
215   - template_name = 'accounts/change_password.html'
216   -
217   - def get_success_url(self):
218   - return reverse('user_profile', kwargs={
219   - 'username': self.request.user.username
220   - })
221   -
222   - def get_object(self, queryset=None):
223   - obj = get_object_or_404(XMPPAccount, user=self.request.user.pk)
224   - self.old_password = obj.password
225   - return obj
226   -
227   - def form_valid(self, form):
228   - transaction.set_autocommit(False)
229   -
230   - response = super(ChangeXMPPPasswordView, self).form_valid(form)
231   -
232   - changed = xmpp.change_password(
233   - self.object.jid,
234   - self.old_password,
235   - form.cleaned_data['password1']
236   - )
237   -
238   - if not changed:
239   - messages.error(
240   - self.request,
241   - _(u'Could not change your password. Please, try again later.')
242   - )
243   - transaction.rollback()
244   - return response
245   - else:
246   - transaction.commit()
247   -
248   - messages.success(
249   - self.request,
250   - _("You've changed your password successfully!")
251   - )
252   - return response
253   -
254   -
255 178 def password_changed(request):
256 179 messages.success(request, _('Your password was changed.'))
257 180  
... ...
colab/badger/__init__.py
colab/badger/admin.py
... ... @@ -1,20 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -
3   -from django.contrib import admin
4   -
5   -from .forms import BadgeForm
6   -from .models import Badge, BadgeI18N
7   -
8   -
9   -class BadgeI18NInline(admin.TabularInline):
10   - model = BadgeI18N
11   -
12   -
13   -class BadgeAdmin(admin.ModelAdmin):
14   - form = BadgeForm
15   - inlines = [BadgeI18NInline, ]
16   - list_display = ['title', 'description', 'order']
17   - list_editable = ['order', ]
18   -
19   -
20   -admin.site.register(Badge, BadgeAdmin)
colab/badger/forms.py
... ... @@ -1,46 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -
3   -from django import forms
4   -from django.utils.translation import ugettext_lazy as _
5   -
6   -from PIL import Image
7   -
8   -from .models import Badge
9   -
10   -try:
11   - from cStringIO import StringIO
12   -except ImportError:
13   - from StringIO import StringIO
14   -
15   -
16   -class BadgeForm(forms.ModelForm):
17   - image = forms.ImageField(label=_(u'Image'), required=False)
18   -
19   - class Meta:
20   - model = Badge
21   - fields = (
22   - 'title', 'description', 'image', 'user_attr', 'comparison',
23   - 'value', 'awardees'
24   - )
25   -
26   - def clean_image(self):
27   - if not self.instance.pk and not self.cleaned_data['image']:
28   - raise forms.ValidationError(_(u'You must add an Image'))
29   - return self.cleaned_data['image']
30   -
31   - def save(self, commit=True):
32   -
33   - instance = super(BadgeForm, self).save(commit=False)
34   -
35   - if self.cleaned_data['image']:
36   - img = Image.open(self.cleaned_data['image'])
37   - img = img.resize((50, 50), Image.ANTIALIAS)
38   - f = StringIO()
39   - img.save(f, 'png')
40   - instance.image_base64 = f.getvalue().encode('base64')
41   - f.close()
42   -
43   - if commit:
44   - instance.save()
45   -
46   - return instance
colab/badger/management/__init__.py
colab/badger/management/commands/__init__.py
colab/badger/management/commands/rebuild_badges.py
... ... @@ -1,44 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -
3   -from django.core.management.base import BaseCommand
4   -from haystack.query import SearchQuerySet
5   -
6   -from colab.accounts.models import User
7   -from colab.badger.models import Badge
8   -
9   -
10   -class Command(BaseCommand):
11   - help = "Rebuild the user's badges."
12   -
13   - def handle(self, *args, **kwargs):
14   - for badge in Badge.objects.filter(type='auto'):
15   - if not badge.comparison:
16   - continue
17   - elif badge.comparison == 'biggest':
18   - order = u'-{}'.format(Badge.USER_ATTR_OPTS[badge.user_attr])
19   - sqs = SearchQuerySet().filter(type='user')
20   - user = sqs.order_by(order)[0]
21   - badge.awardees.remove(*list(badge.awardees.all()))
22   - badge.awardees.add(User.objects.get(pk=user.pk))
23   - continue
24   -
25   - comparison = u'__{}'.format(badge.comparison) if badge.comparison \
26   - is not 'equal' else u''
27   -
28   - key = u'{}{}'.format(
29   - Badge.USER_ATTR_OPTS[badge.user_attr],
30   - comparison
31   - )
32   - opts = {key: badge.value}
33   -
34   - sqs = SearchQuerySet().filter(
35   - type='user',
36   - **opts
37   - )
38   -
39   - # Remove all awardees to make sure that all of then
40   - # still accomplish the necessary to keep the badge
41   - badge.awardees.remove(*list(badge.awardees.all()))
42   -
43   - for user in sqs:
44   - badge.awardees.add(User.objects.get(pk=user.pk))
colab/badger/management/commands/update_badges.py
... ... @@ -1,45 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -
3   -from django.core.management.base import BaseCommand
4   -from haystack.query import SearchQuerySet
5   -
6   -from colab.accounts.models import User
7   -from colab.badger.models import Badge
8   -
9   -import logging
10   -
11   -
12   -class Command(BaseCommand):
13   - help = "Update the user's badges"
14   -
15   - def update_badges(self):
16   - for badge in Badge.objects.filter(type='auto'):
17   - if not badge.comparison:
18   - continue
19   - elif badge.comparison == 'biggest':
20   - order = u'-{}'.format(Badge.USER_ATTR_OPTS[badge.user_attr])
21   - sqs = SearchQuerySet().filter(type='user')
22   - user = sqs.order_by(order)[0]
23   - badge.awardees.add(User.objects.get(pk=user.pk))
24   - continue
25   -
26   - comparison = u'__{}'.format(badge.comparison) if badge.comparison \
27   - is not 'equal' else u''
28   -
29   - key = u'{}{}'.format(
30   - Badge.USER_ATTR_OPTS[badge.user_attr],
31   - comparison
32   - )
33   - opts = {key: badge.value}
34   -
35   - sqs = SearchQuerySet().filter(type='user', **opts)
36   -
37   - for user in sqs:
38   - badge.awardees.add(User.objects.get(pk=user.pk))
39   -
40   - def handle(self, *args, **kwargs):
41   - try:
42   - self.update_badges()
43   - except Exception as e:
44   - logging.exception(e)
45   - raise
colab/badger/migrations/0001_initial.py
... ... @@ -1,53 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -from __future__ import unicode_literals
3   -
4   -from django.db import models, migrations
5   -from django.conf import settings
6   -
7   -
8   -class Migration(migrations.Migration):
9   -
10   - dependencies = [
11   - migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12   - ]
13   -
14   - operations = [
15   - migrations.CreateModel(
16   - name='Badge',
17   - fields=[
18   - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
19   - ('title', models.CharField(max_length=200, null=True, verbose_name='Title', blank=True)),
20   - ('description', models.CharField(max_length=200, null=True, verbose_name='Description', blank=True)),
21   - ('image_base64', models.TextField(verbose_name='Image')),
22   - ('type', models.CharField(max_length=200, verbose_name='Type', choices=[('auto', 'Automatically'), ('manual', 'Manual')])),
23   - ('user_attr', models.CharField(blank=True, max_length=100, null=True, verbose_name='User attribute', choices=[('messages', 'Messages'), ('contributions', 'Contributions'), ('wikis', 'Wikis'), ('revisions', 'Revisions'), ('tickets', 'Ticket')])),
24   - ('comparison', models.CharField(blank=True, max_length=10, null=True, verbose_name='Comparison', choices=[('gte', 'Greater than or equal'), ('lte', 'less than or equal'), ('equal', 'Equal'), ('biggest', 'Biggest')])),
25   - ('value', models.PositiveSmallIntegerField(null=True, verbose_name='Value', blank=True)),
26   - ('order', models.PositiveSmallIntegerField(default=100, verbose_name='Order')),
27   - ('awardees', models.ManyToManyField(to=settings.AUTH_USER_MODEL, null=True, verbose_name='Awardees', blank=True)),
28   - ],
29   - options={
30   - 'ordering': ['order'],
31   - 'verbose_name': 'Badge',
32   - 'verbose_name_plural': 'Badges',
33   - },
34   - bases=(models.Model,),
35   - ),
36   - migrations.CreateModel(
37   - name='BadgeI18N',
38   - fields=[
39   - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
40   - ('i18n_language', models.CharField(max_length=10, verbose_name='language', choices=[(b'pt-br', 'Portuguese'), (b'es', 'Spanish')])),
41   - ('title', models.CharField(max_length=200, null=True, verbose_name='Title', blank=True)),
42   - ('description', models.CharField(max_length=200, null=True, verbose_name='Description', blank=True)),
43   - ('i18n_source', models.ForeignKey(related_name=b'translations', editable=False, to='badger.Badge', verbose_name='source')),
44   - ],
45   - options={
46   - },
47   - bases=(models.Model,),
48   - ),
49   - migrations.AlterUniqueTogether(
50   - name='badgei18n',
51   - unique_together=set([('i18n_source', 'i18n_language')]),
52   - ),
53   - ]
colab/badger/migrations/__init__.py
colab/badger/models.py
... ... @@ -1,83 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -
3   -from django.conf import settings
4   -from django.db import models
5   -from django.utils.translation import ugettext_lazy as _
6   -from i18n_model.models import I18nModel
7   -
8   -
9   -class Badge(models.Model):
10   - COMPARISON_CHOICES = (
11   - (u'gte', _(u'Greater than or equal')),
12   - (u'lte', _(u'less than or equal')),
13   - (u'equal', _(u'Equal')),
14   - (u'biggest', _(u'Biggest')),
15   - )
16   - TYPE_CHOICES = (
17   - (u'auto', _(u'Automatically')),
18   - (u'manual', _(u'Manual')),
19   - )
20   - USER_ATTR_CHOICES = (
21   - (u'messages', _(u'Messages')),
22   - (u'contributions', _(u'Contributions')),
23   - (u'wikis', _(u'Wikis')),
24   - (u'revisions', _(u'Revisions')),
25   - (u'tickets', _(u'Ticket')),
26   - )
27   - USER_ATTR_OPTS = {
28   - u'messages': u'message_count',
29   - u'revisions': u'changeset_count',
30   - u'tickets': u'ticket_count',
31   - u'wikis': u'wiki_count',
32   - u'contributions': u'contribution_count',
33   - }
34   -
35   - title = models.CharField(_(u'Title'), max_length=200, blank=True,
36   - null=True)
37   - description = models.CharField(_(u'Description'), max_length=200,
38   - blank=True, null=True)
39   - image_base64 = models.TextField(_(u'Image'))
40   - type = models.CharField(_(u'Type'), max_length=200, choices=TYPE_CHOICES)
41   - user_attr = models.CharField(
42   - _(u'User attribute'), max_length=100,
43   - choices=USER_ATTR_CHOICES,
44   - blank=True,
45   - null=True,
46   - )
47   - comparison = models.CharField(
48   - _(u'Comparison'),
49   - max_length=10,
50   - choices=COMPARISON_CHOICES,
51   - blank=True,
52   - null=True
53   - )
54   - value = models.PositiveSmallIntegerField(
55   - _(u'Value'),
56   - blank=True,
57   - null=True
58   - )
59   - awardees = models.ManyToManyField(
60   - settings.AUTH_USER_MODEL,
61   - verbose_name=_(u'Awardees'),
62   - blank=True,
63   - null=True
64   - )
65   - order = models.PositiveSmallIntegerField(_(u'Order'), default=100)
66   -
67   - class Meta:
68   - verbose_name = _(u'Badge')
69   - verbose_name_plural = _(u'Badges')
70   - ordering = ['order', ]
71   -
72   - def __unicode__(self):
73   - return u'{} ({}, {})'.format(
74   - self.title,
75   - self.get_user_attr_display(),
76   - self.get_type_display(),
77   - )
78   -
79   -
80   -class BadgeI18N(I18nModel):
81   - class Meta:
82   - source_model = Badge
83   - translation_fields = ('title', 'description')
colab/badger/tests.py
... ... @@ -1,4 +0,0 @@
1   -# uncomment the import if you really use.
2   -# from django.test import TestCase
3   -
4   -# Create your tests here.
colab/badger/utils.py
... ... @@ -1,41 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -
3   -from django.db.models import Count
4   -
5   -# from proxy.trac.models import (Ticket, Wiki)
6   -# from proxy.trac.models import (Revision, WikiCollabCount, TicketCollabCount)
7   -from colab.accounts.models import User
8   -
9   -
10   -# def get_wiki_counters():
11   -# return {author: count for author, count in
12   -# WikiCollabCount.objects.values_list()}
13   -
14   -
15   -# def get_revision_counters():
16   -# return {
17   -# author: count for author, count in Revision.objects.values_list(
18   -# 'author'
19   -# ).annotate(count=Count('author'))
20   -# }
21   -
22   -
23   -# def get_ticket_counters():
24   -# return {author: count for author, count in
25   -# TicketCollabCount.objects.values_list()}
26   -
27   -
28   -def get_users_counters():
29   - # wiki_counters = get_wiki_counters()
30   - # revision_counters = get_revision_counters()
31   - # ticket_counters = get_ticket_counters()
32   -
33   - users_counters = {}
34   - for user in User.objects.annotate(message_count=Count('emails__message')):
35   - users_counters[user.username] = {
36   - 'messages': user.message_count,
37   - # 'wikis': wiki_counters.get(user.username, 0),
38   - # 'revisions': revision_counters.get(user.username, 0),
39   - # 'tickets': ticket_counters.get(user.username, 0),
40   - }
41   - return users_counters
colab/badger/views.py
... ... @@ -1,4 +0,0 @@
1   -# uncomment the import if you really use.
2   -# from django.shortcuts import render
3   -
4   -# Create your views here.
colab/home/context_processors.py
... ... @@ -26,6 +26,3 @@ def ribbon(request):
26 26 }
27 27 }
28 28  
29   -
30   -def browserid_enabled(request):
31   - return {'BROWSERID_ENABLED': getattr(settings, 'BROWSERID_ENABLED', False)}
... ...
colab/locale/en/LC_MESSAGES/django.po
... ... @@ -126,12 +126,11 @@ msgstr &quot;&quot;
126 126 msgid "Register"
127 127 msgstr ""
128 128  
129   -#: accounts/templates/accounts/user_detail.html:8 badger/models.py:21
  129 +#: accounts/templates/accounts/user_detail.html:8
130 130 msgid "Messages"
131 131 msgstr ""
132 132  
133   -#: accounts/templates/accounts/user_detail.html:9 badger/models.py:22
134   -#: templates/home.html:7
  133 +#: accounts/templates/accounts/user_detail.html:9
135 134 msgid "Contributions"
136 135 msgstr ""
137 136  
... ... @@ -175,7 +174,7 @@ msgstr &quot;&quot;
175 174 msgid "Participation by Group"
176 175 msgstr ""
177 176  
178   -#: accounts/templates/accounts/user_detail.html:132 badger/models.py:69
  177 +#: accounts/templates/accounts/user_detail.html:132
179 178 msgid "Badges"
180 179 msgstr ""
181 180  
... ... @@ -291,87 +290,18 @@ msgstr &quot;&quot;
291 290 msgid "You've changed your password successfully!"
292 291 msgstr ""
293 292  
294   -#: badger/forms.py:19 badger/models.py:39 settings.py:160
  293 +#: settings.py:160
295 294 msgid "Image"
296 295 msgstr ""
297 296  
298   -#: badger/forms.py:30
299   -msgid "You must add an Image"
300   -msgstr ""
301   -
302   -#: badger/models.py:11
303   -msgid "Greater than or equal"
304   -msgstr ""
305   -
306   -#: badger/models.py:12
307   -msgid "less than or equal"
308   -msgstr ""
309   -
310   -#: badger/models.py:13
311   -msgid "Equal"
312   -msgstr ""
313   -
314   -#: badger/models.py:14
315   -msgid "Biggest"
316   -msgstr ""
317   -
318   -#: badger/models.py:17
319   -msgid "Automatically"
320   -msgstr ""
321   -
322   -#: badger/models.py:18
323   -msgid "Manual"
324   -msgstr ""
325   -
326   -#: badger/models.py:23
327   -msgid "Wikis"
328   -msgstr ""
329   -
330   -#: badger/models.py:24
331   -msgid "Revisions"
332   -msgstr ""
333   -
334   -#: badger/models.py:25
335 297 #: search/templates/search/includes/search_filters.html:122
336 298 msgid "Ticket"
337 299 msgstr ""
338 300  
339   -#: badger/models.py:35
340   -msgid "Title"
341   -msgstr ""
342   -
343   -#: badger/models.py:37
344   -msgid "Description"
345   -msgstr ""
346   -
347   -#: badger/models.py:40 search/forms.py:18
  301 +#: search/forms.py:18
348 302 msgid "Type"
349 303 msgstr ""
350 304  
351   -#: badger/models.py:42
352   -msgid "User attribute"
353   -msgstr ""
354   -
355   -#: badger/models.py:48
356   -msgid "Comparison"
357   -msgstr ""
358   -
359   -#: badger/models.py:55
360   -msgid "Value"
361   -msgstr ""
362   -
363   -#: badger/models.py:61
364   -msgid "Awardees"
365   -msgstr ""
366   -
367   -#: badger/models.py:65
368   -msgid "Order"
369   -msgstr ""
370   -
371   -#: badger/models.py:68
372   -msgid "Badge"
373   -msgstr ""
374   -
375 305 #: home/context_processors.py:15
376 306 msgid "Fork me!"
377 307 msgstr ""
... ...
colab/locale/pt_BR/LC_MESSAGES/django.po
... ... @@ -149,12 +149,11 @@ msgid &quot;Register&quot;
149 149 msgstr "Cadastre-se"
150 150  
151 151 #: colab/accounts/templates/accounts/user_detail.html:8
152   -#: colab/badger/models.py:21
153 152 msgid "Messages"
154 153 msgstr "Mensagens"
155 154  
156 155 #: colab/accounts/templates/accounts/user_detail.html:9
157   -#: colab/badger/models.py:22 colab/templates/home.html:7
  156 +#: colab/templates/home.html:7
158 157 msgid "Contributions"
159 158 msgstr "Contribuições"
160 159  
... ... @@ -199,7 +198,6 @@ msgid &quot;Participation by Group&quot;
199 198 msgstr "Participação por grupo"
200 199  
201 200 #: colab/accounts/templates/accounts/user_detail.html:132
202   -#: colab/badger/models.py:69
203 201 msgid "Badges"
204 202 msgstr "Medalhas"
205 203  
... ... @@ -365,87 +363,18 @@ msgstr &quot;Nos enviamos o email com as intruções para mudança de senha. Em breve
365 363 msgid "Your password has been set. You may go ahead and log in now."
366 364 msgstr "Sua senha foi redefinida. Você pode prosseguir e autenticar agora."
367 365  
368   -#: colab/badger/forms.py:19 colab/badger/models.py:39 colab/settings.py:160
  366 +#: colab/settings.py:160
369 367 msgid "Image"
370 368 msgstr "Imagem"
371 369  
372   -#: colab/badger/forms.py:30
373   -msgid "You must add an Image"
374   -msgstr "Você deve adicionar uma imagem"
375   -
376   -#: colab/badger/models.py:11
377   -msgid "Greater than or equal"
378   -msgstr "Maior que ou igual"
379   -
380   -#: colab/badger/models.py:12
381   -msgid "less than or equal"
382   -msgstr "menor que ou igual"
383   -
384   -#: colab/badger/models.py:13
385   -msgid "Equal"
386   -msgstr "Igual"
387   -
388   -#: colab/badger/models.py:14
389   -msgid "Biggest"
390   -msgstr "Maior"
391   -
392   -#: colab/badger/models.py:17
393   -msgid "Automatically"
394   -msgstr "Automaticamente"
395   -
396   -#: colab/badger/models.py:18
397   -msgid "Manual"
398   -msgstr "Manual"
399   -
400   -#: colab/badger/models.py:23
401   -msgid "Wikis"
402   -msgstr "Wikis"
403   -
404   -#: colab/badger/models.py:24
405   -msgid "Revisions"
406   -msgstr "Conjunto de mudanças"
407   -
408   -#: colab/badger/models.py:25
409 370 #: colab/search/templates/search/includes/search_filters.html:122
410 371 msgid "Ticket"
411 372 msgstr "Tíquetes"
412 373  
413   -#: colab/badger/models.py:35
414   -msgid "Title"
415   -msgstr "Título"
416   -
417   -#: colab/badger/models.py:37
418   -msgid "Description"
419   -msgstr "Descrição"
420   -
421   -#: colab/badger/models.py:40 colab/search/forms.py:18
  374 +#: colab/search/forms.py:18
422 375 msgid "Type"
423 376 msgstr "Tipo"
424 377  
425   -#: colab/badger/models.py:42
426   -msgid "User attribute"
427   -msgstr "Atributo do usuário"
428   -
429   -#: colab/badger/models.py:48
430   -msgid "Comparison"
431   -msgstr "Comparação"
432   -
433   -#: colab/badger/models.py:55
434   -msgid "Value"
435   -msgstr "Valor"
436   -
437   -#: colab/badger/models.py:61
438   -msgid "Awardees"
439   -msgstr "Premiados"
440   -
441   -#: colab/badger/models.py:65
442   -msgid "Order"
443   -msgstr "Ordem"
444   -
445   -#: colab/badger/models.py:68
446   -msgid "Badge"
447   -msgstr "Medalha"
448   -
449 378 #: colab/home/context_processors.py:20
450 379 msgid "Fork me!"
451 380 msgstr "Fork me!"
... ...
colab/management/initconfig.py
... ... @@ -21,15 +21,6 @@ EMAIL_SUBJECT_PREFIX = &#39;[colab]&#39;
21 21  
22 22 SECRET_KEY = '{secret_key}'
23 23  
24   -# Must use it without trailing slash
25   -SITE_URL = 'http://localhost:8000'
26   -BROWSERID_AUDIENCES = [
27   - 'http://localhost:8000',
28   -# 'http://example.com',
29   -# 'https://example.org',
30   -# 'http://example.net',
31   -]
32   -
33 24 ALLOWED_HOSTS = [
34 25 'localhost',
35 26 # 'example.com',
... ... @@ -37,18 +28,9 @@ ALLOWED_HOSTS = [
37 28 # 'example.net',
38 29 ]
39 30  
40   -### Uncomment to enable Broswer ID protocol for authentication
41   -# BROWSERID_ENABLED = True
42   -
43 31 ### Uncomment to enable social networks fields profile
44 32 # SOCIAL_NETWORK_ENABLED = True
45 33  
46   -### Uncomment to enable Converse.js
47   -# CONVERSEJS_ENABLED = True
48   -
49   -### Uncomment to enable auto-registration
50   -# CONVERSEJS_AUTO_REGISTER = 'xmpp.example.com'
51   -
52 34 ## Database settings
53 35 DATABASES = {{
54 36 'default': {{
... ...
colab/plugins/jenkins/__init__.py
... ... @@ -1,3 +0,0 @@
1   -
2   -
3   -default_app_config = 'colab.plugins.jenkins.apps.ProxyJenkinsAppConfig'
colab/plugins/jenkins/apps.py
... ... @@ -1,16 +0,0 @@
1   -
2   -from django.utils.translation import ugettext_lazy as _
3   -
4   -from ..utils.apps import ColabProxiedAppConfig
5   -
6   -
7   -class ProxyJenkinsAppConfig(ColabProxiedAppConfig):
8   - name = 'colab.plugins.jenkins'
9   - verbose_name = 'Jenkins Proxy'
10   -
11   - menu = {
12   - 'title': _('Code'),
13   - 'links': (
14   - (_('Continuos Integration'), ''),
15   - ),
16   - }
colab/plugins/jenkins/data_api.py
... ... @@ -1,7 +0,0 @@
1   -from colab.plugins.utils.proxy_data_api import ProxyDataAPI
2   -
3   -
4   -class JenkinsDataAPI(ProxyDataAPI):
5   -
6   - def fetch_data(self):
7   - pass
colab/plugins/jenkins/diazo.xml
... ... @@ -1,27 +0,0 @@
1   -<rules
2   - xmlns="http://namespaces.plone.org/diazo"
3   - xmlns:css="http://namespaces.plone.org/diazo/css"
4   - xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
5   -
6   - <before theme-children="/html/head" content-children="/html/head" />
7   - <before css:theme-children="#main-content" css:content-children="body" />
8   -
9   - <merge attributes="class" css:theme="body" css:content="body" />
10   - <drop css:content="#top-panel" />
11   -
12   - <drop attributes="style" css:content="#main-table" />
13   -
14   - <after theme-children="/html/head">
15   - <script>jQuery.noConflict();</script>
16   - <style>
17   - #breadcrumbs {
18   - border: 0 !important;
19   - }
20   -
21   - #right-top-nav {
22   - margin-right: 5em !important;
23   - }
24   - </style>
25   - </after>
26   -
27   -</rules>
colab/plugins/jenkins/models.py
colab/plugins/jenkins/urls.py
... ... @@ -1,10 +0,0 @@
1   -
2   -from django.conf.urls import patterns, url
3   -
4   -from .views import JenkinsProxyView
5   -
6   -
7   -urlpatterns = patterns('',
8   - # Jenkins URLs
9   - url(r'^(?P<path>.*)$', JenkinsProxyView.as_view(), name='jenkins'),
10   -)
colab/plugins/jenkins/views.py
... ... @@ -1,6 +0,0 @@
1   -
2   -from ..utils.views import ColabProxyView
3   -
4   -
5   -class JenkinsProxyView(ColabProxyView):
6   - app_label = 'jenkins'
colab/plugins/redmine/__init__.py
... ... @@ -1,3 +0,0 @@
1   -
2   -
3   -default_app_config = 'colab.plugins.redmine.apps.ProxyRedmineAppConfig'
colab/plugins/redmine/apps.py
... ... @@ -1,7 +0,0 @@
1   -
2   -from ..utils.apps import ColabProxiedAppConfig
3   -
4   -
5   -class ProxyRedmineAppConfig(ColabProxiedAppConfig):
6   - name = 'colab.plugins.redmine'
7   - verbose_name = 'Redmine Proxy'
colab/plugins/redmine/data_api.py
... ... @@ -1,7 +0,0 @@
1   -from colab.plugins.utils.proxy_data_api import ProxyDataAPI
2   -
3   -
4   -class RedmineDataAPI(ProxyDataAPI):
5   -
6   - def fetch_data(self):
7   - pass
colab/plugins/redmine/diazo.xml
... ... @@ -1,11 +0,0 @@
1   -<rules
2   - xmlns="http://namespaces.plone.org/diazo"
3   - xmlns:css="http://namespaces.plone.org/diazo/css"
4   - xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
5   -
6   - <before theme-children="/html/head" content-children="/html/head" />
7   - <before css:theme-children="#main-content" css:content-children="body" />
8   -
9   - <merge attributes="class" css:theme="body" css:content="body" />
10   - <drop css:content="#top-panel" />
11   -</rules>
colab/plugins/redmine/models.py
colab/plugins/redmine/urls.py
... ... @@ -1,10 +0,0 @@
1   -
2   -from django.conf.urls import patterns, url
3   -
4   -from .views import RedmineProxyView
5   -
6   -
7   -urlpatterns = patterns('',
8   - # RedmineProxyView URLs
9   - url(r'^redmine/(?P<path>.*)$', RedmineProxyView.as_view()),
10   -)
colab/plugins/redmine/views.py
... ... @@ -1,7 +0,0 @@
1   -
2   -from ..utils.views import ColabProxyView
3   -
4   -
5   -class RedmineProxyView(ColabProxyView):
6   - app_label = 'redmine'
7   - diazo_theme_template = 'proxy/redmine.html'
colab/plugins/trac/__init__.py
... ... @@ -1,3 +0,0 @@
1   -
2   -
3   -default_app_config = 'colab.plugins.trac.apps.ProxyTracAppConfig'
colab/plugins/trac/admin.py
... ... @@ -1 +0,0 @@
1   -# from . import signals
colab/plugins/trac/apps.py
... ... @@ -1,24 +0,0 @@
1   -
2   -from django.utils.translation import ugettext_lazy as _
3   -
4   -from ..utils.apps import ColabProxiedAppConfig
5   -
6   -
7   -class ProxyTracAppConfig(ColabProxiedAppConfig):
8   - name = 'colab.plugins.trac'
9   - verbose_name = 'Trac Proxy'
10   -
11   - menu = {
12   - 'title': _('Code'),
13   - 'links': (
14   - (_('Timeline'), 'timeline'),
15   - (_('Wiki'), 'wiki'),
16   - (_('View Tickets'), 'report'),
17   - (_('Roadmap'), 'roadmap'),
18   - (_('Browse Source'), 'browser'),
19   - ),
20   - 'auth_links': (
21   - (_('New Ticket'), 'newticket'),
22   - (_('New Wiki Page'), 'wiki/WikiNewPage'),
23   - ),
24   - }
colab/plugins/trac/data_api.py
... ... @@ -1,7 +0,0 @@
1   -from colab.plugins.utils.proxy_data_api import ProxyDataAPI
2   -
3   -
4   -class TracDataAPI(ProxyDataAPI):
5   -
6   - def fetch_data(self):
7   - pass
colab/plugins/trac/diazo.xml
... ... @@ -1,45 +0,0 @@
1   -<rules
2   - xmlns="http://namespaces.plone.org/diazo"
3   - xmlns:css="http://namespaces.plone.org/diazo/css"
4   - xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
5   -
6   - <replace css:theme="#trac-css" content="//head/link" />
7   - <replace css:theme="#trac-js" content="//head/script" />
8   - <replace theme="//head/title" content="//head/title" />
9   -
10   - <before css:theme-children="#main-content" css:content="#main" />
11   -
12   - <after theme-children="/html/head">
13   - <style>
14   - .navbar .nav ul { font-size: 14px; text-align: left; padding: 5px 0; }
15   - .navbar .nav li { border: 0; padding: 0; white-space: normal; display: list-item;}
16   - :link:not(.btn),
17   - :visited:not(.btn) { border: 0; color: rgb(66, 139, 202); }
18   - h1 { font-size: 24px; margin: 0.15em 1em 0.5em 0px; }
19   - h2 { font-size: 20px }
20   - h3 { font-size: 16px }
21   - h4 { font-size: 14px }
22   - input[type="checkbox"], input[type="radio"] { margin: 0 4px; }
23   - fieldset { padding: 1em; margin: 1em 0; border: 1px solid rgb(215, 215, 215); }
24   - label { font-weight: 400; }
25   - legend { margin-bottom: 0; width: auto; }
26   - input, textarea, select { margin: 2px; }
27   -
28   - .wikitoolbar,
29   - .wikitoolbar:before,
30   - .wikitoolbar:after {
31   - -moz-box-sizing: content-box;
32   - -webkit-box-sizing: content-box;
33   - }
34   - .wikitoolbar :link,
35   - .wikitoolbar :visited {
36   - border-width: 1px;
37   - border-style: solid;
38   - border-color: #fff #fff #fff #ccc;
39   - -moz-box-sizing: content-box;
40   - -webkit-box-sizing: content-box;
41   - }
42   - </style>
43   - </after>
44   -
45   -</rules>
colab/plugins/trac/migrations/0001_initial.py
... ... @@ -1,141 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -from __future__ import unicode_literals
3   -
4   -from django.db import models, migrations, connections
5   -
6   -
7   -def create_views(apps, schema_editor):
8   - connection = connections['trac']
9   -
10   - cursor = connection.cursor()
11   -
12   - # revision_view
13   - cursor.execute('''
14   - CREATE OR REPLACE VIEW revision_view AS SELECT
15   - revision.rev,
16   - revision.author,
17   - revision.message,
18   - repository.value AS repository_name,
19   - TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created,
20   - CONCAT(revision.repos, '-', revision.rev) AS key
21   - FROM revision
22   - INNER JOIN repository ON(
23   - repository.id = revision.repos
24   - AND repository.name = 'name'
25   - AND repository.value != ''
26   - );
27   - ''')
28   -
29   - # attachment_view
30   - cursor.execute('''
31   - CREATE OR REPLACE VIEW attachment_view AS SELECT
32   - CONCAT(attachment.type, '/' , attachment.id, '/', attachment.filename) AS url,
33   - attachment.type AS used_by,
34   - attachment.filename AS filename,
35   - attachment.id as attach_id,
36   - (SELECT LOWER(SUBSTRING(attachment.filename FROM '\.(\w+)$'))) AS mimetype,
37   - attachment.author AS author,
38   - attachment.description AS description,
39   - attachment.size AS size,
40   - TIMESTAMP WITH TIME ZONE 'epoch' + (attachment.time/1000000)* INTERVAL '1s' AS created
41   - FROM attachment;
42   - ''')
43   -
44   - # wiki_view
45   - cursor.execute('''
46   - CREATE OR REPLACE VIEW wiki_view AS SELECT
47   - wiki.name AS name,
48   - (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name
49   - AND wiki2.version = MAX(wiki.version)) AS wiki_text,
50   - (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name
51   - AND wiki3.version = 1) AS author,
52   - string_agg(DISTINCT wiki.author, ', ') AS collaborators,
53   - TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,
54   - TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified,
55   - (SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name
56   - AND wiki4.version = MAX(wiki.version)) AS modified_by
57   - FROM wiki
58   - GROUP BY wiki.name;
59   - ''')
60   -
61   - # ticket_view
62   - cursor.execute('''
63   - CREATE OR REPLACE VIEW ticket_view AS SELECT
64   - ticket.id AS id,
65   - ticket.summary as summary,
66   - ticket.description as description,
67   - ticket.milestone as milestone,
68   - ticket.priority as priority,
69   - ticket.component as component,
70   - ticket.version as version,
71   - ticket.severity as severity,
72   - ticket.reporter as reporter,
73   - ticket.reporter as author,
74   - ticket.status as status,
75   - ticket.keywords as keywords,
76   - (SELECT
77   - string_agg(DISTINCT ticket_change.author, ', ')
78   - FROM ticket_change WHERE ticket_change.ticket = ticket.id
79   - GROUP BY ticket_change.ticket) as collaborators,
80   - TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,
81   - TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified,
82   - (SELECT
83   - ticket_change.author
84   - FROM ticket_change
85   - WHERE ticket_change.ticket = ticket.id
86   - AND ticket_change.time = ticket.changetime
87   - LIMIT 1
88   - ) AS modified_by
89   - FROM ticket;
90   - ''')
91   -
92   - # ticket_collab_count_view
93   - cursor.execute('''
94   - CREATE OR REPLACE VIEW ticket_collab_count_view AS
95   - SELECT
96   - COALESCE (t1.author, t2.author) as author,
97   - (COALESCE(t1.count, 0) + COALESCE(t2.count, 0)) as count
98   - FROM
99   - (SELECT author, count(*) as count
100   - FROM ticket_change
101   - GROUP BY author
102   - ORDER BY author
103   - ) AS t1
104   - FULL OUTER JOIN
105   - (SELECT reporter as author, count(*) as count
106   - FROM ticket
107   - GROUP BY reporter
108   - ORDER BY reporter
109   - ) AS t2
110   - ON t1.author = t2.author;
111   - ''')
112   -
113   - # wiki_collab_count_view
114   - cursor.execute('''
115   - CREATE OR REPLACE VIEW wiki_collab_count_view AS
116   - SELECT author, count(*) from wiki GROUP BY author;
117   - ''')
118   -
119   -
120   -def drop_views(apps, schema_editor):
121   - connection = connections['trac']
122   -
123   - cursor = connection.cursor()
124   - cursor.execute('''
125   - DROP VIEW IF EXISTS revision_view;
126   - DROP VIEW IF EXISTS ticket_view;
127   - DROP VIEW IF EXISTS wiki_view;
128   - DROP VIEW IF EXISTS ticket_collab_count_view;
129   - DROP VIEW IF EXISTS wiki_collab_count_view;
130   - DROP VIEW IF EXISTS attachment_view;
131   - ''')
132   -
133   -
134   -class Migration(migrations.Migration):
135   -
136   - dependencies = [
137   - ]
138   -
139   - operations = [
140   - migrations.RunPython(code=create_views, reverse_code=drop_views)
141   - ]
colab/plugins/trac/migrations/__init__.py
colab/plugins/trac/models.py
... ... @@ -1,133 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -import os
3   -import urllib2
4   -
5   -from django.db import models
6   -from django.conf import settings
7   -
8   -from hitcounter.models import HitCounterModelMixin
9   -
10   -from colab.accounts.models import User
11   -
12   -
13   -class Attachment(models.Model, HitCounterModelMixin):
14   - url = models.TextField(primary_key=True)
15   - attach_id = models.TextField()
16   - used_by = models.TextField()
17   - filename = models.TextField()
18   - author = models.TextField(blank=True)
19   - description = models.TextField(blank=True)
20   - created = models.DateTimeField(blank=True)
21   - mimetype = models.TextField(blank=True)
22   - size = models.IntegerField(blank=True)
23   -
24   - class Meta:
25   - managed = False
26   - db_table = 'attachment_view'
27   -
28   - @property
29   - def filepath(self):
30   - return os.path.join(
31   - settings.ATTACHMENTS_FOLDER_PATH,
32   - self.used_by,
33   - self.attach_id,
34   - urllib2.quote(self.filename.encode('utf8'))
35   - )
36   -
37   - def get_absolute_url(self):
38   - return u'/raw-attachment/{}'.format(self.url)
39   -
40   - def get_author(self):
41   - try:
42   - return User.objects.get(username=self.author)
43   - except User.DoesNotExist:
44   - return None
45   -
46   -
47   -class Revision(models.Model, HitCounterModelMixin):
48   - key = models.TextField(blank=True, primary_key=True)
49   - rev = models.TextField(blank=True)
50   - author = models.TextField(blank=True)
51   - message = models.TextField(blank=True)
52   - repository_name = models.TextField(blank=True)
53   - created = models.DateTimeField(blank=True, null=True)
54   -
55   - class Meta:
56   - managed = False
57   - db_table = 'revision_view'
58   -
59   - def get_absolute_url(self):
60   - return u'/changeset/{}/{}'.format(self.rev, self.repository_name)
61   -
62   - def get_author(self):
63   - try:
64   - return User.objects.get(username=self.author)
65   - except User.DoesNotExist:
66   - return None
67   -
68   -
69   -class Ticket(models.Model, HitCounterModelMixin):
70   - id = models.IntegerField(primary_key=True)
71   - summary = models.TextField(blank=True)
72   - description = models.TextField(blank=True)
73   - milestone = models.TextField(blank=True)
74   - priority = models.TextField(blank=True)
75   - component = models.TextField(blank=True)
76   - version = models.TextField(blank=True)
77   - severity = models.TextField(blank=True)
78   - reporter = models.TextField(blank=True)
79   - author = models.TextField(blank=True)
80   - status = models.TextField(blank=True)
81   - keywords = models.TextField(blank=True)
82   - collaborators = models.TextField(blank=True)
83   - created = models.DateTimeField(blank=True, null=True)
84   - modified = models.DateTimeField(blank=True, null=True)
85   - modified_by = models.TextField(blank=True)
86   -
87   - class Meta:
88   - managed = False
89   - db_table = 'ticket_view'
90   -
91   - def get_absolute_url(self):
92   - return u'/ticket/{}'.format(self.id)
93   -
94   - def get_author(self):
95   - try:
96   - return User.objects.get(username=self.author)
97   - except User.DoesNotExist:
98   - return None
99   -
100   - def get_modified_by(self):
101   - try:
102   - return User.objects.get(username=self.modified_by)
103   - except User.DoesNotExist:
104   - return None
105   -
106   -
107   -class Wiki(models.Model, HitCounterModelMixin):
108   - name = models.TextField(primary_key=True)
109   - wiki_text = models.TextField(blank=True)
110   - author = models.TextField(blank=True)
111   - collaborators = models.TextField(blank=True)
112   - created = models.DateTimeField(blank=True, null=True)
113   - modified = models.DateTimeField(blank=True, null=True)
114   - modified_by = models.TextField(blank=True)
115   -
116   - class Meta:
117   - managed = False
118   - db_table = 'wiki_view'
119   -
120   - def get_absolute_url(self):
121   - return u'/wiki/{}'.format(self.name)
122   -
123   - def get_author(self):
124   - try:
125   - return User.objects.get(username=self.author)
126   - except User.DoesNotExist:
127   - return None
128   -
129   - def get_modified_by(self):
130   - try:
131   - return User.objects.get(username=self.modified_by)
132   - except User.DoesNotExist:
133   - return None
colab/plugins/trac/routers.py
... ... @@ -1,23 +0,0 @@
1   -class TracRouter(object):
2   - def db_for_read(self, model, **hints):
3   - if model._meta.app_label == 'proxy':
4   - return 'trac'
5   - return None
6   -
7   - def db_for_write(self, model, **hints):
8   - if model._meta.app_label == 'proxy':
9   - return 'trac'
10   - return None
11   -
12   - def allow_relation(self, obj1, obj2, **hints):
13   - if obj1._meta.app_label == 'proxy' or \
14   - obj2._meta.app_label == 'proxy':
15   - return True
16   - return None
17   -
18   - def allow_migrate(self, db, model):
19   - if db == 'trac':
20   - return model._meta.app_label == 'proxy'
21   - elif model._meta.app_label == 'proxy':
22   - False
23   - return None
colab/plugins/trac/search_indexes.py
... ... @@ -1,155 +0,0 @@
1   -# -*- coding: utf-8 -*-
2   -
3   -import string
4   -
5   -from django.template import loader, Context
6   -from haystack import indexes
7   -from haystack.utils import log as logging
8   -
9   -from colab.search.base_indexes import BaseIndex
10   -from .models import Attachment, Ticket, Wiki, Revision
11   -
12   -
13   -logger = logging.getLogger('haystack')
14   -
15   -# the string maketrans always return a string encoded with latin1
16   -# http://stackoverflow.com/questions/1324067/how-do-i-get-str-translate-to-work-with-unicode-strings # noqa
17   -table = string.maketrans(
18   - string.punctuation,
19   - '.' * len(string.punctuation)
20   -).decode('latin1')
21   -
22   -
23   -class AttachmentIndex(BaseIndex, indexes.Indexable):
24   - title = indexes.CharField(model_attr='filename')
25   - description = indexes.CharField(model_attr='description', null=True)
26   - modified = indexes.DateTimeField(model_attr='created', null=True)
27   - used_by = indexes.CharField(model_attr='used_by', null=True, stored=False)
28   - mimetype = indexes.CharField(
29   - model_attr='mimetype',
30   - null=True,
31   - stored=False
32   - )
33   - size = indexes.IntegerField(model_attr='size', null=True, stored=False)
34   - filename = indexes.CharField(stored=False)
35   -
36   - def get_model(self):
37   - return Attachment
38   -
39   - def get_updated_field(self):
40   - return 'created'
41   -
42   - def prepare(self, obj):
43   - data = super(AttachmentIndex, self).prepare(obj)
44   -
45   - try:
46   - file_obj = open(obj.filepath)
47   - except IOError as e:
48   - logger.warning(u'IOError: %s - %s', e.strerror, e.filename)
49   - return data
50   - backend = self._get_backend(None)
51   -
52   - extracted_data = backend.extract_file_contents(file_obj)
53   - file_obj.close()
54   -
55   - if not extracted_data:
56   - return data
57   -
58   - t = loader.select_template(
59   - ('search/indexes/proxy/attachment_text.txt', )
60   - )
61   - data['text'] = t.render(Context({
62   - 'object': obj,
63   - 'extracted': extracted_data,
64   - }))
65   - return data
66   -
67   - def prepare_filename(self, obj):
68   - return obj.filename.translate(table).replace('.', ' ')
69   -
70   - def prepare_icon_name(self, obj):
71   - return u'file'
72   -
73   - def prepare_type(self, obj):
74   - return u'attachment'
75   -
76   -
77   -class WikiIndex(BaseIndex, indexes.Indexable):
78   - title = indexes.CharField(model_attr='name')
79   - collaborators = indexes.CharField(
80   - model_attr='collaborators',
81   - null=True,
82   - stored=False,
83   - )
84   -
85   - def get_model(self):
86   - return Wiki
87   -
88   - def prepare_description(self, obj):
89   - return u'{}\n{}'.format(obj.wiki_text, obj.collaborators)
90   -
91   - def prepare_icon_name(self, obj):
92   - return u'book'
93   -
94   - def prepare_type(self, obj):
95   - return u'wiki'
96   -
97   -
98   -class TicketIndex(BaseIndex, indexes.Indexable):
99   - tag = indexes.CharField(model_attr='status', null=True)
100   - milestone = indexes.CharField(model_attr='milestone', null=True)
101   - component = indexes.CharField(model_attr='component', null=True)
102   - severity = indexes.CharField(model_attr='severity', null=True)
103   - reporter = indexes.CharField(model_attr='reporter', null=True)
104   - keywords = indexes.CharField(model_attr='keywords', null=True)
105   - collaborators = indexes.CharField(
106   - model_attr='collaborators',
107   - null=True,
108   - stored=False,
109   - )
110   -
111   - def get_model(self):
112   - return Ticket
113   -
114   - def prepare_description(self, obj):
115   - return u'{}\n{}\n{}\n{}\n{}\n{}\n{}'.format(
116   - obj.description, obj.milestone, obj.component, obj.severity,
117   - obj.reporter, obj.keywords, obj.collaborators
118   - )
119   -
120   - def prepare_icon_name(self, obj):
121   - return u'tag'
122   -
123   - def prepare_title(self, obj):
124   - return u'#{} - {}'.format(obj.pk, obj.summary)
125   -
126   - def prepare_type(self, obj):
127   - return 'ticket'
128   -
129   -
130   -class RevisionIndex(BaseIndex, indexes.Indexable):
131   - description = indexes.CharField(model_attr='message', null=True)
132   - modified = indexes.DateTimeField(model_attr='created', null=True)
133   - repository_name = indexes.CharField(
134   - model_attr='repository_name',
135   - stored=False
136   - )
137   -
138   - def get_model(self):
139   - return Revision
140   -
141   - def get_updated_field(self):
142   - return 'created'
143   -
144   - def get_boost(self, obj):
145   - boost = super(RevisionIndex, self).get_boost(obj)
146   - return boost * 0.8
147   -
148   - def prepare_icon_name(self, obj):
149   - return u'align-right'
150   -
151   - def prepare_title(self, obj):
152   - return u'{} [{}]'.format(obj.repository_name, obj.rev)
153   -
154   - def prepare_type(self, obj):
155   - return 'changeset'
colab/plugins/trac/signals.py
... ... @@ -1,33 +0,0 @@
1   -
2   -from django.db import connections
3   -from django.dispatch import receiver
4   -from django.db.models.signals import post_save
5   -
6   -from colab.accounts.models import User
7   -
8   -
9   -@receiver(post_save, sender=User)
10   -def change_session_attribute_email(sender, instance, **kwargs):
11   - cursor = connections['trac'].cursor()
12   -
13   - cursor.execute(("UPDATE session_attribute SET value=%s "
14   - "WHERE name='email' AND sid=%s"),
15   - [instance.email, instance.username])
16   - cursor.execute(("UPDATE session_attribute SET value=%s "
17   - "WHERE name='name' AND sid=%s"),
18   - [instance.get_full_name(), instance.username])
19   -
20   - cursor.execute(("INSERT INTO session_attribute "
21   - "(sid, authenticated, name, value) "
22   - "SELECT %s, '1', 'email', %s WHERE NOT EXISTS "
23   - "(SELECT 1 FROM session_attribute WHERE sid=%s "
24   - "AND name='email')"),
25   - [instance.username, instance.email, instance.username])
26   -
27   - cursor.execute(("INSERT INTO session_attribute "
28   - "(sid, authenticated, name, value) "
29   - "SELECT %s, '1', 'name', %s WHERE NOT EXISTS "
30   - "(SELECT 1 FROM session_attribute WHERE sid=%s "
31   - "AND name='name')"),
32   - [instance.username, instance.get_full_name(),
33   - instance.username])
colab/plugins/trac/templates/proxy/trac.html
... ... @@ -1,7 +0,0 @@
1   -{% extends "base.html" %}
2   -
3   -{% block head %}
4   - <placeholder id="trac-css"/>
5   - <placeholder id="trac-js"/>
6   - {{ block.super }}
7   -{% endblock %}
colab/plugins/trac/templates/search/indexes/proxy/attachment_text.txt
... ... @@ -1,15 +0,0 @@
1   -{{ object.filename }}
2   -{{ object.filename|slugify }}
3   -{{ object.description }}
4   -{{ object.description|slugify }}
5   -{{ object.used_by }}
6   -{{ object.mimetype }}
7   -{{ object.get_author.get_full_name }}
8   -
9   -{% for k, v in extracted.metadata.items %}
10   - {% for val in v %}
11   - {{ k }}: {{ val|safe }}
12   - {% endfor %}
13   -{% endfor %}
14   -
15   -{{ extracted.contents|striptags|safe }}
colab/plugins/trac/templates/search/indexes/proxy/revision_text.txt
... ... @@ -1,8 +0,0 @@
1   -{{ object.repository_name }}
2   -{{ object.repository_name|slugify }}
3   -{{ object.rev }}
4   -{{ object.rev|slugify }}
5   -{% firstof object.get_author.get_full_name object.author %}
6   -{% firstof object.get_author.get_full_name|slugify object.author|slugify %}
7   -{{ object.message }}
8   -{{ object.message|slugify }}
colab/plugins/trac/templates/search/indexes/proxy/ticket_text.txt
... ... @@ -1,20 +0,0 @@
1   -{{ object.summary }}
2   -{{ object.summary|slugify }}
3   -{{ object.description }}
4   -{{ object.description|slugify }}
5   -{{ object.milestone }}
6   -{{ object.milestone|slugify }}
7   -{{ object.component|slugify }}
8   -{{ object.version }}
9   -{{ object.severity }}
10   -{{ object.severity|slugify }}
11   -{{ object.reporter }}
12   -{{ object.reporter|slugify }}
13   -{% firstof object.get_author.get_fullname or object.author %}
14   -{% firstof object.get_author.get_fullname|slugify or object.author|slugify %}
15   -{{ object.status }}
16   -{{ object.status|slugify }}
17   -{{ object.keywords }}
18   -{{ object.keywords|slugify }}
19   -{{ object.collaborators }}
20   -{{ object.collaborators|slugify }}
colab/plugins/trac/templates/search/indexes/proxy/wiki_text.txt
... ... @@ -1,9 +0,0 @@
1   -{{ object.author }}
2   -{{ object.get_author.get_full_name }}
3   -{{ object.get_author.get_full_name|slugify }}
4   -{{ object.name }}
5   -{{ object.name|slugify }}
6   -{{ object.collaborators }}
7   -{{ object.collaborators|slugify }}
8   -{{ object.wiki_text }}
9   -{{ object.wiki_text|slugify }}
colab/plugins/trac/urls.py
... ... @@ -1,10 +0,0 @@
1   -
2   -from django.conf.urls import patterns, url
3   -
4   -from .views import TracProxyView
5   -
6   -
7   -urlpatterns = patterns('',
8   - # Trac
9   - url(r'^(?P<path>.*)$', TracProxyView.as_view(), name='trac'),
10   -)
colab/plugins/trac/views.py
... ... @@ -1,40 +0,0 @@
1   -
2   -from hitcounter.views import HitCounterViewMixin
3   -
4   -from ..utils.views import ColabProxyView
5   -from .models import Wiki, Ticket, Revision
6   -
7   -
8   -class TracProxyView(HitCounterViewMixin, ColabProxyView):
9   - app_label = 'trac'
10   - diazo_theme_template = 'proxy/trac.html'
11   -
12   - def get_object(self):
13   - obj = None
14   -
15   - if self.request.path_info.startswith('/wiki'):
16   - wiki_name = self.request.path_info.split('/', 2)[-1]
17   - if not wiki_name:
18   - wiki_name = 'WikiStart'
19   - try:
20   - obj = Wiki.objects.get(name=wiki_name)
21   - except Wiki.DoesNotExist:
22   - return None
23   - elif self.request.path_info.startswith('/ticket'):
24   - ticket_id = self.request.path_info.split('/')[2]
25   - try:
26   - obj = Ticket.objects.get(id=ticket_id)
27   - except (Ticket.DoesNotExist, ValueError):
28   - return None
29   - elif self.request.path_info.startswith('/changeset'):
30   - try:
31   - changeset, repo = self.request.path_info.split('/')[2:4]
32   - except ValueError:
33   - return None
34   - try:
35   - obj = Revision.objects.get(rev=changeset,
36   - repository_name=repo)
37   - except Revision.DoesNotExist:
38   - return None
39   -
40   - return obj
colab/settings.py
... ... @@ -44,8 +44,6 @@ INSTALLED_APPS = (
44 44 # Not standard apps
45 45 'cliauth',
46 46 'django_mobile',
47   - 'django_browserid',
48   - 'conversejs',
49 47 'haystack',
50 48 'hitcounter',
51 49 'i18n_model',
... ... @@ -58,7 +56,6 @@ INSTALLED_APPS = (
58 56 'colab.api',
59 57 'colab.rss',
60 58 'colab.search',
61   - 'colab.badger',
62 59 'colab.tz',
63 60 )
64 61  
... ... @@ -198,7 +195,6 @@ TEMPLATE_CONTEXT_PROCESSORS = (
198 195 'colab.home.context_processors.robots',
199 196 'colab.home.context_processors.ribbon',
200 197 'colab.home.context_processors.google_analytics',
201   - 'colab.home.context_processors.browserid_enabled',
202 198 )
203 199  
204 200 MIDDLEWARE_CLASSES = (
... ... @@ -213,13 +209,10 @@ MIDDLEWARE_CLASSES = (
213 209 'django_mobile.middleware.MobileDetectionMiddleware',
214 210 'django_mobile.middleware.SetFlavourMiddleware',
215 211 'colab.tz.middleware.TimezoneMiddleware',
216   - 'colab.accounts.middleware.UserRegisterMiddleware',
217 212 )
218 213  
219   -# Add the django_browserid authentication backend.
220 214 AUTHENTICATION_BACKENDS = (
221 215 'django.contrib.auth.backends.ModelBackend',
222   - 'colab.accounts.auth.ColabBrowserIDBackend',
223 216 )
224 217  
225 218 LOCALE_PATHS = (
... ... @@ -247,27 +240,13 @@ SUPER_ARCHIVES_LOCK_FILE = &#39;/var/lock/colab/import_emails.lock&#39;
247 240 # Mailman API settings
248 241 MAILMAN_API_URL = 'http://localhost:8124'
249 242  
250   -# BrowserID / Persona
251   -SITE_URL = 'http://localhost:8000'
252   -BROWSERID_AUDIENCES = [SITE_URL, SITE_URL.replace('https', 'http')]
253   -
254   -
255 243 LOGIN_URL = '/user/login'
256 244 LOGIN_REDIRECT_URL = '/'
257 245 LOGIN_REDIRECT_URL_FAILURE = '/?bid_login_failed=true'
258 246 LOGOUT_REDIRECT_URL = '/'
259   -BROWSERID_CREATE_USER = True
260 247  
261 248 REVPROXY_ADD_REMOTE_USER = True
262 249  
263   -# Converse.js settings
264   -# This URL must use SSL in order to keep chat sessions secure
265   -CONVERSEJS_ENABLED = False
266   -CONVERSEJS_BOSH_SERVICE_URL = SITE_URL + '/http-bind'
267   -
268   -CONVERSEJS_ALLOW_CONTACT_REQUESTS = False
269   -CONVERSEJS_SHOW_ONLY_ONLINE_USERS = True
270   -
271 250 # Tastypie settings
272 251 TASTYPIE_DEFAULT_FORMATS = ['json', ]
273 252  
... ... @@ -279,7 +258,6 @@ if locals().get(&#39;RAVEN_DSN&#39;, False):
279 258 }
280 259 INSTALLED_APPS += ('raven.contrib.django.raven_compat',)
281 260  
282   -BROWSERID_ENABLED = locals().get('BROWSERID_ENABLED') or False
283 261 SOCIAL_NETWORK_ENABLED = locals().get('SOCIAL_NETWORK_ENABLED') or False
284 262  
285 263 locals().update(load_colab_apps())
... ...
colab/templates/base.html
1 1 <!DOCTYPE html>
2   -{% load i18n browserid conversejs gravatar %}
  2 +{% load i18n gravatar plugins %}
3 3 {% load static from staticfiles %}
4 4  
5 5 <html>
... ... @@ -43,10 +43,6 @@
43 43 {% block head_js %}{% endblock %}
44 44 {% block head_css %}{% endblock %}
45 45  
46   - {% if not is_mobile %}
47   - {% conversejs_static %}
48   - {% endif %}
49   -
50 46 <link rel="stylesheet" href="{% static 'css/screen.css' %}"
51 47 type="text/css" media="screen" />
52 48  
... ... @@ -54,10 +50,7 @@
54 50 </head>
55 51  
56 52 <!-- data-no-turbolink will disable Rails TurboLinks for all pages under Colab -->
57   - <body data-no-turbolink>
58   - {% if BROWSERID_ENABLED %}
59   - {% browserid_info %}
60   - {% endif %}
  53 + <body class="container" data-no-turbolink>
61 54  
62 55 {% block ribbon %}
63 56 {% if ribbon %}
... ... @@ -70,8 +63,82 @@
70 63 {% endblock %}
71 64  
72 65 {% block navbar %}
73   -
74   - {% include "header.html" %}
  66 + <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
  67 + <div class="container">
  68 + <div class="navbar-header">
  69 +
  70 + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-main">
  71 + <span class="sr-only">Toggle navigation</span>
  72 + <span class="icon-bar"></span>
  73 + <span class="icon-bar"></span>
  74 + <span class="icon-bar"></span>
  75 + <span class="icon-bar"></span>
  76 + </button>
  77 + <a class="navbar-brand" href="/"><img alt="Colab" src="{% static 'img/logo.svg' %}"></a>
  78 + </div>
  79 + <div class="collapse navbar-collapse navbar-main">
  80 + <ul class="nav navbar-nav">
  81 +
  82 + <li>
  83 + <a href="{% url 'thread_list' %}">{% trans "Groups" %}</a>
  84 + </li>
  85 +
  86 + {% plugins_menu %}
  87 +
  88 + <li class="hidden-lg hidden-md">
  89 + <a href="{% url 'haystack_search' %}?q=">{% trans "Search" %}</a>
  90 + </li>
  91 + </ul>
  92 +
  93 + <ul class="nav navbar-nav navbar-right">
  94 + {% if not user.is_authenticated %}
  95 +
  96 + <li class="dropdown hidden-xs hidden-lg">
  97 + <a href="#" class="dropdown-toggle" data-toggle="dropdown">Acesso <b class="caret"></b></a>
  98 + <ul class="dropdown-menu">
  99 + {% trans 'Login' as login_text %}
  100 + <li><a href="{% url 'signup' %}">{% trans "Register" %}</a></li>
  101 + <li><a href="{% url 'login' %}">{% trans "Login" %}</a></li>
  102 + </ul>
  103 + </li>
  104 + {% trans 'Login' as login_text %}
  105 + <li class="visible-xs hidden-sm hidden-md"><a href="{% url 'signup' %}">{% trans "Register" %}</a></li>
  106 + <li class="visible-xs hidden-sm hidden-md"><a href="{% url 'login' %}">{% trans "Login" %}</a></li>
  107 + {% else %}
  108 + <li id="user-menu" class="dropdown">
  109 + <a href="#" class="dropdown-toggle user" data-toggle="dropdown">{% gravatar user.email 40 %} <b class="caret"></b>&nbsp;&nbsp;</a>
  110 + <ul class="dropdown-menu" role="menu">
  111 + <li>
  112 + <div class="wrapper">
  113 + <div class="thumbnail">{% gravatar user.email 100 %}</div>
  114 + <div class="user-info">
  115 + <span><b>{{ user.get_full_name }}</b></span>
  116 + <span class="quiet">{{ user.email }}</span>
  117 + </div>
  118 + <div>
  119 + <a class="btn btn-info pull-left" href="{% url 'user_profile' user.username %}">{% trans "My Profile" %}</a>
  120 + {% trans 'Logout' as logout_text %}
  121 + <a class="btn btn-default pull-right" href="{% url 'logout' %}"> {% trans "Logout" %}</a>
  122 + </div>
  123 + </div>
  124 + </li>
  125 + </ul>
  126 + </li>
  127 + {% endif %}
  128 + </ul>
  129 +
  130 + <form action="{% url 'haystack_search' %}" method="GET" id="search-form" class="navbar-form navbar-right hidden-xs hidden-sm" role="search">
  131 + <div class="form-group">
  132 + <label class="sr-only" for="header-searchbox">{% trans 'Search here...' %}</label>
  133 + <input name="q" id="header-searchbox"
  134 + class="form-control" value="{{ request.GET.q }}"
  135 + type="search" placeholder="{% trans 'Search here...' %}" />
  136 + </div>
  137 + <button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-search"></span></button>
  138 + </form>
  139 + </div>
  140 + </div>
  141 + </nav>
75 142  
76 143 {% endblock %}
77 144  
... ... @@ -107,19 +174,8 @@
107 174  
108 175 {% endblock %}
109 176  
110   - {% if not is_mobile %}
111   - {% conversejs_chatpanel %}
112   - {% conversejs_initialize %}
113   - {% endif %}
114   -
115 177 {% include "tz/set_utc_offset.html" %}
116 178  
117   - {% if BROWSERID_ENABLED %}
118   - <script src="https://login.persona.org/include.js"></script>
119   - <script src="{% static 'browserid/api.js' %}"></script>
120   - <script src="{% static 'browserid/browserid.js' %}"></script>
121   - {% endif %}
122   -
123 179 {% block footer_js %}{% endblock %}
124 180 </body>
125 181 </html>
... ...
colab/templates/footer.html
1   -{% load i18n browserid conversejs gravatar %}
  1 +{% load i18n gravatar plugins %}
2 2 {% load static from staticfiles %}
3 3  
4 4 <div class="footer row">
... ...
colab/templates/header.html
1   -{% load i18n browserid conversejs gravatar plugins %}
  1 +{% load i18n gravatar plugins %}
2 2 {% load static from staticfiles %}
3 3  
4 4 <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
... ... @@ -21,12 +21,6 @@
21 21 <a href="{% url 'thread_list' %}">{% trans "Groups" %}</a>
22 22 </li>
23 23  
24   - {% if feedzilla %}
25   - <li>
26   - <a href="{% url "feedzilla_index" %}">{% trans "Blogs" %}</a>
27   - </li>
28   - {% endif %}
29   -
30 24 {% plugins_menu %}
31 25  
32 26 <li><a href="/paste">{% trans "Paste" %}</a></li>
... ...
colab/urls.py
... ... @@ -30,16 +30,12 @@ urlpatterns = patterns(&#39;&#39;,
30 30 url(r'^myaccount/(?P<route>.*)$',
31 31 'colab.accounts.views.myaccount_redirect', name='myaccount'),
32 32  
33   - url(r'', include('django_browserid.urls')),
34   -
35 33 # Uncomment the next line to enable the admin:
36 34 url(r'^colab/admin/', include(admin.site.urls)),
37 35  
38   - url(r'^trac/', include('colab.plugins.trac.urls')),
39 36 url(r'^gitlab/', include('colab.plugins.gitlab.urls')),
40 37 url(r'^mezuro/', include('colab.plugins.mezuro.urls')),
41 38 url(r'^social/', include('colab.plugins.noosfero.urls')),
42   - url(r'^ci/', include('colab.plugins.jenkins.urls')),
43 39  
44 40 url(r'', include('colab.plugins.urls')),
45 41 )
... ...
docs/source/user.rst
... ... @@ -139,31 +139,6 @@ Social Networks
139 139 When this variable is True, the social networks fields, like Facebook and
140 140 Twitter, are added in user profile. By default, this fields are disabled.
141 141  
142   -Auth
143   -++++
144   -.. attribute:: BROWSERID_ENABLED
145   -
146   - :default: False
147   -
148   - When this variable is True, Colab use BrowserID authentication. By default,
149   - django authentication system is used.
150   -
151   -.. attribute:: BROWSERID_AUDIENCES
152   -
153   - :default: No default
154   -
155   - List of audiences that your site accepts. An audience is the protocol,
156   - domain name, and (optionally) port that users access your site from. This
157   - list is used to determine the audience a user is part of (how they are
158   - accessing your site), which is used during verification to ensure that the
159   - assertion given to you by the user was intended for your site.
160   -
161   - Without this, other sites that the user has authenticated with via Persona
162   - could use their assertions to impersonate the user on your site.
163   -
164   - Note that this does not have to be a publicly accessible URL, so local URLs
165   - like ``http://localhost:8000`` or ``http://127.0.0.1`` are acceptable as
166   - long as they match what you are using to access your site.
167 142  
168 143 Customization
169 144 -------------
... ...
setup.py
... ... @@ -29,20 +29,8 @@ REQUIREMENTS = [
29 29 'raven==3.5.2',
30 30 'tornado==3.1.1',
31 31  
32   - # Deps for Single SignOn (SSO) - Replaced with django-browserid==0.9
33   - 'django-browserid==0.11',
34 32 'django-revproxy==0.9.3',
35 33  
36   - # Converse.js (XMPP client)
37   - 'django-conversejs==0.3.4',
38   -
39   - # Feedzilla (planet) and deps
40   - 'django-common==0.1.51',
41   - 'feedparser==5.1.3',
42   - 'lxml==3.2.4',
43   - 'grab==0.4.13',
44   - 'transliterate==1.5',
45   -
46 34 # Diazo
47 35 'diazo==1.0.5',
48 36  
... ...