Compare View

switch
from
...
to
 
Commits (219)
Showing 154 changed files   Show diff stats

Too many changes.

To preserve performance only 100 of 154 files displayed.

Rakefile
... ... @@ -41,7 +41,8 @@ if $SPB_ENV == 'lxc'
41 41 end
42 42  
43 43 File.open('config/lxc/iptables-filter-rules', 'w') do |f|
44   - lxc_host_bridge_ip = '192.168.122.1' # FIXME don't hardcode
  44 + lxc_host_bridge_name = `awk '{ if ($1 == "lxc.network.link") { print($3) } }' /etc/lxc/default.conf`.strip
  45 + lxc_host_bridge_ip = ` /sbin/ifconfig #{lxc_host_bridge_name} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1 }' `.strip
45 46 f.puts "-A INPUT -s #{lxc_host_bridge_ip} -p tcp -m state --state NEW --dport 22 -j ACCEPT"
46 47 f.puts "-A INPUT -s #{lxc_host_bridge_ip} -p tcp -m state --state NEW --dport 5555 -j ACCEPT"
47 48 end
... ...
VERSION
1   -5.0a0
  1 +5.0a7
... ...
config/cdtc/config.yaml
... ... @@ -13,3 +13,5 @@ relay_hostname: relay.spb.cdtc.unb.br
13 13 relay_ip: 164.41.9.48
14 14 alt_ssh_port: 55555
15 15 from_address: noreply@spb.cdtc.unb.br
  16 +dev_backup_frequency: true
  17 +disable_send_emails: true
... ...
config/dev/config.yaml
... ... @@ -19,3 +19,5 @@ alt_ssh_port: 55555
19 19 external_outgoing_mail_domain: serpro.gov.br
20 20 raven_dsn: https://a5e2f92a83774dfc9de66486e0fe970b:1a9229a4e1d2483582144d302fb53115@sentry.tracy.com.br/19
21 21 google_analytics_id: 'UA-64206731-2'
  22 +dev_backup_frequency: true
  23 +disable_send_emails: true
... ...
config/homologa/config.yaml
... ... @@ -20,3 +20,5 @@ external_outgoing_mail_relay: 189.9.150.53
20 20 external_outgoing_mail_domain: serpro.gov.br
21 21 raven_dsn: https://a5e2f92a83774dfc9de66486e0fe970b:1a9229a4e1d2483582144d302fb53115@sentry.tracy.com.br/19
22 22 google_analytics_id: 'UA-64206731-3'
  23 +dev_backup_frequency: true
  24 +disable_send_emails: true
... ...
config/lappis/config.yaml
... ... @@ -3,14 +3,16 @@ admins:
3 3 site_url: https://softwarepublico.lappis
4 4 external_hostname: softwarepublico.lappis
5 5 sisp_external_hostname: sisp.lappis
6   -external_ip: 10.0.0.11
  6 +external_ip: 10.0.0.54
7 7 colab_from_address: '"Portal do Software Publico" <noreply@softwarepublico.lappis>'
8 8 server_email: '"Portal do Software Publico" <noreply@softwarepublico.lappis>'
9 9 email_subject_prefix: '[spb]'
10 10 lists_hostname: listas.softwarepublico.lappis
11 11 lists_admin: paulo@softwarelivre.org
12 12 relay_hostname: relay.softwarepublico.lappis
13   -relay_ip: 10.0.0.15
  13 +relay_ip: 10.0.0.51
14 14 alt_ssh_port: 5555
15 15 from_address: noreply@softwarepublico.lappis
16   -
  16 +# define less frequent backup for dev envs
  17 +dev_backup_frequency: true
  18 +disable_send_emails: true
... ...
config/lappis/ips.yaml
1   -reverseproxy: 10.0.0.11
2   -database: 10.0.0.13
3   -social: 10.0.0.14
4   -email: 10.0.0.15
5   -integration: 10.0.0.12
  1 +reverseproxy: 10.0.0.54
  2 +database: 10.0.0.55
  3 +social: 10.0.0.53
  4 +email: 10.0.0.51
  5 +integration: 10.0.0.52
... ...
config/lappis/ssh_config
... ... @@ -2,28 +2,28 @@ Host *
2 2 ForwardAgent yes
3 3  
4 4 Host reverseproxy.unconfigured
5   - Hostname 10.0.0.11
  5 + Hostname 10.0.0.54
6 6  
7 7 Host reverseproxy
8   - Hostname 10.0.0.11
  8 + Hostname 10.0.0.54
9 9 Port 5555
10   - ProxyCommand ssh 10.0.0.11 -p 22 nc %h %p
  10 + ProxyCommand ssh 10.0.0.54 -p 22 nc %h %p
11 11  
12 12 Host database
13   - Hostname 10.0.0.13
  13 + Hostname 10.0.0.55
14 14 # connect via reverseproxy host
15   - ProxyCommand ssh 10.0.0.11 nc %h %p
  15 + ProxyCommand ssh 10.0.0.54 nc %h %p
16 16  
17 17 Host social
18   - Hostname 10.0.0.14
  18 + Hostname 10.0.0.53
19 19 # connect via reverseproxy host
20   - ProxyCommand ssh 10.0.0.11 nc %h %p
  20 + ProxyCommand ssh 10.0.0.54 nc %h %p
21 21  
22 22 Host email
23   - Hostname 10.0.0.15
  23 + Hostname 10.0.0.51
24 24 # connect via reverseproxy host
25   - ProxyCommand ssh 10.0.0.11 nc %h %p
  25 + ProxyCommand ssh 10.0.0.54 nc %h %p
26 26  
27 27 Host integration
28   - Hostname 10.0.0.11
29   - # Porta 22 de 10.0.0.11 cai aqui entao nao precisa de ProxyCommand
  28 + Hostname 10.0.0.54
  29 + # Porta 22 de 10.0.0.54 cai aqui entao nao precisa de ProxyCommand
... ...
config/local/config.yaml
... ... @@ -19,3 +19,5 @@ alt_ssh_port: 5555
19 19 from_address: noreply@softwarepublico.dev
20 20 raven_dsn: https://a5e2f92a83774dfc9de66486e0fe970b:1a9229a4e1d2483582144d302fb53115@sentry.tracy.com.br/19
21 21 colab_http_workers: 1
  22 +dev_backup_frequency: true
  23 +disable_send_emails: true
... ...
cookbooks/backup/recipes/default.rb
... ... @@ -13,7 +13,7 @@ cookbook_file &#39;/usr/local/bin/backup_spb.sh&#39; do
13 13 mode 0755
14 14 end
15 15  
16   -cookbook_file '/etc/cron.d/rsnapshot-spb' do
  16 +template '/etc/cron.d/rsnapshot-spb' do
17 17 owner 'root'
18 18 group 'root'
19 19 mode 0644
... ...
cookbooks/backup/templates/rsnapshot-spb.erb 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +<%if node['config']['dev_backup_frequency']%>
  2 +20 23 1 * * root rsnapshot monthly
  3 +<%else%>
  4 +0 */6 * * * root rsnapshot hourly
  5 +59 23 * * * root rsnapshot daily
  6 +40 23 * * 7 root rsnapshot weekly
  7 +20 23 1 * * root rsnapshot monthly
  8 +<%end%>
... ...
cookbooks/basics/recipes/default.rb
... ... @@ -65,6 +65,7 @@ package &#39;tmux&#39;
65 65 package 'less'
66 66 package 'htop'
67 67 package 'ntp'
  68 +package 'screen'
68 69  
69 70 cookbook_file '/usr/local/bin/is-a-container' do
70 71 owner 'root'
... ...
cookbooks/colab/files/default/dashboard.py 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +from colab.widgets.widget_manager import WidgetManager
  2 +
  3 +from colab.widgets.dashboard.dashboard_latest_collaborations import \
  4 + DashboardLatestCollaborationsWidget
  5 +from colab.widgets.dashboard.dashboard_collaboration_graph import \
  6 + DashboardCollaborationGraphWidget
  7 +from colab_superarchives.widgets.dashboard_most_relevant_threads import \
  8 + DashboardMostRelevantThreadsWidget
  9 +from colab_superarchives.widgets.dashboard_latest_threads import \
  10 + DashboardLatestThreadsWidget
  11 +
  12 +# Dashboard Widgets
  13 +WidgetManager.register_widget('dashboard',
  14 + DashboardLatestCollaborationsWidget())
  15 +WidgetManager.register_widget('dashboard',
  16 + DashboardCollaborationGraphWidget())
  17 +WidgetManager.register_widget('dashboard',
  18 + DashboardMostRelevantThreadsWidget())
  19 +WidgetManager.register_widget('dashboard',
  20 + DashboardLatestThreadsWidget())
  21 +
... ...
cookbooks/colab/files/default/gitlab_profile.py 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +from colab.widgets.widget_manager import WidgetManager
  2 +
  3 +from colab_gitlab.widgets.profile.profile import GitlabProfileWidget
  4 +
  5 +WidgetManager.register_widget('profile', GitlabProfileWidget())
... ...
cookbooks/colab/files/default/profile.py 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +from colab.widgets.widget_manager import WidgetManager
  2 +
  3 +from colab_superarchives.widgets.group import GroupWidget
  4 +from colab_superarchives.widgets.group_membership import GroupMembershipWidget
  5 +from colab_superarchives.widgets.latest_posted import LatestPostedWidget
  6 +from colab.accounts.widgets.latest_contributions import \
  7 + LatestContributionsWidget
  8 +
  9 +from colab.accounts.widgets.collaboration_chart import CollaborationChart
  10 +from colab_superarchives.widgets.participation_chart import ParticipationChart
  11 +
  12 +# Profile Widgets
  13 +WidgetManager.register_widget('group', GroupWidget())
  14 +WidgetManager.register_widget('button', GroupMembershipWidget())
  15 +WidgetManager.register_widget('list', LatestPostedWidget())
  16 +WidgetManager.register_widget('list', LatestContributionsWidget())
  17 +WidgetManager.register_widget('charts', CollaborationChart())
  18 +WidgetManager.register_widget('charts', ParticipationChart())
... ...
cookbooks/colab/recipes/default.rb
... ... @@ -26,7 +26,7 @@ package &#39;colab-spb-theme&#39; do
26 26 notifies :restart, 'service[colab]'
27 27 end
28 28  
29   -package 'colab-spb-theme' do
  29 +package 'colab-spb-plugin' do
30 30 action :upgrade
31 31 notifies :restart, 'service[colab]'
32 32 end
... ... @@ -161,6 +161,13 @@ template &#39;/etc/colab/plugins.d/noosfero.py&#39; do
161 161 variables(:get_private_token => get_private_token)
162 162 end
163 163  
  164 +template '/etc/colab/plugins.d/super_archives.py' do
  165 + owner 'root'
  166 + group 'colab'
  167 + mode 0640
  168 + notifies :restart, 'service[colab]'
  169 +end
  170 +
164 171 template '/etc/colab/plugins.d/spb.py' do
165 172 owner 'root'
166 173 group 'colab'
... ... @@ -177,6 +184,31 @@ end
177 184  
178 185 execute 'colab-admin migrate'
179 186  
  187 +# Adding widgets for colab
  188 +cookbook_file '/etc/colab/widgets.d/dashboard.py' do
  189 + owner 'root'
  190 + group 'colab'
  191 + mode 0640
  192 +
  193 + notifies :restart, 'service[colab]'
  194 +end
  195 +
  196 +cookbook_file '/etc/colab/widgets.d/profile.py' do
  197 + owner 'root'
  198 + group 'colab'
  199 + mode 0640
  200 +
  201 + notifies :restart, 'service[colab]'
  202 +end
  203 +
  204 +cookbook_file '/etc/colab/widgets.d/gitlab_profile.py' do
  205 + owner 'root'
  206 + group 'colab'
  207 + mode 0640
  208 +
  209 + notifies :restart, 'service[colab]'
  210 +end
  211 +
180 212 # Static files
181 213 directory '/var/lib/colab/assets/spb/' do
182 214 owner 'root'
... ...
cookbooks/colab/templates/gitlab.py.erb
... ... @@ -11,6 +11,11 @@ upstream = &#39;http://&lt;%= node[&#39;peers&#39;][&#39;integration&#39;] %&gt;:81/gitlab/&#39;
11 11 private_token = '<%= @get_private_token.call %>'
12 12 verify_ssl = False
13 13  
  14 +middlewares = [
  15 + 'colab.middlewares.cookie_middleware.CookiePreHandlerMiddleware',
  16 + 'colab.middlewares.cookie_middleware.CookiePostHandlerMiddleware'
  17 +]
  18 +
14 19 urls = {
15 20 'include': 'colab_gitlab.urls',
16 21 'namespace': 'gitlab', # TODO: do not allow to change namespace
... ... @@ -35,7 +40,7 @@ menu_urls = (
35 40 url(display=_('Issues'), viewname='gitlab',
36 41 kwargs={'path': 'dashboard/issues'}, auth=True),
37 42 url(display=_('Merge Requests'), viewname='gitlab',
38   - kwargs={'path': 'merge_requests'}, auth=True),
  43 + kwargs={'path': 'dashboard/merge_requests'}, auth=True),
39 44  
40 45 )
41 46  
... ...
cookbooks/colab/templates/noosfero.py.erb
... ... @@ -10,6 +10,11 @@ verbose_name = &#39;Noosfero Plugin&#39;
10 10  
11 11 upstream = 'http://<%= node['peers']['social'] %>:80/social/'
12 12  
  13 +middlewares = [
  14 + 'colab.middlewares.cookie_middleware.CookiePreHandlerMiddleware',
  15 + 'colab.middlewares.cookie_middleware.CookiePostHandlerMiddleware'
  16 +]
  17 +
13 18 private_token = '<%= @get_private_token.call %>'
14 19  
15 20 urls = {
... ...
cookbooks/colab/templates/super_archives.py.erb 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +
  2 +from django.utils.translation import ugettext_lazy as _
  3 +from colab.plugins.utils.menu import colab_url_factory
  4 +
  5 +name = 'colab_superarchives'
  6 +verbose_name = 'Super Archives'
  7 +
  8 +urls = {
  9 + 'include': 'colab_superarchives.urls',
  10 + 'prefix': '^archives/',
  11 +}
  12 +
  13 +menu_title = _('Groups')
  14 +
  15 +url = colab_url_factory('archives')
  16 +
  17 +menu_urls = (
  18 + url(display=_('Groups'), viewname='thread_list', auth=False),
  19 +)
  20 +
  21 +# Imported settings from colab
  22 +LOCALE_PATHS = ('colab_superarchives/locale',)
  23 +
  24 +# Super Archives
  25 +SUPER_ARCHIVES_PATH = '/var/lib/mailman/archives/private'
  26 +SUPER_ARCHIVES_EXCLUDE = []
  27 +SUPER_ARCHIVES_LOCK_FILE = '/var/lock/colab/import_emails.lock'
... ...
cookbooks/gitlab/recipes/default.rb
... ... @@ -110,6 +110,16 @@ execute &#39;change-cache-owner&#39; do
110 110 only_if 'ls -l /usr/lib/gitlab/tmp/cache | grep root'
111 111 end
112 112  
  113 +execute 'change-assets-owner' do
  114 + command 'chown -R git:git /usr/lib/gitlab/public/assets'
  115 + only_if 'ls -l /usr/lib/gitlab/public/assets | grep root'
  116 +end
  117 +
  118 +execute 'change-gitlab-assets-owner' do
  119 + command 'chown -R git:git /var/lib/gitlab-assets'
  120 + only_if 'ls -l /var/lib/gitlab-assets | grep root'
  121 +end
  122 +
113 123 execute 'precompile-assets' do
114 124 user 'git'
115 125 cwd '/usr/lib/gitlab'
... ...
cookbooks/mailman/files/centos/master.cf
... ... @@ -122,7 +122,12 @@ scache unix - - n - 1 scache
122 122 #scalemail-backend unix - n n - 2 pipe
123 123 # flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store
124 124 # ${nexthop} ${user} ${extension}
125   -#
  125 +
126 126 mailman unix - n n - - pipe
127 127 flags=FR user=mailman:mailman argv=/usr/lib/mailman/bin/postfix-to-mailman.py
128 128 ${nexthop} ${user}
  129 +
  130 +fs_mail unix - n n - - pipe
  131 + flags=F user=spb argv=tee --append /var/tmp/fs_mail.dump
  132 +
  133 +
... ...
cookbooks/mailman/recipes/default.rb
... ... @@ -83,6 +83,16 @@ cookbook_file &#39;/etc/cron.d/mailman-spb&#39; do
83 83 mode 0644
84 84 end
85 85  
  86 +execute 'postfix:disable-send-emails' do
  87 + command "postconf 'default_transport = fs_mail'"
  88 + only_if { node['config']['disable_send_emails'] }
  89 +end
  90 +
  91 +execute 'postfix:enable-send-emails' do
  92 + command "postconf 'default_transport = smtp'"
  93 + not_if { node['config']['disable_send_emails'] }
  94 +end
  95 +
86 96 cookbook_file '/etc/postfix/master.cf' do
87 97 notifies :reload, 'service[postfix]'
88 98 end
... ...
cookbooks/noosfero/recipes/default.rb
... ... @@ -87,6 +87,12 @@ plugins_spb.each do |plugin|
87 87 end
88 88 end
89 89  
  90 +execute 'sisp:environment:prepare' do
  91 + command "RAILS_ENV=production bundle exec rake sisp:prepare ADMINUSER=#{node['config']['admins'].first[1]} DOMAIN=#{node['config']['sisp_external_hostname']}"
  92 + cwd '/usr/lib/noosfero'
  93 + user 'noosfero'
  94 +end
  95 +
90 96 execute 'plugins:activate' do
91 97 command "RAILS_ENV=production bundle exec rake noosfero:plugins:enable_all"
92 98 cwd '/usr/lib/noosfero'
... ...
cookbooks/reverse_proxy/templates/reverse_proxy.conf.erb
... ... @@ -67,6 +67,10 @@ server {
67 67 access_log /var/log/nginx/ssl-<%= node['config']['sisp_external_hostname'] %>.access.log;
68 68 error_log /var/log/nginx/ssl-<%= node['config']['sisp_external_hostname'] %>.error.log;
69 69  
  70 + location = / {
  71 + rewrite ^ /social/search/sisp?sort=asc;
  72 + }
  73 +
70 74 # TODO caching
71 75 location / {
72 76 proxy_pass http://colab;
... ...
local.rake.example
1 1 # copy this file to local.rake and adjust to your local environment
2 2 ENV['CHAKE_RSYNC_OPTIONS'] = '--exclude tmp/dump'
  3 +
  4 +# if you have vagrant lxc installed and want to use it, just copy the settings below to your local.rake
  5 +# and run vagrant up --provider lxc
  6 +#ENV['VAGRANT_BOX'] = 'frensjan/centos-7-64-lxc' #you can figure out a different lxc box if you want
  7 +#ENV['SPB_ENV'] = 'lxc'
... ...
src/colab-spb-plugin/VERSION
1   -5.0a0
  1 +5.0a7
... ...
src/colab-spb-plugin/setup.py
... ... @@ -15,7 +15,7 @@ version = open(&#39;VERSION&#39;).read().strip()
15 15  
16 16 setup(
17 17 name='colab-spb-plugin',
18   - version='0.2.5',
  18 + version=version,
19 19 author='Macartur Sousa',
20 20 author_email='macartur.sc@gmail.com',
21 21 url='https://portal.softwarepublico.gov.br/gitlab/softwarepublico/colab-spb-plugin/',
... ...
src/colab-spb-plugin/src/colab_spb/apps.py
1   -
2 1 from django.apps import AppConfig
  2 +from colab.signals.signals import connect_signal, register_signal
  3 +from celery.utils.log import get_task_logger
  4 +from colab_spb.tasks import list_group_and_repository_creation
  5 +
  6 +logger = get_task_logger(__name__)
3 7  
4 8  
5 9 class SpbAppConfig(AppConfig):
6 10 name = 'colab_spb'
7 11 verbose_name = 'SPB'
  12 + short_name = 'spb'
8 13 namespace = 'spb'
  14 +
  15 + signals_list = ['create_repo', 'create_mail_list']
  16 +
  17 + def register_signal(self):
  18 + logger.info('Signals from {0} registed '.format(self.short_name))
  19 + register_signal(self.short_name, self.signals_list)
  20 +
  21 + def connect_signal(self):
  22 + connect_signal('community_creation', 'noosfero',
  23 + list_group_and_repository_creation)
... ...
src/colab-spb-plugin/src/colab_spb/migrations/0001_initial.py
... ... @@ -9,7 +9,7 @@ class Migration(migrations.Migration):
9 9 dependencies = [
10 10 ('colab_gitlab', '0001_initial'),
11 11 ('colab_noosfero', '__first__'),
12   - ('super_archives', '0002_mailinglist_is_private'),
  12 + ('colab_superarchives', '0002_thread_user'),
13 13 ]
14 14  
15 15 operations = [
... ... @@ -19,7 +19,7 @@ class Migration(migrations.Migration):
19 19 ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
20 20 ('community', models.ForeignKey(to='colab_noosfero.NoosferoCommunity', null=True)),
21 21 ('group', models.ForeignKey(to='colab_gitlab.GitlabGroup', null=True)),
22   - ('mail_list', models.ForeignKey(to='super_archives.MailingList', null=True)),
  22 + ('mail_list', models.ForeignKey(to='colab_superarchives.MailingList', null=True)),
23 23 ],
24 24 options={
25 25 },
... ...
src/colab-spb-plugin/src/colab_spb/models.py
1 1 from colab_gitlab import models as gitlab
2 2 from colab_noosfero import models as noosfero
3   -from colab.super_archives import models as mailman
  3 +from colab_superarchives import models as mailman
4 4 from django.db import models
5 5  
6 6  
... ...
src/colab-spb-plugin/src/colab_spb/tasks.py 0 → 100644
... ... @@ -0,0 +1,162 @@
  1 +import requests
  2 +from unicodedata import normalize, category
  3 +
  4 +from django.conf import settings
  5 +
  6 +from celery.utils.log import get_task_logger
  7 +from colab_superarchives.utils.mailman import create_list
  8 +from colab.celery import app
  9 +from colab_gitlab.models import GitlabGroup
  10 +
  11 +logger = get_task_logger(__name__)
  12 +
  13 +
  14 +def normalize_name(name):
  15 + """
  16 + Removes letters' accents, replaces whitespaces for dash (-), and lowercases
  17 + all letters
  18 + """
  19 + name = name.replace(' ', '-')
  20 +
  21 + if not isinstance(name, unicode):
  22 + name = unicode(name, 'utf-8')
  23 +
  24 + name = ''.join(c for c in normalize('NFD', name) if category(c) != 'Mn')
  25 +
  26 + return name.lower()
  27 +
  28 +
  29 +def create_group_from_community(noosfero_community):
  30 + """ Create a group into Gitlab from a Noosfero's Community"""
  31 +
  32 + group_name = normalize_name(noosfero_community.name)
  33 +
  34 + # If project already exist
  35 + group = GitlabGroup.objects.filter(name=group_name)
  36 + if group:
  37 + return group[0].id
  38 +
  39 + app_config = settings.COLAB_APPS.get('colab_gitlab', {})
  40 + private_token = app_config.get('private_token')
  41 + upstream = app_config.get('upstream', '').rstrip('/')
  42 + verify_ssl = app_config.get('verify_ssl', False)
  43 +
  44 + error_msg = u'Error trying to create group "%s" on Gitlab. Reason: %s'
  45 +
  46 + users_endpoint = '{}/api/v3/groups'.format(upstream)
  47 +
  48 + params = {
  49 + 'name': group_name,
  50 + 'path': noosfero_community.identifier,
  51 + 'private_token': private_token
  52 + }
  53 + group_id = None
  54 + try:
  55 + response = requests.post(users_endpoint, params=params,
  56 + verify=verify_ssl)
  57 + except Exception as excpt:
  58 + reason = 'Request to API failed ({})'.format(excpt)
  59 + logger.error(error_msg, group_name, reason)
  60 + return
  61 +
  62 + if response.status_code != 201:
  63 + if response.status_code is 404:
  64 + pass # TODO: should request the existing group id if error 404
  65 + reason = 'Unknown [{}].'.format(response.status_code)
  66 + logger.error(error_msg, group_name, reason)
  67 + return
  68 + else:
  69 + group_id = response.json().get('id')
  70 + logger.info('Group {0} created'.format(group_name))
  71 +
  72 + return group_id
  73 +
  74 +
  75 +def include_members_into_group(admins, group_id):
  76 + """ Include members from a Noosfero's Community into a Gitlab's group """
  77 +
  78 + app_config = settings.COLAB_APPS.get('colab_gitlab', {})
  79 + private_token = app_config.get('private_token')
  80 + upstream = app_config.get('upstream', '').rstrip('/')
  81 + verify_ssl = app_config.get('verify_ssl', False)
  82 + error_msg = u'Error to include "%s" to create group "%s" on Gitlab. \
  83 + Reason: %s'
  84 +
  85 + user_id = None
  86 + users_endpoint = '{}/api/v3/users'.format(upstream)
  87 + for admin in admins:
  88 + params = {'search': admin.username,
  89 + 'private_token': private_token}
  90 + response = requests.get(users_endpoint, params=params,
  91 + verify=verify_ssl)
  92 + users = response.json()
  93 + # Be sure to get only one
  94 + for user in users:
  95 + if user['username'] == admin.username:
  96 + user_id = user['id']
  97 + break
  98 +
  99 + users_endpoint = '{}/api/v3/groups/{}/members'.format(
  100 + upstream, group_id)
  101 + params = {
  102 + 'user_id': user_id,
  103 + 'access_level': 50, # OWNER = 50
  104 + 'private_token': private_token
  105 + }
  106 + try:
  107 + response = requests.post(users_endpoint, params=params,
  108 + verify=verify_ssl)
  109 + except Exception as excpt:
  110 + reason = 'Request to API failed ({})'.format(excpt)
  111 + logger.error(error_msg, admin.username, reason)
  112 + return
  113 + logger.info('Members included')
  114 +
  115 +
  116 +def create_project(project_name, group_id):
  117 + """ Create a project into Gitlab group """
  118 +
  119 + project_name = normalize_name(project_name)
  120 +
  121 + app_config = settings.COLAB_APPS.get('colab_gitlab', {})
  122 + private_token = app_config.get('private_token')
  123 + upstream = app_config.get('upstream', '').rstrip('/')
  124 + verify_ssl = app_config.get('verify_ssl', False)
  125 + error_msg = u'Error to create project "%s" into Gitlab. Reason: %s'
  126 +
  127 + users_endpoint = '{}/api/v3/projects'.format(upstream)
  128 + params = {
  129 + 'name': project_name,
  130 + 'public': True,
  131 + 'visibility_level': 20, # show to all
  132 + 'namespace_id': group_id,
  133 + 'private_token': private_token
  134 + }
  135 + try:
  136 + requests.post(users_endpoint, params=params,
  137 + verify=verify_ssl)
  138 + except Exception as excpt:
  139 + reason = 'Request to API failed ({})'.format(excpt)
  140 + logger.error(error_msg, project_name, reason)
  141 + return
  142 + logger.info('Project created')
  143 +
  144 +
  145 +@app.task(bind=True)
  146 +def list_group_and_repository_creation(self, **kwargs):
  147 + logger.info('Community created: {0}'.format(''.join(kwargs)))
  148 +
  149 + noosfero_community = kwargs['community']
  150 + admins = noosfero_community.admins.all()
  151 + if not len(admins):
  152 + logger.error('Failed to create list, the software does not '
  153 + 'have an admin.')
  154 + return -1
  155 +
  156 + group_id = create_group_from_community(noosfero_community)
  157 + include_members_into_group(admins, group_id)
  158 + create_project(noosfero_community.name, group_id)
  159 + listname = normalize_name(noosfero_community.name)
  160 + create_list(listname, admins[0])
  161 +
  162 + return 0
... ...
src/colab-spb-plugin/src/colab_spb/templatetags/__init__.py 0 → 100644
src/colab-spb-plugin/src/colab_spb/templatetags/spb_extra.py 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +from django import template
  2 +
  3 +from colab_spb.models import CommunityAssociations
  4 +
  5 +register = template.Library()
  6 +
  7 +@register.simple_tag
  8 +def get_community(mailinglist):
  9 + ml = mailinglist
  10 + community = ""
  11 +
  12 + try:
  13 + community_association = CommunityAssociations.objects.get(mail_list=ml)
  14 + community = community_association.community.name
  15 + except CommunityAssociations.DoesNotExist:
  16 + community = "software"
  17 +
  18 + return community
... ...
src/colab-spb-plugin/src/colab_spb/views.py
1 1 # -*- coding: utf-8 -*-
2 2 from django.shortcuts import render
3 3 from django.http import HttpResponse
4   -from colab.super_archives.models import MailingList, Thread
5   -from colab.accounts.utils import mailman
  4 +from colab_superarchives.models import MailingList, Thread
  5 +from colab_superarchives.utils import mailman
6 6 from colab.accounts.models import User
7 7 from colab_spb.models import CommunityAssociations
8 8  
... ...
src/colab-spb-theme-plugin/Makefile
1 1 PACKAGE = colab-spb-theme
2   -VERSION = 0.3.11
  2 +VERSION = $(shell cat VERSION)
3 3 DISTDIR = dist
4 4 PACKAGE_NAME = $(PACKAGE)-$(VERSION)
5 5 TARBALL = $(PACKAGE_NAME).tar.gz
... ...
src/colab-spb-theme-plugin/VERSION
1   -5.0a0
  1 +5.0a7
... ...
src/colab-spb-theme-plugin/colab_spb_theme/static/css/header.css
... ... @@ -428,7 +428,8 @@ header #sisp-header-quick-access a {
428 428 font-weight: bold;
429 429 }
430 430  
  431 +/*
431 432 header #spb-header-content,
432 433 header #sisp-header-content {
433 434 padding-top: 13px;
434   -}
  435 +} */
... ...
src/colab-spb-theme-plugin/colab_spb_theme/static/css/screen.css
... ... @@ -62,8 +62,10 @@ body {
62 62 bottom: 0;
63 63 }
64 64  
65   -#main-content {
  65 +body div#main-content {
66 66 margin-top: 0;
  67 + padding: 20px 0 60px 0;
  68 + color: #172738;
67 69 }
68 70  
69 71 li hr {
... ... @@ -508,11 +510,6 @@ span.highlighted {
508 510 margin: 0 2px;
509 511 }
510 512  
511   -#main-content {
512   - padding: 40px 0 60px 0;
513   - color: #172738;
514   -}
515   -
516 513 .colab-content {
517 514 max-width: 960px;
518 515 min-width: 960px;
... ... @@ -580,10 +577,22 @@ form.signup {
580 577  
581 578 .signup-help {
582 579 font-size: 16px;
583   - font-family: Arial;
  580 +}
  581 +
  582 +.mailinglist-help,
  583 +.signup-help {
584 584 padding-top: 7px;
  585 + font-family: Arial;
  586 + position: absolute;
  587 +}
585 588  
586   - }
  589 +.mailinglist-help {
  590 + font-size: 15px;
  591 +}
  592 +
  593 +.list-container {
  594 + padding-top: 30px;
  595 +}
587 596  
588 597 a.btn {
589 598 margin: 2px 0 2px 0;
... ...
src/colab-spb-theme-plugin/colab_spb_theme/static/css/search.css
... ... @@ -58,7 +58,7 @@
58 58 text-decoration: none;
59 59 }
60 60  
61   -.btn:hover {
  61 +colab-search-form .btn:hover {
62 62 color: white;
63 63 }
64 64  
... ...
src/colab-spb-theme-plugin/colab_spb_theme/static/js/scroll.js 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +var colab = (function( $ ){
  2 + var $window = $(window);
  3 +
  4 + var sidebar, offset, maxMarginTop, reference,
  5 +
  6 + sidebarScroll = function() {
  7 +
  8 + if($window.scrollTop() > offset.top) {
  9 + var marginTop = $window.scrollTop() - offset.top;
  10 + marginTop = marginTop > maxMarginTop ? maxMarginTop : marginTop;
  11 +
  12 + sidebar.stop().animate({
  13 + marginTop: marginTop
  14 + });
  15 + } else {
  16 + sidebar.stop().animate({
  17 + marginTop: 0
  18 + });
  19 + }
  20 + },
  21 +
  22 + init = function(sidebarSelector, referenceSelector) {
  23 + sidebar = $(sidebarSelector);
  24 + reference = $(referenceSelector);
  25 + offset = sidebar.offset();
  26 + maxMarginTop = reference.height() - sidebar.height();
  27 +
  28 + $window.scroll(function() {
  29 + sidebarScroll();
  30 + });
  31 + };
  32 +
  33 +
  34 + return {
  35 + init: init
  36 + };
  37 +})( jQuery );
... ...
src/colab-spb-theme-plugin/colab_spb_theme/templates/accounts/user_create_form.html
1 1 {% extends "base.html" %}
2   -{% load i18n %}
  2 +{% load i18n staticfiles %}
  3 +
  4 +{% block head_js %}
  5 + <script src="{% static 'js/scroll.js' %}"></script>
  6 +{% endblock %}
  7 +
  8 +{% block title %}Cadastre-se - SPB{% endblock %}
3 9 {% block main-content %}
4 10 <div class="colab-content container">
5 11 <h2>Cadastre-se</h2>
... ... @@ -9,6 +15,7 @@
9 15 {% csrf_token %}
10 16 <div class="row">
11 17 <div class="col-md-6 col-lg-6 col-sm-6 col-xs-12">
  18 + <div class="signup-fields">
12 19 <fieldset>
13 20 {% for field in user_form %}
14 21 <div class="form-group{% if field.field.required %} required{% endif %}{% if field.errors %} alert alert-danger has-error{% endif %}">
... ... @@ -22,17 +29,22 @@
22 29 </fieldset>
23 30  
24 31 <input type="submit" value="Cadastrar" id="btn-cadastrar" class="btn btn-primary">
  32 + </div>
25 33 </div>
26 34 <div class="col-md-6 col-lg-6 col-sm-6 col-xs-12">
27 35 <div style="border-left: 1px solid #ccc; padding-left: 52px; min-height: 450px">
28 36 <div class="signup-help">
29   - <p>Em caso de dúvidas visite a seção de <a href="/social/spb/ajuda#faq">Ajuda</a></p>
  37 + <p>Em caso de dúvidas, visite a seção de <a href="/social/spb/ajuda#faq">Ajuda</a></p>
30 38 <hr>
31   - <p>Caso ainda permaneça com dúvidas, fique à vontade para entrar em contato conosco através do email <a href="mailto:admin@softwarepublico.gov.br">admin@softwarepublico.gov.br</a></p>
  39 + <p>Caso ainda permaneça com dúvidas, fique à vontade para entrar em contato conosco através do email: <a href="mailto:admin@softwarepublico.gov.br">admin@softwarepublico.gov.br</a></p>
32 40 </div>
33 41 </div>
34 42 </div>
35 43 </div>
36 44 </form>
37 45 </div>
  46 +
  47 + <script>
  48 + $(colab.init('.signup-help', '.signup-fields'));
  49 + </script>
38 50 {% endblock %}
... ...
src/colab-spb-theme-plugin/colab_spb_theme/templates/footer_sisp.html
... ... @@ -10,65 +10,14 @@
10 10 <div id="footer" role="contentinfo">
11 11 <a name="afooter" id="afooter"></a>
12 12 <div id="doormat-container" class="columns-4">
13   - <div class="doormatColumn column-0">
14   - <dl class="doormatSection">
15   - <dt class="doormatSectionHeader">Assuntos</dt>
16   - <dd class="doormatSectionBody">
17   - <a href="/social/sisp/publique-seu-software" class="external-link">Publique seu software</a>
18   - </dd>
19   - <!--
20   - <dd class="doormatSectionBody">
21   - <a href="http://antigo.softwarepublico.gov.br/mpv/" class="external-link">Prestadores de serviço</a>
22   - </dd>
23   - -->
24   - </dl>
25   - </div>
26   - <div class="doormatColumn column-1">
27   - <dl class="doormatSection">
28   - <dt class="doormatSectionHeader">Portal do SISP</dt>
29   - <dd class="doormatSectionBody">
30   - <a href="/social/sisp/entenda-o-que-e" class="external-link">Entenda o que é</a>
31   - </dd>
32   - <!--
33   - <dd class="doormatSectionBody">
34   - <a href="/social/profile/sisp/events" class="external-link">Eventos</a>
35   - </dd>
36   - -->
37   - </dl>
38   - </div>
39   - <div class="doormatColumn column-2">
40   - <dl class="doormatSection">
41   - <dt class="doormatSectionHeader">Serviços</dt>
42   - <dd class="doormatSectionBody">
43   - <a href="/social/sisp/ajuda#faq" class="external-link">FAQ</a>
44   - </dd>
45   - <dd class="doormatSectionBody">
46   - <a href="/social/sisp/contato" class="external-link">Contato</a>
47   - </dd>
48   - <!--
49   - <dd class="doormatSectionBody">
50   - <a href="/archives/thread/sisp-usuarios/relatar-erros#msg-1635" class="external-link">Relatar erros</a>
51   - </dd>
52   - -->
53   - </dl>
54   - </div>
55   - <div class="doormatColumn column-3">
56   - <dl class="doormatSection">
57   - <dt class="doormatSectionHeader">RSS</dt>
58   - <dd class="doormatSectionBody">
59   - <a href="/social/sisp/rss/o-que-e" class="external-link">O que é?</a>
60   - </dd>
61   - <dd class="doormatSectionBody">
62   - <a href="/rss/colab/latest" class="external-link">Assine</a>
63   - </dd>
64   - </dl>
  13 + <div class ="doormatColumn column-0">
65 14 <dl class="doormatSection">
66 15 <dt class="doormatSectionHeader">Navegação</dt>
67 16 <dd class="doormatSectionBody">
68   - <a href="/social/sisp/acessibilidade" class="external-link">Acessibilidade</a>
  17 + <a href="" onclick="return false;" class="external-link">Acessibilidade</a>
69 18 </dd>
70 19 <dd class="doormatSectionBody">
71   - <a href="/social/sisp/mapa-do-site" class="external-link">Mapa do site</a>
  20 + <a href="" onclick="return false;" class="external-link">Mapa do site</a>
72 21 </dd>
73 22 </dl>
74 23 </div>
... ...
src/colab-spb-theme-plugin/colab_spb_theme/templates/header_sisp.html
... ... @@ -8,9 +8,6 @@
8 8 </div>
9 9 <script src="//barra.brasil.gov.br/barra.js" type="text/javascript" defer async></script>
10 10 <div id="header" role="banner">
11   - <div id="sisp-header-quick-access">
12   - <p class='pull-right'>Acesso rápido: <a href="{{ SPB_PORTAL }}">Software Público Brasileiro</a></p>
13   - </div>
14 11 <div id="sisp-header-content">
15 12 <ul id="accessibility">
16 13 <li>
... ... @@ -49,7 +46,7 @@
49 46 <div id="second-nav">
50 47 <ul id="portal-siteactions">
51 48 <li id="siteaction-accessibility">
52   - <a href="/social/sisp/acessibilidade" title="Acessibilidade" accesskey="5">
  49 + <a href="" onclick="return false;" title="Acessibilidade" accesskey="5">
53 50 Acessibilidade
54 51 </a>
55 52 </li>
... ... @@ -59,7 +56,7 @@
59 56 </a>
60 57 </li>
61 58 <li id="siteaction-mapadosite">
62   - <a href="/social/sisp/mapa-do-site" title="Mapa do Site" accesskey="7">
  59 + <a href="" onclick="return false;" title="Mapa do Site" accesskey="7">
63 60 Mapa do Site
64 61 </a>
65 62 </li>
... ... @@ -67,8 +64,7 @@
67 64 </div>
68 65 <div id="logo">
69 66 <a id="portal-logo" title="" href="/">
70   - <span id="portal-title-1">Portal do</span>
71   - <h1 id="portal-title" class="corto">SISP</h1>
  67 + <h1 id="portal-title" class="corto">Catálogo do SISP</h1>
72 68 <span id="portal-description">MINISTÉRIO DO PLANEJAMENTO, ORÇAMENTO E GESTÃO</span>
73 69 </a>
74 70 </div>
... ...
src/colab-spb-theme-plugin/colab_spb_theme/templates/header_spb.html
... ... @@ -8,9 +8,6 @@
8 8 </div>
9 9 <script src="//barra.brasil.gov.br/barra.js" type="text/javascript" defer async></script>
10 10 <div id="header" role="banner">
11   - <div id="spb-header-quick-access">
12   - <p class='pull-right'>Acesso rápido: <a href="{{ SISP_PORTAL }}">Portal do SISP</a></p>
13   - </div>
14 11 <div id="spb-header-content">
15 12 <ul id="accessibility">
16 13 <li>
... ...
src/colab-spb-theme-plugin/colab_spb_theme/templates/mailinglist-summary.html
1 1 {% extends 'base.html' %}
2   -{% load i18n tz superarchives %}
  2 +{% load i18n tz superarchives staticfiles spb_extra %}
  3 +
  4 +{% block head_js %}
  5 + <script src="{% static 'js/scroll.js' %}"></script>
  6 +{% endblock %}
  7 +
  8 +{% block title %}{{ mailinglist.name|title }} - Listas de discussão - SPB{% endblock %}
  9 +
  10 +{% block title %}{{ mailinglist.name|title }}{% endblock %}
3 11  
4 12 {% block main-content %}
5 13 <div class="colab-content container">
... ... @@ -44,19 +52,37 @@
44 52 {% endblock %}
45 53  
46 54 {% block mailinglist_view_thread_list %}
47   - {% for thread in thread_list %}
48   - <div class="row colab-thread">
49   - <div class="col-md-12 colab-thread">
50   - <small class="colab-thread-modified-time">{{ thread.latest_message.received_time|date:"d F Y" }} {% trans "at" %} {{thread.latest_message.received_time|date:"h:m" }} - <a class="colab-thread-modified-author" href="{{thread.latest_message.author_url}}">{{thread.latest_message.author }}</a>
51   - </small><br>
52   - <h4><a class="colab-thread-subject" href="{{thread.get_absolute_url}}">{{ thread.latest_message.subject_clean }}</h4>
53   - {% with thread.latest_message.body|truncatechars:"85" as description %}
54   - <span class="colab-thread-latest-message">{{description | default_if_none:"a"}}</span></a><br>
55   - {% endwith %}
56   - <hr/>
  55 + <div class="row">
  56 + <div class="list-container">
  57 + <div class="col-md-8">
  58 + <div class="thread-list">
  59 + <div style="border-right: 1px solid #ccc; padding-right: 32px; min-height: 450px">
  60 + {% for thread in thread_list %}
  61 + <div class="row colab-thread">
  62 + <div class="col-md-12 colab-thread">
  63 + <small class="colab-thread-modified-time">{{ thread.latest_message.received_time|date:"d F Y" }} {% trans "at" %} {{thread.latest_message.received_time|date:"h:m" }} - <a class="colab-thread-modified-author" href="{{thread.latest_message.author_url}}">{{thread.latest_message.author }}</a>
  64 + </small><br>
  65 + <h4><a class="colab-thread-subject" href="{{thread.get_absolute_url}}">{{ thread.latest_message.subject_clean }}</h4>
  66 + {% with thread.latest_message.body|truncatechars:"85" as description %}
  67 + <span class="colab-thread-latest-message">{{description | default_if_none:"a"}}</span></a><br>
  68 + {% endwith %}
  69 + <hr/>
  70 + </div>
  71 + </div>
  72 + {% endfor %}
  73 + </div>
  74 + </div>
  75 + </div>
  76 +
  77 + <div class="col-md-4">
  78 + <div class="mailinglist-help">
  79 + <p>Em caso de dúvidas, visite o <a href="/social/{% get_community mailinglist %}/como-participar-da-lista-de-discussao">Guia de Uso</a></p>
  80 + <hr>
  81 + <p>Caso ainda permaneça com dúvidas, fique à vontade para entrar em contato conosco através do email: <a href="mailto:admin@softwarepublico.gov.br">admin@softwarepublico.gov.br</a></p>
  82 + </div>
57 83 </div>
58 84 </div>
59   - {% endfor %}
  85 + </div>
60 86 {% endblock %}
61 87  
62 88 {% block mailinglist_view_paginator %}
... ... @@ -109,4 +135,9 @@
109 135 {% endif %}
110 136 {% endblock %}
111 137 </div>
  138 +
  139 + <script>
  140 + $(colab.init('.mailinglist-help', '.thread-list'));
  141 + </script>
  142 +
112 143 {% endblock %}
... ...
src/colab-spb-theme-plugin/colab_spb_theme/templates/registration/login.html 0 → 100644
... ... @@ -0,0 +1,61 @@
  1 +{% extends 'base.html' %}
  2 +{% load i18n tz superarchives %}
  3 +
  4 +{% block title %}Login - SPB{% endblock %}
  5 +
  6 +{% block main-content %}
  7 +<div class="row">
  8 + {% if form.errors %}
  9 + {% if form.errors.items|length == 1 %}
  10 + <div class="alert alert-danger">
  11 + <b>{% trans "Please correct the error below and try again." %}</b>
  12 + </div>
  13 + {% else %}
  14 + <div class="alert alert-danger">
  15 + <b>{% trans "Please correct the errors below and try again." %}</b>
  16 + </div>
  17 + {% endif %}
  18 + {% endif %}
  19 +
  20 + {% for error in form.non_field_errors %}
  21 + <div class="alert alert-danger">
  22 + {{ error }}
  23 + </div>
  24 + {% endfor %}
  25 +</div>
  26 +
  27 +
  28 +<br>
  29 +<form action="{% url 'login' %}" method="post" role="form" class="form-horizontal signup">
  30 + {% csrf_token %}
  31 +
  32 + <div class="row">
  33 + <div class="col-md-4 col-md-offset-4 col-lg-4 col-lg-4 col-sm-8 col-sm-offset-2 col-xs-12">
  34 + <div class="panel panel-default">
  35 + <div class="panel-heading"><h3 class="panel-title">{% trans 'Login' %}</h3></div>
  36 +
  37 + <div class="panel-body">
  38 + <div class="form-group{% if form.username.errors %} alert alert-danger has-error{% endif %}">
  39 + {{ form.username.label_tag }}
  40 + <input class="form-control" id="id_username" maxlength="254" name="username" type="text">
  41 + {{ form.username.errors }}
  42 + </div>
  43 + <div class="form-group{% if form.password.errors %} alert alert-danger has-error{% endif %}">
  44 + {{ form.password.label_tag }}
  45 + <input class="form-control" id="id_password" name="password" type="password">
  46 + {{ form.password.errors }}
  47 + </div>
  48 + </div>
  49 + </div>
  50 + </div>
  51 + </div>
  52 +
  53 + <div class="row">
  54 + <div class="submit">
  55 + <input type="submit" value="{% trans 'Login' %}" class="btn btn-primary btn-lg btn-block">
  56 + </div>
  57 + <p class="text-center"><a href="{% url 'password_reset' %}">{% trans 'Forgot Password?' %}</a></p>
  58 + </div>
  59 +
  60 +</form>
  61 +{% endblock %}
... ...
src/colab-spb-theme-plugin/colab_spb_theme/templates/search/search.html
... ... @@ -2,7 +2,7 @@
2 2 {% load i18n tz highlight superarchives search_preview_templates %}
3 3 {% load static from staticfiles %}
4 4  
5   -{% block title %}{% trans 'search'|title %}{% endblock %}
  5 +{% block title %}{% trans 'search'|title %} - SPB{% endblock %}
6 6  
7 7 {% block head_js %}
8 8 <script type="text/javascript" src="{% static 'third-party/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js' %}"></script>
... ... @@ -107,7 +107,7 @@
107 107 {% if page.has_previous %}
108 108 {% if page.previous_page_number > 1 %}
109 109 <li>
110   - <a href="{% append_to_get page=page.previous_page_number|add:-2 %}">{{ page.number|add:-2 }}</a>
  110 + <a href="{% append_to_get page=page.previous_page_number|add:-1 %}">{{ page.number|add:-2 }}</a>
111 111 </li>
112 112 {% endif %}
113 113 <li>
... ...
src/colab-spb-theme-plugin/colab_spb_theme/templates/superarchives/thread-dashboard.html
1 1 {% extends 'base.html' %}
2 2 {% load i18n %}
3 3  
4   -{% block title %}Listas de discussão{% endblock %}
  4 +{% block title %}Listas de discussão - SPB{% endblock %}
5 5  
6 6 {% block main-content %}
7 7 <div class="colab-content container">
... ... @@ -25,7 +25,7 @@
25 25 {% endfor %}
26 26 </ul>
27 27 <div class="text-right">
28   - <a href="{% url 'haystack_search' %}?order=latest&list={{ mailinglist.name }}&type=thread">
  28 + <a href="{% url 'haystack_search' %}?order=latest&tag={{ mailinglist.name }}&type=thread">
29 29 {% trans "more..." %}
30 30 </a>
31 31 </div>
... ... @@ -39,7 +39,7 @@
39 39 {% endfor %}
40 40 </ul>
41 41 <div class="text-right">
42   - <a href="{% url 'haystack_search' %}?list={{ mailinglist.name }}&type=thread">
  42 + <a href="{% url 'haystack_search' %}?tag={{ mailinglist.name }}&type=thread">
43 43 {% trans "more..." %}
44 44 </a>
45 45 </div>
... ...
src/noosfero-spb/Makefile
1 1 PACKAGE = noosfero-spb
2   -VERSION = 4.2.12
  2 +VERSION = $(shell cat VERSION)
3 3 DISTDIR = $(PACKAGE)-$(VERSION)
4 4 TARBALL = $(DISTDIR).tar.gz
5 5  
... ... @@ -11,9 +11,10 @@ themes_dir=/usr/lib/noosfero/public/designs/themes
11 11 noosfero_dir=/usr/lib/noosfero
12 12  
13 13 dist: clean
14   - mkdir $(DISTDIR)
15   - tar --exclude=.git --exclude=$(DISTDIR) -cf - * | (cd $(DISTDIR) && tar xaf -)
16   - tar --exclude=.git -czf $(TARBALL) $(DISTDIR)
  14 + mkdir -p dist/$(DISTDIR)
  15 + tar --exclude=.git --exclude=$(DISTDIR) -cf - * | (cd dist/$(DISTDIR) && tar xaf -)
  16 + cd dist/ && tar --exclude=.git -czf $(TARBALL) $(DISTDIR)
  17 + $(RM) -r $(DISTDIR)
17 18  
18 19 clean:
19 20 $(RM) -r dist/
... ...
src/noosfero-spb/VERSION
1   -5.0a0
  1 +5.0a7
... ...
src/noosfero-spb/gov_user/controllers/gov_user_plugin_controller.rb
... ... @@ -5,6 +5,8 @@ class GovUserPluginController &lt; ApplicationController
5 5 :governmental_sphere, :governmental_power, :juridical_nature, :sisp
6 6 ]
7 7  
  8 + protect "create_institution_admin", :environment
  9 +
8 10 def hide_registration_incomplete_percentage
9 11 response = false
10 12  
... ... @@ -65,7 +67,10 @@ class GovUserPluginController &lt; ApplicationController
65 67 def get_institutions
66 68 redirect_to "/" if !request.xhr? || params[:query].blank?
67 69  
68   - institutions = Institution.search_institution(params[:query]).select([:id, :name])
  70 + selected_institutions = Institution.where(id: params[:selected_institutions]).select([:id, :name])
  71 + institutions = Institution.search_institution(params[:query], environment).select("institutions.id, institutions.name")
  72 + institutions -= selected_institutions
  73 +
69 74 institutions_list = institutions.map { |institution|
70 75 {:value=>institution.name, :id=>institution.id}
71 76 }
... ...
src/noosfero-spb/gov_user/controllers/gov_user_plugin_myprofile_controller.rb
1 1 class GovUserPluginMyprofileController < MyProfileController
2 2 append_view_path File.join(File.dirname(__FILE__) + '/../views')
3 3  
  4 + protect "edit_institution", :profile
  5 +
4 6 def index
5 7 end
6 8  
... ... @@ -19,7 +21,7 @@ class GovUserPluginMyprofileController &lt; MyProfileController
19 21  
20 22 def update_institution
21 23 @institution.community.update_attributes(params[:community])
22   - @institution.update_attributes(params[:institutions].except(:governmental_power, :governmental_sphere, :juridical_nature))
  24 + @institution.update_attributes(params[:institutions].except(:governmental_power, :governmental_sphere, :juridical_nature).merge({:name => params[:community][:name]}))
23 25 if @institution.type == "PublicInstitution"
24 26 begin
25 27 governmental_updates
... ...
src/noosfero-spb/gov_user/db/migrate/20160112174948_applies_accentuation_on_models_without_them.rb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +#encoding: utf-8
  2 +
  3 +class AppliesAccentuationOnModelsWithoutThem < ActiveRecord::Migration
  4 + def up
  5 + execute "UPDATE governmental_powers SET name = 'Judiciário' WHERE name = 'Judiciario'"
  6 + execute "UPDATE governmental_powers SET name = 'Não se Aplica' WHERE name = 'Nao se Aplica'"
  7 +
  8 + execute "UPDATE juridical_natures SET name = 'Administração Direta' WHERE name = 'Administracao Direta'"
  9 + execute "UPDATE juridical_natures SET name = 'Empresa Pública' WHERE name = 'Empresa Publica'"
  10 + execute "UPDATE juridical_natures SET name = 'Fundação' WHERE name = 'Fundacao'"
  11 + execute "UPDATE juridical_natures SET name = 'Orgão Autônomo' WHERE name = 'Orgao Autonomo'"
  12 + end
  13 +
  14 + def down
  15 + say "This migration has no back state"
  16 + end
  17 +end
... ...
src/noosfero-spb/gov_user/db/migrate/20160113194207_fix_institutions_with_wrong_country.rb 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +class FixInstitutionsWithWrongCountry < ActiveRecord::Migration
  2 + def up
  3 + select_all("SELECT id, data FROM profiles WHERE type = 'Community'").each do |community|
  4 + settings = YAML.load(community['data'] || {}.to_yaml)
  5 + if !settings[:country].nil? && settings[:country].downcase == "brasil"
  6 + settings[:country] = 'BR'
  7 + assignments = ActiveRecord::Base.send(:sanitize_sql_for_assignment, {:data => settings.to_yaml})
  8 + update("UPDATE profiles SET %s WHERE id = %d" % [assignments, community['id']])
  9 + end
  10 + end
  11 + end
  12 +
  13 + def down
  14 + say "This migration can't be reverted."
  15 + end
  16 +end
... ...
src/noosfero-spb/gov_user/db/migrate/20160120185910_fix_communities_with_wrong_state.rb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +class FixCommunitiesWithWrongState < ActiveRecord::Migration
  2 + def up
  3 + select_all("SELECT id, data FROM profiles WHERE type = 'Community'").each do |community|
  4 + settings = YAML.load(community['data'] || {}.to_yaml)
  5 + new_state = Institution::VALID_STATES[settings[:state].upcase] if settings[:state].present?
  6 +
  7 + if new_state.present?
  8 + settings[:state] = new_state
  9 + assignments = ActiveRecord::Base.send(:sanitize_sql_for_assignment, {:data => settings.to_yaml})
  10 + update("UPDATE profiles SET %s WHERE id = %d" % [assignments, community['id']])
  11 + end
  12 + end
  13 + end
  14 +
  15 + def down
  16 + say "This migration can't be reverted."
  17 + end
  18 +end
... ...
src/noosfero-spb/gov_user/features/institution_registration.feature
... ... @@ -5,9 +5,12 @@ Feature: Institution Field
5 5  
6 6 Background:
7 7 Given "GovUserPlugin" plugin is enabled
  8 + And "SoftwareCommunitiesPlugin" plugin is enabled
8 9 And I am logged in as mpog_admin
  10 + And I go to /admin/environment_themes/set/noosfero-spb-theme
9 11 And I go to /admin/plugins
10 12 And I check "GovUserPlugin"
  13 + And I check "SoftwareCommunitiesPlugin"
11 14 And I press "Save changes"
12 15 And Institutions has initial default values on database
13 16 And I am logged in as mpog_admin
... ... @@ -27,6 +30,19 @@ Feature: Institution Field
27 30 And I should see "CNPJ"
28 31 And I should see "Acronym"
29 32 And I choose "Public Institution"
30   - Then I should see "Governmental Sphere:"
31   - And I should see "Governmental Power:"
32   - And I should see "Juridical Nature:"
  33 + Then I should see "Governmental Sphere"
  34 + And I should see "Governmental Power"
  35 + And I should see "Juridical Nature"
  36 +
  37 + @selenium
  38 + Scenario: Clean state and city values when country is diferent of Brazil
  39 + Given I follow "Edit Profile"
  40 + When I follow "Create new institution"
  41 + And I select "Brazil" from "community_country"
  42 + And I select "Distrito Federal" from "community_state"
  43 + And I fill in "community_city" with "Gama"
  44 + And I select "United States" from "community_country"
  45 + Then I should not see "community_state"
  46 + And I should not see "community_city"
  47 + And I select "Brazil" from "community_country"
  48 + Then I should not see "Gama"
... ...
src/noosfero-spb/gov_user/features/rate_community.feature
... ... @@ -27,8 +27,8 @@ Feature: rate_community
27 27 And Institutions has initial default values on database
28 28 And the following public institutions
29 29 | name | acronym | country | state | city | cnpj | juridical_nature | governmental_power | governmental_sphere | corporate_name |
30   - | Ministerio das Cidades | MC | BR | DF | Gama | 58.745.189/0001-21 | Autarquia | Executivo | Federal | Ministerio das Cidades |
31   - | Ministerio do Planejamento | MP | BR | DF | Brasilia | 41.769.591/0001-43 | Autarquia | Judiciario | Federal | Ministerio do Planejamento |
  30 + | Ministerio das Cidades | MC | BR | Distrito Federal | Gama | 58.745.189/0001-21 | Autarquia | Executivo | Federal | Ministerio das Cidades |
  31 + | Ministerio do Planejamento | MP | BR | Distrito Federal | Brasilia | 41.769.591/0001-43 | Autarquia | Judiciario | Federal | Ministerio do Planejamento |
32 32  
33 33 Scenario: display message on task when a rating with the same institution exists on the same software
34 34 Given the following organization ratings
... ... @@ -38,7 +38,7 @@ Feature: rate_community
38 38 And I go to mycommunity's control panel
39 39 And I follow "Process requests" within ".pending-tasks"
40 40 And I choose "Accept" within ".task_decisions"
41   - Then I should see "This instiution already has an accepted rating" in the page
  41 + Then I should see "This institution already has an accepted rating" in the page
42 42  
43 43 Scenario: do not display message on task when a rating with the same institution does not exist on the same software
44 44 Given the following organization ratings
... ...
src/noosfero-spb/gov_user/features/rating_institution_registration.feature
... ... @@ -8,6 +8,7 @@ Feature: Create institution on user report
8 8 And "SoftwareCommunitiesPlugin" plugin is enabled
9 9 And "OrganizationRatings" plugin is enabled
10 10 And I am logged in as mpog_admin
  11 + And I go to /admin/environment_themes/set/noosfero-spb-theme
11 12 And I go to /admin/plugins
12 13 And I check "GovUserPlugin"
13 14 And I check "SoftwareCommunitiesPlugin"
... ... @@ -23,20 +24,20 @@ Feature: Create institution on user report
23 24 And I should not see "Number of Beneficiaries"
24 25 And I should not see "Saved resources"
25 26 And I should not see "Organization name or Enterprise name"
26   - When I click on anything with selector "#comments-additional-information"
27   - Then I should see "Number of Beneficiaries"
28   - And I should see "Organization name or Enterprise name"
29   - And I should see "Saved resources"
  27 + When I click on anything with selector "comments-additional-information"
  28 + Then I should see "Número de beneficiados"
  29 + And I should see "Nome do órgão ou empresa"
  30 + And I should see "Recursos economizados"
30 31  
31 32 @selenium
32 33 Scenario: Show new institution fields when clicked in add new institution
33 34 Given I go to /profile/noosfero/plugin/organization_ratings/new_rating
34   - And I click on anything with selector "#comments-additional-information"
  35 + And I sleep for 1 seconds
  36 + And I click on anything with selector "comments-additional-information"
35 37 And I fill in "input_institution" with "None institution"
36 38 And I sleep for 2 seconds
37 39 When I follow "Add"
38   - Then I should see "New Institution"
39   - And I should see "Public Institution"
  40 + Then I should see "Public Institution"
40 41 And I should see "Private Institution"
41 42 And I should see "Corporate Name"
42 43 And I should see "Name"
... ... @@ -46,33 +47,30 @@ Feature: Create institution on user report
46 47 And I should see "CNPJ"
47 48 And I should see "Acronym"
48 49 And I choose "Public Institution"
49   - And I should see "Governmental Sphere:"
50   - And I should see "Governmental Power:"
51   - And I should see "Juridical Nature:"
  50 + And I should see "Governmental Sphere"
  51 + And I should see "Governmental Power"
  52 + And I should see "Juridical Nature"
52 53  
53 54 @selenium
54 55 Scenario: Create new institution with name changed in the modal
55 56 Given I go to /profile/noosfero/plugin/organization_ratings/new_rating
56   - And I click on anything with selector "#comments-additional-information"
  57 + And I sleep for 1 seconds
  58 + And I click on anything with selector "comments-additional-information"
57 59 And I fill in "input_institution" with "None institution"
58 60 And I sleep for 2 seconds
59   - When I click on anything with selector "#create_institution_link"
  61 + When I click on anything with selector "create_institution_link"
60 62 And I fill in "community_name" with "Noosfero Institution"
61   - And I select "United States" from "#community_country"
62   - And I follow "#save_institution_button"
  63 + And I select "United States" from "Country"
  64 + And I sleep for 1 seconds
  65 + And I follow "Save"
63 66 Then I should see "Noosfero Institution"
64 67  
65 68 @selenium
66 69 Scenario: Check new institution name in the modal
67 70 Given I go to /profile/noosfero/plugin/organization_ratings/new_rating
68   - And I click on anything with selector "#comments-additional-information"
  71 + And I sleep for 1 seconds
  72 + And I click on anything with selector "comments-additional-information"
69 73 And I fill in "input_institution" with "None institution"
70 74 And I sleep for 2 seconds
71   - When I click on anything with selector "#create_institution_link"
72   - Then I should see "None Institution" within "community_name"
73   -
74   -
75   -
76   -
77   -
78   -
  75 + When I click on anything with selector "create_institution_link"
  76 + Then I should see "None institution" in "Corporate Name" field
... ...
src/noosfero-spb/gov_user/features/user_profile_edition.feature
... ... @@ -5,12 +5,15 @@ Feature: Institution Field
5 5  
6 6 Background:
7 7 Given "GovUserPlugin" plugin is enabled
  8 + And "SoftwareCommunitiesPlugin" plugin is enabled
8 9 And the following users
9 10 | login | name |
10 11 | joao | Joao Silva |
11 12 And I am logged in as admin
  13 + And I go to /admin/environment_themes/set/noosfero-spb-theme
12 14 And I go to /admin/plugins
13 15 And I check "GovUserPlugin"
  16 + And I check "SoftwareCommunitiesPlugin"
14 17 And I press "Save changes"
15 18 And feature "skip_new_user_email_confirmation" is enabled on environment
16 19 And I go to /admin/features/manage_fields
... ... @@ -21,16 +24,16 @@ Feature: Institution Field
21 24 And Institutions has initial default values on database
22 25 And the following public institutions
23 26 | name | acronym | country | state | city | cnpj | juridical_nature | governmental_power | governmental_sphere | corporate_name |
24   - | Ministerio das Cidades | MC | BR | DF | Gama | 58.745.189/0001-21 | Autarquia | Executivo | Federal | Ministerio das Cidades |
25   - | Governo do DF | GDF | BR | DF | Taguatinga | 12.645.166/0001-44 | Autarquia | Legislativo | Federal | Governo do DF |
26   - | Ministerio do Planejamento | MP | BR | DF | Brasilia | 41.769.591/0001-43 | Autarquia | Judiciario | Federal | Ministerio do Planejamento |
  27 + | Ministerio das Cidades | MC | BR | Distrito Federal | Gama | 58.745.189/0001-21 | Autarquia | Executivo | Federal | Ministerio das Cidades |
  28 + | Governo do DF | GDF | BR | Distrito Federal | Taguatinga | 12.645.166/0001-44 | Autarquia | Legislativo | Federal | Governo do DF |
  29 + | Ministerio do Planejamento | MP | BR | Distrito Federal | Brasilia | 41.769.591/0001-43 | Autarquia | Judiciario | Federal | Ministerio do Planejamento |
27 30  
  31 + @selenium
28 32 Scenario: Go to control panel when clicked on 'Complete your profile' link
29 33 Given I am logged in as "joao"
30 34 And I am on joao's control panel
31 35 When I follow "Complete your profile"
32 36 Then I should see "Profile settings for "
33   - And I should see "Personal information"
34 37  
35 38 @selenium
36 39 Scenario: Verify text information to use governmental e-mail
... ... @@ -44,13 +47,12 @@ Feature: Institution Field
44 47 Given I am logged in as "joao"
45 48 And I am on joao's control panel
46 49 When I follow "Edit Profile"
47   - And I follow "Add new institution"
48 50 And I type in "Minis" in autocomplete list "#input_institution" and I choose "Ministerio do Planejamento"
49   - And I follow "Add new institution"
  51 + And I follow "Add institution"
50 52 And I type in "Gover" in autocomplete list "#input_institution" and I choose "Governo do DF"
51   - And I follow "Add new institution"
52   - Then I should see "Ministerio do Planejamento" within ".institutions_added"
53   - And I should see "Governo do DF" within ".institutions_added"
  53 + And I follow "Add institution"
  54 + Then I should see "Ministerio do Planejamento"
  55 + And I should see "Governo do DF"
54 56  
55 57 @selenium
56 58 Scenario: Verify if field 'city' is shown when Brazil is selected
... ... @@ -75,3 +77,14 @@ Feature: Institution Field
75 77 And I fill in "input_institution" with "Some Nonexistent Institution"
76 78 And I sleep for 1 seconds
77 79 Then I should see "No institution found"
  80 +
  81 + @selenium
  82 + Scenario: Does not suggest institution that already exists
  83 + Given I am logged in as "joao"
  84 + And I am on joao's control panel
  85 + When I follow "Edit Profile"
  86 + And I type in "Minis" in autocomplete list "#input_institution" and I choose "Ministerio do Planejamento"
  87 + And I follow "Add institution"
  88 + And I fill in "input_institution" with "Minis"
  89 + And I sleep for 1 seconds
  90 + Then I should not see "Ministerio do Planejamento" within "ul.ui-autocomplete"
... ...