diff options
| -rw-r--r-- | app/controllers/calendars_controller.rb | 4 | ||||
| -rw-r--r-- | app/models/chouette/vehicle_journey.rb | 9 | ||||
| -rw-r--r-- | app/views/calendars/_filters.html.slim | 2 | ||||
| -rw-r--r-- | install/README | 9 | ||||
| -rwxr-xr-x | install/deploy-helper.sh | 102 | ||||
| -rw-r--r-- | install/sidekiq-stif-boiv.service | 52 | ||||
| -rwxr-xr-x | install/stif-boiv-setup.sh | 84 | ||||
| -rw-r--r-- | install/stif-boiv.conf | 38 | ||||
| -rw-r--r-- | install/template-stif-boiv.sql | 11 | ||||
| -rw-r--r-- | lib/tasks/install.rake | 18 | ||||
| -rw-r--r-- | spec/features/calendars_spec.rb | 10 | ||||
| -rw-r--r-- | spec/models/chouette/vehicle_journey_spec.rb | 12 | 
12 files changed, 341 insertions, 10 deletions
| diff --git a/app/controllers/calendars_controller.rb b/app/controllers/calendars_controller.rb index 5370d9cbb..86d567882 100644 --- a/app/controllers/calendars_controller.rb +++ b/app/controllers/calendars_controller.rb @@ -33,10 +33,8 @@ class CalendarsController < BreadcrumbController    def collection      return @calendars if @calendars -    scope = Calendar.where('organisation_id = ?', current_organisation.id) - +    scope = Calendar.where('organisation_id = ? OR shared = ?', current_organisation.id, true)      scope = shared_scope(scope) -      @q = scope.ransack(params[:q])      calendars = @q.result diff --git a/app/models/chouette/vehicle_journey.rb b/app/models/chouette/vehicle_journey.rb index 24de88015..44dd85864 100644 --- a/app/models/chouette/vehicle_journey.rb +++ b/app/models/chouette/vehicle_journey.rb @@ -36,13 +36,14 @@ module Chouette        :calculate_vehicle_journey_at_stop_day_offset      def vjas_departure_time_must_be_before_next_stop_arrival_time +      notice = 'departure time must be before next stop arrival time'        vehicle_journey_at_stops.each_with_index do |current_stop, index|          next_stop = vehicle_journey_at_stops[index + 1] -        next unless next_stop -        if next_stop[:arrival_time] <= current_stop[:departure_time] -          current_stop.errors.add(:departure_time, 'departure time must be before next stop arrival time') -        end +        next unless next_stop && (next_stop[:arrival_time] < current_stop[:departure_time]) + +        current_stop.errors.add(:departure_time, notice) +        self.errors.add(:vehicle_journey_at_stops, notice)        end      end diff --git a/app/views/calendars/_filters.html.slim b/app/views/calendars/_filters.html.slim index 4f625e4f0..6bcf25f99 100644 --- a/app/views/calendars/_filters.html.slim +++ b/app/views/calendars/_filters.html.slim @@ -1,7 +1,7 @@  = search_form_for @q, url: calendars_path, builder: SimpleForm::FormBuilder, html: { method: :get, class: 'form form-filter' } do |f|    .ffg-row      .input-group.search_bar -      = f.search_field :short_name_cont, class: 'form-control', placeholder: 'Indiquez un nom de calendrier...' +      = f.search_field :name_or_short_name_cont, class: 'form-control', placeholder: 'Indiquez un nom/nom court de calendrier...'        span.input-group-btn          button.btn.btn-default#search_btn type='submit'            span.fa.fa-search diff --git a/install/README b/install/README new file mode 100644 index 000000000..9825e6575 --- /dev/null +++ b/install/README @@ -0,0 +1,9 @@ +Script d'initialisation de l'environnement logiciel pour accueillir le BOIV +Prérequis : debian 8 (Jessie) netinst + +Paramètres : exporter les variables d'environnements +DATABASE_HOST permet de régler l'hôte qui héberge la base de données +valeur par défaut : localhost + +Procédure : en tant qu'utilisateur root, exécuter la commande depuis le répertoire courrant +./stif-boiv-setup.sh diff --git a/install/deploy-helper.sh b/install/deploy-helper.sh new file mode 100755 index 000000000..487c4539c --- /dev/null +++ b/install/deploy-helper.sh @@ -0,0 +1,102 @@ +#!/bin/bash -e + +export BASEDIR=$PREFIX/var/www/stif-boiv + +export RUN_USER=www-data +export RUN_GROUP=src + +export SUDO="" + +function setup() { +    mkdir -p $BASEDIR +    mkdir -p $BASEDIR/releases $BASEDIR/shared + +    $SUDO mkdir -p $PREFIX/etc/stif-boiv +    ln -fs $PREFIX/etc/stif-boiv $BASEDIR/shared/config + +    mkdir -p $BASEDIR/shared/config/environments + +    mkdir -p $BASEDIR/shared/public +    mkdir -p $BASEDIR/shared/public/uploads +    mkdir -p $BASEDIR/shared/public/assets + +    mkdir -p $BASEDIR/shared/tmp/uploads + +    $SUDO chown $RUN_USER:$RUN_GROUP $BASEDIR/shared/public/uploads $BASEDIR/shared/tmp/uploads + +    default_config +} + +function default_config() { +    DATABASE_PASSWORD=${DATABASE_PASSWORD:-FIXME} +    DATABASE_HOST=${DATABASE_HOST:-"localhost"} + +    cd $BASEDIR/shared/config + +    if [ ! -f secrets.yml ]; then +        cat > secrets.yml <<EOF +production: +  secret_key_base: `echo $RANDOM | sha512sum | cut -f1 -d' '` +EOF +    fi + +    if [ ! -f database.yml ]; then +        cat > database.yml <<EOF +production: +  adapter: postgresql +  encoding: unicode +  pool: 5 + +  host: $DATABASE_HOST +  database: stif-boiv + +  username: stif-boiv +  password: $DATABASE_PASSWORD +EOF +    fi +} + +function install() { +    tar_file=$1 + +    # stif-boiv-20160617154541.tar +    release_name=`echo $tar_file | sed 's/.*-\([0-9]*\)\.tar/\1/g'` + +    RELEASE_PATH=$BASEDIR/releases/$release_name + +    if [ -d $RELEASE_PATH ]; then +        echo "Release directory $RELEASE_PATH already exists" +        return +    fi + +    mkdir -p $RELEASE_PATH + +    tar -xf $tar_file -C $RELEASE_PATH + +    cd $RELEASE_PATH + +    mkdir -p tmp + +    for directory in public/uploads tmp/uploads public/assets; do +        local_directory=$BASEDIR/shared/$directory +        release_directory=$directory + +        rm -rf $release_directory +        ln -s $local_directory $release_directory +    done + +    for file in secrets.yml database.yml environments/production.rb; do +        local_file=$BASEDIR/shared/config/$file +        release_file=config/$file + +        rm $release_file && ln -fs $local_file $release_file +    done + +    echo "Release installed into $RELEASE_PATH" +} + +command=$1 +shift + +set -x +$command $@ diff --git a/install/sidekiq-stif-boiv.service b/install/sidekiq-stif-boiv.service new file mode 100644 index 000000000..90c6ed391 --- /dev/null +++ b/install/sidekiq-stif-boiv.service @@ -0,0 +1,52 @@ +# +# systemd unit file for CentOS 7, Ubuntu 15.04 +# +# Customize this file based on your bundler location, app directory, etc. +# Put this in /usr/lib/systemd/system (CentOS) or /lib/systemd/system (Ubuntu). +# Run: +#   - systemctl enable sidekiq +#   - systemctl {start,stop,restart} sidekiq +# +# This file corresponds to a single Sidekiq process.  Add multiple copies +# to run multiple processes (sidekiq-1, sidekiq-2, etc). +# +# See Inspeqtor's Systemd wiki page for more detail about Systemd: +# https://github.com/mperham/inspeqtor/wiki/Systemd +# +[Unit] +Description=sidekiq stif-boiv +# start us only once the network and logging subsystems are available, +# consider adding redis-server.service if Redis is local and systemd-managed. +After=syslog.target network.target + +# See these pages for lots of options: +# http://0pointer.de/public/systemd-man/systemd.service.html +# http://0pointer.de/public/systemd-man/systemd.exec.html +[Service] +Type=simple +WorkingDirectory=/var/www/stif-boiv/current +PIDFile=/var/run/sidekiq-stif-boiv.pid + +PermissionsStartOnly=true +ExecStartPre=-/bin/touch /var/run/sidekiq-stif-boiv.pid +ExecStartPre=/bin/chown www-data:www-data /var/run/sidekiq-stif-boiv.pid + +ExecStart= /usr/local/bin/bundle exec sidekiq -e production -P /var/run/sidekiq-stif-boiv.pid + +User=www-data +Group=www-data +UMask=0002 + +# if we crash, restart +RestartSec=10 +Restart=on-failure + +# output goes to /var/log/syslog +StandardOutput=syslog +StandardError=syslog + +# This will default to "bundler" if we don't specify it +SyslogIdentifier=stif-boiv/sidekiq + +[Install] +WantedBy=multi-user.target diff --git a/install/stif-boiv-setup.sh b/install/stif-boiv-setup.sh new file mode 100755 index 000000000..a2b8bd4a6 --- /dev/null +++ b/install/stif-boiv-setup.sh @@ -0,0 +1,84 @@ +#!/bin/bash -e + +DATABASE_HOST=${DATABASE_HOST:-"localhost"} + +# mandatory packages and distribution upgrade +apt-get update && apt-get dist-upgrade +apt-get install -y wget sudo + +# ruby +echo "==== Installation de Ruby 2.3" +cat > /etc/apt/sources.list.d/bearstech.list <<EOF +deb http://deb.bearstech.com/debian jessie-bearstech main +EOF + +wget -q -O - http://deb.bearstech.com/bearstech-archive.gpg | apt-key add - +apt-get update +apt-get install -y ruby2.3 ruby2.3-dev +apt-get install -y libsqlite3-dev libproj-dev libpq-dev +gem2.3 install bundler + +# Apache / Passenger +echo "==== Installation de Apache 2.4 et Passenger" +apt-get install -y apache2 libapache2-mod-passenger + +cp stif-boiv.conf /etc/apache2/sites-available/ + +a2enmod expires +a2ensite stif-boiv + +# Redis + +echo "==== Installation de Redis" + +apt-get install -y redis-server + +# Sidekiq + +echo "==== Installation de Sidekiq comme service" +cp sidekiq-stif-boiv.service /etc/systemd/system/ +systemctl enable sidekiq-stif-boiv + + +echo "==== Installation de PostgreSQL" +if [ "x$DATABASE_HOST" = "xlocalhost" ]; then +apt-get install -y postgresql-9.4 postgresql-9.4-postgis-2.1 postgresql-contrib-9.4 +[ -d /usr/local/share/postgresql ] || mkdir -p /usr/local/share/postgresql/ +cp template-stif-boiv.sql /usr/local/share/postgresql/ +pushd . +cd /usr/local/share/postgresql +sudo -u postgres createdb --encoding UTF-8 template_stif_boiv < template-stif-boiv.sql +popd +echo "Saisissez le mot de passe de la base de données. Il vous sera redemandé ultérieurement" +sudo -u postgres createuser --pwprompt stif_boiv +sudo -u postgres createdb --owner stif_boiv --template template_stif_boiv stif_boiv +else +echo "W! Base de donnée externe : Pas d'installation" +fi + +# NodeJS + +echo "==== Installation de NodeJS 5.x" +apt-get install -y apt-transport-https + +cat > /etc/apt/sources.list.d/nodesource.list <<EOF +deb https://deb.nodesource.com/node_5.x  jessie main +EOF + +wget -q -O - https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - +apt-get update + +apt-get install -y nodejs + +# Configuration de l'applicatif + +echo "==== Paramétrage de l'applicatif" +echo -n "Veuillez saisir à nouveau le mot de passe d'accès à la base de données :" +read -s DATABASE_PASSWORD + +export DATABASE_PASSWORD + +PGPASSWORD=$DATABASE_PASSWORD PGHOST=$DATABASE_HOST PGUSER=stif_boiv psql -q -c 'select 1' stif_boiv >/dev/null 2>&1 && echo "Mot de passe correct"  +./deploy-helper.sh setup + +echo "!!! Configuration intiale terminée. Vous pouvez maintenant déployer l'applicatif" diff --git a/install/stif-boiv.conf b/install/stif-boiv.conf new file mode 100644 index 000000000..6b2abe4eb --- /dev/null +++ b/install/stif-boiv.conf @@ -0,0 +1,38 @@ +<VirtualHost *:80> +    ServerName boiv.stif.info + +    DocumentRoot /var/www/stif-boiv/current/public + +    PassengerDefaultUser www-data +    PassengerUserSwitching off + +    PassengerRuby /usr/bin/ruby2.3 +    RackEnv production + +    ExpiresActive On + +    ExpiresByType application/javascript "access plus 1 year" +    ExpiresByType application/x-javascript "access plus 1 year" +    ExpiresByType application/x-shockwave-flash "access plus 1 year" +    ExpiresByType image/gif "access plus 1 year" +    ExpiresByType image/ico "access plus 1 year" +    ExpiresByType image/jpeg "access plus 1 year" +    ExpiresByType image/jpg "access plus 1 year" +    ExpiresByType image/png "access plus 1 year" +    ExpiresByType image/vnd.microsoft.icon "access plus 1 year" +    ExpiresByType image/x-icon "access plus 1 year" +    ExpiresByType text/css "access plus 1 year" +    ExpiresByType text/javascript "access plus 1 year" +    ExpiresByType font/truetype "access plus 1 year" +    ExpiresByType application/x-font-ttf "access plus 1 year" + +    <Directory /var/www/stif-boiv/current/public> +        AllowOverride None +        Require all granted +    </Directory> + +    <Location /sidekiq> +        # Replace with correct policy +        Require all denied +    </Location> +</virtualHost> diff --git a/install/template-stif-boiv.sql b/install/template-stif-boiv.sql new file mode 100644 index 000000000..4d4a19afe --- /dev/null +++ b/install/template-stif-boiv.sql @@ -0,0 +1,11 @@ +set ON_ERROR_STOP=on; + +CREATE SCHEMA shared_extensions; +GRANT ALL ON SCHEMA shared_extensions TO PUBLIC; +CREATE EXTENSION IF NOT EXISTS postgis WITH SCHEMA shared_extensions; +CREATE EXTENSION IF NOT EXISTS hstore WITH SCHEMA shared_extensions; + +UPDATE pg_database SET datistemplate = TRUE WHERE datname = 'template_stif_boiv'; + +VACUUM FULL FREEZE; + diff --git a/lib/tasks/install.rake b/lib/tasks/install.rake new file mode 100644 index 000000000..f32f3f240 --- /dev/null +++ b/lib/tasks/install.rake @@ -0,0 +1,18 @@ +task :package do +  release_name = Time.now.strftime('%Y%m%d%H%M%S') + +  rm_rf "tmp/package" +  mkdir_p "tmp/package" + +  sh "git archive --format=tar --output=tmp/package/stif-boiv-release-#{release_name}.tar HEAD" + +  sh "bundle package --all" +  sh "tar -rf tmp/package/stif-boiv-release-#{release_name}.tar vendor/cache" + +  %w{deploy-helper.sh README sidekiq-stif-boiv.service stif-boiv.conf stif-boiv-setup.sh template-stif-boiv.sql}.each do |f| +    cp "install/#{f}", "tmp/package/#{f}" +  end + +  sh "tar -czf stif-boiv-#{release_name}.tar.gz -C tmp/package ." +  sh "rm -rf tmp/package vendor/cache" +end diff --git a/spec/features/calendars_spec.rb b/spec/features/calendars_spec.rb index 2089939bb..e15624295 100644 --- a/spec/features/calendars_spec.rb +++ b/spec/features/calendars_spec.rb @@ -19,12 +19,20 @@ describe 'Calendars', type: :feature do      context 'filtering' do        it 'supports filtering by short name' do -        fill_in 'q[short_name_cont]', with: calendars.first.short_name +        fill_in 'q[name_or_short_name_cont]', with: calendars.first.short_name          click_button 'search_btn'          expect(page).to have_content(calendars.first.short_name)          expect(page).not_to have_content(calendars.last.short_name)        end +      it 'supports filtering by name' do +        fill_in 'q[name_or_short_name_cont]', with: calendars.first.name +        click_button 'search_btn' +        expect(page).to have_content(calendars.first.name) +        expect(page).not_to have_content(calendars.last.name) +      end + +        it 'supports filtering by shared' do          shared_calendar = create :calendar, organisation_id: 1, shared: true          visit calendars_path diff --git a/spec/models/chouette/vehicle_journey_spec.rb b/spec/models/chouette/vehicle_journey_spec.rb index f96c687f4..8f9080b99 100644 --- a/spec/models/chouette/vehicle_journey_spec.rb +++ b/spec/models/chouette/vehicle_journey_spec.rb @@ -6,13 +6,23 @@ describe Chouette::VehicleJourney, :type => :model do      let(:vjas) { vehicle_journey.vehicle_journey_at_stops }      it 'should add errors a stop departure_time is greater then next stop arrival time' do -      vjas[0][:departure_time] = vjas[1][:arrival_time] + 1.hour +      vjas[0][:departure_time] = vjas[1][:arrival_time] + 1.minute        vehicle_journey.validate        expect(vjas[0].errors[:departure_time]).not_to be_blank +      expect(vehicle_journey.errors[:vehicle_journey_at_stops].count).to eq(1)        expect(vehicle_journey).not_to be_valid      end +    it 'should consider valid to have departure_time equal to next stop arrival time' do +      vjas[0][:departure_time] = vjas[1][:arrival_time] +      vehicle_journey.validate + +      expect(vjas[0].errors[:departure_time]).to be_blank +      expect(vehicle_journey.errors[:vehicle_journey_at_stops]).to be_empty +      expect(vehicle_journey).to be_valid +    end +      it 'should not add errors when departure_time is less then next stop arrival time' do        vehicle_journey.validate        vjas.each do |stop| | 
