<commit_before># -*- mode: python; coding: utf-8 -*-
# Copyright 2016 the HERA Collaboration
# Licensed under the 2-clause BSD license.

"""Keeping track of geo-located stations.

"""

from __future__ import absolute_import, division, print_function

import os
import sys
import copy
from astropy.time import Time

import numpy as np
import matplotlib.pyplot as plt
from pyproj import Proj

from hera_mc import mc, part_connect, cm_utils, geo_location

current_cofa = 'COFA_HSA7458_V000'

def cofa(show_cofa=False):
    """
    Shortcut to just get the current cofa (current_cofa is hard-coded in geo_handling.py)

    Returns location class of current COFA

    Parameters:
    -------------
    show_cofa:  boolean to print out cofa info or just return class
    """

    located = get_location(current_cofa)
    if show_cofa:
        print('Center of array: %s' % (located.station_name))
        try:
            print('UTM:  {} {:.0f}E {:.0f}N at {:.1f}m   ({})'.format(located.tile, located.easting, located.northing, located.elevation, located.datum))
        except TypeError:
            print('UTM:  {} {:.0f}E {:.0f}N   ({})'.format(located.tile, located.easting, located.northing, located.datum))
        print('Lat/Lon:  {}  {}'.format(located.lat, located.lon))
    return located

def get_location(location_name):
    """This provides a function to query a location and get a geo_location class back, with lon/lat added to the class

    Returns location class of called name

    Parameters:
    -------------
    location_name:  location name, may be either a station or an antenna
    """

    local_argv = ['--locate', location_name]
    parser = mc.get_mc_argument_parser()
    parser.add_argument('-l', '--locate', default=None)
    parser.add_argument('-v', '--verbosity', default='l')
    parser.add_argument('--date', default='now')
    parser.add_argument('--time', default='now')
    args = parser.parse_args(local_argv)
    located = locate_station(args.locate, '>', show_location=False)
    return located

def find_station_of_antenna(args, antenna, query_date):
    """
    checks to see what station an antenna is at

    Returns False or the active station_name (must be an active station for the query_date)

    Parameters:
    ------------
    args:  needed arguments to open database
    antenna:  antenna number as float (why?), int, or string. If needed, it prepends the 'A'
    query_date:  is the astropy Time for contemporary antenna
    """

    if type(antenna) == float or type(antenna) == int or antenna[0] != 'A':
        antenna = 'A' + str(antenna).strip('0')
    db = mc.connect_to_mc_db(args)
    with db.sessionmaker() as session:
        connected_antenna = session.query(part_connect.Connections).filter( (part_connect.Connections.downstream_part == antenna) &
                                                                            (query_date.gps >= part_connect.Connections.start_gpstime) &
                                                                            (query_date.gps <= part_connect.Connections.stop_gpstime) )
        if connected_antenna.count() == 0:
            antenna_connected = False
        elif connected_antenna.count() == 1:
            antenna_connected = connected_antenna.first().upstream_part
        else:
            raise ValueError('More than one active connection')
    return antenna_connected

def locate_station(args, to_find, query_date, show_location=False):
    """
    Return the location of station_name or antenna_number as contained in args.locate.
    This accepts the fact that antennas are sort of stations, even though they are parts

    Parameters:
    ------------
    args:  needed arguments to open database
    station_to_fine:  station name to find
    query_date:  astropy Time for contemporary antenna
    show_location:   if True, it will print the information.
    """

    found_location = None
    station_name = False
    try:
        antenna_number = int(to_find)
        station_name = find_station_of_antenna(args, antenna_number, query_date)
    except ValueError:
        station_name = to_find.upper()
    found_it = False
    if station_name:
        db = mc.connect_to_mc_db(args)
        with db.sessionmaker() as session:
            station_type = session.get_station_type()
            for a in session.query(geo_location.GeoLocation).filter(geo_location.GeoLocation.station_name == station_name):
                for key in station_type.keys():
                    if a.station_name in station_type[key]['Stations']:
                        this_station = key
                        break
                    else:
                        this_station = 'No station type data.'
                a.gps2Time()
                ever_connected = geo_location.is_in_connections(args, a.station_name, '<')
                active = geo_location.is_in_connections(args, a.station_name, query_date)
                found_it = True
                hera_proj = Proj(proj='utm', zone=a.tile, ellps=a.datum, south=True)
                a.lon, a.lat = hera_proj(a.easting, a.northing, inverse=True)
                found_location = copy.copy(a)
                if show_location:
                    if args.verbosity == 'm' or args.verbosity == 'h':
                        print('station_name: ', a.station_name)
                        print('\teasting: ', a.easting)
                        print('\tnorthing: ', a.northing)
                        print('\tlon/lat:  ', a.lon, a.lat)
                        print('\televation: ', a.elevation)
                        print('\tstation description ({}):  {}'.format(this_station, station_type[this_station]['Description']))
                        print('\tever connected:  ', ever_connected)
                        print('\tactive:  ', active)
                        print('\tcreated:  ', cm_utils._get_displayTime(a.created_date))
                    elif args.verbosity == 'l':
                        print(a, this_station)
    if show_location:
        if not found_it and args.verbosity == 'm' or args.verbosity == 'h':
            print(args.locate, ' not found.')
    return found_location

def get_all_locations(args):
    db = mc.connect_to_mc_db(args)
    with db.sessionmaker() as session:
        stations = session.query(geo_location.GeoLocation).all()
        connections = session.query(part_connect.Connections).all()
        stations_new = []
        for stn in stations:
            hera_proj = Proj(proj='utm', zone=stn.tile, ellps=stn.datum, south=True)
            stn.lon, stn.lat = hera_proj(stn.easting, stn.northing, inverse=True)
            ever_connected = geo_location.is_in_connections(args, stn.station_name,'>')
            if ever_connected is True:
                connections = session.query(part_connect.Connections).filter(
                    part_connect.Connections.upstream_part == stn.station_name)
                for conn in connections:
                    ant_num = int(conn.downstream_part[1:])
                    conn.gps2Time()
                    stations_new.append({'station_name': stn.station_name,
                                         'station_type': stn.station_type_name,
                                         'longitude': stn.lon,
                                         'latitude': stn.lat,
                                         'elevation': stn.elevation,
                                         'antenna_number': ant_num,
                                         'start_date': start_date,
                                         'stop_date': stop_date})
    return stations_new

def get_since_date(args,query_date):
    dt = query_date.gps
    db = mc.connect_to_mc_db(args)
    found_stations = []
    with db.sessionmaker() as session:
        for a in session.query(geo_location.GeoLocation).filter(geo_location.GeoLocation.created_gpstime >= dt):
            found_stations.append(a.station_name)
    return found_stations

coord = {'E': 'easting', 'N': 'northing', 'Z': 'elevation'}

def plot_stations(args, stations_to_plot, fignm, query_date=False, marker_color='g', marker_shape='o', marker_size='8', label_station=False):
    """Plot a list of stations.

       Parameters:
       ------------
       args:  needed arguments to open database and set date/time
       stations_to_plot:  list containing station_names (note:  NOT antenna_numbers)
       fignm:  figure name/number to plot on
       marker_color, marker_shape:  color and shape of marker
       label_station:  flag to either label the station or not.  If not false, give label type.
    """

    plt.figure(fignm)
    db = mc.connect_to_mc_db(args)
    with db.sessionmaker() as session:
        for station in stations_to_plot:
            for a in session.query(geo_location.GeoLocation).filter(geo_location.GeoLocation.station_name == station):
                show_it = True
                if args.active:
                    show_it = geo_location.is_in_connections(args, station, query_date)
                if show_it is not False:  # Need this since 0 is a valid antenna
                    pt = {'easting': a.easting, 'northing': a.northing, 'elevation': a.elevation}
                    plt.plot(pt[coord[args.xgraph]], pt[coord[args.ygraph]],
                             color=marker_color, marker=marker_shape, markersize=marker_size, label=a.station_name)
                    if label_station:
                        if args.label_type == 'station_name':
                            labeling = a.station_name
                        else:
                            antrev = geo_location.is_in_connections(args, station, query_date)
                            if antrev is False:
                                labeling = 'NA'
                            else:
                                ant = antrev.split(':')[0]
                                rev = antrev.split(':')[1]
                                if args.label_type == 'antenna_number':
                                    labeling = ant.strip('A')
                                elif args.label_type == 'serial_number':
                                    p = session.query(part_connect.Parts).filter((part_connect.Parts.hpn == ant) &
                                                                                (part_connect.Parts.hpn_rev == rev))
                                    if p.count() == 1:
                                        labeling = p.first().manufacturer_number.replace('S/N', '')
                                    else:
                                        labeling = '-'
                                else:
                                    labeling = 'S'
                        plt.annotate(labeling, xy=(pt[coord[args.xgraph]], pt[coord[args.ygraph]]),
                                     xytext=(pt[coord[args.xgraph]] + 2, pt[coord[args.ygraph]]))

def plot_station_types(args, label_station=False, query_date=False):
    """Plot the various sub-array types

       Return fignm of plot

       Parameters:
       ------------
       args:  needed arguments to open database and set date/time
       label_station:  flag to either label the station or not.  If not false, give label type.
    """

    if ',' in args.graph:
        prefixes_to_plot = args.graph.split(',')
        prefixes_to_plot = [x.upper() for x in prefixes_to_plot]
    elif args.graph == 'all':
        prefixes_to_plot = 'all'
    else:
        prefixes_to_plot = [args.graph.upper()]
    fignm = args.xgraph + args.ygraph
    db = mc.connect_to_mc_db(args)
    with db.sessionmaker() as session:
        station_type = session.get_station_type()
        for key in station_type.keys():
            if prefixes_to_plot == 'all' or key.upper() in prefixes_to_plot:
                stations_to_plot = []
                for loc in station_type[key]['Stations']:
                    for a in session.query(geo_location.GeoLocation).filter(geo_location.GeoLocation.station_name == loc):
                        show_it = True
                        if args.active:
                            show_it = geo_location.is_in_connections(args, loc, query_date)
                        if show_it is not False:  # Need this since 0 is a valid antenna
                            stations_to_plot.append(loc)
                plot_stations(args, stations_to_plot, fignm, query_date, marker_color=station_type[key]['Marker'][0],
                              marker_shape=station_type[key]['Marker'][1], marker_size='6',
                              label_station=label_station)
    if args.xgraph != 'Z' and args.ygraph != 'Z':
        plt.axis('equal')
    plt.plot(xaxis=args.xgraph, yaxis=args.ygraph)
    return fignm

def overplot(args, located, fignm):
    """Overplot a station on an existing plot.  It sets specific symbols/colors for active, connected, etc

       Parameters:
       ------------
       args:  needed arguments to open database and set date/time
       located:  geo class of station to plot
       fignm:  figure name/number to plot on
    """
    if located:
        ever_connected = geo_location.is_in_connections(args, located.station_name)
        active = geo_location.is_in_connections(args, located.station_name, True)
        if ever_connected and active:
            over_marker = 'g*'
            mkr_lbl = 'ca'
        elif ever_connected and not active:
            over_marker = 'gx'
            mkr_lbl = 'cx'
        elif active and not ever_connected:
            over_marker = 'yx'
            mkr_lbl = 'xa'
        else:
            over_marker = 'rx'
            mkr_lbl = 'xx'
        opt = {'easting': located.easting, 'northing': located.northing, 'elevation': located.elevation}
        plt.figure(fignm)
        overplot_station = plt.plot(opt[coord[args.xgraph]], opt[coord[args.ygraph]], over_marker, markersize=14)
        legendEntries = [overplot_station]
        legendText = [located.station_name + ':' + str(active)]
        plt.legend((overplot_station), (legendText), numpoints=1, loc='upper right')

def show_it_now(fignm):
    plt.figure(fignm)
    plt.show()
<commit_msg>now passes nosetests locally again...<commit_after># -*- mode: python; coding: utf-8 -*-
# Copyright 2016 the HERA Collaboration
# Licensed under the 2-clause BSD license.

"""Keeping track of geo-located stations.

"""

from __future__ import absolute_import, division, print_function

import os
import sys
import copy
from astropy.time import Time

import numpy as np
import matplotlib.pyplot as plt
from pyproj import Proj

from hera_mc import mc, part_connect, cm_utils, geo_location

current_cofa = 'COFA_HSA7458_V000'

def cofa(show_cofa=False):
    """
    Shortcut to just get the current cofa (current_cofa is hard-coded in geo_handling.py)

    Returns location class of current COFA

    Parameters:
    -------------
    show_cofa:  boolean to print out cofa info or just return class
    """

    located = get_location(current_cofa)
    if show_cofa:
        print('Center of array: %s' % (located.station_name))
        try:
            print('UTM:  {} {:.0f}E {:.0f}N at {:.1f}m   ({})'.format(located.tile, located.easting, located.northing, located.elevation, located.datum))
        except TypeError:
            print('UTM:  {} {:.0f}E {:.0f}N   ({})'.format(located.tile, located.easting, located.northing, located.datum))
        print('Lat/Lon:  {}  {}'.format(located.lat, located.lon))
    return located

def get_location(location_name):
    """This provides a function to query a location and get a geo_location class back, with lon/lat added to the class

    Returns location class of called name

    Parameters:
    -------------
    location_name:  location name, may be either a station or an antenna
    """

    local_argv = ['--locate', location_name]
    parser = mc.get_mc_argument_parser()
    parser.add_argument('-l', '--locate', default=None)
    parser.add_argument('-v', '--verbosity', default='l')
    parser.add_argument('--date', default='now')
    parser.add_argument('--time', default='now')
    args = parser.parse_args(local_argv)
    located = locate_station(args, args.locate, '>', show_location=False)
    return located

def find_station_of_antenna(args, antenna, query_date):
    """
    checks to see what station an antenna is at

    Returns False or the active station_name (must be an active station for the query_date)

    Parameters:
    ------------
    args:  needed arguments to open database
    antenna:  antenna number as float (why?), int, or string. If needed, it prepends the 'A'
    query_date:  is the astropy Time for contemporary antenna
    """

    if type(antenna) == float or type(antenna) == int or antenna[0] != 'A':
        antenna = 'A' + str(antenna).strip('0')
    db = mc.connect_to_mc_db(args)
    with db.sessionmaker() as session:
        connected_antenna = session.query(part_connect.Connections).filter( (part_connect.Connections.downstream_part == antenna) &
                                                                            (query_date.gps >= part_connect.Connections.start_gpstime) &
                                                                            (query_date.gps <= part_connect.Connections.stop_gpstime) )
        if connected_antenna.count() == 0:
            antenna_connected = False
        elif connected_antenna.count() == 1:
            antenna_connected = connected_antenna.first().upstream_part
        else:
            raise ValueError('More than one active connection')
    return antenna_connected

def locate_station(args, to_find, query_date, show_location=False):
    """
    Return the location of station_name or antenna_number as contained in args.locate.
    This accepts the fact that antennas are sort of stations, even though they are parts

    Parameters:
    ------------
    args:  needed arguments to open database
    station_to_fine:  station name to find
    query_date:  astropy Time for contemporary antenna
    show_location:   if True, it will print the information.
    """

    found_location = None
    station_name = False
    try:
        antenna_number = int(to_find)
        station_name = find_station_of_antenna(args, antenna_number, query_date)
    except ValueError:
        station_name = to_find.upper()
    found_it = False
    if station_name:
        db = mc.connect_to_mc_db(args)
        with db.sessionmaker() as session:
            station_type = session.get_station_type()
            for a in session.query(geo_location.GeoLocation).filter(geo_location.GeoLocation.station_name == station_name):
                for key in station_type.keys():
                    if a.station_name in station_type[key]['Stations']:
                        this_station = key
                        break
                    else:
                        this_station = 'No station type data.'
                a.gps2Time()
                ever_connected = geo_location.is_in_connections(args, a.station_name, '<')
                active = geo_location.is_in_connections(args, a.station_name, query_date)
                found_it = True
                hera_proj = Proj(proj='utm', zone=a.tile, ellps=a.datum, south=True)
                a.lon, a.lat = hera_proj(a.easting, a.northing, inverse=True)
                found_location = copy.copy(a)
                if show_location:
                    if args.verbosity == 'm' or args.verbosity == 'h':
                        print('station_name: ', a.station_name)
                        print('\teasting: ', a.easting)
                        print('\tnorthing: ', a.northing)
                        print('\tlon/lat:  ', a.lon, a.lat)
                        print('\televation: ', a.elevation)
                        print('\tstation description ({}):  {}'.format(this_station, station_type[this_station]['Description']))
                        print('\tever connected:  ', ever_connected)
                        print('\tactive:  ', active)
                        print('\tcreated:  ', cm_utils._get_displayTime(a.created_date))
                    elif args.verbosity == 'l':
                        print(a, this_station)
    if show_location:
        if not found_it and args.verbosity == 'm' or args.verbosity == 'h':
            print(args.locate, ' not found.')
    return found_location

def get_all_locations(args):
    db = mc.connect_to_mc_db(args)
    with db.sessionmaker() as session:
        stations = session.query(geo_location.GeoLocation).all()
        connections = session.query(part_connect.Connections).all()
        stations_new = []
        for stn in stations:
            hera_proj = Proj(proj='utm', zone=stn.tile, ellps=stn.datum, south=True)
            stn.lon, stn.lat = hera_proj(stn.easting, stn.northing, inverse=True)
            ever_connected = geo_location.is_in_connections(args, stn.station_name,'>')
            if ever_connected is True:
                connections = session.query(part_connect.Connections).filter(
                    part_connect.Connections.upstream_part == stn.station_name)
                for conn in connections:
                    ant_num = int(conn.downstream_part[1:])
                    conn.gps2Time()
                    stations_new.append({'station_name': stn.station_name,
                                         'station_type': stn.station_type_name,
                                         'longitude': stn.lon,
                                         'latitude': stn.lat,
                                         'elevation': stn.elevation,
                                         'antenna_number': ant_num,
                                         'start_date': start_date,
                                         'stop_date': stop_date})
    return stations_new

def get_since_date(args,query_date):
    dt = query_date.gps
    db = mc.connect_to_mc_db(args)
    found_stations = []
    with db.sessionmaker() as session:
        for a in session.query(geo_location.GeoLocation).filter(geo_location.GeoLocation.created_gpstime >= dt):
            found_stations.append(a.station_name)
    return found_stations

coord = {'E': 'easting', 'N': 'northing', 'Z': 'elevation'}

def plot_stations(args, stations_to_plot, fignm, query_date=False, marker_color='g', marker_shape='o', marker_size='8', label_station=False):
    """Plot a list of stations.

       Parameters:
       ------------
       args:  needed arguments to open database and set date/time
       stations_to_plot:  list containing station_names (note:  NOT antenna_numbers)
       fignm:  figure name/number to plot on
       marker_color, marker_shape:  color and shape of marker
       label_station:  flag to either label the station or not.  If not false, give label type.
    """

    plt.figure(fignm)
    db = mc.connect_to_mc_db(args)
    with db.sessionmaker() as session:
        for station in stations_to_plot:
            for a in session.query(geo_location.GeoLocation).filter(geo_location.GeoLocation.station_name == station):
                show_it = True
                if args.active:
                    show_it = geo_location.is_in_connections(args, station, query_date)
                if show_it is not False:  # Need this since 0 is a valid antenna
                    pt = {'easting': a.easting, 'northing': a.northing, 'elevation': a.elevation}
                    plt.plot(pt[coord[args.xgraph]], pt[coord[args.ygraph]],
                             color=marker_color, marker=marker_shape, markersize=marker_size, label=a.station_name)
                    if label_station:
                        if args.label_type == 'station_name':
                            labeling = a.station_name
                        else:
                            antrev = geo_location.is_in_connections(args, station, query_date)
                            if antrev is False:
                                labeling = 'NA'
                            else:
                                ant = antrev.split(':')[0]
                                rev = antrev.split(':')[1]
                                if args.label_type == 'antenna_number':
                                    labeling = ant.strip('A')
                                elif args.label_type == 'serial_number':
                                    p = session.query(part_connect.Parts).filter((part_connect.Parts.hpn == ant) &
                                                                                (part_connect.Parts.hpn_rev == rev))
                                    if p.count() == 1:
                                        labeling = p.first().manufacturer_number.replace('S/N', '')
                                    else:
                                        labeling = '-'
                                else:
                                    labeling = 'S'
                        plt.annotate(labeling, xy=(pt[coord[args.xgraph]], pt[coord[args.ygraph]]),
                                     xytext=(pt[coord[args.xgraph]] + 2, pt[coord[args.ygraph]]))

def plot_station_types(args, label_station=False, query_date=False):
    """Plot the various sub-array types

       Return fignm of plot

       Parameters:
       ------------
       args:  needed arguments to open database and set date/time
       label_station:  flag to either label the station or not.  If not false, give label type.
    """

    if ',' in args.graph:
        prefixes_to_plot = args.graph.split(',')
        prefixes_to_plot = [x.upper() for x in prefixes_to_plot]
    elif args.graph == 'all':
        prefixes_to_plot = 'all'
    else:
        prefixes_to_plot = [args.graph.upper()]
    fignm = args.xgraph + args.ygraph
    db = mc.connect_to_mc_db(args)
    with db.sessionmaker() as session:
        station_type = session.get_station_type()
        for key in station_type.keys():
            if prefixes_to_plot == 'all' or key.upper() in prefixes_to_plot:
                stations_to_plot = []
                for loc in station_type[key]['Stations']:
                    for a in session.query(geo_location.GeoLocation).filter(geo_location.GeoLocation.station_name == loc):
                        show_it = True
                        if args.active:
                            show_it = geo_location.is_in_connections(args, loc, query_date)
                        if show_it is not False:  # Need this since 0 is a valid antenna
                            stations_to_plot.append(loc)
                plot_stations(args, stations_to_plot, fignm, query_date, marker_color=station_type[key]['Marker'][0],
                              marker_shape=station_type[key]['Marker'][1], marker_size='6',
                              label_station=label_station)
    if args.xgraph != 'Z' and args.ygraph != 'Z':
        plt.axis('equal')
    plt.plot(xaxis=args.xgraph, yaxis=args.ygraph)
    return fignm

def overplot(args, located, fignm):
    """Overplot a station on an existing plot.  It sets specific symbols/colors for active, connected, etc

       Parameters:
       ------------
       args:  needed arguments to open database and set date/time
       located:  geo class of station to plot
       fignm:  figure name/number to plot on
    """
    if located:
        ever_connected = geo_location.is_in_connections(args, located.station_name)
        active = geo_location.is_in_connections(args, located.station_name, True)
        if ever_connected and active:
            over_marker = 'g*'
            mkr_lbl = 'ca'
        elif ever_connected and not active:
            over_marker = 'gx'
            mkr_lbl = 'cx'
        elif active and not ever_connected:
            over_marker = 'yx'
            mkr_lbl = 'xa'
        else:
            over_marker = 'rx'
            mkr_lbl = 'xx'
        opt = {'easting': located.easting, 'northing': located.northing, 'elevation': located.elevation}
        plt.figure(fignm)
        overplot_station = plt.plot(opt[coord[args.xgraph]], opt[coord[args.ygraph]], over_marker, markersize=14)
        legendEntries = [overplot_station]
        legendText = [located.station_name + ':' + str(active)]
        plt.legend((overplot_station), (legendText), numpoints=1, loc='upper right')

def show_it_now(fignm):
    plt.figure(fignm)
    plt.show()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##
##
## This file is part of Indico.
## Copyright (C) 2002 - 2014 European Organization for Nuclear Research (CERN).
##
## Indico is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 3 of the
## License, or (at your option) any later version.
##
## Indico is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Indico;if not, see <http://www.gnu.org/licenses/>.
from flask import session, request, flash
from cStringIO import StringIO

from MaKaC.webinterface.rh.conferenceDisplay import RHConferenceBaseDisplay, RHConfSignIn
import MaKaC.webinterface.urlHandlers as urlHandlers
import MaKaC.webinterface.pages.registrationForm as registrationForm
from MaKaC import registration
from MaKaC.errors import FormValuesError, MaKaCError, AccessError, NotFoundError, NoReportError
from indico.core.config import Config
from MaKaC.user import AvatarHolder
from MaKaC.webinterface.rh.registrantsModif import RHRegistrantListModif

from MaKaC.common.mail import GenericMailer
from MaKaC.common.utils import validMail
from MaKaC.PDFinterface.conference import TicketToPDF
from indico.modules.payment import event_settings as payment_event_settings
from indico.web.flask.util import send_file

from indico.util import json

class RHBaseRegistrationForm(RHConferenceBaseDisplay):

    def _checkParams(self, params):
        RHConferenceBaseDisplay._checkParams(self, params)
        self._regForm = self._conf.getRegistrationForm()

    def _processIfActive(self):
        """only override this method if the RegForm must be activated for
            carrying on the handler execution"""
        return "regForm"

    def _process(self):
        #if the RegForm is not activated we show up a form informing about that.
        #   This must be done at RH level because there can be some RH not
        #   displaying pages.
        if not self._regForm.isActivated() or not self._conf.hasEnabledSection("regForm"):
            p = registrationForm.WPRegFormInactive(self, self._conf)
            return p.display()
        else:
            return self._processIfActive()

class RHRegistrationForm(RHBaseRegistrationForm):
    _uh = urlHandlers.UHConfRegistrationForm

    def _processIfActive(self):
        p = registrationForm.WPRegistrationForm(self, self._conf)
        return p.display()

class RHRegistrationFormSignIn(RHBaseRegistrationForm, RHConfSignIn):
    _uh = urlHandlers.UHConfRegistrationFormSignIn

    def _checkParams(self, params):
        RHBaseRegistrationForm._checkParams(self, params)
        RHConfSignIn._checkParams(self, params)
        self._signInPage = registrationForm.WPRegistrationFormSignIn(self, self._conf)

    def _processIfActive(self):
        return self._makeLoginProcess()

class RHRegistrationFormDisplayBase(RHBaseRegistrationForm):
    _uh = urlHandlers.UHConfRegistrationFormDisplay

    def _getLoginURL(self):
        urlLogin = str(urlHandlers.UHConfRegistrationFormSignIn.getURL(self._conf, request.url))
        if Config.getInstance().getLoginURL().startswith("https"):
            urlLogin = urlLogin.replace("http://", "https://")
        return urlLogin

    def _checkProtection(self):
        RHBaseRegistrationForm._checkProtection(self)
        if self._regForm.inRegistrationPeriod() and self._regForm.isMandatoryAccount() and self._getUser() is None:
            self._redirect(self._getLoginURL())
            self._doProcess = False

class RHRegistrationFormDisplay(RHRegistrationFormDisplayBase):
    _uh = urlHandlers.UHConfRegistrationFormDisplay

    def _processIfActive(self):
        if self._getUser() is not None and self._getUser().isRegisteredInConf(self._conf):
            p = registrationForm.WPRegistrationFormAlreadyRegistered(self, self._conf)
        else:
            if self._conf.getRegistrationForm().isFull():
                p = registrationForm.WPRegistrationFormFull(self, self._conf)
            elif not self._conf.getRegistrationForm().inRegistrationPeriod() or \
                    (payment_event_settings.get(self._conf, 'active') and
                     self._conf.getRegistrationForm().getCurrency() == "not selected"):
                p = registrationForm.WPRegistrationFormClosed(self, self._conf)
            else:
                p = registrationForm.WPRegistrationFormDisplay(self, self._conf)
        return p.display()

class RHRegistrationFormCreation(RHRegistrationFormDisplayBase):
    _uh = urlHandlers.UHConfRegistrationFormDisplay

    def _checkParams(self, params):
        RHBaseRegistrationForm._checkParams(self, params)
        self._regForm = self._conf.getRegistrationForm()
        # SESSIONS
        sessionForm = self._regForm.getSessionsForm()
        sessions = sessionForm.getSessionsFromParams(params)
        params["sessions"] = sessions
        # ACCMMODATION
        params["accommodationType"] = self._regForm.getAccommodationForm().getAccommodationTypeById(params.get("accommodation_type", ""))
        # SOCIAL EVENTS
        socialEventIds = self._normaliseListParam(params.get("socialEvents", []))
        se = []
        for id in socialEventIds:
            se.append(self._regForm.getSocialEventForm().getSocialEventById(id))
        params["socialEvents"] = se

    def _process(self):
        canManageRegistration = self._conf.canManageRegistration(self._getUser())
        if not canManageRegistration and not self._regForm.isActivated():
            p = registrationForm.WPRegFormInactive(self, self._conf)
            return p.display()
        params = self._getRequestParams()
        email = self._regForm.getPersonalData().getValueFromParams(params, 'email')
        if email is None:
            raise FormValuesError(_("An email address has to be set in order to make the registration in the event."))
        elif not validMail(email, False):
            raise FormValuesError(_("The given email address is not valid."))
        matchedUsers = AvatarHolder().match({"email": email}, exact=1)
        if matchedUsers:
            user = matchedUsers[0]
        else:
            user = None
        # Check if the user can register
        if not canManageRegistration:  # normal user registering. Managers can.
            if self._conf.getRegistrationForm().isFull():
                self._redirect(urlHandlers.UHConfRegistrationFormDisplay.getURL(self._conf))
                return
            elif not self._conf.getRegistrationForm().inRegistrationPeriod():
                p = registrationForm.WPRegistrationFormClosed(self, self._conf)
                return p.display()
        if user is None:
            if self._conf.hasRegistrantByEmail(email):
                raise FormValuesError("There is already a user with the email \"%s\". Please choose another one" % email)
        else:
            if user.isRegisteredInConf(self._conf) or self._conf.hasRegistrantByEmail(email):
                if canManageRegistration:
                    raise FormValuesError("There is already a user with the email \"%s\". Please choose another one" % email)
                else:
                    raise FormValuesError("You have already registered with the email address \"%s\". If you need to modify your registration, please contact the managers of the conference." % email)

        rp = registration.Registrant()
        self._conf.addRegistrant(rp, user)
        rp.setValues(self._getRequestParams(), user)

        if user is not None:
            user.addRegistrant(rp)
            rp.setAvatar(user)

        # This creates the email to the new registrant and SENDS the email to the organizers if necessary... WTF.
        email = self._regForm.getNotification().createEmailNewRegistrant(self._regForm, rp)
        if self._regForm.isSendRegEmail() and rp.getEmail().strip():
            modEticket = self._conf.getRegistrationForm().getETicket()

            if modEticket.isEnabled() and modEticket.isAttachedToEmail():
                attachment = {
                    'name': "{0}-Ticket.pdf".format(self._target.getTitle()),
                    'binary': TicketToPDF(self._target, rp).getPDFBin(),
                }
                email["attachments"] = [attachment]
            GenericMailer.send(email)

        if canManageRegistration and user != self._getUser():
            self._redirect(RHRegistrantListModif._uh.getURL(self._conf))
        else:
            self._redirect(urlHandlers.UHConfRegistrationFormCreationDone.getURL(rp))

class RHRegistrationFormRegistrantBase(RHRegistrationFormDisplayBase):
    def _checkParams(self, params):
        RHRegistrationFormDisplayBase._checkParams(self, params)
        self._registrant = None
        regId = params.get("registrantId", None)
        if regId is None:
            raise MaKaCError(_("registrant id not set"))
        self._registrant = self._conf.getRegistrantById(regId)
        if self._registrant is None:
            raise NotFoundError(_("The registrant with id %s does not exist or has been deleted") % regId)

class RHRegistrationFormCreationDone(RHRegistrationFormRegistrantBase):

    def _checkParams(self, params):
        RHRegistrationFormRegistrantBase._checkParams(self, params)
        self._authkey = params.get("authkey", "")
        if self._registrant.getRandomId() != self._authkey or self._authkey == "":
            raise AccessError("You are not authorized to access this web page")

    def _processIfActive(self):
        if self._registrant is not None:
            flash(_(u"Your registration has been recorded successfully."), 'success')
            p = registrationForm.WPRegistrationForm(self, self._conf)
            return p.display(registrant=self._registrant)

class RHConferenceTicketPDF(RHRegistrationFormCreationDone):

    def _process(self):
        filename = "{0}-Ticket.pdf".format(self._target.getTitle())
        pdf = TicketToPDF(self._target, self._registrant)
        return send_file(filename, StringIO(pdf.getPDFBin()), 'PDF')

class RHRegistrationFormconfirmBooking(RHRegistrationFormRegistrantBase):
    _uh = urlHandlers.UHConfRegistrationFormDisplay

    def _checkParams(self, params):
        RHRegistrationFormRegistrantBase._checkParams(self, params)
        self._regForm = self._conf.getRegistrationForm()
        if self._conf.getModPay().hasPaymentConditions() and params.get("conditions", "false") != "on":
            raise NoReportError("You cannot pay without accepting the conditions")
        else:
            session['conditionsAccepted'] = True

    def _processIfActive(self):
        if self._registrant is not None:
            if self._regForm.isSendReceiptEmail():
                self._regForm.getNotification().sendEmailNewRegistrantDetailsPay(self._regForm, self._registrant)
            url = urlHandlers.UHConfRegistrationFormconfirmBookingDone.getURL(self._conf)
            url.addParam("registrantId", self._registrant.getId())
            self._redirect(url)

class RHRegistrationFormconfirmBookingDone(RHRegistrationFormRegistrantBase):

    def _checkParams(self, params):
        RHRegistrationFormRegistrantBase._checkParams(self, params)
        if not session.get('conditionsAccepted'):
            self._redirect(urlHandlers.UHConfRegistrationFormCreationDone.getURL(self._registrant))
            self._doProcess = False

    def _processIfActive(self):
        if self._registrant is not None:
            p = registrationForm.WPRegistrationFormconfirmBooking(self, self._conf, self._registrant)
            return p.display()

class RHRegistrationFormModify(RHRegistrationFormDisplayBase):
    _uh = urlHandlers.UHConfRegistrationFormDisplay

    def _process(self):
        user = self._getUser()
        canManageRegistration = self._conf.canManageRegistration(user)
        if not canManageRegistration and (not self._regForm.isActivated() or not self._conf.hasEnabledSection("regForm")):
            p = registrationForm.WPRegFormInactive(self, self._conf)
            return p.display()
        if user is not None and user.isRegisteredInConf(self._conf):
            if not self._conf.getRegistrationForm().inRegistrationPeriod() and not self._conf.getRegistrationForm().inModificationPeriod():
                p = registrationForm.WPRegistrationFormClosed(self, self._conf)
                return p.display()
            else:
                p = registrationForm.WPRegistrationFormModify(self, self._conf)
                return p.display()
        self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf))

class RHRegistrationFormPerformModify(RHRegistrationFormCreation):
    _uh = urlHandlers.UHConfRegistrationFormModify

    def _process(self):
        flash(_(u"Your registration has been modified successfully."), 'success')
        if self._getUser() is not None and self._getUser().isRegisteredInConf(self._conf):
            if not self._conf.getRegistrationForm().inRegistrationPeriod() and not self._conf.getRegistrationForm().inModificationPeriod():
                p = registrationForm.WPRegistrationFormClosed(self, self._conf)
                return p.display()
            else:
                rp = self._getUser().getRegistrantById(self._conf.getId())
                # check if the email is being changed by another one that already exists
                if self._getRequestParams().get("email", "") != rp.getEmail() and self._conf.hasRegistrantByEmail(self._getRequestParams().get("email", "")):
                    raise FormValuesError(_("There is already a user with the email \"%s\". Please choose another one") % self._getRequestParams().get("email", "--no email--"))
                rp.setValues(self._getRequestParams(), self._getUser())
                self._regForm.getNotification().sendEmailModificationRegistrant(self._regForm, rp)
                if rp.doPay():
                    self._redirect(urlHandlers.UHConfRegistrationFormCreationDone.getURL(rp))
                else:
                    self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf))
        else:
            self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf))

class RHRegistrationFormConditions(RHRegistrationFormDisplayBase):

    def _process(self):
        p = registrationForm.WPRegistrationFormConditions(self, self._conf)
        return p.display()

class RHRegistrationFormUserData(RHRegistrationFormDisplayBase):

    def _checkProtection(self):
        RHBaseRegistrationForm._checkProtection(self)

    def _process(self):
        user = self._aw.getUser()
        reg_data = {}
        if user is not None:
            if user.isRegisteredInConf(self._conf):
                registrant = user.getRegistrantById(self._conf.getId())
                reg_data = registrant.fossilize()
            else:
                personalData = self._regForm.getPersonalData()
                reg_data['avatar'] = personalData.getFormValuesFromAvatar(user)
        return json.dumps(reg_data)
<commit_msg>Flash success message only on creation and no pay<commit_after># -*- coding: utf-8 -*-
##
##
## This file is part of Indico.
## Copyright (C) 2002 - 2014 European Organization for Nuclear Research (CERN).
##
## Indico is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 3 of the
## License, or (at your option) any later version.
##
## Indico is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Indico;if not, see <http://www.gnu.org/licenses/>.
from flask import session, request, flash
from cStringIO import StringIO

from MaKaC.webinterface.rh.conferenceDisplay import RHConferenceBaseDisplay, RHConfSignIn
import MaKaC.webinterface.urlHandlers as urlHandlers
import MaKaC.webinterface.pages.registrationForm as registrationForm
from MaKaC import registration
from MaKaC.errors import FormValuesError, MaKaCError, AccessError, NotFoundError, NoReportError
from indico.core.config import Config
from MaKaC.user import AvatarHolder
from MaKaC.webinterface.rh.registrantsModif import RHRegistrantListModif

from MaKaC.common.mail import GenericMailer
from MaKaC.common.utils import validMail
from MaKaC.PDFinterface.conference import TicketToPDF
from indico.modules.payment import event_settings as payment_event_settings
from indico.web.flask.util import send_file

from indico.util import json

class RHBaseRegistrationForm(RHConferenceBaseDisplay):

    def _checkParams(self, params):
        RHConferenceBaseDisplay._checkParams(self, params)
        self._regForm = self._conf.getRegistrationForm()

    def _processIfActive(self):
        """only override this method if the RegForm must be activated for
            carrying on the handler execution"""
        return "regForm"

    def _process(self):
        #if the RegForm is not activated we show up a form informing about that.
        #   This must be done at RH level because there can be some RH not
        #   displaying pages.
        if not self._regForm.isActivated() or not self._conf.hasEnabledSection("regForm"):
            p = registrationForm.WPRegFormInactive(self, self._conf)
            return p.display()
        else:
            return self._processIfActive()

class RHRegistrationForm(RHBaseRegistrationForm):
    _uh = urlHandlers.UHConfRegistrationForm

    def _processIfActive(self):
        p = registrationForm.WPRegistrationForm(self, self._conf)
        return p.display()

class RHRegistrationFormSignIn(RHBaseRegistrationForm, RHConfSignIn):
    _uh = urlHandlers.UHConfRegistrationFormSignIn

    def _checkParams(self, params):
        RHBaseRegistrationForm._checkParams(self, params)
        RHConfSignIn._checkParams(self, params)
        self._signInPage = registrationForm.WPRegistrationFormSignIn(self, self._conf)

    def _processIfActive(self):
        return self._makeLoginProcess()

class RHRegistrationFormDisplayBase(RHBaseRegistrationForm):
    _uh = urlHandlers.UHConfRegistrationFormDisplay

    def _getLoginURL(self):
        urlLogin = str(urlHandlers.UHConfRegistrationFormSignIn.getURL(self._conf, request.url))
        if Config.getInstance().getLoginURL().startswith("https"):
            urlLogin = urlLogin.replace("http://", "https://")
        return urlLogin

    def _checkProtection(self):
        RHBaseRegistrationForm._checkProtection(self)
        if self._regForm.inRegistrationPeriod() and self._regForm.isMandatoryAccount() and self._getUser() is None:
            self._redirect(self._getLoginURL())
            self._doProcess = False

class RHRegistrationFormDisplay(RHRegistrationFormDisplayBase):
    _uh = urlHandlers.UHConfRegistrationFormDisplay

    def _processIfActive(self):
        if self._getUser() is not None and self._getUser().isRegisteredInConf(self._conf):
            p = registrationForm.WPRegistrationFormAlreadyRegistered(self, self._conf)
        else:
            if self._conf.getRegistrationForm().isFull():
                p = registrationForm.WPRegistrationFormFull(self, self._conf)
            elif not self._conf.getRegistrationForm().inRegistrationPeriod() or \
                    (payment_event_settings.get(self._conf, 'active') and
                     self._conf.getRegistrationForm().getCurrency() == "not selected"):
                p = registrationForm.WPRegistrationFormClosed(self, self._conf)
            else:
                p = registrationForm.WPRegistrationFormDisplay(self, self._conf)
        return p.display()

class RHRegistrationFormCreation(RHRegistrationFormDisplayBase):
    _uh = urlHandlers.UHConfRegistrationFormDisplay

    def _checkParams(self, params):
        RHBaseRegistrationForm._checkParams(self, params)
        self._regForm = self._conf.getRegistrationForm()
        # SESSIONS
        sessionForm = self._regForm.getSessionsForm()
        sessions = sessionForm.getSessionsFromParams(params)
        params["sessions"] = sessions
        # ACCMMODATION
        params["accommodationType"] = self._regForm.getAccommodationForm().getAccommodationTypeById(params.get("accommodation_type", ""))
        # SOCIAL EVENTS
        socialEventIds = self._normaliseListParam(params.get("socialEvents", []))
        se = []
        for id in socialEventIds:
            se.append(self._regForm.getSocialEventForm().getSocialEventById(id))
        params["socialEvents"] = se

    def _process(self):
        canManageRegistration = self._conf.canManageRegistration(self._getUser())
        if not canManageRegistration and not self._regForm.isActivated():
            p = registrationForm.WPRegFormInactive(self, self._conf)
            return p.display()
        params = self._getRequestParams()
        email = self._regForm.getPersonalData().getValueFromParams(params, 'email')
        if email is None:
            raise FormValuesError(_("An email address has to be set in order to make the registration in the event."))
        elif not validMail(email, False):
            raise FormValuesError(_("The given email address is not valid."))
        matchedUsers = AvatarHolder().match({"email": email}, exact=1)
        if matchedUsers:
            user = matchedUsers[0]
        else:
            user = None
        # Check if the user can register
        if not canManageRegistration:  # normal user registering. Managers can.
            if self._conf.getRegistrationForm().isFull():
                self._redirect(urlHandlers.UHConfRegistrationFormDisplay.getURL(self._conf))
                return
            elif not self._conf.getRegistrationForm().inRegistrationPeriod():
                p = registrationForm.WPRegistrationFormClosed(self, self._conf)
                return p.display()
        if user is None:
            if self._conf.hasRegistrantByEmail(email):
                raise FormValuesError("There is already a user with the email \"%s\". Please choose another one" % email)
        else:
            if user.isRegisteredInConf(self._conf) or self._conf.hasRegistrantByEmail(email):
                if canManageRegistration:
                    raise FormValuesError("There is already a user with the email \"%s\". Please choose another one" % email)
                else:
                    raise FormValuesError("You have already registered with the email address \"%s\". If you need to modify your registration, please contact the managers of the conference." % email)

        rp = registration.Registrant()
        self._conf.addRegistrant(rp, user)
        rp.setValues(self._getRequestParams(), user)

        if user is not None:
            user.addRegistrant(rp)
            rp.setAvatar(user)

        # This creates the email to the new registrant and SENDS the email to the organizers if necessary... WTF.
        email = self._regForm.getNotification().createEmailNewRegistrant(self._regForm, rp)
        if self._regForm.isSendRegEmail() and rp.getEmail().strip():
            modEticket = self._conf.getRegistrationForm().getETicket()

            if modEticket.isEnabled() and modEticket.isAttachedToEmail():
                attachment = {
                    'name': "{0}-Ticket.pdf".format(self._target.getTitle()),
                    'binary': TicketToPDF(self._target, rp).getPDFBin(),
                }
                email["attachments"] = [attachment]
            GenericMailer.send(email)

        if canManageRegistration and user != self._getUser():
            self._redirect(RHRegistrantListModif._uh.getURL(self._conf))
        else:
            if not rp.doPay():
                flash(_(u"Your registration has been recorded successfully."), 'success')
            self._redirect(urlHandlers.UHConfRegistrationFormCreationDone.getURL(rp))

class RHRegistrationFormRegistrantBase(RHRegistrationFormDisplayBase):
    def _checkParams(self, params):
        RHRegistrationFormDisplayBase._checkParams(self, params)
        self._registrant = None
        regId = params.get("registrantId", None)
        if regId is None:
            raise MaKaCError(_("registrant id not set"))
        self._registrant = self._conf.getRegistrantById(regId)
        if self._registrant is None:
            raise NotFoundError(_("The registrant with id %s does not exist or has been deleted") % regId)

class RHRegistrationFormCreationDone(RHRegistrationFormRegistrantBase):

    def _checkParams(self, params):
        RHRegistrationFormRegistrantBase._checkParams(self, params)
        self._authkey = params.get("authkey", "")
        if self._registrant.getRandomId() != self._authkey or self._authkey == "":
            raise AccessError("You are not authorized to access this web page")

    def _processIfActive(self):
        if self._registrant is not None:
            p = registrationForm.WPRegistrationForm(self, self._conf)
            return p.display(registrant=self._registrant)

class RHConferenceTicketPDF(RHRegistrationFormCreationDone):

    def _process(self):
        filename = "{0}-Ticket.pdf".format(self._target.getTitle())
        pdf = TicketToPDF(self._target, self._registrant)
        return send_file(filename, StringIO(pdf.getPDFBin()), 'PDF')

class RHRegistrationFormconfirmBooking(RHRegistrationFormRegistrantBase):
    _uh = urlHandlers.UHConfRegistrationFormDisplay

    def _checkParams(self, params):
        RHRegistrationFormRegistrantBase._checkParams(self, params)
        self._regForm = self._conf.getRegistrationForm()
        if self._conf.getModPay().hasPaymentConditions() and params.get("conditions", "false") != "on":
            raise NoReportError("You cannot pay without accepting the conditions")
        else:
            session['conditionsAccepted'] = True

    def _processIfActive(self):
        if self._registrant is not None:
            if self._regForm.isSendReceiptEmail():
                self._regForm.getNotification().sendEmailNewRegistrantDetailsPay(self._regForm, self._registrant)
            url = urlHandlers.UHConfRegistrationFormconfirmBookingDone.getURL(self._conf)
            url.addParam("registrantId", self._registrant.getId())
            self._redirect(url)

class RHRegistrationFormconfirmBookingDone(RHRegistrationFormRegistrantBase):

    def _checkParams(self, params):
        RHRegistrationFormRegistrantBase._checkParams(self, params)
        if not session.get('conditionsAccepted'):
            self._redirect(urlHandlers.UHConfRegistrationFormCreationDone.getURL(self._registrant))
            self._doProcess = False

    def _processIfActive(self):
        if self._registrant is not None:
            p = registrationForm.WPRegistrationFormconfirmBooking(self, self._conf, self._registrant)
            return p.display()

class RHRegistrationFormModify(RHRegistrationFormDisplayBase):
    _uh = urlHandlers.UHConfRegistrationFormDisplay

    def _process(self):
        user = self._getUser()
        canManageRegistration = self._conf.canManageRegistration(user)
        if not canManageRegistration and (not self._regForm.isActivated() or not self._conf.hasEnabledSection("regForm")):
            p = registrationForm.WPRegFormInactive(self, self._conf)
            return p.display()
        if user is not None and user.isRegisteredInConf(self._conf):
            if not self._conf.getRegistrationForm().inRegistrationPeriod() and not self._conf.getRegistrationForm().inModificationPeriod():
                p = registrationForm.WPRegistrationFormClosed(self, self._conf)
                return p.display()
            else:
                p = registrationForm.WPRegistrationFormModify(self, self._conf)
                return p.display()
        self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf))

class RHRegistrationFormPerformModify(RHRegistrationFormCreation):
    _uh = urlHandlers.UHConfRegistrationFormModify

    def _process(self):
        flash(_(u"Your registration has been modified successfully."), 'success')
        if self._getUser() is not None and self._getUser().isRegisteredInConf(self._conf):
            if not self._conf.getRegistrationForm().inRegistrationPeriod() and not self._conf.getRegistrationForm().inModificationPeriod():
                p = registrationForm.WPRegistrationFormClosed(self, self._conf)
                return p.display()
            else:
                rp = self._getUser().getRegistrantById(self._conf.getId())
                # check if the email is being changed by another one that already exists
                if self._getRequestParams().get("email", "") != rp.getEmail() and self._conf.hasRegistrantByEmail(self._getRequestParams().get("email", "")):
                    raise FormValuesError(_("There is already a user with the email \"%s\". Please choose another one") % self._getRequestParams().get("email", "--no email--"))
                rp.setValues(self._getRequestParams(), self._getUser())
                self._regForm.getNotification().sendEmailModificationRegistrant(self._regForm, rp)
                if rp.doPay():
                    self._redirect(urlHandlers.UHConfRegistrationFormCreationDone.getURL(rp))
                else:
                    self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf))
        else:
            self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf))

class RHRegistrationFormConditions(RHRegistrationFormDisplayBase):

    def _process(self):
        p = registrationForm.WPRegistrationFormConditions(self, self._conf)
        return p.display()

class RHRegistrationFormUserData(RHRegistrationFormDisplayBase):

    def _checkProtection(self):
        RHBaseRegistrationForm._checkProtection(self)

    def _process(self):
        user = self._aw.getUser()
        reg_data = {}
        if user is not None:
            if user.isRegisteredInConf(self._conf):
                registrant = user.getRegistrantById(self._conf.getId())
                reg_data = registrant.fossilize()
            else:
                personalData = self._regForm.getPersonalData()
                reg_data['avatar'] = personalData.getFormValuesFromAvatar(user)
        return json.dumps(reg_data)
<|endoftext|>


<commit_before>from django.core.management.base import BaseCommand, CommandError
from django.core.mail import send_mail
from django.contrib.auth.models import User
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from sesame import utils
from sources.models import Person
from sources.forms import SubmitForm
from sources.tokens import account_confirmation_token
from sourcelist.settings import PROJECT_NAME, EMAIL_SENDER, SITE_URL

def email_user(email_address, status):
    person = Person.objects.get(email_address=email_address)
    person_id = person.id

    fields = SubmitForm.Meta.fields ## abstracted to use same fields as the submission form
    fields.append('status') ## add status field bc it's not included in the SubmitForm and it's necessary for sending email
    person = Person.objects.filter(email_address=email_address).values(*fields).exclude()[0]
    person_info = '
'
    spaces = ' ' * 5
    ## loop thru and unpack values
    for key, value in person.items():
        if value:
            new_key = key.title().replace('_', ' ')
            person_info += '\

 \
                    {}:	 \
                    {}	 \
                    {}	\

'.format(
                    new_key,
                    spaces,
                    value
                )
    person_info += '
'

    admin_url = '{}/admin/sources/person/{}/change/'.format(SITE_URL, person_id)

    ## django-sesame bits for magic link
    user = User.objects.get(email=email_address)
    # login_token = utils.get_query_string(user) ## using their URL
    login_token = utils.get_parameters(user) ## making your own URL
    login_link = '{}?method=magic&url_auth_token={}'.format(admin_url, login_token['url_auth_token']) ## change from admin url to live url?

    ## confirmation url (for both user and admin?)
    confirm_token = account_confirmation_token.make_token(user)
    uid = urlsafe_base64_encode(force_bytes(user.pk))
    confirm_url = '{}/confirmation/{}/{}'.format(
        SITE_URL,
        uid,
        confirm_token
    )

    status = person['status']
    status_type = status.split('_')[0]

    message = ''

    if status_type == 'added':
        subject_title = 'You have been added as a source by '
        if status == 'added_by_self':
            subject_title += 'yourself'
        elif status == 'added_by_other':
            subject_title += 'someone else'
        elif status == 'added_by_admin':
            subject_title += 'an admin'

        html_message = 'To confirm you would like be included in the {project_name} database and to confirm the following information is correct, please click here:

 {confirm_url}

 \
            {person_info}

 \
            If the information if incorrect, please edit your entry:

 {login_link}

View the database:

 {site_url}\
            '.format(
                project_name=PROJECT_NAME,
                confirm_url=confirm_url,
                person_info=person_info,
                login_link=login_link,
                site_url=SITE_URL
            )
    # elif status_type == 'approved':
    #     subject_title = 'You have been approved as a source!'
    #     html_message = 'Congratulations! Your entry has been approved and now be viewed or updated by you here: {}'.format(person_url)

    subject = '[{}] {}'.format(PROJECT_NAME, subject_title)
    sender = EMAIL_SENDER
    recipients = [email_address]
    # reply_email = sender

    send_mail(
        subject,
        message,
        sender,
        recipients,
        # reply_to=[reply_email],
        html_message=html_message,
        fail_silently=False,
    )

class Command(BaseCommand):
    help = 'Email new user when added.'

    def add_arguments(self, parser):
        ## required
        parser.add_argument('email',
            help='Specify the user email.'
        )

        parser.add_argument('status',
            help='Specify the status.'
        )

        ## optional
        # parser.add_argument('-t' '--test',
        #     action='store_true',
        #     # type=str,
        #     dest='test',
        #     default=False,
        #     help="Specific whether it's a test or not"
        # )

    def handle(self, *args, **options):
        ## unpack args
        email_address = options['email']
        status = options['status']

        ## call the function
        email_user(email_address, status)

<commit_msg>updated subject line to remove 'by ' bc we don't include that<commit_after>from django.core.management.base import BaseCommand, CommandError
from django.core.mail import send_mail
from django.contrib.auth.models import User
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from sesame import utils
from sources.models import Person
from sources.forms import SubmitForm
from sources.tokens import account_confirmation_token
from sourcelist.settings import PROJECT_NAME, EMAIL_SENDER, SITE_URL

def email_user(email_address, status):
    person = Person.objects.get(email_address=email_address)
    person_id = person.id

    fields = SubmitForm.Meta.fields ## abstracted to use same fields as the submission form
    fields.append('status') ## add status field bc it's not included in the SubmitForm and it's necessary for sending email
    person = Person.objects.filter(email_address=email_address).values(*fields).exclude()[0]
    person_info = '
'
    spaces = ' ' * 5
    ## loop thru and unpack values
    for key, value in person.items():
        if value:
            new_key = key.title().replace('_', ' ')
            person_info += '\

 \
                    {}:	 \
                    {}	 \
                    {}	\

'.format(
                    new_key,
                    spaces,
                    value
                )
    person_info += '
'

    admin_url = '{}/admin/sources/person/{}/change/'.format(SITE_URL, person_id)

    ## django-sesame bits for magic link
    user = User.objects.get(email=email_address)
    # login_token = utils.get_query_string(user) ## using their URL
    login_token = utils.get_parameters(user) ## making your own URL
    login_link = '{}?method=magic&url_auth_token={}'.format(admin_url, login_token['url_auth_token']) ## change from admin url to live url?

    ## confirmation url (for both user and admin?)
    confirm_token = account_confirmation_token.make_token(user)
    uid = urlsafe_base64_encode(force_bytes(user.pk))
    confirm_url = '{}/confirmation/{}/{}'.format(
        SITE_URL,
        uid,
        confirm_token
    )

    status = person['status']
    status_type = status.split('_')[0]

    message = ''

    if status_type == 'added':
        subject_title = 'You have been added as a source'
        if status == 'added_by_self':
            subject_title += 'yourself'
        elif status == 'added_by_other':
            subject_title += 'someone else'
        elif status == 'added_by_admin':
            subject_title += 'an admin'

        html_message = 'To confirm you would like be included in the {project_name} database and to confirm the following information is correct, please click here:

 {confirm_url}

 \
            {person_info}

 \
            If the information if incorrect, please edit your entry:

 {login_link}

View the database:

 {site_url}\
            '.format(
                project_name=PROJECT_NAME,
                confirm_url=confirm_url,
                person_info=person_info,
                login_link=login_link,
                site_url=SITE_URL
            )
    # elif status_type == 'approved':
    #     subject_title = 'You have been approved as a source!'
    #     html_message = 'Congratulations! Your entry has been approved and now be viewed or updated by you here: {}'.format(person_url)

    subject = '[{}] {}'.format(PROJECT_NAME, subject_title)
    sender = EMAIL_SENDER
    recipients = [email_address]
    # reply_email = sender

    send_mail(
        subject,
        message,
        sender,
        recipients,
        # reply_to=[reply_email],
        html_message=html_message,
        fail_silently=False,
    )

class Command(BaseCommand):
    help = 'Email new user when added.'

    def add_arguments(self, parser):
        ## required
        parser.add_argument('email',
            help='Specify the user email.'
        )

        parser.add_argument('status',
            help='Specify the status.'
        )

        ## optional
        # parser.add_argument('-t' '--test',
        #     action='store_true',
        #     # type=str,
        #     dest='test',
        #     default=False,
        #     help="Specific whether it's a test or not"
        # )

    def handle(self, *args, **options):
        ## unpack args
        email_address = options['email']
        status = options['status']

        ## call the function
        email_user(email_address, status)

<|endoftext|>


<commit_before><commit_msg>Changed parameter order of _perform_step.<commit_after><|endoftext|>


<commit_before>import logging
import re

from base import Plugin

LOG = logging.getLogger("crawler")

class URLConf(Plugin):
    """
    Plugin to check validity of URLConf.
    Run after the spider is done to show what URLConf entries got hit.
    """

    def finish_run(self, sender, **kwargs):
        for pattern in sender.conf_urls.keys():
            pattern = pattern.replace('^', '').replace('$', '').replace('//', '/')
            curr = re.compile(pattern)
            matched = False

            for url in sender.crawled:
                if curr.search(url):
                    matched = True

            if not matched:
                LOG.warning("This pattern was not matched by any crawled page: %s", pattern)
<commit_msg>crawler: better reporting of unmatched URL patterns<commit_after>import logging
import re

from base import Plugin

LOG = logging.getLogger("crawler")

class URLConf(Plugin):
    """
    Plugin to check validity of URLConf.
    Run after the spider is done to show what URLConf entries got hit.
    """

    def finish_run(self, sender, **kwargs):
        normal_patterns = list()
        admin_patterns = list()

        for pattern in sender.conf_urls.keys():
            pattern = pattern.replace('^', '').replace('$', '').replace('//', '/')
            curr = re.compile(pattern)

            if any(curr.search(url) for url in sender.crawled):
                continue

            if pattern.startswith("admin"):
                admin_patterns.append(pattern)
            else:
                normal_patterns.append(pattern)

        if admin_patterns:
            logging.debug("These admin pages were not crawled: %s", "\n\t".join(sorted(admin_patterns)))

        if normal_patterns:
            logging.debug("These patterns were not matched during the crawl: %s", "\n\t".join(sorted(normal_patterns)))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.utils import timezone
from django.views.decorators.cache import never_cache
from django.utils.translation import ugettext_lazy as _
from rest_framework import generics, mixins
from rest_framework.exceptions import NotFound, MethodNotAllowed
from rest_framework.pagination import LimitOffsetPagination
from rest_framework.renderers import BrowsableAPIRenderer
from rest_framework.exceptions import PermissionDenied
from rest_framework.permissions import BasePermission
from shop.rest.money import JSONRenderer
from shop.rest.renderers import CMSPageRenderer
from shop.serializers.order import OrderListSerializer, OrderDetailSerializer
from shop.models.order import OrderModel

class OrderPagination(LimitOffsetPagination):
    default_limit = 25
    template = 'shop/templatetags/paginator.html'

class OrderPermission(BasePermission):
    """
    Allow access to a given Order if the user is entitled to.
    """
    def has_permission(self, request, view):
        if view.many and request.customer.is_visitor:
            detail = _("Only signed in customers can view their orders.")
            raise PermissionDenied(detail=detail)
        return True

    def has_object_permission(self, request, view, order):
        if request.user.is_authenticated:
            return order.customer.pk == request.user.pk
        if order.secret and order.secret == view.kwargs.get('secret'):
            return True
        detail = _("This order does not belong to you.")
        raise PermissionDenied(detail=detail)

class OrderView(mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin,
                generics.GenericAPIView):
    """
    Base View class to render the fulfilled orders for the current user.
    """
    renderer_classes = [CMSPageRenderer, JSONRenderer, BrowsableAPIRenderer]
    list_serializer_class = OrderListSerializer
    detail_serializer_class = OrderDetailSerializer
    pagination_class = OrderPagination
    permission_classes = [OrderPermission]
    lookup_field = lookup_url_kwarg = 'slug'
    many = True
    last_order_lapse = timezone.timedelta(minutes=15)

    def get_queryset(self):
        queryset = OrderModel.objects.all()
        if not self.request.customer.is_visitor:
            queryset = queryset.filter(customer=self.request.customer).order_by('-updated_at')
        return queryset

    def get_serializer_class(self):
        if self.many:
            return self.list_serializer_class
        return self.detail_serializer_class

    def get_renderer_context(self):
        renderer_context = super(OrderView, self).get_renderer_context()
        if self.request.accepted_renderer.format == 'html':
            renderer_context.update(many=self.many)
            if not self.many:
                # add an extra ance to the breadcrumb to show the order number
                renderer_context.update(
                    is_last_order = self.is_last(),
                    extra_ance=self.get_object().get_number(),
                )
        return renderer_context

    def is_last(self):
        """
        Returns ``True`` if the given order is considered as the last order for its customer.
        This information may be used to distinguish between a "thank you" and a normal detail view.
        """
        assert self.many is False, "This method can be called for detail views only"
        lapse = timezone.now() - self.last_order_lapse
        current_order = self.get_object()
        last_order = self.get_queryset().first()
        return current_order.id == last_order.id and current_order.created_at > lapse

    @property
    def allowed_methods(self):
        """Restrict method "POST" only on the detail view"""
        allowed_methods = self._allowed_methods()
        if self.many:
            allowed_methods.remove('POST')
        return allowed_methods

    @never_cache
    def get(self, request, *args, **kwargs):
        if self.many:
            return self.list(request, *args, **kwargs)
        return self.retrieve(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        if self.many:
            raise MethodNotAllowed("Method POST is not allowed on Order List View")
        self.update(request, *args, **kwargs)
        return self.retrieve(request, *args, **kwargs)

    def list(self, request, *args, **kwargs):
        try:
            return super(OrderView, self).list(request, *args, **kwargs)
        except OrderModel.DoesNotExist:
            raise NotFound("No orders have been found for the current user.")

    def retrieve(self, request, *args, **kwargs):
        try:
            return super(OrderView, self).retrieve(request, *args, **kwargs)
        except OrderModel.DoesNotExist:
            raise NotFound("No order has been found for the current user.")
<commit_msg>reduce to 15 order per page<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.utils import timezone
from django.views.decorators.cache import never_cache
from django.utils.translation import ugettext_lazy as _
from rest_framework import generics, mixins
from rest_framework.exceptions import NotFound, MethodNotAllowed
from rest_framework.pagination import LimitOffsetPagination
from rest_framework.renderers import BrowsableAPIRenderer
from rest_framework.exceptions import PermissionDenied
from rest_framework.permissions import BasePermission
from shop.rest.money import JSONRenderer
from shop.rest.renderers import CMSPageRenderer
from shop.serializers.order import OrderListSerializer, OrderDetailSerializer
from shop.models.order import OrderModel

class OrderPagination(LimitOffsetPagination):
    default_limit = 15
    template = 'shop/templatetags/paginator.html'

class OrderPermission(BasePermission):
    """
    Allow access to a given Order if the user is entitled to.
    """
    def has_permission(self, request, view):
        if view.many and request.customer.is_visitor:
            detail = _("Only signed in customers can view their orders.")
            raise PermissionDenied(detail=detail)
        return True

    def has_object_permission(self, request, view, order):
        if request.user.is_authenticated:
            return order.customer.pk == request.user.pk
        if order.secret and order.secret == view.kwargs.get('secret'):
            return True
        detail = _("This order does not belong to you.")
        raise PermissionDenied(detail=detail)

class OrderView(mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin,
                generics.GenericAPIView):
    """
    Base View class to render the fulfilled orders for the current user.
    """
    renderer_classes = [CMSPageRenderer, JSONRenderer, BrowsableAPIRenderer]
    list_serializer_class = OrderListSerializer
    detail_serializer_class = OrderDetailSerializer
    pagination_class = OrderPagination
    permission_classes = [OrderPermission]
    lookup_field = lookup_url_kwarg = 'slug'
    many = True
    last_order_lapse = timezone.timedelta(minutes=15)

    def get_queryset(self):
        queryset = OrderModel.objects.all()
        if not self.request.customer.is_visitor:
            queryset = queryset.filter(customer=self.request.customer).order_by('-updated_at')
        return queryset

    def get_serializer_class(self):
        if self.many:
            return self.list_serializer_class
        return self.detail_serializer_class

    def get_renderer_context(self):
        renderer_context = super(OrderView, self).get_renderer_context()
        if self.request.accepted_renderer.format == 'html':
            renderer_context.update(many=self.many)
            if not self.many:
                # add an extra ance to the breadcrumb to show the order number
                renderer_context.update(
                    is_last_order = self.is_last(),
                    extra_ance=self.get_object().get_number(),
                )
        return renderer_context

    def is_last(self):
        """
        Returns ``True`` if the given order is considered as the last order for its customer.
        This information may be used to distinguish between a "thank you" and a normal detail view.
        """
        assert self.many is False, "This method can be called for detail views only"
        lapse = timezone.now() - self.last_order_lapse
        current_order = self.get_object()
        last_order = self.get_queryset().first()
        return current_order.id == last_order.id and current_order.created_at > lapse

    @property
    def allowed_methods(self):
        """Restrict method "POST" only on the detail view"""
        allowed_methods = self._allowed_methods()
        if self.many:
            allowed_methods.remove('POST')
        return allowed_methods

    @never_cache
    def get(self, request, *args, **kwargs):
        if self.many:
            return self.list(request, *args, **kwargs)
        return self.retrieve(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        if self.many:
            raise MethodNotAllowed("Method POST is not allowed on Order List View")
        self.update(request, *args, **kwargs)
        return self.retrieve(request, *args, **kwargs)

    def list(self, request, *args, **kwargs):
        try:
            return super(OrderView, self).list(request, *args, **kwargs)
        except OrderModel.DoesNotExist:
            raise NotFound("No orders have been found for the current user.")

    def retrieve(self, request, *args, **kwargs):
        try:
            return super(OrderView, self).retrieve(request, *args, **kwargs)
        except OrderModel.DoesNotExist:
            raise NotFound("No order has been found for the current user.")
<|endoftext|>