diff options
59 files changed, 1668 insertions, 327 deletions
| diff --git a/bin/ec2-rewrite-conf b/bin/ec2-rewrite-conf new file mode 100755 index 000000000..0163ef511 --- /dev/null +++ b/bin/ec2-rewrite-conf @@ -0,0 +1,20 @@ +#!/bin/sh + +# This is a helper script for writing the current EC2 hostname into +# the FixMyStreet configuration file.  Its intended usage is for lines +# like these to be added to /etc/rc.local: +# +#   su -l -c /home/fms/fixmystreet/bin/ec2-rewrite-conf fms +#   /etc/init.d/apache2 restart + +set -e + +BIN_DIR=$(dirname $(readlink -f $0)) +CONF_DIR=$BIN_DIR/../conf + +HOST=`curl -s http://169.254.169.254/latest/meta-data/public-hostname` + +sed -i -r \ +    -e "s,^( *BASE_URL:).*,\\1 'http://$HOST'," \ +    -e "s,^( *EMAIL_DOMAIN:).*,\\1 '$HOST'," \ +    $CONF_DIR/general.yml diff --git a/bin/install-as-user b/bin/install-as-user new file mode 100755 index 000000000..4757090aa --- /dev/null +++ b/bin/install-as-user @@ -0,0 +1,126 @@ +#!/bin/sh + +set -e +set -x + +DEFAULT_SERVER=false +if [ x"$1" = x"--default" ] +then +    DEFAULT_SERVER=true +    shift +fi + +if [ $# -ne 2 ] +then +    cat >&2 <<EOUSAGE +Usage: $0 [--default] <UNIX-USER> <HOST> +--default means to install as the default site for this server, +rather than a virtualhost for HOST. +EOUSAGE +    exit 1 +fi + +UNIX_USER="$1" +HOST="$2" +DB_NAME="fixmystreet" + +# Check that the arguments we've been passed are sensible: + +IP_ADDRESS_FOR_HOST="$(dig +short $HOST)" + +if [ x = x"$IP_ADDRESS_FOR_HOST" ] +then +    echo "The hostname $HOST didn't resolve to an IP address" +    exit 1 +fi + +if ! id "$UNIX_USER" 2> /dev/null > /dev/null +then +    echo "The user '$UNIX_USER' didn't exist." +    echo "(You should have run \"sudo pre-install-as-root '$UNIX_USER' '$HOST'\" before this.)" +    exit 1 +fi + +if [ "$(whoami)" != "$UNIX_USER" ] +then +    echo "This script should be run by the user '$UNIX_USER'." +    exit 1 +fi + +if [ $DEFAULT_SERVER = true ] +then +    FMS_DIRECTORY="/var/www/fixmystreet" +else +    FMS_DIRECTORY="/var/www/$HOST" +fi +FMS_REPOSITORY="$FMS_DIRECTORY/fixmystreet" +FMS_LINK_DESTINATION="$HOME/fixmystreet" + +ln -sfn "$FMS_REPOSITORY" $FMS_LINK_DESTINATION +cd "$FMS_REPOSITORY" + +# Add regularly scheduled tasks to cron: + +TEMPORARY_CRONTAB=$(mktemp) + +echo crontab file is $TEMPORARY_CRONTAB + +cp "$FMS_REPOSITORY"/conf/crontab.example "$TEMPORARY_CRONTAB" + +sed -i \ +    -e 's,$FMS,'"$FMS_REPOSITORY,g" \ +    -e 's,$LOCK_DIR,'"$FMS_DIRECTORY,g" \ +    "$TEMPORARY_CRONTAB" + +crontab $TEMPORARY_CRONTAB + +# Install the compass gem locally - it's required for generating the +# CSS: + +export GEM_HOME="$FMS_DIRECTORY/gems" +mkdir -p "$GEM_HOME" +export GEM_PATH= +export PATH="$GEM_HOME/bin:$PATH" + +gem install --no-ri --no-rdoc compass + +# Use compass to generate the CSS, if it doesn't seem to already +# exist: + +if [ ! -f web/cobrands/default/base.css ] +then +    bin/make_css +fi + +# Write sensible values into the config file: + +sed -r \ +    -e "s,^( *FMS_DB_HOST:).*,\\1 ''," \ +    -e "s,^( *FMS_DB_NAME:).*,\\1 '$DB_NAME'," \ +    -e "s,^( *FMS_DB_USER:).*,\\1 '$UNIX_USER'," \ +    -e "s,^( *BASE_URL:).*,\\1 'http://$HOST'," \ +    -e "s,^( *EMAIL_DOMAIN:).*,\\1 '$HOST'," \ +    -e "s,^( *CONTACT_EMAIL:).*,\\1 'help@$HOST'," \ +    conf/general.yml-example > conf/general.yml + +# Create the database if it doesn't exist: +if ! psql -l | egrep "^ *$DB_NAME *\|" > /dev/null +then +    createdb --owner "$UNIX_USER" "$DB_NAME" +    echo 'CREATE LANGUAGE plpgsql;' | psql -U "$UNIX_USER" "$DB_NAME" || true +    psql -U "$UNIX_USER" "$DB_NAME" < "$FMS_REPOSITORY"/db/schema.sql +    psql -U "$UNIX_USER" "$DB_NAME" < "$FMS_REPOSITORY"/db/alert_types.sql +    psql -U "$UNIX_USER" "$DB_NAME" < "$FMS_REPOSITORY"/db/generate_secret.sql +fi + +# Install the required Perl modules - this may take a very long time: + +cd "$FMS_REPOSITORY" +bin/install_perl_modules + +# Generate po and mo files (these invocations taken from Kagee's script): + +./bin/cron-wrapper ./bin/make_emptyhomes_po +./bin/cron-wrapper ./bin/make_emptyhomes_welsh_po + +commonlib/bin/gettext-makemo FixMyStreet diff --git a/bin/open311-populate-service-list b/bin/open311-populate-service-list index 33be61af7..99f8502a7 100755 --- a/bin/open311-populate-service-list +++ b/bin/open311-populate-service-list @@ -4,11 +4,18 @@ use strict;  use warnings;  use FixMyStreet::App;  use Open311::PopulateServiceList; +use Getopt::Long::Descriptive; +my ($opt, $usage) = describe_options( +    '%c %o', +    ['verbose|v',  "print out all services as they are found"], +    ['help',       "print usage message and exit" ], +); +print($usage->text), exit if $opt->help;  my $council_list = FixMyStreet::App->model('DB::Open311conf')->search( {      send_method => 'Open311'  } ); -my $p = Open311::PopulateServiceList->new( council_list => $council_list ); +my $p = Open311::PopulateServiceList->new( council_list => $council_list, verbose => $opt->verbose? 1:0 );  $p->process_councils; diff --git a/bin/pre-install-as-root b/bin/pre-install-as-root new file mode 100755 index 000000000..8d4c9dd26 --- /dev/null +++ b/bin/pre-install-as-root @@ -0,0 +1,307 @@ +#!/bin/sh + +# On a clean Debian squeeze or Ubuntu precise installation you should +# be able to install FixMyStreet with: +# +#     curl https://raw.github.com/mysociety/fixmystreet/master/bin/pre-install-as-root | \ +#         sh -s fms whatever.compute.amazonaws.com +# +# ... where the first argument is the Unix user who will own the code +# and the application will run as, and the second argument is the +# public hostname for the server, which will be used for creating the +# named virtualhost. + +set -e +set -x + +SITE=fixmystreet + +DEFAULT_SERVER=false +if [ x"$1" = x"--default" ] +then +    DEFAULT_SERVER=true +    shift +fi + +# Install some packages that we will definitely need: +apt-get install -y git-core lockfile-progs rubygems curl dnsutils lsb-release + +# If we're not running on an EC2 instance, an empty body is returned +# by this request: +EC2_HOSTNAME=`curl -s http://169.254.169.254/latest/meta-data/public-hostname || true` + +usage_and_exit() { +    cat >&2 <<EOUSAGE +Usage: $0 [--default] <UNIX-USER> [HOST] +HOST is only optional if you are running this on an EC2 instance. +--default means to install as the default site for this server, +rather than a virtualhost for HOST. +EOUSAGE +    exit 1 +} + +if [ $# = 1 ] +then +    if [ x = x$EC2_HOSTNAME ] +    then +        usage_and_exit +    else +        HOST="$EC2_HOSTNAME" +    fi +elif [ $# = 2 ] +then +    HOST="$2" +else +    usage_and_exit +fi + +UNIX_USER="$1" + +if [ $DEFAULT_SERVER = true ] +then +    DIRECTORY="/var/www/$SITE" +else +    DIRECTORY="/var/www/$HOST" +fi +REPOSITORY="$DIRECTORY/$SITE" + +REPOSITORY_URL=git://github.com/mysociety/$SITE.git +BRANCH=master + +DISTRIBUTION="$(lsb_release -i -s  | tr A-Z a-z)" +VERSION="$(lsb_release -c -s)" + +IP_ADDRESS_FOR_HOST="$(dig +short $HOST)" + +if [ x = x"$IP_ADDRESS_FOR_HOST" ] +then +    echo "The hostname $HOST didn't resolve to an IP address" +    exit 1 +fi + +generate_locales() { +    # If language-pack-en is present, install that: +    apt-get install -y language-pack-en || true + +    # We get lots of locale errors if the en_GB.UTF-8 locale isn't +    # present.  (This is from Kagee's script.) +    if [ "$(locale -a | egrep -i '^en_GB.utf-?8$' | wc -l)" = "1" ] +    then +        echo "en_GB.utf8 activated and generated" +    else +        echo "en_GB.utf8 not generated" +        if [ x"$(grep -c '^en_GB.UTF-8 UTF-8' /etc/locale.gen)" = x1 ] +        then +            echo "'en_GB.UTF-8 UTF-8' already in /etc/locale.gen we will only generate" +        else +            echo "Appending 'en_GB.UTF-8 UTF-8' and 'cy_GB.UTF-8 UTF-8'" +            echo "to /etc/locale.gen for generation" +            echo "\nen_GB.UTF-8 UTF-8\ncy_GB.UTF-8 UTF-8" >> /etc/locale.gen +        fi +        echo "Generating new locales" +        locale-gen +    fi +} + +set_locale() { +    echo 'LANG="en_GB.UTF-8"' > /etc/default/locale +    export LANG="en_GB.UTF-8" +} + +add_unix_user() { +    # Create the required user if it doesn't already exist: +    if id "$1" 2> /dev/null > /dev/null +    then +        echo "The user $1 already exists." +    else +        adduser --disabled-password --gecos 'The FixMyStreet User' "$1" +    fi +} + +add_postgresql_user() { +    su -l -c "createuser --createdb --no-createrole --no-superuser '$UNIX_USER'" postgres || true +} + +update_apt_sources() { +    if [ x"$DISTRIBUTION" = x"ubuntu" ] && [ x"$VERSION" = x"precise" ] +    then +        cat > /etc/apt/sources.list.d/mysociety-extra.list <<EOF +deb http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise multiverse +deb-src http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise multiverse +deb http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise-updates multiverse +deb-src http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise-updates multiverse +EOF +    elif [ x"$DISTRIBUTION" = x"debian" ] && [ x"$VERSION" = x"squeeze" ] +    then +        # Install the basic packages we require: +        cat > /etc/apt/sources.list.d/mysociety-extra.list <<EOF +# Debian mirror to use, including contrib and non-free: +deb http://the.earth.li/debian/ squeeze main contrib non-free +deb-src http://the.earth.li/debian/ squeeze main contrib non-free + +# Security Updates: +deb http://security.debian.org/ squeeze/updates main non-free +deb-src http://security.debian.org/ squeeze/updates main non-free + +# Debian Backports +deb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free +deb-src http://backports.debian.org/debian-backports squeeze-backports main contrib non-free +EOF +    else +        echo Unsupport distribution and version combination $DISTRIBUTION $VERSION +        exit 1 +    fi +    apt-get update +} + +clone_or_update_repository() { +    # Clone the repository into place if the directory isn't already +    # present: +    if [ -d $REPOSITORY ] +    then +        echo the directory $REPOSITORY already exists +        cd $REPOSITORY +        git remote set-url origin "$REPOSITORY_URL" +        git fetch origin +        # Check that there are no uncommitted changes before doing a +        # git reset --hard: +        git diff --quiet || { echo "There were changes in the working tree in $REPOSITORY; exiting."; exit 1; } +        git diff --cached --quiet || { echo "There were staged but uncommitted changes in $REPOSITORY; exiting."; exit 1; } +        # If that was fine, carry on: +        git reset --hard origin/"$BRANCH" +        git submodule sync +        git submodule update --recursive +    else +        PARENT="$(dirname $REPOSITORY)" +        echo creating $PARENT +        mkdir -p $PARENT +        git clone --recursive --branch "$BRANCH" "$REPOSITORY_URL" "$REPOSITORY" +    fi +} + +install_nginx() { +    apt-get install -y nginx libfcgi-procmanager-perl +} + +add_website_to_nginx() { +    UNIX_USER="$1" +    HOST="$2" +    REPOSITORY="$3" +    NGINX_SITE="$HOST" +    if [ $DEFAULT_SERVER = true ] +    then +        NGINX_SITE=default +    fi +    SITE_FILENAME=/etc/nginx/sites-available/"$NGINX_SITE" +    SITE_LINK=/etc/nginx/sites-enabled/"$NGINX_SITE" +    cp $REPOSITORY/conf/nginx.conf.example $SITE_FILENAME +    sed -i "s,/var/www/$SITE,$DIRECTORY," $SITE_FILENAME +    if [ $DEFAULT_SERVER = false ] +    then +        sed -i "/listen 80/a\ +\    server_name $HOST; +" $SITE_FILENAME +    fi +    ln -nsf "$SITE_FILENAME" "$SITE_LINK" +    LOG_DIRECTORY="$(readlink -f $REPOSITORY/../logs)" +    mkdir -p "$LOG_DIRECTORY" +    chown -R "$UNIX_USER"."$UNIX_USER" "$LOG_DIRECTORY" +    /etc/init.d/nginx restart +} + +install_sysvinit_script() { +    SYSVINIT_FILENAME=/etc/init.d/$SITE +    cp $REPOSITORY/conf/sysvinit.example $SYSVINIT_FILENAME +    sed -i "s,/var/www/$SITE,$DIRECTORY,g" $SYSVINIT_FILENAME +    sed -i "s/^ *USER=.*/USER=$UNIX_USER/" $SYSVINIT_FILENAME +    chmod a+rx $SYSVINIT_FILENAME +    update-rc.d $SITE start 20 2 3 4 5 . stop 20 0 1 6 . +    /etc/init.d/$SITE restart +} + +install_website_packages() { +    EXACT_PACKAGES="$1/conf/packages.$DISTRIBUTION-$VERSION" +    PRECISE_PACKAGES="$1/conf/packages.ubuntu-precise" +    SQUEEZE_PACKAGES="$1/conf/packages.debian-squeeze" +    GENERIC_PACKAGES="$1/conf/packages" +    # If there's an exact match for the distribution and release, use that: +    if [ -e "$EXACT_PACKAGES" ] +    then +        PACKAGES_FILE="$EXACT_PACKAGES" +    # Otherwise, if this is Ubuntu, and there's a version specifically +    # for precise, use that: +    elif [ x"$DISTRIBUTION" = x"ubuntu" ] && [ -e "$PRECISE_PACKAGES" ] +    then +        PACKAGES_FILE="$PRECISE_PACKAGES" +    # Otherwise, if this is Debian, and there's a version specifically +    # for squeeze, use that: +    elif [ x"$DISTRIBUTION" = x"debian" ] && [ -e "$SQUEEZE_PACKAGES" ] +    then +        PACKAGES_FILE="$SQUEEZE_PACKAGES" +    else +        PACKAGES_FILE="$GENERIC_PACKAGES" +    fi +    xargs -a "$PACKAGES_FILE" apt-get -y install +} + +overwrite_rc_local() { +    cat > /etc/rc.local <<EOF +#!/bin/sh -e + +su -l -c $REPOSITORY/bin/ec2-rewrite-conf $UNIX_USER +/etc/init.d/$SITE restart + +exit 0 + +EOF +    chmod a+rx /etc/rc.local +} + +generate_locales +set_locale + +add_unix_user "$UNIX_USER" + +update_apt_sources + +# And remove one crippling package, if it's installed: +apt-get remove -y --purge apt-xapian-index || true + +clone_or_update_repository $REPOSITORY + +chown -R "$UNIX_USER"."$UNIX_USER" "$DIRECTORY" + +install_nginx + +install_website_packages "$REPOSITORY" + +su -l -c "touch '$DIRECTORY/admin-htpasswd'" "$UNIX_USER" + +add_website_to_nginx "$UNIX_USER" "$HOST" "$REPOSITORY" + +add_postgresql_user "$UNIX_USER" + +DEFAULT_PARAMETER='' +if [ $DEFAULT_SERVER = true ] +then +    DEFAULT_PARAMETER='--default' +fi + +su -l -c "$REPOSITORY/bin/install-as-user $DEFAULT_PARAMETER '$UNIX_USER' '$HOST'" "$UNIX_USER" + +install_sysvinit_script + +if [ $DEFAULT_SERVER = true ] && [ x != x$EC2_HOSTNAME ] +then +    # If we're setting up as the default on an EC2 instance, +    # make sure the ec2-rewrite-conf script is called from +    # /etc/rc.local +    overwrite_rc_local +fi + +# Tell the user what to do next: + +echo Installation complete - you should now be able to view the site at: +echo   http://$HOST/ +echo Or you can run the tests by switching to the "'$UNIX_USER'" user and +echo running: $REPOSITORY/bin/cron-wrapper prove -r t diff --git a/bin/problem-creation-graph b/bin/problem-creation-graph index 6692ae724..b96d45540 100755 --- a/bin/problem-creation-graph +++ b/bin/problem-creation-graph @@ -26,12 +26,12 @@ else      DATE="2007-02-01"  fi -SOURCEA=/tmp/bci-creation-rate-graph-data-$RANDOM$RANDOM -SOURCEB=/tmp/bci-creation-rate-graph-data-$RANDOM$RANDOM -SOURCEC=/tmp/bci-creation-rate-graph-data-$RANDOM$RANDOM -SOURCED=/tmp/bci-creation-rate-graph-data-$RANDOM$RANDOM -SOURCEE=/tmp/bci-creation-rate-graph-data-$RANDOM$RANDOM -GPSCRIPT=/tmp/bci-creation-rate-graph-script-$RANDOM$RANDOM +SOURCEA=/tmp/fms-creation-rate-graph-data-$RANDOM$RANDOM +SOURCEB=/tmp/fms-creation-rate-graph-data-$RANDOM$RANDOM +SOURCEC=/tmp/fms-creation-rate-graph-data-$RANDOM$RANDOM +SOURCED=/tmp/fms-creation-rate-graph-data-$RANDOM$RANDOM +SOURCEE=/tmp/fms-creation-rate-graph-data-$RANDOM$RANDOM +GPSCRIPT=/tmp/fms-creation-rate-graph-script-$RANDOM$RANDOM  #    where status in ('draft')  @@ -104,6 +104,6 @@ END  #echo "gpscript $GPSCRIPT"  export GDFONTPATH=/usr/share/fonts/truetype/ttf-bitstream-vera -gnuplot < $GPSCRIPT > fixmystreet/web/bci-live-creation$EXTENSION 2>/dev/null +gnuplot < $GPSCRIPT > fixmystreet/web/fms-live-creation$EXTENSION 2>/dev/null diff --git a/bin/problems-filed-graph b/bin/problems-filed-graph index 8addacd62..e5946b078 100755 --- a/bin/problems-filed-graph +++ b/bin/problems-filed-graph @@ -20,8 +20,8 @@ source fixmystreet/commonlib/shlib/deployfns  read_conf fixmystreet/conf/general.yml -SOURCEO=/tmp/bci-report-rate-graph-data-nonwmc-$RANDOM$RANDOM -GPSCRIPT=/tmp/bci-report-rate-graph-script-$RANDOM$RANDOM +SOURCEO=/tmp/fms-report-rate-graph-data-nonwmc-$RANDOM$RANDOM +GPSCRIPT=/tmp/fms-report-rate-graph-script-$RANDOM$RANDOM  echo "select       date(created), count(*) @@ -57,5 +57,5 @@ END  #echo "gpscript $GPSCRIPT"  export GDFONTPATH=/usr/share/fonts/truetype/ttf-bitstream-vera -gnuplot < $GPSCRIPT > fixmystreet/web/bci-live-line$EXTENSION 2>/dev/null +gnuplot < $GPSCRIPT > fixmystreet/web/fms-live-line$EXTENSION 2>/dev/null diff --git a/commonlib b/commonlib -Subproject f81ec03692fac90792fc102f88f0afbf3d2f73b +Subproject cfa9543e2fd50b08d27f6543ae5ef64600bff90 diff --git a/conf/apache-vhost.conf.example b/conf/apache-vhost.conf.example new file mode 100644 index 000000000..97a34fe66 --- /dev/null +++ b/conf/apache-vhost.conf.example @@ -0,0 +1,34 @@ +# An example Apache virtualhost configuration file. +# +# See our installation help at http://code.fixmystreet.com/ + +<VirtualHost *:80> +    ServerName fixmystreet.yourservername +    DocumentRoot /home/yourname/fixmystreet/web/ + +    # Pull in the specific config +    Include /home/yourname/fixmystreet/conf/httpd.conf + +    <Directory /home/yourname/fixmystreet/web> +        # You also need to enable cgi files to run as CGI scripts.  For example: +        # on production servers these are run under fastcgi +        Options +ExecCGI +        AddHandler cgi-script .cgi +        AllowOverride None +    </Directory> + +    <Location /admin> +        #  +        #  WARNING - enable auth here on production machine +        #  +    </Location> + +    Alias /admin/ /home/yourname/fixmystreet/web-admin/ + +    Alias /jslib/ /home/yourname/fixmystreet/commonlib/jslib/ +    <Location /jslib> +        AddOutputFilter DEFLATE js +        Header append Cache-Control "no-transform" +    </Location> + +</VirtualHost> diff --git a/conf/crontab.example b/conf/crontab.example new file mode 100644 index 000000000..f33e949e8 --- /dev/null +++ b/conf/crontab.example @@ -0,0 +1,28 @@ +# Timed tasks for FixMyStreet. + +# This is an example crontab that you may want to use as a basis for +# one on your own server.  You should replace $FMS with the path to the +# clone of the FixMyStreet repository that you are using.  You should +# also replace $LOCK_DIR with a writeable directory for the lock files. + +# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. +# Email: matthew@mysociety.org. WWW: http://www.mysociety.org/ + +PATH=/usr/local/bin:/usr/bin:/bin + +5,10,15,20,25,30,35,40,45,50,55 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$FMS/send-reports.lock" "$FMS/bin/cron-wrapper send-reports" || echo "stalled?" +0 0-8,10,11,13,14,16,17,19-23 * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/send-reports.lock" "$FMS/bin/cron-wrapper send-reports" || echo "stalled?" +0 9,12,15,18 * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/send-reports.lock" "$FMS/bin/cron-wrapper send-reports --verbose" || echo "stalled?" +2 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/send-alerts.lock" "$FMS/bin/cron-wrapper send-alerts" || echo "stalled?" +0,30 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/send-questionnaires.lock" "$FMS/bin/cron-wrapper send-questionnaires" || echo "stalled?" +5,10,15,20,25,30,35,40,45,50,55 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/send-comments.lock" "$FMS/bin/cron-wrapper send-comments" || echo "stalled?" +5,10,15,20,25,30,35,40,45,50,55 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/fetch-comments.lock" "$FMS/bin/cron-wrapper fetch-comments" || echo "stalled?" +0,30 * * * * "$FMS/commonlib/bin/run-with-lockfile.sh" -n "$LOCK_DIR/open311-populate-service-list.lock" "$FMS/bin/cron-wrapper open311-populate-service-list" || echo "stalled?" + +# Once an hour, update the all reports stats +13 * * * * "$FMS/bin/cron-wrapper" update-all-reports + +# Once a day on all servers +39 2 * * * "$FMS/bin/problems-filed-graph" +43 2 * * * "$FMS/bin/problem-creation-graph" +00 8 * * * "$FMS/bin/check-for-zombies" $UNIX_USER diff --git a/conf/httpd.conf-example b/conf/httpd.conf-example index e7900161e..ab17dcec3 100644 --- a/conf/httpd.conf-example +++ b/conf/httpd.conf-example @@ -1,42 +1,10 @@  # Apache configuration for FixMyStreet.  # -# Add lines something like this to your /etc/apache2/sites-enabled/fixmystreet - -# replacing '/home/yourname/fixmystreet' with the path to your install +# This file should be included in an Apache <VirtualHost> section.  An +# example of such a virtualhost configuration file can be found in the +# file apache-vhost.conf.example in this directory.  # -# # FixMyStreet -# <VirtualHost *:80> -#     ServerName fixmystreet.yourservername -#     DocumentRoot /home/yourname/fixmystreet/web/ -#  -#     # Pull in the specific config -#     Include /home/yourname/fixmystreet/conf/httpd.conf -#  -#     <Directory /home/yourname/fixmystreet/web> -#         # You also need to enable cgi files to run as CGI scripts.  For example: -#         # on production servers these are run under fastcgi -#         Options +ExecCGI -#         AddHandler cgi-script .cgi -#         AllowOverride None -#     </Directory> -#  -#     <Location /admin> -#         #  -#         #  WARNING - enable auth here on production machine -#         #  -#         Options +ExecCGI -#         AddHandler cgi-script .cgi -#     </Location> -# -#     Alias /admin/ /home/yourname/fixmystreet/web-admin/ -#  -#     Alias /jslib/ "/home/yourname/fixmystreet/commonlib/jslib/" -#  -# </VirtualHost> -# -#  -# Copyright (c) 2011 UK Citizens Online Democracy. All rights reserved. -# Email: team@mysociety.org -# WWW: http://www.mysociety.org +# See our installation help at http://code.fixmystreet.com/  RewriteEngine on  # RewriteLog /var/log/apache2/rewrite.log diff --git a/conf/nginx.conf.example b/conf/nginx.conf.example new file mode 100644 index 000000000..7b26afdbf --- /dev/null +++ b/conf/nginx.conf.example @@ -0,0 +1,75 @@ +# An example configuration for running FixMyStreet under nginx.  You +# will also need to set up the FixMyStreet Catalyst FastCGI backend. +# An example sysvinit script to help with this is shown given in the file +# sysvinit-catalyst-fastcgi.example in this directory. +# +# See our installation help at http://code.fixmystreet.com/ + +server { + +    access_log /var/www/fixmystreet/logs/access.log; +    error_log /var/www/fixmystreet/logs/error.log; + +    listen 80; +    root /var/www/fixmystreet/fixmystreet/web; +    error_page 503 /down.html; + +    # Make sure that Javascript and CSS are compressed.  (HTML is +    # already compressed under the default configuration of the nginx +    # package.) + +    gzip on; +    gzip_disable "msie6"; +    gzip_types application/javascript application/x-javascript text/css; + +    # Set a long expiry time for CSS and Javascript, and prevent +    # the mangling of Javascript by proxies: + +    location ~ \.css$ { +        expires 10y; +    } + +    location ~ \.js$ { +        add_header Cache-Control no-transform; +        expires 10y; +        try_files $uri @catalyst; +    } + +    # These rewrite rules are ported from the Apache configuration in +    # conf/httpd.conf + +    rewrite ^/rss/council/([0-9]+)$  /rss/reports/$1 permanent; +    rewrite ^/report$                /reports        permanent; +    rewrite '^/{/rss/(.*)}$'         /rss/$1         permanent; +    rewrite '^/reports/{/rss/(.*)}$' /rss/$1         permanent; +    rewrite ^/alerts/?$              /alert          permanent; + +    location /mapit { +        proxy_pass http://mapit.mysociety.org/; +        proxy_set_header X-Real-IP $remote_addr; +    } + +    location /admin { +        auth_basic "FixMyStreet admin interface"; +        auth_basic_user_file /var/www/fixmystreet/admin-htpasswd; +        try_files $uri @catalyst; +    } + +    location / { +        if (-f $document_root/down.html) { +            return 503; +        } +        try_files $uri @catalyst; +    } + +    location /down.html { +        internal; +    } + +    location @catalyst { +        include /etc/nginx/fastcgi_params; +        fastcgi_param PATH_INFO $fastcgi_script_name; +        fastcgi_param SCRIPT_NAME ''; +        fastcgi_pass 127.0.0.1:9000; +    } +} diff --git a/conf/packages.ubuntu-precise b/conf/packages.ubuntu-precise new file mode 100644 index 000000000..fc8a7d511 --- /dev/null +++ b/conf/packages.ubuntu-precise @@ -0,0 +1,16 @@ +make +jhead +liberror-perl +liblocale-gettext-perl +libsoap-lite-perl +memcached +perl +perlmagick +libmath-bigint-gmp-perl +gettext +libhaml-ruby +postgresql-9.1 +postgresql-server-dev-9.1 +gnuplot +ttf-bitstream-vera +libexpat1-dev diff --git a/conf/sysvinit.example b/conf/sysvinit.example new file mode 100755 index 000000000..44424281b --- /dev/null +++ b/conf/sysvinit.example @@ -0,0 +1,53 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides:          application-catalyst-fixmystreet +# Required-Start:    $local_fs $network +# Required-Stop:     $local_fs $network +# Default-Start:     2 3 4 5 +# Default-Stop:      0 1 6 +# Short-Description: Starts the FastCGI app server for the "FixMyStreet" site +# Description:       The FastCGI application server for the "FixMyStreet" site +### END INIT INFO + +# This example sysvinit script is based on the helpful example here: +# http://richard.wallman.org.uk/2010/02/howto-deploy-a-catalyst-application-using-fastcgi-and-nginx/ + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +SITE_HOME=/var/www/fixmystreet +NAME=fixmystreet +DESC="FixMyStreet app server" +USER=fms + +echo $DAEMON +test -f $DAEMON || exit 0 + +set -e + +start_daemon() { +  su -l -c "cd $SITE_HOME/fixmystreet && bin/cron-wrapper web/fixmystreet_app_fastcgi.cgi -d -l :9000 -n 2" $USER +} + +stop_daemon() { +  pkill -f perl-fcgi -u $USER || true +} + +case "$1" in + start) + start_daemon + ;; + stop) + stop_daemon + ;; + reload|restart|force-reload) + stop_daemon + sleep 5 + start_daemon + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|reload|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/db/alert_types.sql b/db/alert_types.sql index 4ebd33cf9..4116d29dc 100644 --- a/db/alert_types.sql +++ b/db/alert_types.sql @@ -17,7 +17,7 @@ insert into alert_type      item_title, item_link, item_description, template)  values ('new_problems', '', '',      'New problems on FixMyStreet', '/', 'The latest problems reported by users', -    'problem', 'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc', +    'problem', 'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc',      '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem');  -- New fixed problems anywhere on the site @@ -28,7 +28,7 @@ insert into alert_type      item_title, item_link, item_description, template)  values ('new_fixed_problems', '', '',      'Problems recently reported fixed on FixMyStreet', '/', 'The latest problems reported fixed by users', -    'problem', 'problem.state in (''fixed'', ''fixed - user'', ''fixed - council'')', 'lastupdate desc', +    'problem', 'problem.non_public = ''f'' and problem.state in (''fixed'', ''fixed - user'', ''fixed - council'')', 'lastupdate desc',      '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem');  -- New problems around a location @@ -39,7 +39,7 @@ insert into alert_type      item_title, item_link, item_description, template)  values ('local_problems', '', '',      'New local problems on FixMyStreet', '/', 'The latest local problems reported by users', -    'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc', +    'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc',      '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby');  -- New problems around a location @@ -50,7 +50,7 @@ insert into alert_type      item_title, item_link, item_description, template)  values ('local_problems_state', '', '',      'New local problems on FixMyStreet', '/', 'The latest local problems reported by users', -    'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (?)', 'created desc', +    'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (?)', 'created desc',      '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby');  -- New problems around a postcode @@ -61,7 +61,7 @@ insert into alert_type      item_title, item_link, item_description, template)  values ('postcode_local_problems', '', '',      'New problems near {{POSTCODE}} on FixMyStreet', '/', 'The latest local problems reported by users', -    'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc', +    'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc',      '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby');  -- New problems around a postcode with a particular state @@ -72,7 +72,7 @@ insert into alert_type      item_title, item_link, item_description, template)  values ('postcode_local_problems_state', '', '',      'New problems near {{POSTCODE}} on FixMyStreet', '/', 'The latest local problems reported by users', -    'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (?)', 'created desc', +    'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (?)', 'created desc',      '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby');  -- New problems sent to a particular council @@ -83,7 +83,7 @@ insert into alert_type      item_title, item_link, item_description, template)  values ('council_problems', '', '',      'New problems to {{COUNCIL}} on FixMyStreet', '/reports', 'The latest problems for {{COUNCIL}} reported by users', -    'problem', 'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%'' +    'problem', 'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%''          or council is null) and areas like ''%,''||?||'',%''', 'created desc',      '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-council'  ); @@ -97,7 +97,7 @@ insert into alert_type  values ('ward_problems', '', '',      'New problems for {{COUNCIL}} within {{WARD}} ward on FixMyStreet', '/reports',      'The latest problems for {{COUNCIL}} within {{WARD}} ward reported by users', -    'problem', 'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%'' +    'problem', 'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%''          or council is null) and areas like ''%,''||?||'',%''', 'created desc',      '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-ward'  ); @@ -111,7 +111,7 @@ insert into alert_type  values ('area_problems', '', '',      'New problems within {{NAME}}''s boundary on FixMyStreet', '/reports',      'The latest problems within {{NAME}}''s boundary reported by users', 'problem', -    'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and areas like ''%,''||?||'',%''', 'created desc', +    'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and areas like ''%,''||?||'',%''', 'created desc',      '{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-area'  ); diff --git a/db/generate_secret.sql b/db/generate_secret.sql new file mode 100644 index 000000000..ad4b48200 --- /dev/null +++ b/db/generate_secret.sql @@ -0,0 +1,8 @@ +-- assumes there's a secret table (from the schema.sql) +-- use your own secret if you have one :-) +-- otherwise you can use this to populate the secret table with a random secret + +-- empty the table in case it has a value already (i.e., this is *destructive*!) +delete from secret; + +insert into secret values (md5(random()::text)); diff --git a/db/migrate_from_osgb36_to_wgs84.pl b/db/migrate_from_osgb36_to_wgs84.pl index abd504fb8..676ffea9b 100644 --- a/db/migrate_from_osgb36_to_wgs84.pl +++ b/db/migrate_from_osgb36_to_wgs84.pl @@ -21,11 +21,11 @@ use Utils;  BEGIN {      mySociety::Config::set_file("$FindBin::Bin/../conf/general");      mySociety::DBHandle::configure( -        Name     => mySociety::Config::get('BCI_DB_NAME'), -        User     => mySociety::Config::get('BCI_DB_USER'), -        Password => mySociety::Config::get('BCI_DB_PASS'), -        Host     => mySociety::Config::get( 'BCI_DB_HOST', undef ), -        Port     => mySociety::Config::get( 'BCI_DB_PORT', undef ) +        Name     => mySociety::Config::get('FMS_DB_NAME'), +        User     => mySociety::Config::get('FMS_DB_USER'), +        Password => mySociety::Config::get('FMS_DB_PASS'), +        Host     => mySociety::Config::get( 'FMS_DB_HOST', undef ), +        Port     => mySociety::Config::get( 'FMS_DB_PORT', undef )      );  } diff --git a/db/schema.sql b/db/schema.sql index a4323f880..1f0d0d4c3 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -83,6 +83,9 @@ create table contacts (      -- extra fields required for open311      extra text, +    -- for things like missed bin collections +    non_public boolean default 'f' +      -- per contact endpoint configuration      endpoint     text,      jurisdiction text default '', @@ -206,6 +209,9 @@ create table problem (      -- record send_method used, which can be used to infer usefulness of external_id      send_method_used text, +    -- for things like missed bin collections +    non_public BOOLEAN default 'f' +      -- record details about messages from external sources, eg. message manager      external_source text,      external_source_id text, diff --git a/db/schema_0024-add_non_public_categories_and_problems.sql b/db/schema_0024-add_non_public_categories_and_problems.sql new file mode 100644 index 000000000..c133b3ef2 --- /dev/null +++ b/db/schema_0024-add_non_public_categories_and_problems.sql @@ -0,0 +1,37 @@ +BEGIN; + +    ALTER TABLE contacts +        ADD COLUMN non_public BOOLEAN DEFAULT 'f'; + +    ALTER TABLE problem +        ADD COLUMN non_public BOOLEAN DEFAULT 'f'; + + +    UPDATE alert_type set item_where = 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in  +    (''confirmed'', ''investigating'', ''planned'', ''in progress'',  +     ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')' WHERE ref = 'postcode_local_problems'; +    UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in  +        (''confirmed'', ''investigating'', ''planned'', ''in progress'',  +         ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'' )' WHERE ref = 'new_problems'; +    UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in (''fixed'', ''fixed - user'', ''fixed - council'')' WHERE ref = 'new_fixed_problems'; +    UPDATE alert_type set item_where = 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in  +    (''confirmed'', ''investigating'', ''planned'', ''in progress'',  +     ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')' WHERE ref = 'local_problems'; +    UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in  +    (''confirmed'', ''investigating'', ''planned'', ''in progress'',  +      ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and  +    (council like ''%''||?||''%'' or council is null) and  +    areas like ''%,''||?||'',%''' WHERE ref = 'council_problems'; +    UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in  +    (''confirmed'', ''investigating'', ''planned'', ''in progress'',  +     ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and  +    (council like ''%''||?||''%'' or council is null) and  +    areas like ''%,''||?||'',%''' WHERE ref = 'ward_problems'; +    UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in  +    (''confirmed'', ''investigating'', ''planned'', ''in progress'',  +     ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and  +    areas like ''%,''||?||'',%''' WHERE ref = 'area_problems'; + +commit; + +COMMIT; diff --git a/locale/de_DE.UTF-8/LC_MESSAGES/FixMyStreet.mo b/locale/de_DE.UTF-8/LC_MESSAGES/FixMyStreet.moBinary files differ deleted file mode 100644 index e09194c2b..000000000 --- a/locale/de_DE.UTF-8/LC_MESSAGES/FixMyStreet.mo +++ /dev/null diff --git a/locale/nb_NO.UTF-8/LC_MESSAGES/FixMyStreet.po b/locale/nb_NO.UTF-8/LC_MESSAGES/FixMyStreet.po index 58b307d58..bcf77f56c 100644 --- a/locale/nb_NO.UTF-8/LC_MESSAGES/FixMyStreet.po +++ b/locale/nb_NO.UTF-8/LC_MESSAGES/FixMyStreet.po @@ -5,20 +5,22 @@  #  # Matthew Somerville <matthew@mysociety.org>, 2008-04-15.  # Petter Reinholdtsen <pere@hungry.com>, 2011. +# Anders Einar Hilden <hildenae@gmail.com>, 2012.  msgid ""  msgstr ""  "Project-Id-Version: FixMyStreet\n"  "Report-Msgid-Bugs-To: matthew@mysociety.org\n"  "POT-Creation-Date: 2012-08-21 09:54+0100\n" -"PO-Revision-Date: 2012-08-07 01:09+0100\n" +"PO-Revision-Date: 2012-09-14 00:22+0100\n"  "Last-Translator: Anders Einar Hilden <hildenae@gmail.com>\n"  "Language-Team: Norwegian Bokmål <i18n-nb@lister.ping.uio.no>\n" -"Language: \n"  "MIME-Version: 1.0\n"  "Content-Type: text/plain; charset=UTF-8\n"  "Content-Transfer-Encoding: 8bit\n"  "Plural-Forms: nplurals=2; plural=n != 1;\n"  "X-Generator: KBabel 1.11.4\n" +"X-Poedit-Basepath: ../../../\n" +"Language: Norwegian Bokmål\n"  #: perllib/FixMyStreet/DB/Result/Problem.pm:555  #: perllib/FixMyStreet/DB/ResultSet/Problem.pm:337 @@ -107,7 +109,7 @@ msgstr "%s - oppsummeringsrapporter"  #: perllib/FixMyStreet/DB/Result/Problem.pm:605  msgid "%s ref: %s" -msgstr "" +msgstr "%s ref: %s"  #: perllib/FixMyStreet/Cobrand/UK.pm:288 perllib/FixMyStreet/Cobrand/UK.pm:300  msgid "%s ward, %s" @@ -150,9 +152,8 @@ msgstr "(alternativt kan RSS-strømmen tilpasses, innenfor"  #: templates/web/default/around/around_map_list_items.html:12  #: templates/web/default/around/on_map_list_items.html:9  #: templates/web/fixmystreet/report/_item.html:23 -#, fuzzy  msgid "(closed)" -msgstr "Lukket" +msgstr "(lukket)"  #: templates/web/default/around/around_map_list_items.html:10  #: templates/web/default/around/on_map_list_items.html:7 @@ -203,12 +204,11 @@ msgstr "-- Velg en kategori --"  msgid "-- Pick a property type --"  msgstr "-- Velg en eiendomsstype --" -# Bør "portalen" byttes ut med et annet ord? (trenger kontekst) +# Trenger kontekst for bedre oversettelse  #: templates/web/default/tokens/confirm_problem.html:14  #: templates/web/default/tokens/confirm_problem.html:22 -#, fuzzy  msgid ". You can <a href=\"%s%s\">view the problem on this site</a>." -msgstr ". Du kan <a href=\"%s\">lese om problemet på portalen </a>." +msgstr ". Du kan <a href=\"%s\">lese om problemet på denne siden</a>."  #: templates/web/default/questionnaire/completed.html:20  msgid "" @@ -218,8 +218,8 @@ msgstr ""  "<p style=\"font-size:150%\">Tusen takk for at du fylte ut vårt spørreskjema. "  "Vi er glad for å høre at ditt problem er blitt fikset.</p>" +# Er pledgebank noe vi vil sende uvitende, norske innbyggere til?  #: templates/web/fiksgatami/questionnaire/completed-open.html:1 -#, fuzzy  msgid ""  "<p style=\"font-size:150%\">We’re sorry to hear that. We have two\n"  "suggestions: why not try <a href=\"http://www.norge.no/styresmakter/" @@ -229,15 +229,14 @@ msgid ""  "<a href=\"http://www.pledgebank.com/new\">make and publicise a pledge</a>?\n"  "</p>"  msgstr "" -"<p style=\"font-size:150%%\">Det var trist å høre dette. Vi har to forslag: " +"<p style=\"font-size:150%\">Det var trist å høre dette. Vi har to forslag: "  "hva med å forsøke\n" -"<a href=\"%s\">å skrive direkte til dine representanter</a>, eller hvis det " -"er et problem som kan fikses\n" +"<a href=\"http://www.norge.no/styresmakter/\">å skrive direkte til dine \n" +"representanter</a>, eller hvis det er et problem som kan fikses\n"  "av folk i nabolaget som jobber sammen, hva med å <a href=\"http://www."  "pledgebank.com/new\">publisere en utfordring om å bidra</a>?</p>"  #: templates/web/fixmystreet/questionnaire/completed-open.html:1 -#, fuzzy  msgid ""  "<p style=\"font-size:150%\">We’re sorry to hear that. We have two\n"  "suggestions: why not try <a href=\"http://www.writetothem.com/\">writing " @@ -248,7 +247,7 @@ msgid ""  "<a href=\"http://www.pledgebank.com/new\">make and publicise a pledge</a>?\n"  "</p>"  msgstr "" -"<p style=\"font-size:150%%\">Det var trist å høre dette. Vi har to forslag: " +"<p style=\"font-size:150%\">Det var trist å høre dette. Vi har to forslag: "  "hva med å forsøke\n"  "<a href=\"%s\">å skrive direkte til dine representanter</a>, eller hvis det "  "er et problem som kan fikses\n" @@ -256,7 +255,6 @@ msgstr ""  "pledgebank.com/new\">publisere en utfordring om å bidra</a>?</p>"  #: templates/web/default/questionnaire/completed-open.html:1 -#, fuzzy  msgid ""  "<p style=\"font-size:150%\">We’re sorry to hear that. We have two\n"  "suggestions: why not try writing to your local representative or, if " @@ -267,8 +265,8 @@ msgid ""  msgstr ""  "<p style=\"font-size:150%%\">Det var trist å høre dette. Vi har to forslag: "  "hva med å forsøke\n" -"<a href=\"%s\">å skrive direkte til dine representanter</a>, eller hvis det " -"er et problem som kan fikses\n" +"å skrive direkte til dine representanter, eller hvis det er et problem som " +"kan fikses\n"  "av folk i nabolaget som jobber sammen, hva med å <a href=\"http://www."  "pledgebank.com/new\">publisere en utfordring om å bidra</a>?</p>" @@ -429,12 +427,11 @@ msgstr "All informasjonen du har lagt inn her vil bli sendt til"  #: templates/web/default/report/new/councils_text_all.html:10  #: templates/web/default/report/new/councils_text_all.html:12 -#, fuzzy  msgid ""  "All the information you provide here will be sent to <strong>%s</strong> or "  "<strong>Roads Service</strong>."  msgstr "" -"All informasjonen du har lagt inn her vil bli sendt til <strong>%s</strong>." +"All informasjon du legger inn her vil bli sendt til <strong>%s</strong>."  #: templates/web/default/report/new/councils_text_all.html:3  #: templates/web/default/report/new/councils_text_all.html:5 @@ -768,7 +765,7 @@ msgstr "For tiden har 1+ slettet"  #: templates/web/default/dashboard/index.html:5  #: templates/web/default/dashboard/index.html:7  msgid "Dashboard" -msgstr "" +msgstr "Oversikt"  #: templates/web/default/admin/council_contacts.html:38  #: templates/web/default/admin/council_contacts.html:85 @@ -906,22 +903,22 @@ msgstr "Sluttmåned:"  msgid "Enter a nearby GB postcode, or street name and area"  msgstr "Skriv inn GB-postnummer i nærheten, eller veinavn og sted" +# Fra UK cobrand  #: perllib/FixMyStreet/Cobrand/UK.pm:18 -#, fuzzy  msgid "Enter a nearby UK postcode, or street name and area" -msgstr "Skriv inn postnummer i nærheten, eller veinavn og sted" +msgstr "Skriv inn et britisk postnummer i nærheten, eller veinavn og sted"  #: perllib/FixMyStreet/Cobrand/FiksGataMi.pm:25  msgid "Enter a nearby postcode, or street name and area"  msgstr "Skriv inn postnummer i nærheten, eller veinavn og sted" +# Kan "Oppgi" være bedre?  #: templates/web/default/around/postcode_form.html:1  #: templates/web/default/around/postcode_form.html:2  #: templates/web/fixmystreet/around/postcode_form.html:10  #: templates/web/fixmystreet/around/postcode_form.html:11 -#, fuzzy  msgid "Enter a nearby street name and area" -msgstr "Skriv inn postnummer i nærheten, eller veinavn og sted" +msgstr "Skriv inn et veinavn og sted"  #: templates/web/default/auth/general.html:64  #: templates/web/default/report/display.html:171 @@ -962,9 +959,8 @@ msgid "Examples:"  msgstr "Eksempler:"  #: templates/web/default/admin/report_edit.html:40 -#, fuzzy  msgid "Extra data:" -msgstr "Merkevaresamarbeidsdata:" +msgstr "Ekstra data:"  #: templates/web/bromley/contact/submit.html:14  #: templates/web/default/contact/submit.html:15 @@ -978,9 +974,8 @@ msgstr ""  #: templates/web/bromley/report/display.html:189  #: templates/web/bromley/report/new/fill_in_details_form.html:113  #: templates/web/bromley/report/new/fill_in_details_form.html:160 -#, fuzzy  msgid "First Name" -msgstr "Første gang" +msgstr "Fornavn"  #: templates/web/default/questionnaire/index.html:79  #: templates/web/fixmystreet/questionnaire/index.html:73 @@ -1117,7 +1112,6 @@ msgstr "Få oppdateringer"  #: templates/web/fixmystreet/reports/_rss.html:3  #: templates/web/fixmystreet/reports/_rss.html:9 -#, fuzzy  msgid "Get updates of %s problems"  msgstr "Få oppdateringer for problemer i denne %s" @@ -1389,9 +1383,8 @@ msgstr "Husk min innlogging på denne datamaskinen"  #: templates/web/bromley/report/display.html:195  #: templates/web/bromley/report/new/fill_in_details_form.html:119  #: templates/web/bromley/report/new/fill_in_details_form.html:166 -#, fuzzy  msgid "Last Name" -msgstr "Siste oppdatering:" +msgstr "Etternavn"  #: templates/web/default/admin/council_contacts.html:39  msgid "Last editor" @@ -1950,6 +1943,8 @@ msgid ""  "Please describe the exact location of the report. Example: “2 dumped "  "mattresses outside Number 19 Stockwell Close”"  msgstr "" +"Vennligst beskriv den nøyaktige posisjonen til problemet. For eksempel: «2 " +"madrasser dumpet utenfor Jernbanegata 19»"  #: templates/web/default/contact/blurb.html:2  msgid "" @@ -2022,9 +2017,8 @@ msgid "Please enter your email address"  msgstr "Vennligst tast inn din e-postadresse"  #: templates/web/default/js/validation_strings.html:19 -#, fuzzy  msgid "Please enter your first name" -msgstr "Legg inn ditt navn" +msgstr "Vennligst tast inn ditt fornavn"  #: perllib/FixMyStreet/DB/Result/Problem.pm:340  #: templates/web/default/js/validation_strings.html:7 @@ -2045,14 +2039,12 @@ msgid "Please enter your name"  msgstr "Legg inn ditt navn"  #: templates/web/default/js/validation_strings.html:20 -#, fuzzy  msgid "Please enter your second name" -msgstr "Legg inn ditt navn" +msgstr "Vennligst tast inn ditt mellomnavn"  #: templates/web/default/js/validation_strings.html:18 -#, fuzzy  msgid "Please enter your title" -msgstr "Legg inn din e-post" +msgstr "Vennligst legg inn din tittel"  #: templates/web/emptyhomes/report/new/fill_in_details_text.html:1  msgid "" @@ -2112,6 +2104,8 @@ msgstr "Vennligst indiker om du ønsker å motta et nytt spørreskjema"  #: templates/web/fixmystreet/report/updates-sidebar-notes.html:3  msgid "Please note that updates are not sent to the council."  msgstr "" +"Vær oppmerksom på at oppdaterginger ikke blir videresendt til " +"administrasjonen."  #: templates/web/default/report/display.html:56  msgid "" @@ -2125,16 +2119,15 @@ msgstr ""  "\">personvernpolicy</a>"  #: templates/web/barnet/report/updates-sidebar-notes.html:1 -#, fuzzy  msgid ""  "Please note that updates are not sent to the relevant department. If you "  "leave your name it will be public. Your information will only be used in "  "accordance with our <a href=\"/faq#privacy\">privacy policy</a>"  msgstr "" -"Vennligst merk at oppdateringer ikke blir sendt til administrasjonen.  Hvis " -"du legger igjen navnet ditt så vil det være offentlig tilgjengelig. Din " +"Vennligst merk at oppdateringer ikke vil bli sendt til administrasjonen. " +"Dersom du legger igjen navnet ditt vil det være synlig for alle. Din "  "informasjon vil kun bli brukt i henhold til våre <a href=\"/faq#privacy" -"\">personvernpolicy</a>" +"\">personvernsregler</a>"  #: templates/web/bromley/report/new/fill_in_details_form.html:23  #: templates/web/default/report/new/fill_in_details_form.html:5 @@ -2190,9 +2183,8 @@ msgid "Please upload a JPEG image only"  msgstr "Vennligst last opp kun JPEG-bilder"  #: perllib/FixMyStreet/App/Controller/Photo.pm:183 -#, fuzzy  msgid "Please upload a JPEG image only\n" -msgstr "Vennligst last opp kun JPEG-bilder" +msgstr "Vennligst last opp kun JPEG eller JPG-bilder\n"  #: perllib/FixMyStreet/App/Controller/Contact.pm:98  msgid "Please write a message" @@ -2327,14 +2319,13 @@ msgid "Provide an update"  msgstr "Bidra med en oppdatering"  #: templates/web/bromley/report/new/fill_in_details_form.html:180 -#, fuzzy  msgid ""  "Providing a password is optional, but doing so will allow you to more easily "  "report future problems, leave updates and manage your reports."  msgstr ""  "Det er valgfritt å oppgi et passord, men om du gjør det vil det bli enklere "  "for deg å rapportere problemer, legge inn oppdateringer og holde oversikt " -"over dine rapporter" +"over dine rapporter."  #: templates/web/bromley/report/display.html:142  #: templates/web/default/report/display.html:175 @@ -2947,14 +2938,13 @@ msgstr ""  "å løse UKs tomme hjem-krise."  #: templates/web/fixmystreet/around/around_index.html:27 -#, fuzzy  msgid ""  "Thanks for uploading your photo. We now need to locate your problem, so "  "please enter a nearby street name or postcode in the box above :"  msgstr "" -"Takk for at du lastet opp ditt bilde.  Nå trenger vi å plassere ditt problem," -"så vær så snill å skriv inn navn på vei i nærheten, eller postnummer i " -"boksen under :" +"Takk for at du lastet opp ditt bilde.  Vi må nå plassere ditt problem, så " +"vær så snill å skriv inn navnet på en vei eller et postnummer i området i " +"boksen ovenfor :"  #: templates/web/default/around/around_index.html:28  msgid "" @@ -2983,17 +2973,15 @@ msgid ""  msgstr "Bildet ser ikke ut til å blitt lastet opp riktig (%s), prøv på nytt."  #: perllib/FixMyStreet/App/Controller/Council.pm:91 -#, fuzzy  msgid ""  "That location does not appear to be covered by a council; perhaps it is "  "offshore or outside the country. Please try again."  msgstr "" -"Det stedet dekkes ikke av noen administrasjon, kanskje det er til havs - " -"vennligst forsøk et mer spesifikt sted." +"Det stedet dekkes ikke av noen administrasjon, kanskje det er til havs eller " +"utenfor lander - vennligst forsøk et annet sted."  # Should this be "Norge" or "Storbritannia" ?  #: perllib/FixMyStreet/App/Controller/Location.pm:107 -#, fuzzy  msgid "That location does not appear to be in the UK; please try again."  msgstr "Det stedet virker ikke å være i Storbritannia. Vennligst prøv igjen." @@ -3199,11 +3187,8 @@ msgstr ""  "senere."  #: perllib/FixMyStreet/App/Controller/Dashboard.pm:59 -#, fuzzy  msgid "There was a problem showing this page. Please try again later." -msgstr "" -"Det var problemer med å vise 'Alle rapporter'-siden.  Vennligst prøv igjen " -"senere." +msgstr "Det var problemer med å vise denne siden. Vennligst prøv igjen senere."  #: perllib/FixMyStreet/App/Controller/Report/New.pm:733  #: perllib/FixMyStreet/App/Controller/Report/Update.pm:130 @@ -3370,12 +3355,11 @@ msgstr ""  "For å <strong>rapportere et problem</strong>, klikk på kartet på riktig sted."  #: templates/web/default/alert/index.html:27 -#, fuzzy  msgid ""  "To find out what local alerts we have for you, please enter your postcode or "  "street name and area"  msgstr "" -"Du finner lokale problemer ved å søke på ditt postnummer, veinavn eller sted:" +"Du finner lokale problemer ved å søke på ditt postnummer, veinavn eller sted"  #: perllib/FixMyStreet/DB/ResultSet/Problem.pm:268  msgid "To view a map of the precise location of this issue" @@ -3505,9 +3489,8 @@ msgid "View report on site"  msgstr "Se rapport på nettstedet"  #: templates/web/default/reports/council.html:18 -#, fuzzy  msgid "View reports by ward" -msgstr "Se rapport på nettstedet" +msgstr "Se rapport per bydel"  #: templates/web/emptyhomes/tokens/confirm_problem.html:39  msgid "View your report" @@ -3595,13 +3578,12 @@ msgstr ""  "faq#privacy\">personvernpolicy.</a>"  #: templates/web/fixmystreet/report/new/notes.html:4 -#, fuzzy  msgid ""  "We will only use your personal information in accordance with our <a href=\"/"  "privacy\">privacy policy.</a>"  msgstr "" -"Vi vil kun bruke personlig informasjon om deg i henhold til vår <a href=\"/" -"faq#privacy\">personvernpolicy.</a>" +"Vi vil kun bruke personlige informasjon om deg i henhold til våre <a href=\"/" +"faq#privacy\">personvernsregler.</a>"  #: templates/web/emptyhomes/contact/blurb.html:2  msgid "" @@ -3648,7 +3630,6 @@ msgstr ""  "href=\"%s\">MaPit</a>."  #: templates/web/fixmystreet/footer.html:22 -#, fuzzy  msgid ""  "Would you like better integration with FixMyStreet? <a href=\"http://www."  "mysociety.org/for-councils/fixmystreet/\">Find out about FixMyStreet for " @@ -3886,25 +3867,22 @@ msgstr "Din e-post"  #: templates/web/bromley/report/display.html:193  #: templates/web/bromley/report/new/fill_in_details_form.html:117  #: templates/web/bromley/report/new/fill_in_details_form.html:164 -#, fuzzy  msgid "Your first name" -msgstr "Ditt navn" +msgstr "Ditt fornavn"  #: templates/web/fixmystreet/report/updates-sidebar-notes.html:5 -#, fuzzy  msgid ""  "Your information will only be used in accordance with our <a href=\"/privacy"  "\">privacy policy</a>"  msgstr "" -"Vi vil kun bruke personlig informasjon om deg i henhold til vår <a href=\"/" -"faq#privacy\">personvernpolicy.</a>" +"Vi vil kun bruke personlig informasjon om deg i henhold til våre <a href=\"/" +"faq#privacy\">personvernsregler.</a>"  #: templates/web/bromley/report/display.html:199  #: templates/web/bromley/report/new/fill_in_details_form.html:123  #: templates/web/bromley/report/new/fill_in_details_form.html:170 -#, fuzzy  msgid "Your last name" -msgstr "Ditt navn" +msgstr "Ditt etternavn"  #: templates/web/fixmystreet/auth/general.html:53  #: templates/web/fixmystreet/contact/index.html:65 @@ -4043,7 +4021,7 @@ msgstr "kartet ble ikke brukt, så nåleposisjon kan være unøyaktig"  #: perllib/FixMyStreet/DB/Result/Problem.pm:603  msgid "their ref: %s" -msgstr "" +msgstr "deres ref: %s"  #: perllib/FixMyStreet/DB/ResultSet/Problem.pm:330  msgid "this type of local problem" diff --git a/notes/no-update-server b/notes/no-update-server index 2d149d850..da3656829 100644 --- a/notes/no-update-server +++ b/notes/no-update-server @@ -511,7 +511,7 @@ case "$1" in  	;;      update)  	fetch_git_source -	fgmdbpassword=$(grep OPTION_BCI_DB_PASS $basedir/fixmystreet/conf/general | cut -d\' -f4) +	fgmdbpassword=$(grep OPTION_FMS_DB_PASS $basedir/fixmystreet/conf/general | cut -d\' -f4)  	midbpassword=$(grep OPTION_MAPIT_DB_PASS $basedir/mapit/conf/general | cut -d\' -f4)  	update_fixmystreet_config www-data $fgmdbpassword fixmystreet diff --git a/perllib/CrossSell.pm b/perllib/CrossSell.pm index f9a02a61b..f9cde6936 100644 --- a/perllib/CrossSell.pm +++ b/perllib/CrossSell.pm @@ -19,7 +19,6 @@ package CrossSell;  use strict;  use LWP::Simple qw($ua get); -$ua->timeout(5);  use URI::Escape;  use mySociety::AuthToken;  use mySociety::Web qw(ent); @@ -169,6 +168,8 @@ sub display_advert ($$;$%) {      return '' unless $c->cobrand->moniker eq 'fixmystreet'; +    $ua->timeout(5); +      #if (defined $data{council} && $data{council} eq '2326') {      #    my ($out, $ad) = display_hfyc_cheltenham_advert($email, $name);      #    if ($out) { diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index f05639b41..2d1cf2c5a 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -301,6 +301,7 @@ sub update_contacts : Private {          $contact->email( $email );          $contact->confirmed( $c->req->param('confirmed') ? 1 : 0 );          $contact->deleted( $c->req->param('deleted') ? 1 : 0 ); +        $contact->non_public( $c->req->param('non_public') ? 1 : 0 );          $contact->note( $c->req->param('note') );          $contact->whenedited( \'ms_current_timestamp()' );          $contact->editor( $editor ); @@ -649,6 +650,7 @@ sub report_edit : Path('report_edit') : Args(1) {          }          my $flagged = $c->req->param('flagged') ? 1 : 0; +        my $non_public = $c->req->param('non_public') ? 1 : 0;          # do this here so before we update the values in problem          if (   $c->req->param('anonymous') ne $problem->anonymous @@ -656,8 +658,10 @@ sub report_edit : Path('report_edit') : Args(1) {              || $c->req->param('email')  ne $problem->user->email              || $c->req->param('title')  ne $problem->title              || $c->req->param('detail') ne $problem->detail -            || $flagged != $problem->flagged ) +            || $flagged != $problem->flagged +            || $non_public != $problem->non_public )          { +            warn "edited";              $edited = 1;          } @@ -667,6 +671,7 @@ sub report_edit : Path('report_edit') : Args(1) {          $problem->state( $c->req->param('state') );          $problem->name( $c->req->param('name') );          $problem->flagged( $flagged ); +        $problem->non_public( $non_public );          if ( $c->req->param('email') ne $problem->user->email ) {              my $user = $c->model('DB::User')->find_or_create( diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm index 57d27b3e4..a7e1e8a3a 100644 --- a/perllib/FixMyStreet/App/Controller/Report.pm +++ b/perllib/FixMyStreet/App/Controller/Report.pm @@ -91,6 +91,13 @@ sub load_problem_or_display_error : Private {              '/page_error_410_gone',              [ _('That report has been removed from FixMyStreet.') ]    #          ); +    } elsif ( $problem->non_public ) { +        if ( !$c->user || $c->user->id != $problem->user->id ) { +            $c->detach( +                '/page_error_403_access_denied', +                [ _('That report cannot be viewed on FixMyStreet.') ]    # +            ); +        }      }      $c->stash->{problem} = $problem; diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm index b18e6e39f..a4462e035 100644 --- a/perllib/FixMyStreet/App/Controller/Report/New.pm +++ b/perllib/FixMyStreet/App/Controller/Report/New.pm @@ -595,6 +595,8 @@ sub setup_categories_and_councils : Private {      my @category_options = ();       # categories to show      my $category_label   = undef;    # what to call them      my %category_extras  = ();       # extra fields to fill in for open311 +    my %non_public_categories = +      ();    # categories for which the reports are not public      # FIXME - implement in cobrand      if ( $c->cobrand->moniker eq 'emptyhomes' ) { @@ -646,6 +648,8 @@ sub setup_categories_and_councils : Private {                  $category_extras{ $contact->category } = $contact->extra                      if $contact->extra; + +                $non_public_categories{ $contact->category } = 1 if $contact->non_public;              }              $seen{$contact->category} = 1;          } @@ -663,6 +667,7 @@ sub setup_categories_and_councils : Private {      $c->stash->{category_label}   = $category_label;      $c->stash->{category_options} = \@category_options;      $c->stash->{category_extras}  = \%category_extras; +    $c->stash->{non_public_categories}  = \%non_public_categories;      $c->stash->{category_extras_json}  = encode_json \%category_extras;      $c->stash->{extra_name_info} = $first_council->{id} == COUNCIL_ID_BROMLEY ? 1 : 0; @@ -872,6 +877,10 @@ sub process_report : Private {              };          } +        if ( $c->stash->{non_public_categories}->{ $report->category } ) { +            $report->non_public( 1 ); +        } +          $c->cobrand->process_extras( $c, $contacts[0]->area_id, \@extra );          if ( @extra ) { diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm index 37766db44..444389ec2 100644 --- a/perllib/FixMyStreet/App/Controller/Reports.pm +++ b/perllib/FixMyStreet/App/Controller/Reports.pm @@ -170,13 +170,6 @@ sub rss_ward : Regex('^rss/(reports|area)$') : Args(2) {      $url   .= '/' . $c->cobrand->short_name( $c->stash->{ward}    ) if $c->stash->{ward};      $c->stash->{qs} = "/$url"; -    my @params; -    push @params, $c->stash->{council}->{id} if $rss eq 'reports'; -    push @params, $c->stash->{ward} -        ? $c->stash->{ward}->{id} -        : $c->stash->{council}->{id}; -    $c->stash->{db_params} = [ @params ]; -      if ( $rss eq 'area' && $c->stash->{ward} ) {          # All problems within a particular ward          $c->stash->{type}         = 'area_problems'; @@ -236,6 +229,7 @@ sub council_check : Private {          type => $area_types,          min_generation => $c->cobrand->area_min_generation      ); +      if (keys %$areas == 1) {          ($c->stash->{council}) = values %$areas;          return; @@ -318,7 +312,8 @@ sub load_and_group_problems : Private {      my $page = $c->req->params->{p} || 1;      my $where = { -        state => [ FixMyStreet::DB::Result::Problem->visible_states() ] +        non_public => 0, +        state      => [ FixMyStreet::DB::Result::Problem->visible_states() ]      };      if ($c->stash->{ward}) {          $where->{areas} = { 'like', '%,' . $c->stash->{ward}->{id} . ',%' }; diff --git a/perllib/FixMyStreet/App/Controller/Root.pm b/perllib/FixMyStreet/App/Controller/Root.pm index 7f7d7f5fd..769a147bf 100644 --- a/perllib/FixMyStreet/App/Controller/Root.pm +++ b/perllib/FixMyStreet/App/Controller/Root.pm @@ -94,6 +94,13 @@ sub page_error_410_gone : Private {      $c->response->status(410);  } +sub page_error_403_access_denied : Private { +    my ( $self, $c, $error_msg ) = @_; +    $c->stash->{template}  = 'index.html'; +    $c->stash->{error} = $error_msg; +    $c->response->status(403); +} +  =head2 end  Attempt to render a view, if needed. diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm index 64e08f44c..cfc9455b5 100644 --- a/perllib/FixMyStreet/Cobrand/Default.pm +++ b/perllib/FixMyStreet/Cobrand/Default.pm @@ -4,6 +4,7 @@ use base 'FixMyStreet::Cobrand::Base';  use strict;  use warnings;  use FixMyStreet; +use Encode;  use URI;  use Digest::MD5 qw(md5_hex); @@ -674,7 +675,9 @@ sub _fallback_council_sender {  };  sub example_places { -    return FixMyStreet->config('EXAMPLE_PLACES') || [ 'High Street', 'Main Street' ]; +    my $e = FixMyStreet->config('EXAMPLE_PLACES') || [ 'High Street', 'Main Street' ]; +    $e = [ map { Encode::decode('UTF-8', $_) } @$e ]; +    return $e;  }  =head2 only_authed_can_create diff --git a/perllib/FixMyStreet/Cobrand/UK.pm b/perllib/FixMyStreet/Cobrand/UK.pm index feb3c9ecf..75f6ba061 100644 --- a/perllib/FixMyStreet/Cobrand/UK.pm +++ b/perllib/FixMyStreet/Cobrand/UK.pm @@ -145,13 +145,13 @@ sub find_closest {      my $str = $self->SUPER::find_closest( $latitude, $longitude, $problem );      # Get nearest postcode from Matthew's random gazetteer (put in MaPit? Or elsewhere?) -    my $url = "http://gazetteer.dracos.vm.bytemark.co.uk/point/$latitude,$longitude.json"; +    my $url = "http://mapit.mysociety.org/nearest/4326/$longitude,$latitude";      my $j = LWP::Simple::get($url);      if ($j) {          $j = JSON->new->utf8->allow_nonref->decode($j);          if ($j->{postcode}) {              $str .= sprintf(_("Nearest postcode to the pin placed on the map (automatically generated): %s (%sm away)"), -                $j->{postcode}[0], $j->{postcode}[1]) . "\n\n"; +                $j->{postcode}{postcode}, $j->{postcode}{distance}) . "\n\n";          }      } diff --git a/perllib/FixMyStreet/DB/Result/Contact.pm b/perllib/FixMyStreet/DB/Result/Contact.pm index 2a6ffa2fe..993e3524b 100644 --- a/perllib/FixMyStreet/DB/Result/Contact.pm +++ b/perllib/FixMyStreet/DB/Result/Contact.pm @@ -36,6 +36,8 @@ __PACKAGE__->add_columns(    { data_type => "text", is_nullable => 0 },    "extra",    { data_type => "text", is_nullable => 1 }, +  "non_public", +  { data_type => "boolean", default_value => \"false", is_nullable => 1 },    "endpoint",    { data_type => "text", is_nullable => 1 },    "jurisdiction", @@ -49,8 +51,8 @@ __PACKAGE__->set_primary_key("id");  __PACKAGE__->add_unique_constraint("contacts_area_id_category_idx", ["area_id", "category"]); -# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-08-29 17:34:28 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:getDAgTeXkAYQTcxHWflmA +# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-08-31 10:29:17 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:t6yOPhZmedV/eH6AUvHI6w  __PACKAGE__->filter_column(      extra => { diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm index af62a299b..761f57b01 100644 --- a/perllib/FixMyStreet/DB/Result/Problem.pm +++ b/perllib/FixMyStreet/DB/Result/Problem.pm @@ -92,6 +92,8 @@ __PACKAGE__->add_columns(    { data_type => "timestamp", is_nullable => 1 },    "send_method_used",    { data_type => "text", is_nullable => 1 }, +  "non_public", +  { data_type => "boolean", default_value => \"false", is_nullable => 1 },    "external_source",    { data_type => "text", is_nullable => 1 },    "external_source_id", @@ -120,8 +122,8 @@ __PACKAGE__->belongs_to(  ); -# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-08-23 12:14:00 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:05LIWlb0CUWAR7bN5RAhOA +# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-08-31 10:25:34 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:mudIAiLAUdmK8gGWIPiq6g  # Add fake relationship to stored procedure table  __PACKAGE__->has_one( diff --git a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm index a0320ccc3..2d206d84e 100644 --- a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm +++ b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm @@ -65,6 +65,9 @@ sub email_alerts ($) {              # call checks if this is the host that sends mail for this cobrand.              next unless $cobrand->email_host; +            # this is for the new_updates alerts +            next if $row->{non_public} and $row->{user_id} != $row->{alert_user_id}; +              my $hashref_restriction = $cobrand->site_restriction( $row->{cobrand_data} );              FixMyStreet::App->model('DB::AlertSent')->create( { @@ -151,6 +154,7 @@ sub email_alerts ($) {              where nearby.problem_id = problem.id              and problem.user_id = users.id              and problem.state in ($states) +            and problem.non_public = 'f'              and problem.confirmed >= ? and problem.confirmed >= ms_current_timestamp() - '7 days'::interval              and (select whenqueued from alert_sent where alert_sent.alert_id = ? and alert_sent.parameter::integer = problem.id) is null              and users.email <> ? diff --git a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm index 83fc85a88..191223572 100644 --- a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm +++ b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm @@ -8,6 +8,7 @@ sub nearby {      my ( $rs, $c, $dist, $ids, $limit, $mid_lat, $mid_lon, $interval ) = @_;      my $params = { +        non_public => 0,          state => [ FixMyStreet::DB::Result::Problem::visible_states() ],      };      $params->{'current_timestamp-lastupdate'} = { '<', \"'$interval'::interval" } diff --git a/perllib/FixMyStreet/DB/ResultSet/Problem.pm b/perllib/FixMyStreet/DB/ResultSet/Problem.pm index e946e01c2..f7f88edf0 100644 --- a/perllib/FixMyStreet/DB/ResultSet/Problem.pm +++ b/perllib/FixMyStreet/DB/ResultSet/Problem.pm @@ -85,7 +85,8 @@ sub _recent {      $key .= ":$site_key:$num";      my $query = { -        state => [ FixMyStreet::DB::Result::Problem->visible_states() ], +        non_public => 0, +        state      => [ FixMyStreet::DB::Result::Problem->visible_states() ],      };      $query->{photo} = { '!=', undef } if $photos; @@ -141,6 +142,7 @@ sub around_map {      $attr->{rows} = $limit if $limit;      my $q = { +            non_public => 0,              state => [ FixMyStreet::DB::Result::Problem->visible_states() ],              latitude => { '>=', $min_lat, '<', $max_lat },              longitude => { '>=', $min_lon, '<', $max_lon }, diff --git a/perllib/FixMyStreet/Geocode/OSM.pm b/perllib/FixMyStreet/Geocode/OSM.pm index ba939b443..78db7fe44 100644 --- a/perllib/FixMyStreet/Geocode/OSM.pm +++ b/perllib/FixMyStreet/Geocode/OSM.pm @@ -15,9 +15,10 @@ use Digest::MD5 qw(md5_hex);  use Encode;  use File::Slurp;  use File::Path (); -use LWP::Simple; +use LWP::Simple qw($ua);  use Memcached;  use XML::Simple; +use mySociety::Locale;  my $osmapibase    = "http://www.openstreetmap.org/api/";  my $nominatimbase = "http://nominatim.openstreetmap.org/"; @@ -49,6 +50,7 @@ sub string {      if (-s $cache_file) {          $js = File::Slurp::read_file($cache_file);      } else { +        $ua->timeout(15);          $js = LWP::Simple::get($url);          $js = encode_utf8($js) if utf8::is_utf8($js);          File::Path::mkpath($cache_dir); diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm index 2a49cc2f8..5866ee21c 100644 --- a/perllib/FixMyStreet/TestMech.pm +++ b/perllib/FixMyStreet/TestMech.pm @@ -378,6 +378,49 @@ sub extract_update_metas {      return \@metas;  } +=head2 extract_problem_list + +    $problems = $mech->extract_problem_list + +Returns an array ref of all problem titles on a page featuring standard issue lists + +=cut + +sub extract_problem_list { +    my $mech = shift; + +    my $result = scraper { +        process 'ul.issue-list-a li a h4', 'problems[]', 'TEXT'; +    }->scrape( $mech->response ); + +    return $result->{ problems } || []; +} + +=head2 extract_report_stats + +    $stats = $mech->extract_report_stats + +Returns a hash ref keyed by council name of all the council stats from the all reports +page. Each value is an array ref with the first element being the council name and the +rest being the stats in the order the appear in each row. + +=cut + +sub extract_report_stats { +    my $mech = shift; + +    my $result = scraper { +        process 'tr[align=center]', 'councils[]' => scraper { +            process 'td.title a', 'council', 'TEXT', +            process 'td', 'stats[]', 'TEXT' +        } +    }->scrape( $mech->response ); + +    my %councils = map { $_->{council} => $_->{stats} } @{ $result->{councils} }; + +    return \%councils; +} +  =head2 visible_form_values      $hashref = $mech->visible_form_values(  ); @@ -475,4 +518,67 @@ sub get_ok_json {      return decode_json( $res->content );  } +sub delete_problems_for_council { +    my $mech = shift; +    my $council = shift; + +    my $reports = FixMyStreet::App->model('DB::Problem')->search( { council => $council } ); +    if ( $reports ) { +        for my $r ( $reports->all ) { +            $r->comments->delete; +        } +        $reports->delete; +    } +} + +sub create_problems_for_council { +    my ( $mech, $count, $council, $title, $params ) = @_; + +    my $dt = $params->{dt} || DateTime->now(); + +    my $user = $params->{user} || +      FixMyStreet::App->model('DB::User') +      ->find_or_create( { email => 'test@example.com', name => 'Test User' } ); + +    delete $params->{user}; +    delete $params->{dt}; + +    my @problems; + +    while ($count) { +        my $default_params = { +            postcode           => 'SW1A 1AA', +            council            => $council, +            areas              => ',105255,11806,11828,2247,2504,', +            category           => 'Other', +            title              => "$title Test $count for $council", +            detail             => "$title Test $count for $council Detail", +            used_map           => 't', +            name               => 'Test User', +            anonymous          => 'f', +            state              => 'confirmed', +            confirmed          => $dt->ymd . ' ' . $dt->hms, +            lang               => 'en-gb', +            service            => '', +            cobrand            => 'default', +            cobrand_data       => '', +            send_questionnaire => 't', +            latitude           => '51.5016605453401', +            longitude          => '-0.142497580865087', +            user_id            => $user->id, +            photo              => 1, +        }; + +        my %report_params = ( %$default_params, %$params ); + +        my $problem = +          FixMyStreet::App->model('DB::Problem')->create( \%report_params ); + +        push @problems, $problem; +        $count--; +    } + +    return @problems; +} +  1; diff --git a/perllib/Open311.pm b/perllib/Open311.pm index aa0e64b53..1027c756f 100644 --- a/perllib/Open311.pm +++ b/perllib/Open311.pm @@ -65,7 +65,11 @@ sub send_service_request {          if ( $obj ) {              if ( $obj->{ request }->{ service_request_id } ) { -                return $obj->{ request }->{ service_request_id }; +                my $request_id = $obj->{request}->{service_request_id}; + +                unless ( ref $request_id ) { +                    return $request_id; +                }              } else {                  my $token = $obj->{ request }->{ token };                  if ( $token ) { @@ -75,8 +79,10 @@ sub send_service_request {          }          warn sprintf( "Failed to submit problem %s over Open311, response\n: %s\n%s", $problem->id, $response, $self->debug_details ); -        return 0; +    } else { +        warn sprintf( "Failed to submit problem %s over Open311, details:\n%s", $problem->id, $self->error);      } +    return 0;  }  sub _populate_service_request_params { @@ -259,8 +265,10 @@ sub post_service_request_update {          }          warn sprintf( "Failed to submit comment %s over Open311, response - %s\n%s\n", $comment->id, $response, $self->debug_details ); -        return 0; +    } else { +        warn sprintf( "Failed to submit comment %s over Open311, details\n%s\n", $comment->id, $self->error);      } +    return 0;  }  sub _populate_service_request_update_params { @@ -379,7 +387,6 @@ sub _post {              $self->_process_error( $res->decoded_content ),              $self->debug_details          ) ); -        warn $self->error;          return 0;      }  } diff --git a/perllib/Utils.pm b/perllib/Utils.pm index 6a47fd17d..23a87485d 100644 --- a/perllib/Utils.pm +++ b/perllib/Utils.pm @@ -159,7 +159,6 @@ sub barnet_categories {          }      } else {          return { -            'Abandoned Vehicle'         => 468,              'Accumulated Litter'        => 349,              'Dog Bin'                   => 203,              'Dog Fouling'               => 288, diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t index 09d99cfdf..839bfd6b9 100644 --- a/t/app/controller/admin.t +++ b/t/app/controller/admin.t @@ -163,19 +163,32 @@ subtest 'check contact creation' => sub {      $mech->get_ok('/admin/council_contacts/2650');      $mech->submit_form_ok( { with_fields => {  -        category => 'test category', -        email    => 'test@example.com', -        note     => 'test note', +        category   => 'test category', +        email      => 'test@example.com', +        note       => 'test note', +        non_public => undef,      } } );      $mech->content_contains( 'test category' );      $mech->content_contains( '<td>test@example.com' );      $mech->content_contains( '<td>test note' ); +    $mech->content_contains( '<td>Public' ); + +    $mech->submit_form_ok( { with_fields => {  +        category   => 'private category', +        email      => 'test@example.com', +        note       => 'test note', +        non_public => 'on', +    } } ); + +    $mech->content_contains( 'private category' ); +    $mech->content_contains( '<td>Non Public' );      $mech->submit_form_ok( { with_fields => {          category => 'test/category',          email    => 'test@example.com',          note     => 'test/note', +        non_public => 'on',      } } );      $mech->get_ok('/admin/council_edit/2650/test/category'); @@ -187,11 +200,21 @@ subtest 'check contact editing' => sub {      $mech->submit_form_ok( { with_fields => {           email    => 'test2@example.com',          note     => 'test2 note', +        non_public => undef,      } } );      $mech->content_contains( 'test category' );      $mech->content_contains( '<td>test2@example.com' );      $mech->content_contains( '<td>test2 note' ); +    $mech->content_contains( '<td>Public' ); + +    $mech->submit_form_ok( { with_fields => {  +        email    => 'test2@example.com', +        note     => 'test2 note', +        non_public => 'on', +    } } ); + +    $mech->content_contains( '<td>Non Public' );      $mech->get_ok('/admin/council_edit/2650/test%20category');      $mech->content_contains( '<td><strong>test2@example.com' ); @@ -293,206 +316,229 @@ ok $report, "created test report - $report_id";  foreach my $test (      {          description => 'edit report title', -        fields => { -            title  => 'Report to Edit', -            detail => 'Detail for Report to Edit', -            state  => 'confirmed', -            name   => 'Test User', -            email  => $user->email, -            anonymous => 0, -            flagged => undef, -        }, -        changes => { -            title => 'Edited Report', +        fields      => { +            title      => 'Report to Edit', +            detail     => 'Detail for Report to Edit', +            state      => 'confirmed', +            name       => 'Test User', +            email      => $user->email, +            anonymous  => 0, +            flagged    => undef, +            non_public => undef,          }, -        log_count => 1, -        log_entries => [ qw/edit/ ], -        resend => 0, +        changes     => { title => 'Edited Report', }, +        log_count   => 1, +        log_entries => [qw/edit/], +        resend      => 0,      },      {          description => 'edit report description', -        fields => { -            title  => 'Edited Report', -            detail => 'Detail for Report to Edit', -            state  => 'confirmed', -            name   => 'Test User', -            email  => $user->email, -            anonymous => 0, -            flagged => undef, +        fields      => { +            title      => 'Edited Report', +            detail     => 'Detail for Report to Edit', +            state      => 'confirmed', +            name       => 'Test User', +            email      => $user->email, +            anonymous  => 0, +            flagged    => undef, +            non_public => undef,          }, -        changes => { -            detail => 'Edited Detail', -        }, -        log_count => 2, -        log_entries => [ qw/edit edit/ ], -        resend => 0, +        changes     => { detail => 'Edited Detail', }, +        log_count   => 2, +        log_entries => [qw/edit edit/], +        resend      => 0,      },      {          description => 'edit report user name', -        fields => { -            title  => 'Edited Report', -            detail => 'Edited Detail', -            state  => 'confirmed', -            name   => 'Test User', -            email  => $user->email, -            anonymous => 0, -            flagged => undef, -        }, -        changes => { -            name => 'Edited User', +        fields      => { +            title      => 'Edited Report', +            detail     => 'Edited Detail', +            state      => 'confirmed', +            name       => 'Test User', +            email      => $user->email, +            anonymous  => 0, +            flagged    => undef, +            non_public => undef,          }, -        log_count => 3, -        log_entries => [ qw/edit edit edit/ ], -        resend => 0, -        user => $user, +        changes     => { name => 'Edited User', }, +        log_count   => 3, +        log_entries => [qw/edit edit edit/], +        resend      => 0, +        user        => $user,      },      {          description => 'edit report set flagged true', -        fields => { -            title  => 'Edited Report', -            detail => 'Edited Detail', -            state  => 'confirmed', -            name   => 'Edited User', -            email  => $user->email, -            anonymous => 0, -            flagged => undef, +        fields      => { +            title      => 'Edited Report', +            detail     => 'Edited Detail', +            state      => 'confirmed', +            name       => 'Edited User', +            email      => $user->email, +            anonymous  => 0, +            flagged    => undef, +            non_public => undef,          },          changes => { -            flagged => 'on', +            flagged    => 'on',          }, -        log_count => 4, -        log_entries => [ qw/edit edit edit edit/ ], -        resend => 0, -        user => $user, +        log_count   => 4, +        log_entries => [qw/edit edit edit edit/], +        resend      => 0, +        user        => $user,      },      {          description => 'edit report user email', -        fields => { -            title  => 'Edited Report', -            detail => 'Edited Detail', -            state  => 'confirmed', -            name   => 'Edited User', -            email  => $user->email, -            anonymous => 0, -            flagged => 'on', -        }, -        changes => { -            email => $user2->email, +        fields      => { +            title      => 'Edited Report', +            detail     => 'Edited Detail', +            state      => 'confirmed', +            name       => 'Edited User', +            email      => $user->email, +            anonymous  => 0, +            flagged    => 'on', +            non_public => undef,          }, -        log_count => 5, -        log_entries => [ qw/edit edit edit edit edit/ ], -        resend => 0, -        user => $user2, +        changes     => { email => $user2->email, }, +        log_count   => 5, +        log_entries => [qw/edit edit edit edit edit/], +        resend      => 0, +        user        => $user2,      },      {          description => 'change state to unconfirmed', -        fields => { -            title  => 'Edited Report', -            detail => 'Edited Detail', -            state  => 'confirmed', -            name   => 'Edited User', -            email  => $user2->email, -            anonymous => 0, -            flagged => 'on', -        }, -        changes => { -            state => 'unconfirmed' +        fields      => { +            title      => 'Edited Report', +            detail     => 'Edited Detail', +            state      => 'confirmed', +            name       => 'Edited User', +            email      => $user2->email, +            anonymous  => 0, +            flagged    => 'on', +            non_public => undef,          }, +        changes   => { state => 'unconfirmed' },          log_count => 6, -        log_entries => [ qw/state_change edit edit edit edit edit/ ], -        resend => 0, +        log_entries => [qw/state_change edit edit edit edit edit/], +        resend      => 0,      },      {          description => 'change state to confirmed', -        fields => { -            title  => 'Edited Report', -            detail => 'Edited Detail', -            state  => 'unconfirmed', -            name   => 'Edited User', -            email  => $user2->email, -            anonymous => 0, -            flagged => 'on', -        }, -        changes => { -            state => 'confirmed' +        fields      => { +            title      => 'Edited Report', +            detail     => 'Edited Detail', +            state      => 'unconfirmed', +            name       => 'Edited User', +            email      => $user2->email, +            anonymous  => 0, +            flagged    => 'on', +            non_public => undef,          }, +        changes   => { state => 'confirmed' },          log_count => 7, -        log_entries => [ qw/state_change state_change edit edit edit edit edit/ ], -        resend => 0, +        log_entries => [qw/state_change state_change edit edit edit edit edit/], +        resend      => 0,      },      {          description => 'change state to fixed', -        fields => { -            title  => 'Edited Report', -            detail => 'Edited Detail', -            state  => 'confirmed', -            name   => 'Edited User', -            email  => $user2->email, -            anonymous => 0, -            flagged => 'on', -        }, -        changes => { -            state => 'fixed' +        fields      => { +            title      => 'Edited Report', +            detail     => 'Edited Detail', +            state      => 'confirmed', +            name       => 'Edited User', +            email      => $user2->email, +            anonymous  => 0, +            flagged    => 'on', +            non_public => undef,          }, +        changes   => { state => 'fixed' },          log_count => 8, -        log_entries => [ qw/state_change state_change state_change edit edit edit edit edit/ ], +        log_entries => +          [qw/state_change state_change state_change edit edit edit edit edit/],          resend => 0,      },      {          description => 'change state to hidden', -        fields => { -            title  => 'Edited Report', -            detail => 'Edited Detail', -            state  => 'fixed', -            name   => 'Edited User', -            email  => $user2->email, -            anonymous => 0, -            flagged => 'on', -        }, -        changes => { -            state => 'hidden' +        fields      => { +            title      => 'Edited Report', +            detail     => 'Edited Detail', +            state      => 'fixed', +            name       => 'Edited User', +            email      => $user2->email, +            anonymous  => 0, +            flagged    => 'on', +            non_public => undef,          }, -        log_count => 9, -        log_entries => [ qw/state_change state_change state_change state_change edit edit edit edit edit/ ], +        changes     => { state => 'hidden' }, +        log_count   => 9, +        log_entries => [ +            qw/state_change state_change state_change state_change edit edit edit edit edit/ +        ],          resend => 0,      },      {          description => 'edit and change state', -        fields => { -            title  => 'Edited Report', -            detail => 'Edited Detail', -            state  => 'hidden', -            name   => 'Edited User', -            email  => $user2->email, -            anonymous => 0, -            flagged => 'on', +        fields      => { +            title      => 'Edited Report', +            detail     => 'Edited Detail', +            state      => 'hidden', +            name       => 'Edited User', +            email      => $user2->email, +            anonymous  => 0, +            flagged    => 'on', +            non_public => undef,          },          changes => { -            state => 'confirmed', +            state     => 'confirmed',              anonymous => 1,          }, -        log_count => 11, -        log_entries => [ qw/edit state_change state_change state_change state_change state_change edit edit edit edit edit/ ], +        log_count   => 11, +        log_entries => [ +            qw/edit state_change state_change state_change state_change state_change edit edit edit edit edit/ +        ],          resend => 0,      },      {          description => 'resend', -        fields => { -            title  => 'Edited Report', -            detail => 'Edited Detail', -            state  => 'confirmed', -            name   => 'Edited User', -            email  => $user2->email, -            anonymous => 1, -            flagged => 'on', -        }, -        changes => { +        fields      => { +            title      => 'Edited Report', +            detail     => 'Edited Detail', +            state      => 'confirmed', +            name       => 'Edited User', +            email      => $user2->email, +            anonymous  => 1, +            flagged    => 'on', +            non_public => undef,          }, -        log_count => 12, -        log_entries => [ qw/resend edit state_change state_change state_change state_change state_change edit edit edit edit edit/ ], +        changes     => {}, +        log_count   => 12, +        log_entries => [ +            qw/resend edit state_change state_change state_change state_change state_change edit edit edit edit edit/ +        ],          resend => 1,      }, -) { +    { +        description => 'non public', +        fields      => { +            title      => 'Edited Report', +            detail     => 'Edited Detail', +            state      => 'confirmed', +            name       => 'Edited User', +            email      => $user2->email, +            anonymous  => 1, +            flagged    => 'on', +            non_public => undef, +        }, +        changes     => { +            non_public => 'on', +        }, +        log_count   => 13, +        log_entries => [ +            qw/edit resend edit state_change state_change state_change state_change state_change edit edit edit edit edit/ +        ], +        resend => 0, +    }, +  ) +{      subtest $test->{description} => sub {          $log_entries->reset;          $mech->get_ok("/admin/report_edit/$report_id"); @@ -523,6 +569,8 @@ foreach my $test (          }          $test->{changes}->{flagged} = 1 if $test->{changes}->{flagged}; +        $test->{changes}->{non_public} = 1 if $test->{changes}->{non_public}; +          is $report->$_, $test->{changes}->{$_}, "$_ updated" for grep { $_ ne 'email' } keys %{ $test->{changes} };          if ( $test->{user} ) { @@ -547,6 +595,7 @@ subtest 'change email to new user' => sub {          email  => $report->user->email,          anonymous => 1,          flagged => 'on', +        non_public => 'on',      };      is_deeply( $mech->visible_form_values(), $fields, 'initial form values' ); diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t index d66590c57..cb787d959 100644 --- a/t/app/controller/alert_new.t +++ b/t/app/controller/alert_new.t @@ -464,4 +464,194 @@ subtest "Test normal alert signups and that alerts are sent" => sub {      $mech->delete_user($user2);  }; +for my $test ( +    { +        desc => 'check non public reports are not included in council problems alerts', +        alert_params => { +            alert_type => 'council_problems', +            parameter => '2651', +            parameter2 => '2651', +        } +    }, +    { +        desc => 'check non public reports are not included in ward problems alerts', +        alert_params => { +            alert_type => 'ward_problems', +            parameter => '2651', +            parameter2 => '20728', +        } +    }, +    { +        desc => 'check non public reports are not included in local problems alerts', +        alert_params => { +            alert_type => 'local_problems', +            parameter => '-3.189944', +            parameter2 => '55.951963', +        } +    }, +    { +        desc => 'check non public reports are not included in area problems alerts', +        alert_params => { +            alert_type => 'area_problems', +            parameter => '20728', +            parameter2 => '20728', +        } +    }, +) { +    subtest $test->{desc} => sub { +        my $user1 = FixMyStreet::App->model('DB::User') +          ->find_or_create( { email => 'reporter@example.com', name => 'Reporter User' } ); +        ok $user1, "created test user"; +        $user1->alerts->delete; + +        my $user2 = FixMyStreet::App->model('DB::User') +          ->find_or_create( { email => 'alerts@example.com', name => 'Alert User' } ); +        ok $user2, "created test user"; +        $user2->alerts->delete; + +        my $dt = DateTime->now->add( minutes => -30 ); +        my $r_dt = $dt->clone->add( minutes => 20 ); + +        my $alert_params = $test->{alert_params}; +        $alert_params->{user} = $user1; +        $alert_params->{whensubscribed} = $dt; +        $alert_params->{confirmed} = 1; + +        my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( $alert_params ); +        ok $alert_user1, "alert created"; + +        my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { +            postcode           => 'EH1 1BB', +            council            => '2651', +            areas              => ',11808,135007,14419,134935,2651,20728,', +            category           => 'Street lighting', +            title              => 'Alert test for non public reports', +            detail             => 'Testing Detail', +            used_map           => 1, +            name               => $user2->name, +            anonymous          => 0, +            state              => 'confirmed', +            confirmed          => $r_dt, +            lastupdate         => $r_dt, +            whensent           => $r_dt->clone->add( minutes => 5 ), +            lang               => 'en-gb', +            service            => '', +            cobrand            => 'default', +            cobrand_data       => '', +            send_questionnaire => 1, +            latitude           => '55.951963', +            longitude          => '-3.189944', +            user_id            => $user2->id, +            non_public         => 1, +        } ); + +        $mech->clear_emails_ok; +        FixMyStreet::App->model('DB::AlertType')->email_alerts(); +        $mech->email_count_is(0); + +        $report->update( { non_public => 0 } ); +        FixMyStreet::App->model('DB::AlertType')->email_alerts(); +        $mech->email_count_is(1); +        my $email = $mech->get_email; +        like $email->body, qr/Alert\s+test\s+for\s+non\s+public\s+reports/, 'alert contains public report'; + +        $mech->delete_user( $user1 ); +        $mech->delete_user( $user2 ); +    }; +} + +subtest 'check new updates alerts for non public reports only go to report owner' => sub { +    my $user1 = FixMyStreet::App->model('DB::User') +      ->find_or_create( { email => 'reporter@example.com', name => 'Reporter User' } ); +    ok $user1, "created test user"; +    $user1->alerts->delete; + +    my $user2 = FixMyStreet::App->model('DB::User') +      ->find_or_create( { email => 'alerts@example.com', name => 'Alert User' } ); +    ok $user2, "created test user"; +    $user2->alerts->delete; + +    my $user3 = FixMyStreet::App->model('DB::User') +      ->find_or_create( { email => 'updates@example.com', name => 'Update User' } ); +    ok $user3, "created test user"; + +    my $dt = DateTime->now->add( minutes => -30 ); +    my $r_dt = $dt->clone->add( minutes => 20 ); + +    my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { +        postcode           => 'EH1 1BB', +        council            => '2651', +        areas              => ',11808,135007,14419,134935,2651,20728,', +        category           => 'Street lighting', +        title              => 'Alert test for non public reports', +        detail             => 'Testing Detail', +        used_map           => 1, +        name               => $user2->name, +        anonymous          => 0, +        state              => 'confirmed', +        confirmed          => $r_dt, +        lastupdate         => $r_dt, +        whensent           => $r_dt->clone->add( minutes => 5 ), +        lang               => 'en-gb', +        service            => '', +        cobrand            => 'default', +        cobrand_data       => '', +        send_questionnaire => 1, +        latitude           => '55.951963', +        longitude          => '-3.189944', +        user_id            => $user2->id, +        non_public         => 1, +    } ); + +    my $update = FixMyStreet::App->model('DB::Comment')->create( { +        problem_id => $report->id, +        user_id    => $user3->id, +        name       => 'Anonymous User', +        mark_fixed => 'false', +        text       => 'This is some more update text', +        state      => 'confirmed', +        confirmed  => $r_dt->clone->add( minutes => 8 ), +        anonymous  => 't', +    } ); + +    my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( { +            user       => $user1, +            alert_type => 'new_updates', +            parameter  => $report->id, +            confirmed  => 1, +            whensubscribed => $dt, +    } ); +    ok $alert_user1, "alert created"; + + +    $mech->clear_emails_ok; +    FixMyStreet::App->model('DB::AlertType')->email_alerts(); +    $mech->email_count_is(0); + +    my $alert_user2 = FixMyStreet::App->model('DB::Alert')->create( { +            user       => $user2, +            alert_type => 'new_updates', +            parameter  => $report->id, +            confirmed  => 1, +            whensubscribed => $dt, +    } ); +    ok $alert_user2, "alert created"; + +    FixMyStreet::App->model('DB::AlertType')->email_alerts(); +    $mech->email_count_is(1); +    my $email = $mech->get_email; +    like $email->body, qr/This is some more update text/, 'alert contains update text'; + +    $mech->clear_emails_ok; +    $report->update( { non_public => 0 } ); +    FixMyStreet::App->model('DB::AlertType')->email_alerts(); +    $mech->email_count_is(1); +    $email = $mech->get_email; +    like $email->body, qr/This is some more update text/, 'alert contains update text'; + +    $mech->delete_user( $user1 ); +    $mech->delete_user( $user2 ); +    $mech->delete_user( $user3 ); +}; +  done_testing(); diff --git a/t/app/controller/around.t b/t/app/controller/around.t index db03e00f4..e1c76ff9f 100644 --- a/t/app/controller/around.t +++ b/t/app/controller/around.t @@ -78,4 +78,30 @@ foreach my $test (      };  } +subtest 'check non public reports are not displayed on around page' => sub { +    my $params = { +        postcode  => 'EH99 1SP', +        latitude  => 55.9519637512, +        longitude => -3.17492254484, +    }; +    my @edinburgh_problems = +      $mech->create_problems_for_council( 5, 2651, 'Around page', $params ); + +    $mech->get_ok('/'); +    $mech->submit_form_ok( { with_fields => { pc => 'EH99 1SP' } }, +        "good location" ); +    $mech->content_contains( 'Around page Test 3 for 2651', +        'problem to be marked non public visible' ); + +    my $private = $edinburgh_problems[2]; +    ok $private->update( { non_public => 1 } ), 'problem marked non public'; + +    $mech->get_ok('/'); +    $mech->submit_form_ok( { with_fields => { pc => 'EH99 1SP' } }, +        "good location" ); +    $mech->content_lacks( 'Around page Test 3 for 2651', +        'problem marked non public is not visible' ); +}; + +  done_testing(); diff --git a/t/app/controller/index.t b/t/app/controller/index.t index bf9124ee0..462b21064 100644 --- a/t/app/controller/index.t +++ b/t/app/controller/index.t @@ -55,4 +55,23 @@ subtest "does pc, (x,y), (e,n) or (lat,lon) go to /around" => sub {      }  }; +$mech->delete_problems_for_council( 2651 ); + +my $problem_rs = FixMyStreet::App->model('DB::Problem'); +my $num = $problem_rs->count; + +my @edinburgh_problems = $mech->create_problems_for_council(5, 2651, 'Front page'); +is scalar @edinburgh_problems, 5, 'correct number of edinburgh problems created'; + +$mech->get_ok('/report/' . $edinburgh_problems[2]->id); +$mech->content_contains('Front page Test 3 for 2651', 'problem to be marked non public visible'); +is $problem_rs->count, $num+5; + +my $private = $edinburgh_problems[2]; +ok $private->update( { non_public => 1 } ), 'problem marked non public'; + +ok $mech->get('/report/' . $edinburgh_problems[2]->id); +is $mech->res->code, 403, 'page forbidden'; +is $problem_rs->count, $num+5; +  done_testing(); diff --git a/t/app/controller/report_display.t b/t/app/controller/report_display.t index 6c2733e36..3bb0913f1 100644 --- a/t/app/controller/report_display.t +++ b/t/app/controller/report_display.t @@ -16,6 +16,11 @@ my $user =    ->find_or_create( { email => 'test@example.com', name => 'Test User' } );  ok $user, "created test user"; +my $user2 = +  FixMyStreet::App->model('DB::User') +  ->find_or_create( { email => 'test2@example.com', name => 'Other User' } ); +ok $user2, "created test user"; +  my $dt = DateTime->new(      year   => 2011,      month  => 04, @@ -98,6 +103,32 @@ subtest "change report to hidden and check for 410 status" => sub {      ok $report->update( { state => 'confirmed' } ), 'confirm report again';  }; +subtest "change report to non_public and check for 403 status" => sub { +    ok $report->update( { non_public => 1 } ), 'make report non public'; +    ok $mech->get("/report/$report_id"), "get '/report/$report_id'"; +    is $mech->res->code, 403, "access denied"; +    is $mech->uri->path, "/report/$report_id", "at /report/$report_id"; +    $mech->content_contains('That report cannot be viewed on FixMyStreet.'); +    ok $report->update( { non_public => 0 } ), 'make report public'; +}; + +subtest "check owner of report can view non public reports" => sub { +    ok $report->update( { non_public => 1 } ), 'make report non public'; +    $mech->log_in_ok( $report->user->email ); +    ok $mech->get("/report/$report_id"), "get '/report/$report_id'"; +    is $mech->res->code, 200, "report can be viewed"; +    is $mech->uri->path, "/report/$report_id", "at /report/$report_id"; +    $mech->log_out_ok; + +    $mech->log_in_ok( $user2->email ); +    ok $mech->get("/report/$report_id"), "get '/report/$report_id'"; +    is $mech->res->code, 403, "access denied to user who is not report creator"; +    is $mech->uri->path, "/report/$report_id", "at /report/$report_id"; +    $mech->content_contains('That report cannot be viewed on FixMyStreet.'); +    $mech->log_out_ok; +    ok $report->update( { non_public => 0 } ), 'make report public'; +}; +  subtest "test a good report" => sub {      $mech->get_ok("/report/$report_id");      is $mech->uri->path, "/report/$report_id", "at /report/$report_id"; diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t index 88236a1c3..2e7e60f75 100644 --- a/t/app/controller/report_new.t +++ b/t/app/controller/report_new.t @@ -788,6 +788,74 @@ foreach my $test (  } +subtest "test report creation for a category that is non public" => sub { +    $mech->log_out_ok; +    $mech->clear_emails_ok; + +    # check that the user does not exist +    my $test_email = 'test-2@example.com'; + +    my $user = FixMyStreet::App->model('DB::User')->find_or_create( { email => $test_email } ); +    ok $user, "test user does exist"; + +    $contact1->update( { non_public => 1 } ); + +    # submit initial pc form +    $mech->get_ok('/around'); +    $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB', } }, +        "submit location" ); + +    # click through to the report page +    $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, +        "follow 'skip this step' link" ); + +    $mech->submit_form_ok( +        { +            button      => 'submit_register', +            with_fields => { +                title         => 'Test Report', +                detail        => 'Test report details.', +                photo         => '', +                email         => 'test-2@example.com', +                name          => 'Joe Bloggs', +                category      => 'Street lighting', +            } +        }, +        "submit good details" +    ); + +    # find the report +    my $report = $user->problems->first; +    ok $report, "Found the report"; + +    # Check the report is not public +    ok $report->non_public, 'report is not public'; + +    my $email = $mech->get_email; +    ok $email, "got an email"; +    like $email->body, qr/confirm the problem/i, "confirm the problem"; + +    my ($url) = $email->body =~ m{(http://\S+)}; +    ok $url, "extracted confirm url '$url'"; + +    # confirm token +    $mech->get_ok($url); +    $report->discard_changes; + +    is $report->state, 'confirmed', "Report is now confirmed"; + +    $mech->logged_in_ok; +    $mech->get_ok( '/report/' . $report->id, 'user can see own report' ); + +    $mech->log_out_ok; +    ok $mech->get("/report/" . $report->id), "fetched report"; +    is $mech->res->code, 403, "access denied to report"; + +    # cleanup +    $mech->delete_user($user); +    $contact1->update( { non_public => 0 } ); +}; +  $contact2->category( "Pothol\xc3\xa9s" );  $contact2->update;  $mech->get_ok( '/report/new/ajax?latitude=' . $saved_lat . '&longitude=' . $saved_lon ); @@ -970,6 +1038,7 @@ SKIP: {      $mech->log_out_ok;      $mech->get_ok('/around'); +    $mech->content_contains( "Lichfield District Council FixMyStreet" );      $mech->submit_form_ok( { with_fields => { pc => 'WS13 7RD' } }, "submit location" );      $mech->follow_link_ok( { text_regex => qr/skip this step/i, }, "follow 'skip this step' link" );      $mech->submit_form_ok( diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t index cf6af16cb..82670d6cc 100644 --- a/t/app/controller/report_updates.t +++ b/t/app/controller/report_updates.t @@ -577,7 +577,12 @@ for my $test (          is $update->problem_state, $test->{state}, 'problem state set';          my $update_meta = $mech->extract_update_metas; -        like $update_meta->[0], qr/marked as $test->{fields}->{state}$/, 'update meta includes state change'; +        # setting it to confirmed shouldn't say anything +        if ( $test->{fields}->{state} ne 'confirmed' ) { +            like $update_meta->[0], qr/marked as $test->{fields}->{state}$/, 'update meta includes state change'; +        } else { +            like $update_meta->[0], qr/reopened$/, 'update meta includes state change'; +        }          like $update_meta->[0], qr{Test User \(Westminster City Council\)}, 'update meta includes council name';          $mech->content_contains( 'Test User (<strong>Westminster City Council</strong>)', 'council name in bold'); @@ -586,6 +591,44 @@ for my $test (      };  } +subtest 'check meta correct for comments marked confirmed but not marked open' => sub { +    $report->comments->delete; +    my $comment = FixMyStreet::App->model('DB::Comment')->create( +        { +            user          => $user, +            problem_id    => $report->id, +            text          => 'update text', +            confirmed     => DateTime->now, +            problem_state => 'confirmed', +            anonymous     => 0, +            mark_open     => 0, +            mark_fixed    => 0, +            state         => 'confirmed', +        } +    ); + +    $mech->get_ok( "/report/" . $report->id ); +    my $update_meta = $mech->extract_update_metas; +    like $update_meta->[0], qr/reopened$/, +      'update meta does not say reopened'; + +    $comment->update( { mark_open => 1, problem_state => undef } ); +    $mech->get_ok( "/report/" . $report->id ); +    $update_meta = $mech->extract_update_metas; + +    unlike $update_meta->[0], qr/marked as open$/, +      'update meta does not says marked as open'; +    like $update_meta->[0], qr/reopened$/, 'update meta does say reopened'; + +    $comment->update( { mark_open => 0, problem_state => undef } ); +    $mech->get_ok( "/report/" . $report->id ); +    $update_meta = $mech->extract_update_metas; + +    unlike $update_meta->[0], qr/marked as open$/, +      'update meta does not says marked as open'; +    unlike $update_meta->[0], qr/reopened$/, 'update meta does not say reopened'; +  }; +  $user->from_council(0);  $user->update; diff --git a/t/app/controller/reports.t b/t/app/controller/reports.t index 801dbeddb..a4dab6597 100644 --- a/t/app/controller/reports.t +++ b/t/app/controller/reports.t @@ -1,10 +1,21 @@  use strict;  use warnings;  use Test::More; -use Test::WWW::Mechanize::Catalyst 'FixMyStreet::App'; +use FixMyStreet::TestMech;  use mySociety::MaPit; +use FixMyStreet::App; +use DateTime; -ok( my $mech = Test::WWW::Mechanize::Catalyst->new, 'Created mech object' ); +ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' ); + +$mech->delete_problems_for_council( 2504 ); +$mech->delete_problems_for_council( 2651 ); + +my @edinburgh_problems = $mech->create_problems_for_council(3, 2651, 'All reports'); +my @westminster_problems = $mech->create_problems_for_council(5, 2504, 'All reports'); + +is scalar @westminster_problems, 5, 'correct number of westminster problems created'; +is scalar @edinburgh_problems, 3, 'correct number of edinburgh problems created';  # Run the cron script that makes the data for /reports so we don't get an error.  system( "bin/cron-wrapper update-all-reports" ); @@ -13,8 +24,35 @@ system( "bin/cron-wrapper update-all-reports" );  $mech->get_ok('/reports');  $mech->title_like(qr{Summary reports});  $mech->content_contains('Birmingham'); + +my $stats = $mech->extract_report_stats; + +is $stats->{'City of Edinburgh Council'}->[1], 3, 'correct number of reports for Edinburgh'; +is $stats->{'Westminster City Council'}->[1], 5, 'correct number of reports for Westminster'; +  $mech->follow_link_ok( { text_regex => qr/Birmingham/ } ); +$mech->get_ok('/reports/Westminster'); +$mech->title_like(qr/Westminster City Council/); +$mech->content_contains('Westminster City Council'); +$mech->content_contains('All reports Test 3 for 2504', 'problem to be marked non public visible'); + +my $problems = $mech->extract_problem_list; +is scalar @$problems, 5, 'correct number of problems displayed'; + +my $private = $westminster_problems[2]; +ok $private->update( { non_public => 1 } ), 'problem marked non public'; + +$mech->get_ok('/reports/Westminster'); +$problems = $mech->extract_problem_list; +is scalar @$problems, 4, 'only public problems are displayed'; + +$mech->content_lacks('All reports Test 3 for 2504', 'non public problem is not visible'); + +$mech->get_ok('/reports'); +$stats = $mech->extract_report_stats; +is $stats->{'Westminster City Council'}->[1], 5, 'non public reports included in stats'; +  SKIP: {      skip( "Need 'emptyhomes' in ALLOWED_COBRANDS config", 8 )          unless FixMyStreet::Cobrand->exists('emptyhomes'); diff --git a/t/cobrand/closest.t b/t/cobrand/closest.t index 02c979756..464c95e67 100644 --- a/t/cobrand/closest.t +++ b/t/cobrand/closest.t @@ -54,7 +54,7 @@ ok $report, "created test report - $report_id";  $report->geocode( undef ); -ok !$report->geocode, 'no gecode entry for report'; +ok !$report->geocode, 'no geocode entry for report';  my $near = $c->find_closest( $report->latitude, $report->longitude, $report ); diff --git a/t/open311.t b/t/open311.t index f082179ea..ce0a4ed90 100644 --- a/t/open311.t +++ b/t/open311.t @@ -37,9 +37,10 @@ my $p = FixMyStreet::App->model('DB::Problem')->new( {      title => 'title',      detail => 'detail',      user => $u, +    id => 1,  } ); -my $expected_error = qr{.*request failed: 500 Can.t connect to 192.168.50.1:80 \([^)]*\).*}; +my $expected_error = qr{Failed to submit problem 1 over Open311}ism;  warning_like {$o2->send_service_request( $p, { url => 'http://example.com/' }, 1 )} $expected_error, 'warning generated on failed call'; @@ -410,20 +411,48 @@ for my $test (      };  } +subtest 'No request id in reponse' => sub { +    my $results; +    warning_like { +        $results = make_service_req( +            $problem, +            { url => 'http://example.com/report/1' }, +            $problem->category, +            '<?xml version="1.0" encoding="utf-8"?><service_requests><request><service_request_id></service_request_id></request></service_requests>'  +        ); +    } qr/Failed to submit problem \d+ over Open311/, 'correct error message for missing request_id'; + +    is $results->{ res }, 0, 'No request_id is a failure'; +}; + +subtest 'Bad data in request_id element in reponse' => sub { +    my $results; +    warning_like { +        $results = make_service_req( +            $problem, +            { url => 'http://example.com/report/1' }, +            $problem->category, +            '<?xml version="1.0" encoding="utf-8"?><service_requests><request><service_request_id><bad_data>BAD</bad_data></service_request_id></request></service_requests>'  +        ); +    } qr/Failed to submit problem \d+ over Open311/, 'correct error message for bad data in request_id'; + +    is $results->{ res }, 0, 'No request_id is a failure'; +}; +  subtest 'No update id in reponse' => sub {      my $results;      warning_like {          $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id></update_id></request_update></service_request_updates>' ) -    } qr/Failed to submit comment \d+ over Open311/, 'correct error message'; +    } qr/Failed to submit comment \d+ over Open311/, 'correct error message for missing update_id';      is $results->{ res }, 0, 'No update_id is a failure';  }; -subtest 'error reponse' => sub { +subtest 'error response' => sub {      my $results;      warning_like {          $results = make_update_req( $comment, '<?xml version="1.0" encoding="utf-8"?><errors><error><code>400</code><description>There was an error</description</error></errors>' ) -    } qr/Failed to submit comment \d+ over Open311.*There was an error/, 'correct error messages'; +    } qr/Failed to submit comment \d+ over Open311.*There was an error/, 'correct error messages for general error';      is $results->{ res }, 0, 'error in response is a failure';  }; diff --git a/templates/web/default/admin/council_contacts.html b/templates/web/default/admin/council_contacts.html index 7f23a442d..eb9606a31 100644 --- a/templates/web/default/admin/council_contacts.html +++ b/templates/web/default/admin/council_contacts.html @@ -41,6 +41,7 @@              <th>[% loc('Devolved') %]</th>              <th>[% loc('Last editor') %]</th>              <th>[% loc('Note') %]</th> +            <th>[% loc('Public') %]</th>              <th>[% loc('When edited') %]</th>              <th>[% loc('Confirm') %]</th>          </tr> @@ -53,6 +54,7 @@                  <td>[% IF conf.can_be_devolved && contact.send_method %][% loc('Yes') %][% ELSE %][% loc('No') %][% END %]</td>                  <td>[% contact.editor %]</td>                  <td>[% contact.note | html %]</td> +                <td>[% contact.non_public ? loc('Non Public') : loc('Public') %]</td>                  <td>[% contact.whenedited.ymd _ ' ' _ contact.whenedited.hms %]</td>                  <td><input type="checkbox" name="confirmed" value="[% contact.category %]"></td>              </tr> @@ -85,7 +87,7 @@          <input type="checkbox" name="confirmed" value="1" id="confirmed">           <label for="confirmed">[% loc('Confirmed') %]</label> -        <input type="checkbox" name="deleted" value="1"id="deleted">  +        <input type="checkbox" name="deleted" value="1" id="deleted">           <label for="deleted">[% loc('Deleted') %]</label>          </p> @@ -94,6 +96,11 @@          </p>          <p> +        <input type="checkbox" name="non_public" value="1" id="non_public">  +        <label for="non_public">[% loc('Private') %]</label> +        </p> + +        <p>          <input type="hidden" name="area_id" value="[% area_id %]" >          <input type="hidden" name="posted" value="new" >          <input type="hidden" name="token" value="[% token %]" > diff --git a/templates/web/default/admin/council_edit.html b/templates/web/default/admin/council_edit.html index 716c2cb08..408466b51 100644 --- a/templates/web/default/admin/council_edit.html +++ b/templates/web/default/admin/council_edit.html @@ -26,7 +26,8 @@      <strong>[% loc('Email:') %] </strong>      <input type="text" name="email" value="[% contact.email | html %]" size="30">       <input type="checkbox" name="confirmed" value="1" id="confirmed"[% ' checked' IF contact.confirmed %]> <label for="confirmed">[% loc('Confirmed' ) %]</label>  -    <input type="checkbox" name="deleted" value="1" id="deleted"[% ' checked' IF contact.deleted %]> <label for="deleted">[% loc('Deleted') %]</label><br> +    <input type="checkbox" name="deleted" value="1" id="deleted"[% ' checked' IF contact.deleted %]> <label for="deleted">[% loc('Deleted') %]</label> +    <input type="checkbox" name="non_public" value="1" id="non_public"[% ' checked' IF contact.non_public %]> <label for="non_public">[% loc('Private') %]</label><br>      <strong>[% loc('Note:') %] </strong><textarea name="note" rows="3" cols="40">[% contact.note | html %]</textarea> <br> diff --git a/templates/web/default/admin/index.html b/templates/web/default/admin/index.html index b1eddaa3a..2c5ee55db 100644 --- a/templates/web/default/admin/index.html +++ b/templates/web/default/admin/index.html @@ -21,7 +21,7 @@  [% IF c.cobrand.admin_show_creation_graph -%]      <p> -        <a href="[% c.config.BASE_URL %]/bci-live-creation.png">[% loc('Graph of problem creation by status over time') %]</a> +        <a href="[% c.config.BASE_URL %]/fms-live-creation.png">[% loc('Graph of problem creation by status over time') %]</a>      </p>  [% END -%] diff --git a/templates/web/default/admin/report_edit.html b/templates/web/default/admin/report_edit.html index 9ef7e8248..d283037c2 100644 --- a/templates/web/default/admin/report_edit.html +++ b/templates/web/default/admin/report_edit.html @@ -40,6 +40,7 @@  <li>[% loc('Extra data:') %] [% problem.extra ? 'Yes' : 'No' %]</li>  <li>[% loc('Going to send questionnaire?') %] [% IF problem.send_questionnaire %][% loc('Yes') %][% ELSE %][% loc('No') %][% END %]</li>  <li><label for="flagged">[% loc('Flagged:') %]</label> <input type="checkbox" name="flagged"[% ' checked' IF problem.flagged %]></li> +<li><label for="non_public">[% loc('Private:') %]</label> <input type="checkbox" name="non_public"[% ' checked' IF problem.non_public %]></li>  [% IF problem.photo %]  [% photo = problem.get_photo_params %] diff --git a/templates/web/default/report/updates.html b/templates/web/default/report/updates.html index de873e2ed..eaf5209ff 100644 --- a/templates/web/default/report/updates.html +++ b/templates/web/default/report/updates.html @@ -23,7 +23,7 @@          [% tprintf( loc( 'Posted by %s at %s' ), update.name, prettify_epoch( update.confirmed_local.epoch ) ) | html -%]      [%- END -%]      [%- ", " _ loc( 'marked as fixed' ) IF update.mark_fixed %] -    [%- ", " _ loc( 'reopened' ) IF update.mark_open %] -    [%- ", " _ tprintf(loc( 'marked as %s' ), update.meta_problem_state) IF update.problem_state %] +    [%- ", " _ loc( 'reopened' ) IF update.mark_open OR update.problem_state == 'confirmed' %] +    [%- ", " _ tprintf(loc( 'marked as %s' ), update.meta_problem_state) IF update.problem_state AND update.problem_state != 'confirmed' %]  [% END %] diff --git a/templates/web/default/reports/index.html b/templates/web/default/reports/index.html index 283df5285..76c2afcd2 100755 --- a/templates/web/default/reports/index.html +++ b/templates/web/default/reports/index.html @@ -34,6 +34,7 @@  <td class="data">[% fixed.${area.id}.new or 0 %]</td>  <td class="data">[% fixed.${area.id}.old or 0 %]</td>  </tr> +[% TRY %][% PROCESS "reports/_extras.html" %][% CATCH file %][% END %]  [% END %]  </tbody>  </table> diff --git a/templates/web/fixmystreet/faq/faq-en-gb.html b/templates/web/fixmystreet/faq/faq-en-gb.html index bd94ecd38..9edb21426 100755 --- a/templates/web/fixmystreet/faq/faq-en-gb.html +++ b/templates/web/fixmystreet/faq/faq-en-gb.html @@ -18,6 +18,8 @@  or discuss local problems they’ve found to their local council by  simply locating them on a map. It launched in early February  2007.</dd> +        <dt>How do I get in touch with FixMyStreet?</dt> +        <dd>Here’s our <a href="/contact">contact page</a>.</dd>          <dt>What sort of problems should I report with FixMyStreet?</dt>          <dd>FixMyStreet is primarily for reporting things which are  <strong>broken or dirty or damaged or dumped, and need fixing, cleaning diff --git a/templates/web/fixmystreet/reports/_extras.html b/templates/web/fixmystreet/reports/_extras.html new file mode 100755 index 000000000..e210b9c07 --- /dev/null +++ b/templates/web/fixmystreet/reports/_extras.html @@ -0,0 +1,24 @@ +[% +    fms_councils = { +        'Bromley Council' = 'fix.bromley.gov.uk' +        'Barnet Borough Council' = 'barnet.fixmystreet.com' +        'Lichfield District Council' = 'lichfielddc.fixmystreet.com' +        'Reading Borough Council' = 'reading.fixmystreet.com' +        'Southampton City Council' = 'southampton.fixmystreet.com' +    } +    secure = { +        'fix.bromley.gov.uk' = 's' +    } +    site = fms_councils.${area.name} +%] +[% IF site %] +<tr align="center" +[%- IF ! (loop.count % 2) %] class="a" +[%- END %]> +<td class="title" colspan="6" style="padding-top:0"> +    <small title="This council's online reporting is powered by FixMyStreet">(includes reports from +    <a href="http[% secure.$site %]://[% site %]">[% site %]</a> using +    <a href="http://www.mysociety.org/for-councils/fixmystreet/">FixMyStreet for Councils</a>)</small> +</td> +</tr> +[% END %] diff --git a/templates/web/southampton/header.html b/templates/web/southampton/header.html index 43553468c..e02083a99 100644 --- a/templates/web/southampton/header.html +++ b/templates/web/southampton/header.html @@ -51,7 +51,6 @@  				</form>  			</div> -			<a class="mctv" href="http://www.southampton.mycounciltv.org"><img src="/cobrands/southampton/mctv.png" alt="Link to MyCouncilTV videos" /></a>  			<ul id="topNav">  				<li><a href="http://www.southampton.gov.uk/online/">Do it online</a></li>  				<li><a href="http://www.southampton.gov.uk/customer-service/">Customer Services</a></li> diff --git a/web/.gitignore b/web/.gitignore index 124be032a..d6e2f1a1a 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -1,4 +1,4 @@  /down.html  /_Inline -/bci-live-creation.png -/bci-live-line.png +/fms-live-creation.png +/fms-live-line.png diff --git a/web/cobrands/fixmystreet/_base.scss b/web/cobrands/fixmystreet/_base.scss index 5d71c33e6..72c039075 100644 --- a/web/cobrands/fixmystreet/_base.scss +++ b/web/cobrands/fixmystreet/_base.scss @@ -1306,9 +1306,6 @@ table.nicetable {      &.a {        background:#f6f6f6;      } -    &:nth-child(even) { -      background:#f6f6f6; -    }      &.gone {          color: #666666;          background-color: #cccccc; | 
