def perform_create(self, serializer): username = serializer.validated_data['username'] try: user = User.objects.get_by_natural_key(username) if user.is_superuser: raise RestValidationError({ api_settings.NON_FIELD_ERRORS_KEY: _('Super users cannot be edited') }) roles = Role.objects.get_roles_for_user(user) changing_role = self.request.data.get('change-role', '').lower() == 'true' if roles and not changing_role: raise RestValidationError({ '__mtp__': { 'condition': 'user-exists', 'roles': [{ 'role': role.name, 'application': role.application.name, 'login_url': role.login_url, } for role in roles] }, api_settings.NON_FIELD_ERRORS_KEY: _('This username already exists'), }) # copy user details that shouldn't change for key in ('first_name', 'last_name', 'email'): serializer.validated_data[key] = getattr(user, key) except User.DoesNotExist: pass super().perform_create(serializer)
def deactivate_user(self, user_id): u2p = self.user_projects.get(user_id=user_id) if u2p.role == UserProject.OWNER: raise RestValidationError({ 'detail': 'You cannot deactivate an owner from his own project' }) if u2p.status == UserProject.DEACTIVATED: raise RestValidationError({'detail': 'User already deactivated'}) u2p.status = UserProject.DEACTIVATED u2p.save(update_fields=['status'])
class ModelViewSet(viewsets.ModelViewSet): """ Generic ModelViewSet Base Class This should probably be moved to a common lib ? Ueaj """ paginate_by_param = ("limit", ) # use django namespace permissions backend, this is also specified in the # settings but for some reason it only works when explicitly set here, # need to investigate permission_classes = (nsp_rest.BasePermission, ) def get_queryset(self): """ Prepare the queryset """ qset = self.model.handleref.all() self.request.meta_response = {} if hasattr(self.serializer_class, "prepare_query"): try: qset, p_filters = self.serializer_class.prepare_query( qset, **self.request.query_params) except ValidationError, inst: raise RestValidationError({"detail": str(inst[0])}) except ValueError, inst: raise RestValidationError({"detail": str(inst[0])}) except TypeError, inst: raise RestValidationError({"detail": str(inst[0])})
def compose_file(request): if request.method == "GET": config = docker.compose_config() serializer = ComposeFileSerializer({ "path": config.compose_file_path, "project_name": config.project_name, "file_content": config.original_file_content(), }) return Response(serializer.data) if request.method == "PUT": serializer = ComposeFileSerializer(data=request.data) if serializer.is_valid(): file_content = serializer.validated_data["file_content"] if file_content: try: docker.update_compose_file_content( file_content=file_content) except ValidationError as error: raise RestValidationError(detail=error.message) except Exception: raise APIException() else: Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def do_ext(self, request, obj): errors = dict() ex_objs = list() for model_fields in self.get_ext_model_fields(): param = getattr(request.params, model_fields.field_name) if param is None: continue def _get_ext_obj(*args, **kwargs): return self.get_ext_obj(*args, **kwargs) try: add_objs, edit_objs, del_objs = model_fields.gen_objs( param, obj, _get_ext_obj) ex_objs.append( (model_fields.ext_model, add_objs, edit_objs, del_objs)) except RestValidationError as e: errors[model_fields.field_name] = e if errors: raise RestValidationError(parse_validation_error(errors)) for ext_model, add_objs, edit_objs, del_objs in ex_objs: if del_objs: self.delete_ext_objs(del_objs) if edit_objs: self.edit_ext_objs(edit_objs) if add_objs: self.add_ext_objs(ext_model, add_objs)
def post(self, request, *args, **kwargs): label_config = self.request.data.get('label_config') if not label_config: raise RestValidationError('Label config is not set or empty') project = self.get_object() return Response({'sample_task': project.get_sample_task(label_config)}, status=200)
def perform_update(self, serializer): place = serializer.validated_data['place'] if place.has_staff(self.request.user): return super().perform_update(serializer) else: raise RestValidationError( translation.gettext('Non-staff users cannot add week days'))
def register_error(self, error_message, field_name=None, error_key=None, error_code=None): if field_name is None: if error_code is None: raise ValueError('For non field error you must provide ' 'an error code') error = {'code': error_code, 'message': error_message, 'field': None} else: field_instance = self.fields.get(field_name) if field_instance is None: raise ValueError('Incorrect field name') field_type = field_instance.__class__.__name__ if error_key is None and error_code is None: raise ValueError('You have to provide either error key' ' or error code') if error_code is not None: error_code = error_code else: try: error_code = settings.FRIENDLY_FIELD_ERRORS[field_type].get( error_key) except KeyError: raise ValueError('Unknown field type: "%s"' % field_type) if error_code is None: raise ValueError('Unknown error key: "%s" ' 'for field type: "%s"' % (error_key, field_type)) error = {'code': error_code, 'field': field_name, 'message': error_message} key = '%s_%s_%s' % (error_message, error_code, field_name) self.registered_errors[key] = error raise RestValidationError(key)
def get_queryset(self): """ Prepare the queryset """ qset = self.model.handleref.all() self.request.meta_response = {} if hasattr(self.serializer_class, "prepare_query"): try: qset, p_filters = self.serializer_class.prepare_query( qset, **self.request.query_params) except ValidationError, inst: raise RestValidationError({"detail": str(inst[0])}) except ValueError, inst: raise RestValidationError({"detail": str(inst[0])})
def invite_user(self, email: str): if self.user_projects.filter(user__email=email).exists(): raise RestValidationError({'detail': 'User already in project'}) if self.invitations.filter(email=email, deleted_at__isnull=True).exists(): raise RestValidationError({'detail': 'User already invited'}) invitation, created = Invitation.objects.get_or_create( email=email, project=self, ) if not created: invitation.deleted_at = None invitation.save(update_fields=['deleted_at']) print(f'EMAIL: user {email} invited')
def perform_update(self, serializer): day = serializer.validated_data['day'] place = day.place if place.has_staff( self.request.user) and day.owner == self.request.user: work_time = WorkTime(day=day, begin=serializer.validated_data['begin'], end=serializer.validated_data['end']) if work_places.is_working_time_valid(work_time): return super().perform_update(serializer) else: raise RestValidationError( translation.gettext('Work time is invalid')) else: return RestValidationError( translation.gettext( "You don't have permission to update this work time"))
def gen_objs(self, data, obj, get_ext_obj): params = dict() params[self.ext_foreign_key] = obj add_objs = [] edit_objs = [] edit_ids = [] param_errors = dict() for idx, p in enumerate(data): if self.pk_field is not None and self.pk_field in p and p[ self.pk_field] is not None: if p[self.pk_field] in edit_ids: param_errors[idx] = ValidationError( _('Primary key duplicate')) continue edit_ids.append(p[self.pk_field]) obj = get_ext_obj(self.ext_model, self.pk_field, p[self.pk_field]) if obj is None: param_errors[idx] = ValidationError( _('Modification item not found')) continue for ext_key, ext_value in params.items(): if getattr(obj, ext_key) != ext_value: param_errors[idx] = ValidationError( _('Modification item not found')) break else: for key, value in p.items(): if key in self.edit_field_list and value is not None: setattr(obj, key, value) try: obj.full_clean() except ValidationError as e: param_errors[idx] = e edit_objs.append(obj) else: obj = self.ext_model( **self.add_default_fields, **params, **dict( filter(lambda x: x[0] in self.add_field_list, p.items())), ) try: obj.full_clean() except ValidationError as e: param_errors[idx] = e add_objs.append(obj) del_objs = [] if self.delete_not_found: queryset = self.ext_model.objects.filter(**params) if edit_ids: queryset = queryset.exclude( **{"%s__in" % self.pk_field: edit_ids}) del_objs = list(queryset) if param_errors: raise RestValidationError(parse_validation_error(param_errors)) return add_objs, edit_objs, del_objs
def get_context(self, request, *args, **kwargs): with transaction.atomic(): try: obj = self.model() self.init_fields(request, obj) self.save_obj(request, obj) except ValidationError as e: raise RestValidationError(parse_validation_error(e)) return self.serializer_response(obj, request=request)
def _check_user_invitation(self, user): try: invitation = self.invitations.get( email=user.email, deleted_at__isnull=True, ) except Invitation.DoesNotExist: raise RestValidationError({'detail': 'User is not invited'}) return invitation
def disable(self): for u2p in self.user_projects.all(): if u2p.is_default: raise RestValidationError({ 'detail': 'You cannot disable default project', }) self.disabled_at = timezone.now() self.save(update_fields=['disabled_at'])
def post(self, request, *args, **kwargs): project = self.get_object() label_config = self.request.data.get('label_config') if not label_config: raise RestValidationError('Label config is not set or is empty') # check new config includes meaningful changes has_changed = config_essential_data_has_changed(label_config, project.label_config) project.validate_config(label_config) return Response({'config_essential_data_has_changed': has_changed}, status=status.HTTP_200_OK)
def register_error(self, error_message, field_name=None, error_key=None, error_code=None, meta=None, raise_validation_error=True): if field_name is None: if error_code is None: raise ValueError('For non field error you must provide ' 'an error code') error = { 'code': error_code, 'message': error_message, 'field': None } key = '%s_%s' % (error_message, error_code) else: key = field_name field_instance = self.fields.get(field_name) if field_instance is None: raise ValueError('Incorrect field name') field_type = field_instance.__class__.__name__ if error_key is None and error_code is None: raise ValueError('You have to provide either error key' ' or error code') if error_code is None: try: error_code = settings.FRIENDLY_FIELD_ERRORS[ field_type].get(error_key) except KeyError: raise ValueError('Unknown field type: "%s"' % field_type) if error_code is None: raise ValueError('Unknown error key: "%s" ' 'for field type: "%s"' % (error_key, field_type)) error = { 'code': error_code, 'field': field_name, 'message': error_message } if meta is not None: error['meta'] = meta if field_name is not None: self.registered_errors[field_name] = [error] else: non_field_errors_key = api_settings.NON_FIELD_ERRORS_KEY if not self.registered_errors.get(non_field_errors_key): self.registered_errors[non_field_errors_key] = [] self.registered_errors[non_field_errors_key].append({key: [error]}) if raise_validation_error: raise RestValidationError(self.registered_errors)
def register(self, request: Request): serializer = UserRegisterSerializer(data=request.data, context={'request': request}) serializer.is_valid() errors = serializer.errors # Avoid confusion: don't allow registration for existing email addresses through the API email = serializer.data.get('email') if email and user_model.objects.filter(email=email).exists(): errors.setdefault('email', []).append( _("A user with this email address already exists.")) password = serializer.validated_data.pop('password', '') try: validate_password(password) except ValidationError as ex: errors.setdefault('password', []).extend(ex.messages) # Show errors if there are any if errors: raise RestValidationError(errors) # Create a new user user = user_model.objects.create(is_active=False, password=make_password(password), **serializer.validated_data) # Use the new user's token to create the authentication code token, created = Token.objects.get_or_create(user=user) hmac = salted_hmac(user.username, token.key) code = hmac.hexdigest() try: session = Session() session.request(method='POST', url='{}/wp-json/gui/v1/user/activation/'.format( settings.FRONTEND_BASE_URL), json={ "user_id": user.id, "username": user.username, "first_name": user.first_name, "last_name": user.last_name, "email": user.email, "code": code, }, timeout=(10, 30)) except OSError: pass return Response(status=201, data=UserAdminSerializer(user, context={ 'request': request }).data)
def register_error(self, error_message, field_name=None, error_key=None): if field_name is None: error = {'message': error_message, 'field': None} else: field_instance = self.fields.get(field_name) if field_instance is None: raise ValueError('Incorrect field name') error = {'field': field_name, 'message': error_message} key = '%s_%s' % (error_message, field_name) self.registered_errors[key] = error raise RestValidationError(key)
def confirm_invitation(self, user): invitation = self._check_user_invitation(user) if user in self.users.all(): raise RestValidationError({'detail': 'User already in project'}) self.user_projects.create( user=user, role=UserProject.MEMBER, status=UserProject.ACTIVE, ) invitation.soft_delete()
def authenticate(self, request, pk=None): user = self.get_object() serializer = AuthCodeSerializer(data=request.data) serializer.is_valid(raise_exception=True) # Don't activate accounts that are already active, that's silly if user.is_active: return Response({'status': 'account has already been activated'}) # Don't reactivate accounts that have been used, we might have deactivated them for some other reason if user.last_login: raise RestValidationError({ api_settings.NON_FIELD_ERRORS_KEY: [_('Account cannot be activated')] }) # Use the user's token to create the authentication code token, created = Token.objects.get_or_create(user=user) hmac = salted_hmac(user.username, token.key) code = hmac.hexdigest() if serializer.validated_data['code'] != code: raise RestValidationError({ 'code': [_('Invalid authentication code, account not activated')] }) if user.date_joined < timezone.now() - timedelta(days=7): raise RestValidationError({ 'code': [_('Authentication code expired, account not activated')] }) user.is_active = True user.save(update_fields=['is_active']) return Response({'status': 'account activated'})
def clean_dict_data(self, data): data = super().clean_dict_data(data) if self.ext_model_field_key.pk_field is None: return data errors = dict() if data.get(self.ext_model_field_key.pk_field, None) is not None: for field_name in self.ext_model_field_key.add_field_list: if field_name in self.ext_model_field_key.add_not_required_field_list: continue if data.get(field_name, None) is None: try: self.children[field_name].fail('required') except RestValidationError as e: errors[field_name] = e.detail if errors: raise RestValidationError(errors) return data
def create(self, validated_data): for field in READABLE_FIELDS: validated_data.pop(field, None) withdraw_address = validated_data.pop('withdraw_address') payment_id = withdraw_address.pop('payment_id', None) destination_tag = withdraw_address.pop('destination_tag', None) validated_data.pop('pair') # Just making sure addr_list = Address.objects.filter(address=withdraw_address['address']) order = Order(pair=self.pair, **validated_data) if payment_id: order.payment_id = payment_id if destination_tag: order.destination_tag = destination_tag if not addr_list: address = Address(**withdraw_address) address.type = Address.WITHDRAW address.currency = order.pair.base address.save() else: address = addr_list[0] order.withdraw_address = address try: order.save() # get post_save stuff in sync order.refresh_from_db() self.fields['deposit_address'] = NestedReadOnlyAddressSerializer( many=False, read_only=True, additional_params={ 'destination_tag': order.quote_destination_tag, 'payment_id': order.quote_payment_id }) self.fields['withdraw_address'] = NestedAddressSerializer( many=False, read_only=False, additional_params={ 'destination_tag': order.base_destination_tag, 'payment_id': order.base_payment_id }) return order except ValidationError as e: raise RestValidationError({'non_field_errors': [e.message]})
def create(self, request, *args, **kwargs): is_start = request.data['status_type'] == 'Start' data = request.data.copy() # import because request objects is immutable for field in ['session_time', 'input_octets', 'output_octets']: if is_start and request.data[field] == '': data[field] = 0 serializer = self.get_serializer(data=data) serializer.is_valid() error_keys = serializer.errors.keys() errors = len(error_keys) if not errors: self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(None, status=201, headers=headers) # trying to create a record which # already exist, fallback to update if errors == 1 and 'unique_id' in error_keys: return self.update(request, *args, **kwargs) else: raise RestValidationError(serializer.errors)
def project_editor_import_indicator(request, project_pk, parent_indicator_id): try: project = Project.objects.get(pk=project_pk) except Project.DoesNotExist: return HttpResponseNotFound() except Project.MultipleObjectsReturned: return HttpResponseBadRequest() user = request.user if not user.can_import_results(project): return HttpResponseForbidden() try: indicator = project.import_indicator(parent_indicator_id) except (Project.DoesNotExist, Project.MultipleObjectsReturned, Indicator.DoesNotExist, Indicator.MultipleObjectsReturned, ValidationError) as e: raise RestValidationError(str(e)) data = {'indicator_id': indicator.pk, 'import_success': True} return Response(data=data, status=http_status.HTTP_201_CREATED)
def project_editor_import_indicator(request, project_pk, parent_indicator_id): try: project = Project.objects.get(pk=project_pk) except Project.DoesNotExist: return HttpResponseNotFound() except Project.MultipleObjectsReturned: return HttpResponseBadRequest() user = request.user if not (user.is_superuser or user.can_import_results() and user.has_perm('rsr.change_project', project)): return HttpResponseForbidden() try: project.import_indicator(parent_indicator_id) except (Project.DoesNotExist, Project.MultipleObjectsReturned, Indicator.DoesNotExist, Indicator.MultipleObjectsReturned, ValidationError) as e: raise RestValidationError(e.message) return Response(data=None, status=http_status.HTTP_201_CREATED)
def create(self, validated_data): for field in READABLE_FIELDS: validated_data.pop(field, None) withdraw_address = validated_data.pop('withdraw_address') refund_address = validated_data.pop('refund_address') validated_data.pop('pair') withdraw_addr_list = Address.objects.filter( address=withdraw_address['address']) order = LimitOrder(pair=self.pair, order_book=self.order_book, **validated_data) if not withdraw_addr_list: w_address = Address(**withdraw_address) w_address.type = Address.WITHDRAW w_address.currency = order.withdraw_currency w_address.save() else: w_address = withdraw_addr_list[0] order.withdraw_address = w_address refund_addr_list = Address.objects.filter( address=refund_address['address']) if not refund_addr_list: r_address = Address(**refund_address) r_address.type = Address.REFUND r_address.currency = order.refund_currency r_address.save() else: r_address = refund_addr_list[0] order.refund_address = r_address try: order.save() # get post_save stuff in sync order.refresh_from_db() return order except ValidationError as e: raise RestValidationError({'non_field_errors': [e.message]})
def _get(self, request, pair_name=None): order = self._get_order(request, pair_name=pair_name) main_data = { 'pair': { 'base': order.pair.base.code, 'quote': order.pair.quote.code }, 'max_amount_base': order.get_amount_base_max(user_format=True), 'max_amount_quote': order.get_amount_quote_max(user_format=True), 'min_amount_base': order.get_amount_base_min(user_format=True), 'min_amount_quote': order.get_amount_quote_min(user_format=True), } try: order._validate_order_amount() data = OrderedDict({ 'amount_base': order.amount_base, 'amount_quote': order.amount_quote, 'timestamp': timezone.now().timestamp(), 'price': order.rate, **main_data }) except ValidationError as e: raise RestValidationError({'detail': e.message, **main_data}) return Response(data)
def validate_timed_on(self, value): if value <= timezone.localtime() + timedelta(seconds=5): raise RestValidationError( 'Set a reminder with an offset of atleast 10 seconds in the future' ) return value
def partial_update(self, request, *args, **kwargs): instance = self.get_object() user_admin = request.data.get('user_admin', '').lower() == 'true' try: user = User.objects.get_by_natural_key(instance.username) if request.user.pk == user.pk: raise RestValidationError({ api_settings.NON_FIELD_ERRORS_KEY: _('You cannot confirm changes to yourself') }) if user.is_superuser: raise RestValidationError({ api_settings.NON_FIELD_ERRORS_KEY: _('Super users cannot be edited') }) serializer_kwargs = {'instance': user} user.is_active = True user.save() user_existed = True except User.DoesNotExist: serializer_kwargs = {} user_existed = False if instance.prison: prisons = [instance.prison] else: prisons = None user_serializer = UserSerializer(data=dict( first_name=instance.first_name, last_name=instance.last_name, email=instance.email, username=instance.username, role=instance.role.name, prisons=prisons, user_admin=user_admin, ), context={ 'request': request, 'from_account_request': True }, **serializer_kwargs) user_serializer.is_valid() user = user_serializer.save() context = { 'username': user.username, 'service_name': instance.role.application.name.lower(), 'login_url': instance.role.login_url, } if user_existed: send_email( user.email, 'mtp_auth/user_moved.txt', capfirst( gettext( 'Your new %(service_name)s account is ready to use') % context), context=context, html_template='mtp_auth/user_moved.html', anymail_tags=['user-moved'], ) LogEntry.objects.log_action( user_id=request.user.pk, content_type_id=get_content_type_for_model(user).pk, object_id=user.pk, object_repr=gettext('Accepted account request for %(username)s') % { 'username': user.username, }, action_flag=CHANGE_LOG_ENTRY, ) instance.delete() return Response({})