Beispiel #1
0
async def switch_user_status(request):
    user_id = int(request.match_info['pk'])
    status = await request['conn'].fetchval(
        'SELECT status FROM users WHERE id=$1 AND company=$2',
        user_id,
        request['company_id'],
    )
    if not status:
        raise JsonErrors.HTTPNotFound(message='user not found')
    new_status = 'suspended' if status == 'active' else 'active'
    await request['conn'].execute('UPDATE users SET status=$1 WHERE id=$2', new_status, user_id)
    return json_response(new_status=new_status)
Beispiel #2
0
 async def check_permissions(self):
     await check_session(self.request, 'admin')
     v = await self.conn.fetchval_b(
         """
         SELECT 1 FROM events AS e
         JOIN categories AS c on e.category = c.id
         WHERE e.id=:id AND c.company=:company
         """,
         id=int(self.request.match_info['id']),
         company=self.request['company_id']
     )
     if not v:
         raise JsonErrors.HTTPNotFound(message='Event not found')
Beispiel #3
0
async def check_event_sig(request):
    company_id = request['company_id']
    category_slug = request.match_info['category']
    event_slug = request.match_info['event']
    r = await request['conn'].fetchrow(event_id_public_sql, company_id,
                                       category_slug, event_slug)

    # so we always do the hashing even for an event that does exist to avoid timing attack, probably over kill
    if r:
        event_id, event_is_public = r
    else:
        event_id, event_is_public = 0, False

    if not event_is_public:
        url_sig = request.match_info.get('sig')
        if not url_sig:
            raise JsonErrors.HTTPNotFound(message='event not found')
        sig = hmac.new(request.app['settings'].auth_key.encode(),
                       f'/{category_slug}/{event_slug}/'.encode(),
                       digestmod=hashlib.md5).hexdigest()
        if not compare_digest(url_sig, sig):
            raise JsonErrors.HTTPNotFound(message='event not found')
    return event_id
Beispiel #4
0
    async def execute(self, m: Model):
        event_id = await _check_event_permissions(self.request)
        ticket_id = int(self.request.match_info['tid'])
        r = await self.conn.fetchrow(
            """
            select a.type, t.price, a.extra->>'charge_id'
            from tickets as t
            join actions as a on t.booked_action = a.id
            where t.event = $1 and t.id = $2 and t.status = 'booked'
            """,
            event_id,
            ticket_id,
        )
        if not r:
            raise JsonErrors.HTTPNotFound(message='Ticket not found')
        booking_type, price, charge_id = r
        if m.refund_amount is not None:
            if booking_type != ActionTypes.buy_tickets:
                raise JsonErrors.HTTPBadRequest(
                    message=
                    'Refund not possible unless ticket was bought through stripe.'
                )
            if m.refund_amount > price:
                raise JsonErrors.HTTPBadRequest(
                    message=f'Refund amount must not exceed {price:0.2f}.')

        async with self.conn.transaction():
            action_id = await record_action_id(
                self.request, self.session['user_id'],
                ActionTypes.cancel_booked_tickets)
            await self.conn.execute(
                "update tickets set status='cancelled', cancel_action=$1 where id=$2",
                action_id, ticket_id)
            await self.conn.execute('SELECT check_tickets_remaining($1, $2)',
                                    event_id, self.settings.ticket_ttl)
            if m.refund_amount is not None:
                await stripe_refund(
                    refund_charge_id=charge_id,
                    ticket_id=ticket_id,
                    amount=int(m.refund_amount * 100),
                    user_id=self.session['user_id'],
                    company_id=self.request['company_id'],
                    app=self.app,
                    conn=self.conn,
                )
        await self.app['email_actor'].send_tickets_available(event_id)
Beispiel #5
0
async def _check_event_permissions(request, check_upcoming=False):
    event_id = int(request.match_info['id'])
    r = await request['conn'].fetchrow(
        """
        SELECT host, start_ts
        FROM events AS e
        JOIN categories AS cat ON e.category = cat.id
        WHERE e.id=$1 AND cat.company=$2
        """, event_id, request['company_id'])
    if not r:
        raise JsonErrors.HTTPNotFound(message='event not found')
    host_id, start_ts = r
    if request['session']['role'] != 'admin':
        if host_id != request['session']['user_id']:
            raise JsonErrors.HTTPForbidden(message='user is not the host of this event')
        if check_upcoming and start_ts < datetime.utcnow().replace(tzinfo=timezone.utc):
            raise JsonErrors.HTTPForbidden(message="you can't modify past events")
    return event_id
Beispiel #6
0
    async def execute(self, m: Model):
        old_event_id = int(self.request.match_info['id'])
        slug = slugify(m.name)

        tz = await self.conn.fetchval(
            """
            SELECT timezone FROM events e
            JOIN categories c ON e.category = c.id
            WHERE e.id=$1 AND c.company=$2
            """,
            old_event_id,
            self.request['company_id'],
        )
        if not tz:
            raise JsonErrors.HTTPNotFound(message='Event not found')

        start, duration = prepare_event_start(m.date.dt, m.date.dur,
                                              pytz.timezone(tz))
        kwargs = dict(slug=slug,
                      old_event_id=old_event_id,
                      name=m.name,
                      start=start,
                      duration=duration,
                      status=m.status.value)

        async with self.conn.transaction():
            new_event_id = await self.conn.fetchval_b(self.clone_event_sql,
                                                      **kwargs)
            while new_event_id is None:
                # event with this slug already exists
                kwargs['slug'] = slug + '-' + pseudo_random_str(4)
                new_event_id = await self.conn.fetchval_b(
                    self.clone_event_sql, **kwargs)

            await self.conn.execute(self.duplicate_ticket_types_sql,
                                    old_event_id, new_event_id)

        return {'id': new_event_id, 'status_': 201}
Beispiel #7
0
async def donation_image_upload(request):
    co_id = request['company_id']
    don_opt_id = int(request.match_info['pk'])
    r = await request['conn'].fetchrow(
        """
        SELECT co.slug, cat.slug, d.image
        FROM donation_options AS d
        JOIN categories AS cat ON d.category = cat.id
        JOIN companies AS co ON cat.company = co.id
        WHERE d.id = $1 AND cat.company = $2
        """,
        don_opt_id,
        co_id,
    )
    if not r:
        raise JsonErrors.HTTPNotFound(message='donation option not found')

    co_slug, cat_slug, old_image = r
    content = await request_image(request, expected_size=IMAGE_SIZE)

    upload_path = Path(co_slug) / cat_slug / str(don_opt_id)
    image_url = await upload_other(
        content,
        upload_path=upload_path,
        settings=request.app['settings'],
        req_size=IMAGE_SIZE,
        thumb=True,
    )

    await request['conn'].execute(
        'UPDATE donation_options SET image=$1 WHERE id=$2', image_url,
        don_opt_id)

    if old_image:
        await delete_image(old_image, request.app['settings'])
    return json_response(status='success')
Beispiel #8
0
 async def _fetchval_response(self, sql, **kwargs):
     json_str = await self.conn.fetchval_b(sql, **kwargs)
     if not json_str:
         raise JsonErrors.HTTPNotFound(
             message=f'{self.meta["single_title"]} not found')
     return raw_json_response(json_str)
Beispiel #9
0
def get_trigger(request):
    trigger = request.match_info['trigger']
    try:
        return Triggers(trigger)
    except ValueError:
        raise JsonErrors.HTTPNotFound(message='no such trigger')