示例#1
0
 def errors(self):
     errors = ApiErrors()
     data = self.__class__.__table__.columns._data
     for key in data.keys():
         col = data[key]
         val = getattr(self, key)
         if not isinstance(col, Column):
             continue
         if not col.nullable\
            and not col.foreign_keys\
            and not col.primary_key\
            and col.default is None\
            and val is None:
             errors.addError(key, 'Cette information est obligatoire')
         if val is None:
             continue
         if (isinstance(col.type, String) or isinstance(col.type, CHAR))\
            and not isinstance(col.type, Enum)\
            and not isinstance(val, str):
             errors.addError(key, 'doit etre une chaine de caracteres')
         if (isinstance(col.type, String) or isinstance(col.type, CHAR))\
            and isinstance(val, str)\
            and col.type.length\
            and len(val)>col.type.length:
             errors.addError(
                 key, 'Vous devez saisir moins de ' + str(col.type.length) +
                 ' caracteres')
         if isinstance(col.type, Integer)\
            and not isinstance(val, int):
             errors.addError(key, 'doit etre un entier')
         if isinstance(col.type, Float)\
            and not isinstance(val, float):
             errors.addError(key, 'doit etre un nombre')
     return errors
示例#2
0
def export_table(model_name):
    check_token()
    ae = ApiErrors()
    try:
        model = app.model[model_name]
    except KeyError:
        ae.addError('global', 'Nom de classe incorrect : '+model_name)
        return jsonify(ae.errors), 400

    if not is_exportable(model_name):
        ae.addError('global', 'Classe non exportable : '+model_name)
        return jsonify(ae.errors), 400

    objects = model.query.all()
    csvfile = StringIO()
    header = objects[0]._asdict().keys()
    if model_name == 'User':
        header = list(filter(lambda h: h!='id' and h!='password', header))
    writer = csv.DictWriter(csvfile, header)
    writer.writeheader()
    for obj in objects:
        dct = obj._asdict()
        if model_name == 'User':
            del(dct['password'])
            del(dct['id'])
        writer.writerow(dct)
    csvfile.seek(0)
    mem = BytesIO()
    mem.write(csvfile.getvalue().encode('utf-8'))
    mem.seek(0)
    csvfile.close()
    return send_file(mem,
                     attachment_filename='export.csv',
                     as_attachment=True)
示例#3
0
def get_offerer(id):
    dehumanize_id = dehumanize(id)
    for offerer in current_user.offerers:
        if offerer.id == dehumanize_id:
            return jsonify(offerer._asdict(include=OFFERERS_INCLUDES)), 200
    e = ApiErrors()
    e.addError('global', "Cette structure n'est pas enregistrée chez cet utilisateur.")
    return jsonify(e.errors), 400
示例#4
0
def check_token():
    if EXPORT_TOKEN is None or EXPORT_TOKEN == '':
        raise ValueError("Missing environment variable EXPORT_TOKEN")
    token = request.args.get('token')
    ae = ApiErrors()
    if token is None:
        ae.addError('token', 'Vous devez préciser un jeton dans l''adresse (token=XXX)')
    if not token == EXPORT_TOKEN:
        ae.addError('token', 'Le jeton est invalide')
    if ae.errors:
        raise ae
示例#5
0
def list_offerers_venues(id):
    dehumanize_id = dehumanize(id)
    for offerer in current_user.offerers:
        if offerer.id == dehumanize_id:
            venues = [
                o._asdict(include=VENUES_INCLUDES)
                for o in offerer.managedVenues
            ]
            return jsonify(venues), 200
    e = ApiErrors()
    e.addError('global', "Cette structure n'est pas enregistrée chez cet utilisateur.")
    return jsonify(e.errors), 400
示例#6
0
def list_venue_providers():
    venueId = request.args.get('venueId')
    if venueId is None:
        e = ApiErrors()
        e.addError('venueId', 'Vous devez obligatoirement fournir le paramètre venueId')
        return jsonify(e.errors), 400

    vp_query = VenueProvider.query\
                            .filter_by(venueId=dehumanize(venueId))
    return jsonify([
        vp._asdict(include=VENUE_PROVIDER_INCLUDES)
        for vp in vp_query.all()
    ])
示例#7
0
    def check_and_save(*objects):
        if not objects:
            raise ValueError('Objects to save need to be passed as arguments' +
                             ' to check_and_save')

        # CUMULATE ERRORS IN ONE SINGLE API ERRORS DURING ADD TIME
        api_errors = ApiErrors()
        for obj in objects:
            obj_api_errors = obj.errors()
            if obj_api_errors.errors.keys():
                api_errors.errors.update(obj_api_errors.errors)
            else:
                db.session.add(obj)

        # CHECK BEFORE COMMIT
        if api_errors.errors.keys():
            raise api_errors

        # COMMIT
        try:
            db.session.commit()
        except DataError as de:
            api_errors.addError(*BaseObject.restize_data_error(de))
            raise api_errors
        except IntegrityError as ie:
            api_errors.addError(*BaseObject.restize_integrity_error(ie))
            raise api_errors
        except TypeError as te:
            api_errors.addError(*BaseObject.restize_type_error(te))
            raise api_errors
        except ValueError as ve:
            api_errors.addError(*BaseObject.restize_value_error(ve))
            raise api_errors
        if api_errors.errors.keys():
            raise api_errors
示例#8
0
def post_booking():
    offer_id = request.json.get('offerId')
    ae = ApiErrors()
    if current_user.canBook == False:
        ae.addError('canBook',
                    'L\'utilisateur n\'a pas le droit de réserver d\'offre')
        return jsonify(ae.errors), 400

    if offer_id is None:
        ae.addError('offerId', 'Vous devez préciser un identifiant d\'offre')
        return jsonify(ae.errors), 400

    offer = Offer.query.filter_by(id=dehumanize(offer_id)).first()

    if offer is None:
        ae.addError('offerId', 'offerId ne correspond à aucune offer')
        return jsonify(ae.errors), 400

    if offer.bookingLimitDatetime is not None and\
       offer.bookingLimitDatetime < datetime.utcnow():
        ae.addError(
            'global',
            'la date limite de réservation de cette offre' + ' est dépassée')
        return jsonify(ae.errors), 400

    new_booking = Booking()
    new_booking.offerId = dehumanize(offer_id)

    token = random_token()
    new_booking.token = token
    new_booking.user = current_user
    recommendation_id = request.json.get('recommendationId')
    if recommendation_id is not None:
        new_booking.recommendationId = dehumanize(recommendation_id)

    try:
        app.model.PcObject.check_and_save(new_booking)
    except InternalError as ie:
        if 'check_booking' in str(ie.orig):
            ae.addError(
                'global',
                'la quantité disponible pour cette offre' + ' est atteinte')
            return jsonify(ae.errors), 400
        else:
            raise ie

    send_booking_recap_emails(app.model.Offer.query.get(new_booking.offerId),
                              new_booking)
    return jsonify(new_booking._asdict(include=BOOKINGS_INCLUDES,
                                       venueTz=True)), 201
示例#9
0
def handle_rest_get_list(modelClass, query=None, filter_fn=None,
                         refine=None, order_by=None, flask_request=None,
                         include=None, resolve=None, print_elements=None,
                         paginate=None, page=None):
    if flask_request is None:
        flask_request = request
    if query is None:
        query = modelClass.query
    # DELETED
    if hasattr(modelClass, 'deleted'):
        query = query.filter_by(deleted=False)
    # FILTER
    filters = flask_request.args.copy()
    if filter_fn:
        query = filter_fn(query, filters)
    # REFINE
    if refine:
        query = refine(query)
    # ORDER BY
    if order_by:
        try:
            order_by = [order_by] if not isinstance(order_by, list)\
                       else order_by
            query = query.order_by(*order_by)
        except ProgrammingError as e:
            field = re.search('column "?(.*?)"? does not exist', e._message, re.IGNORECASE)
            if field:
                errors = ApiErrors()
                errors.addError('order_by', 'order_by value references an unknown field : '+field.group(1))
                raise errors
            else:
                raise e
    # PAGINATE
    if paginate:
        page = 'page' in filters and filters['page']
        query = query.paginate(page, per_page=paginate, error_out=False)\
                     .items
    # DICTIFY
    elements = list(map(
        lambda o: o._asdict(
            include=include,
            resolve=resolve,
            filters=filters
        ),
        query))
    # PRINT
    if print_elements:
        print(elements)
    # RETURN
    return jsonify(elements), 200
示例#10
0
def edit_offer(offer_id):
    updated_offer_dict = request.json
    query = Offer.query.filter_by(id=dehumanize(offer_id))
    offer = query.first_or_404()
    ensure_provider_can_update(offer)
    update(offer, updated_offer_dict)
    try:
        app.model.PcObject.check_and_save(offer)
    except InternalError as ie:
        if 'check_offer' in str(ie.orig):
            ae = ApiErrors()
            ae.addError(
                'available', 'la quantité pour cette offre' +
                ' ne peut pas être inférieure' +
                ' au nombre de réservations existantes.')
            return jsonify(ae.errors), 400
        else:
            raise ie
    return jsonify(offer._asdict(include=OFFERS_INCLUDES)), 200
示例#11
0
def create_mediation():
    # TODO: Allow to receive a URL from request.form['thumb']
    # save_thumb already does it so it should be easy, but I can't make it ...

    if 'thumb' not in request.files\
       or request.files['thumb'].filename == '':
        e = ApiErrors()
        e.addError('thumb', "Vous devez fournir une image d'accroche")
        return jsonify(e.errors), 400

    thumb = request.files['thumb']
    filename_parts = thumb.filename.rsplit('.', 1)
    if len(filename_parts)<2\
       or filename_parts[1].lower() not in ALLOWED_EXTENSIONS:
        e = ApiErrors()
        e.addError('thumb', "Ce format d'image n'est pas autorisé")
        return jsonify(e.errors), 400

    offererId = dehumanize(request.form['offererId'])
    ensure_current_user_has_rights(RightsType.editor, offererId)

    new_mediation = Mediation()
    new_mediation.author = current_user
    new_mediation.eventId = dehumanize(request.form['eventId'])
    new_mediation.offererId = offererId
    app.model.PcObject.check_and_save(new_mediation)

    if 'croppingRect[x]' in request.form:
        crop = [
            float(request.form['croppingRect[x]']),
            float(request.form['croppingRect[y]']),
            float(request.form['croppingRect[height]'])
        ]
    else:
        crop = None

    new_mediation.save_thumb(thumb.read(), 0, crop=crop)

    return jsonify(new_mediation), 201
def find_or_make_recommendation(user,
                                occasion_type,
                                occasion_id,
                                mediation_id,
                                from_user_id=None):
    query = Recommendation.query
    print('(special) offer_id', occasion_id, 'mediation_id', mediation_id)
    if not mediation_id and not (occasion_id and occasion_type):
        return None
    if mediation_id:
        filter = (Recommendation.mediationId == mediation_id)
    elif occasion_id and occasion_type:
        if occasion_type == 'thing':
            filter = (Recommendation.thingId == mediation_id)
        elif occasion_type == 'event':
            filter = (Recommendation.eventId == mediation_id)
        else:
            ae = ApiErrors()
            ae.addError('occasion_type',
                        "Invalid occasion type : " + occasion_type)
            raise ae
    requested_recommendation = query.filter(filter & (Recommendation.userId==user.id))\
                                    .first()
    if requested_recommendation is None:
        if mediation_id:
            return None
        elif occasion_type == 'thing':
            occasion = Thing.query.get(occasion_id)
        elif occasion_type == 'event':
            occasion = Event.query.get(occasion_id)
        mediation = Mediation.query.get(mediation_id)
        requested_recommendation = create_recommendation(user,
                                                         occasion,
                                                         mediation=mediation)

    return requested_recommendation
def get_user_with_credentials(identifier, password):
    errors = ApiErrors()
    errors.status_code = 401

    if identifier is None:
        errors.addError('identifier', 'Identifiant manquant')
    if password is None:
        errors.addError('password', 'Mot de passe manquant')
    errors.maybeRaise()

    user = User.query.filter_by(email=identifier).first()

    if not user:
        errors.addError('identifier', 'Identifiant incorrect')
        raise errors
    if not user.checkPassword(password):
        errors.addError('password', 'Mot de passe incorrect')
        raise errors

    login_user(user, remember=True)
    return user
def send_401():
    e = ApiErrors()
    e.addError('global', 'Authentification nécessaire')
    return jsonify(e.errors), 401
示例#15
0
def signup():
    if 'contact_ok' not in request.json or\
       (request.json['contact_ok'] is not True and
        str(request.json['contact_ok']).lower() != 'true'):
        e = ApiErrors()
        e.addError('contact_ok',
                   'Vous devez obligatoirement cocher cette case')
        return jsonify(e.errors), 400

    departement_code = None
    if 'email' in request.json:
        scope = [
            'https://spreadsheets.google.com/feeds',
            'https://www.googleapis.com/auth/drive'
        ]
        key_path = Path(path.dirname(
            path.realpath(__file__))) / '..' / 'private' / 'google_key.json'
        credentials = ServiceAccountCredentials.from_json_keyfile_name(
            key_path, scope)

        gc = gspread.authorize(credentials)

        spreadsheet = gc.open_by_key(
            '1YCLVZNU5Gzb2P4Jaf9OW50Oedm2-Z9S099FGitFG64s')
        worksheet = spreadsheet.worksheet('Utilisateurs')

        labels = worksheet.row_values(1)
        email_index = None
        departement_index = None
        for index, label in enumerate(labels):
            if label == 'Email':
                email_index = index
            elif label == 'Département':
                departement_index = index
        if email_index is None:
            raise ValueError("Can't find 'Email' column in users spreadsheet")
        if departement_index is None:
            raise ValueError(
                "Can't find 'Département' column in users spreadsheet")

        values = worksheet.get_all_values()[1:]

        authorized_emails = list(map(lambda v: v[email_index], values))

        try:
            email_index = authorized_emails.index(request.json['email'])
        except ValueError:
            e = ApiErrors()
            e.addError('email', "Adresse non autorisée pour l'expérimentation")
            return jsonify(e.errors), 400

        departement_code = values[email_index][departement_index]
        if departement_code.strip() == '':
            print(
                "[ERROR] Missing departement code in users spreadsheet for " +
                request.json['email'])

            e = ApiErrors()
            e.addError('email', "Adresse non autorisée pour l'expérimentation")
            return jsonify(e.errors), 400

    new_user = app.model.User(from_dict=request.json)
    new_user.id = None
    new_user.departementCode = departement_code

    offerer = None
    user_offerer = None
    if 'siren' in request.json:
        #TODO: handle case of already existing Offerer
        new_user.canBook = False
        offerer = app.model.Offerer()
        update(offerer, request.json)
        user_offerer = offerer.make_admin(new_user)
        offerer.bookingEmail = new_user.email
        offerer.isActive = False
        app.model.PcObject.check_and_save(new_user, offerer, user_offerer)
    else:
        app.model.PcObject.check_and_save(new_user)
    login_user(new_user)
    return jsonify(new_user._asdict(include=USERS_INCLUDES)), 201