def get_object(self): token = self.request.data.get('token') try: decoded_token = jwt_decode_handler(token) except jwt.ExpiredSignature: msg = _('This invitation is expired.') raise BadRequest(msg) except jwt.DecodeError: msg = _('Error decoding signature.') raise BadRequest(msg) user_id = decoded_token.get('user_id') invitation_code = decoded_token.get('invitation_code') if User.objects.filter(used_invitation_code=invitation_code): msg = _('This invitation link has been already used') raise BadRequest(msg) try: user = User.objects.filter( invitation_mail_sent=True, ).get(id=user_id) except User.DoesNotExist: raise BadRequest(_('No user found')) self.request.user = user self.request.user.used_invitation_code = invitation_code return user
def verify_signer_or_bad_request(signer): try: signer.verify() except SignatureExpired: raise BadRequest('Signature expired') except BadSignature: raise BadRequest('Invalid signature')
def get(self, request): user = request.user state_id = getattr(self, 'state_id', None) zipcode = getattr(self, 'zipcode', None) dosages = request.query_params.getlist('dosages[]', []) end_date = request.query_params.get('end_date') med_id = request.query_params.get('med_id') provider_categories = request.query_params.getlist( 'provider_categories[]', []) provider_types = request.query_params.getlist('provider_types[]', []) start_date = request.query_params.get('start_date') # check permission state_id, zipcode = force_user_state_id_and_zipcode( user, state_id, zipcode) # ensure correct geography filters if zipcode: geography = zipcode elif state_id: try: geography = State.objects.get(id=state_id).state_name except State.DoesNotExist: raise BadRequest('No such state exists') else: geography = 'US' try: med_name = MedicationName.objects.get(id=med_id) except MedicationName.DoesNotExist: raise BadRequest('No such medication in database') filename = '{medication_name}_{geography}_{date_from}_{date_to}_{user_id}_{timestamp}.csv'.format( medication_name=med_name.name.replace(' ', '_').replace( '(', '').replace(')', ''), geography=geography, date_from=start_date.format('%Y-%m-%d'), date_to=end_date.format('%Y-%m-%d'), user_id=user.id, timestamp=str(time.time()), ) if hasattr(settings, 'AWS_S3_BUCKET_NAME'): file_url = boto3.client('s3').generate_presigned_url( ClientMethod='get_object', Params={ 'Bucket': settings.AWS_S3_BUCKET_NAME, 'Key': filename }) else: file_url = 'local_csv_url' generate_csv_export.delay(filename, file_url, user.id, med_id, dosages, start_date, end_date, provider_types, provider_categories, state_id, zipcode) return Response({'file_url': file_url})
def login(request): ''' Logs in the user via given login and password. ''' serializer = LoginSerializer(data=request.data) serializer.is_valid(raise_exception=True) data = serializer.data user_class = get_user_model() login_fields = (registration_settings.USER_LOGIN_FIELDS or getattr(user_class, 'LOGIN_FIELDS', None) or [user_class.USERNAME_FIELD]) for field_name in login_fields: kwargs = { field_name: data['login'], 'password': data['password'], } user = auth.authenticate(**kwargs) if user: break if not user: raise BadRequest('Login or password invalid.') if should_authenticate_session(): auth.login(request, user) extra_data = {} if should_retrieve_token(): token, _ = Token.objects.get_or_create(user=user) extra_data['token'] = token.key return get_ok_response('Login successful', extra_data=extra_data)
def process_verify_email_data(input_data, serializer_context=None): if serializer_context is None: serializer_context = {} if not registration_settings.REGISTER_EMAIL_VERIFICATION_ENABLED: raise Http404() serializer = VerifyEmailSerializer( data=input_data, context=serializer_context, ) serializer.is_valid(raise_exception=True) data = serializer.validated_data signer = RegisterEmailSigner(data) verify_signer_or_bad_request(signer) request = serializer_context.get('request') new_email = data['email'] if is_user_email_field_unique() and user_with_email_exists(new_email): raise BadRequest(_("This email is already registered.")) email_field_name = get_user_email_field_name() user = get_user_by_verification_id(data['user_id']) old_email = getattr(user, email_field_name) setattr(user, email_field_name, new_email) user.save() signals.user_changed_email.send( sender=None, user=user, new_email=new_email, old_email=old_email, request=request, )
def send_reset_password_link(request): ''' Send email with reset password link. --- serializer: SendResetPasswordLinkSerializer ''' serializer = SendResetPasswordLinkSerializer(data=request.data) serializer.is_valid(raise_exception=True) login = serializer.data['login'] user_class = get_user_model_class() user_queryset = user_class.objects.all() user = None for login_field in get_login_fields(): try: user = get_object_or_404(user_queryset, **{login_field: login}) break except Http404: pass if not user: raise BadRequest('User not found') signer = ResetPasswordSigner({ 'user_id': user.pk, }, request=request) template_config = ( registration_settings.RESET_PASSWORD_VERIFICATION_EMAIL_TEMPLATES) send_verification(user, signer, template_config) return get_ok_response('Reset link sent')
def validate_dates(query_params): start_date = query_params.get('start_date') end_date = query_params.get('end_date') if not (start_date and end_date): raise BadRequest(_('start_date and end_date required')) try: start_date = datetime.strptime(start_date, '%Y-%m-%d').astimezone() end_date = datetime.strptime(end_date, '%Y-%m-%d').astimezone() except ValueError as e: raise BadRequest(_('Incorrect date: {}').format(e)) if end_date <= start_date: raise BadRequest(_('start_date must precede end_date.')) return start_date, end_date
def register(request): ''' Register new user. ''' serializer_class = registration_settings.REGISTER_SERIALIZER_CLASS serializer = serializer_class(data=request.data) serializer.is_valid(raise_exception=True) kwargs = {} if registration_settings.REGISTER_VERIFICATION_ENABLED: verification_flag_field = get_user_setting('VERIFICATION_FLAG_FIELD') kwargs[verification_flag_field] = False email_field = get_user_setting('EMAIL_FIELD') if (email_field not in serializer.validated_data or not serializer.validated_data[email_field]): raise BadRequest("User without email cannot be verified") user = serializer.save(**kwargs) signals.user_registered.send(sender=None, user=user, request=request) output_serializer_class = registration_settings.REGISTER_OUTPUT_SERIALIZER_CLASS # noqa: E501 output_serializer = output_serializer_class(instance=user) user_data = output_serializer.data if registration_settings.REGISTER_VERIFICATION_ENABLED: signer = RegisterSigner({ 'user_id': get_user_verification_id(user), }, request=request) template_config = ( registration_settings.REGISTER_VERIFICATION_EMAIL_TEMPLATES) send_verification_notification(user, signer, template_config) return Response(user_data, status=status.HTTP_201_CREATED)
def register(request): ''' Register new user. ''' serializer_class = registration_settings.REGISTER_SERIALIZER_CLASS serializer = serializer_class(data=request.data) serializer.is_valid(raise_exception=True) kwargs = {} if registration_settings.REGISTER_VERIFICATION_ENABLED: verification_flag_field = get_user_setting('VERIFICATION_FLAG_FIELD') kwargs[verification_flag_field] = False email_field = get_user_setting('EMAIL_FIELD') if (email_field in serializer.validated_data and not serializer.validated_data[email_field]): raise BadRequest("User without email cannot be verified") user = serializer.save(**kwargs) profile_serializer_class = registration_settings.PROFILE_SERIALIZER_CLASS profile_serializer = profile_serializer_class(instance=user) user_data = profile_serializer.data if registration_settings.REGISTER_VERIFICATION_ENABLED: signer = RegisterSigner({ 'user_id': user.pk, }, request=request) template_config = ( registration_settings.REGISTER_VERIFICATION_EMAIL_TEMPLATES) send_verification(user, signer, template_config) return Response(user_data, status=status.HTTP_201_CREATED)
def register(request): ''' Register new user. ''' serializer_class = registration_settings.REGISTER_SERIALIZER_CLASS serializer = serializer_class(data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) kwargs = {} if registration_settings.REGISTER_VERIFICATION_ENABLED: verification_flag_field = get_user_setting('VERIFICATION_FLAG_FIELD') kwargs[verification_flag_field] = False email_field_name = get_user_email_field_name() if (email_field_name not in serializer.validated_data or not serializer.validated_data[email_field_name]): raise BadRequest(_("User without email cannot be verified")) with transaction.atomic(): user = serializer.save(**kwargs) if registration_settings.REGISTER_VERIFICATION_ENABLED: send_register_verification_email_notification(request, user) signals.user_registered.send(sender=None, user=user, request=request) output_serializer_class = registration_settings.REGISTER_OUTPUT_SERIALIZER_CLASS output_serializer = output_serializer_class( instance=user, context={'request': request}, ) user_data = output_serializer.data return Response(user_data, status=status.HTTP_201_CREATED)
def register(request): ''' Register new user. ''' # Check reCaptcha serializer_class = registration_settings.REGISTER_SERIALIZER_CLASS serializer = serializer_class(data=request.data) serializer.is_valid(raise_exception=True) kwargs = {} if registration_settings.REGISTER_VERIFICATION_ENABLED: verification_flag_field = get_user_setting('VERIFICATION_FLAG_FIELD') kwargs[verification_flag_field] = False email_field = get_user_setting('EMAIL_FIELD') if (email_field not in serializer.validated_data or not serializer.validated_data[email_field]): raise BadRequest("User without email cannot be verified") # Check if reCaptcha is enabled if registration_settings.RECAPTCHA_ENABLED: recaptcha_key = get_user_setting('RECAPTCHA_KEY') recaptcha_token = request.data.get('recaptcha_token', None) if recaptcha_key is None: raise BadRequest("reCaptcha enabled, missing key") if recaptcha_token is None: raise BadRequest("reCaptcha enabled, missing token") if not check_recaptcha_token: raise BadRequest("Error with reCaptcha token") user = serializer.save(**kwargs) output_serializer_class = registration_settings.REGISTER_OUTPUT_SERIALIZER_CLASS # noqa: E501 output_serializer = output_serializer_class(instance=user) user_data = output_serializer.data if registration_settings.REGISTER_VERIFICATION_ENABLED: signer = RegisterSigner({ 'user_id': user.pk, }, request=request) template_config = ( registration_settings.REGISTER_VERIFICATION_EMAIL_TEMPLATES) send_verification_notification(user, signer, template_config) return Response(user_data, status=status.HTTP_201_CREATED)
def logout(request): ''' Logs out the user. returns an error if the user is not authenticated. ''' if not request.user.is_authenticated: raise BadRequest('Not logged in') auth.logout(request) return get_ok_response('Logout successful')
def force_user_state_id_and_zipcode(user, state_id, zipcode): from medications.models import ZipCode if user.permission_level == user.STATE_LEVEL: if not user.state_id or (zipcode and ZipCode.objects.filter( zipcode=zipcode, state_id=user.state_id).count() == 0): msg = _( 'Permission denied - Please check with system administrator') raise BadRequest(msg) return user.state_id, zipcode return state_id, zipcode
def register_email(request): ''' Register new email. ''' user = request.user serializer_class = registration_settings.REGISTER_EMAIL_SERIALIZER_CLASS serializer = serializer_class( data=request.data, context={'request': request}, ) serializer.is_valid(raise_exception=True) email = serializer.get_email() email_already_used = is_user_email_field_unique( ) and user_with_email_exists(email) # noqa: E501 if registration_settings.REGISTER_EMAIL_VERIFICATION_ENABLED: signer = RegisterEmailSigner( { 'user_id': get_user_verification_id(user), 'email': email, }, request=request) notification_data = { 'params_signer': signer, 'email_already_used': email_already_used, } template_config_data = registration_settings.REGISTER_EMAIL_VERIFICATION_EMAIL_TEMPLATES # noqa: E501 send_verification_notification( NotificationType.REGISTER_EMAIL_VERIFICATION, user, notification_data, template_config_data, custom_user_address=email) else: if email_already_used: raise BadRequest(_("This email is already registered.")) email_field_name = get_user_email_field_name() old_email = getattr(user, email_field_name) setattr(user, email_field_name, email) user.save() signals.user_changed_email.send( sender=None, user=user, new_email=email, old_email=old_email, request=request, ) return get_ok_response(_("Register email link email sent"))
def login(request): ''' Logs in the user via given login and password. ''' serializer_class = registration_settings.LOGIN_SERIALIZER_CLASS serializer = serializer_class(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.get_authenticated_user() if not user: raise BadRequest('Login or password invalid.') extra_data = perform_login(request, user) return get_ok_response('Login successful', extra_data=extra_data)
def register(request): ''' Register new user. ''' serializer_class = registration_settings.REGISTER_SERIALIZER_CLASS serializer = serializer_class( data=request.data, context={'request': request}, ) serializer.is_valid(raise_exception=True) kwargs = {} if registration_settings.REGISTER_VERIFICATION_ENABLED: verification_flag_field = get_user_setting('VERIFICATION_FLAG_FIELD') kwargs[verification_flag_field] = False email_field_name = get_user_email_field_name() if (email_field_name not in serializer.validated_data or not serializer.validated_data[email_field_name]): raise BadRequest("User without email cannot be verified") with transaction.atomic(): user = serializer.save(**kwargs) if registration_settings.REGISTER_VERIFICATION_ENABLED: signer = RegisterSigner({ 'user_id': get_user_verification_id(user), }, request=request) template_config_data = registration_settings.REGISTER_VERIFICATION_EMAIL_TEMPLATES # noqa: E501 notification_data = { 'params_signer': signer, } send_verification_notification( NotificationType.REGISTER_VERIFICATION, user, notification_data, template_config_data) signals.user_registered.send(sender=None, user=user, request=request) output_serializer_class = registration_settings.REGISTER_OUTPUT_SERIALIZER_CLASS # noqa: E501 output_serializer = output_serializer_class( instance=user, context={'request': request}, ) user_data = output_serializer.data return Response(user_data, status=status.HTTP_201_CREATED)
def logout(request): ''' Logs out the user. returns an error if the user is not authenticated. ''' user = request.user serializer = LogoutSerializer(data=request.data) serializer.is_valid(raise_exception=True) data = serializer.validated_data if should_authenticate_session(): auth.logout(request) if should_retrieve_token() and data['revoke_token']: try: user.auth_token.delete() except Token.DoesNotExist: raise BadRequest('Cannot remove non-existent token') return get_ok_response('Logout successful')
def login(request): ''' Logs in the user via given login and password. ''' serializer_class = registration_settings.LOGIN_SERIALIZER_CLASS serializer = serializer_class(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.get_authenticated_user() if not user: raise BadRequest('Login or password invalid.') if should_authenticate_session(): auth.login(request, user) extra_data = {} if should_retrieve_token(): token, _ = Token.objects.get_or_create(user=user) extra_data['token'] = token.key return get_ok_response('Login successful', extra_data=extra_data)
def get_queryset(self): ''' query_params: - med_ids: list of MedicaitonName ids - dosages: list of Dosage ids - localization: list of 2 coordinates (must be int or float) - distance: int, in miles ''' med_ids = self.request.query_params.getlist('med_ids[]', None) dosages = self.request.query_params.getlist('dosages[]', None) location = self.request.query_params.get('localization') distance = self.request.query_params.get('distance') # 1 - validate location try: location = list(map(float, location.split(','))) location_point = Point( location[0], location[1], srid=4326, ) except (IndexError, ValueError, AttributeError): raise BadRequest( 'Location should be provided and be a list of 2 coordinates') # 2 - fetch ndc codes from filters: med id and dosage + support for all if len(med_ids) == 1 and med_ids[0] == 'all': med_ndc_qs = MedicationMedicationNameMedicationDosageThrough.objects.all( ) else: med_ndc_qs = MedicationMedicationNameMedicationDosageThrough.objects.filter( medication_name_id__in=med_ids, medication_dosage_id__in=dosages) med_ndc_ids = med_ndc_qs.select_related( 'medication__ndc_codes', ).distinct().values_list( 'medication__ndc_codes', flat=True) # 2 - fetch provider medication entries (supply levels) for the ndc ndc_codes # and filter by distance provider_medication_ids = ProviderMedicationNdcThrough.objects.filter( latest=True, medication_ndc_id__in=med_ndc_ids, provider__geo_localization__distance_lte=( location_point, D(mi=distance), ), ).values_list( 'id', flat=True, ) # SPECIAL INSTRUCTION # Exclude providers from vaccine finder organization ID 4504 (4383 in medfinder) # vaccine finder type needs to be 4 (pharamacy), exclude all other # More info at https://www.pivotaltracker.com/story/show/162711148 provider_qs = Provider.objects.filter( Q(organization_id=4383) | Q(vaccine_finder_type=4) ).filter(geo_localization__distance_lte=( location_point, D(mi=distance), ), ).annotate( distance=Distance( 'geo_localization', location_point, ), total_supply=Coalesce( Sum( 'provider_medication__level', filter=Q( provider_medication__id__in=provider_medication_ids, provider_medication__latest=True, active=True, ), ), 0, ), amount_medications=Count( 'provider_medication', filter=Q( provider_medication__id__in=provider_medication_ids, provider_medication__latest=True, active=True, ), )).prefetch_related( Prefetch( 'provider_medication', queryset=ProviderMedicationNdcThrough.objects.filter( latest=True, id__in=provider_medication_ids, ).select_related( 'medication_ndc__medication', 'medication_ndc__medication__medication_name', ).order_by( '-level', '-medication_ndc__medication__drug_type'))).order_by( '-total_supply', '-active', '-amount_medications', 'distance') return provider_qs