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)
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')
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
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)
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
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}
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')
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)
def get_trigger(request): trigger = request.match_info['trigger'] try: return Triggers(trigger) except ValueError: raise JsonErrors.HTTPNotFound(message='no such trigger')