def obj_create(self, bundle, request=None, **kwargs): try: email = bundle.data['email'] salt = bundle.data['salt'] password_hash = bundle.data['password_hash'] except KeyError: raise exceptions.BadRequest('Specify email, salt and password_hash.') try: salt = crypto.from_string(salt) except (ValueError, TypeError, ): raise exceptions.BadRequest('Incorrect salt value.') try: password_hash = crypto.from_string(password_hash) except (ValueError, TypeError, ): raise exceptions.BadRequest('Incorrect password_hash value.') try: bundle.obj = self._meta.object_class.objects.create( email = email, username = email, password = crypto.make_password(password_hash, salt), ) except db.IntegrityError: raise exceptions.BadRequest('There\'s already user with this email.') except (ValueError, TypeError, ): raise exceptions.BadRequest('Invalid data provided (mismatched type).') models.UserProfile.objects.create( user=bundle.obj, ) bundle.data = {} # To prevent creation data e.g. `password_hash` population. return bundle
def _wrap_request(self, request, fun): type_map = getattr(self._meta, 'polymorphic', {}) if not type_map: return fun() object_type = self._get_object_type(request) if not object_type: # Polymorphic resources are enabled, but # nothing is passed, so set it to a default try: object_type = self._get_type_from_class( type_map, self._meta.object_class) except KeyError: raise tastypie_exceptions.BadRequest("Invalid object type.") if object_type not in type_map: raise tastypie_exceptions.BadRequest("Invalid object type.") resource = type_map[object_type](self._meta.api_name) # Optimization if resource._meta.object_class is self._meta.object_class: return fun() return self._wrap_polymorphic(resource, fun)
def get_limit(self): # Mostly just a copy of parent get_limit, but using # API_DETAIL_LIMIT_PER_PAGE and allowing limit to be 0. limit = self.request_data.get('limit', self.limit) if limit is None: limit = getattr(settings, 'API_DETAIL_LIMIT_PER_PAGE', 20) try: limit = int(limit) except ValueError: raise exceptions.BadRequest( "Invalid limit '%s' provided. Please provide a positive integer." % limit) if limit < 0: raise exceptions.BadRequest( "Invalid limit '%s' provided. Please provide a positive integer >= 0." % limit) # We allow limit to be 0 if self.max_limit and limit > self.max_limit: return self.max_limit return limit
def hydrate(self, bundle): store = self.get_task_store(bundle.request) for key, field_instance in store.client.config.get_udas().items(): value = bundle.data.get(key, None) if value and isinstance(field_instance, DateField): try: setattr(bundle.obj, key, parse(value)) except (TypeError, ValueError): raise exceptions.BadRequest( "Invalid date provided for field %s: " % ( key, value, )) elif value: setattr(bundle.obj, key, value) try: depends = [] for task_id in bundle.data.get('depends', []): depends.append(uuid.UUID(task_id)) bundle.data['depends'] = depends except (TypeError, ValueError): raise exceptions.BadRequest( "Invalid task IDs provided for field depends: %s" % (bundle.data.get('depends'))) return bundle
def get_limit(self): if 'l' not in self.request_data: return super(Paginator, self).get_limit() limit = self.request_data['l'] try: limit = int(self.request_data['l']) except ValueError: raise exceptions.BadRequest("Invalid limit '%s' provided. Please provide a positive integer.", limit) if limit < 0: raise exceptions.BadRequest("Invalid limit '%s' provided. Please provide an integer >= 0.", limit) return limit
def get_offset(self): if 'o' not in self.request_data: return super(Paginator, self).get_offset() offset = self.request_data['o'] try: offset = int(offset) except ValueError: raise exceptions.BadRequest("Invalid offset '%s' provided. Please provide an integer.", offset) if offset < 0: raise exceptions.BadRequest("Invalid offset '%s' provided. Please provide an integer >= 0.", offset) return offset
def obj_get(self, bundle, **kwargs): credentials = (bundle.request.GET and bundle.request.GET.dict()) or (bundle.request.body and self.deserialize(bundle.request, bundle.request.body, format=bundle.request.META.get('CONTENT_TYPE', 'application/json'))) or {} try: object_list = self.get_object_list(bundle.request).filter(**kwargs) stringified_kwargs = ', '.join(["%s=%s" % (k, v) for k, v in kwargs.items()]) if len(object_list) <= 0: raise self._meta.object_class.DoesNotExist("Couldn't find an instance of '%s' which matched '%s'." % (self._meta.object_class.__name__, stringified_kwargs)) elif len(object_list) > 1: raise MultipleObjectsReturned("More than '%s' matched '%s'." % (self._meta.object_class.__name__, stringified_kwargs)) bundle.obj = object_list[0] if self.is_authenticating(bundle.obj, credentials, bundle.request): auth.authenticate( request=bundle.request, user=bundle.obj, salt=credentials['salt'], one_time_salt=credentials['one_time_salt'], data=credentials.get('data'), password_hash=credentials['password_hash'], ) one_time_salt = self.rotate_one_time_salt(bundle.request) if not bundle.request.user.is_authenticated(): self.unauthorized_result(bundle=bundle) self.authorized_read_detail(object_list, bundle) return bundle.obj except ValueError: raise exceptions.BadRequest('Invalid resource lookup data provided (mismatched type).')
def obj_create(self, bundle, store, **kwargs): with git_checkpoint(store, "Creating Task", sync=True): if not bundle.data['description']: raise exceptions.BadRequest( "You must specify a description for each task.") bundle.obj = self.get_empty_task(bundle.request) bundle = self.full_hydrate(bundle) data = bundle.obj.get_json() for k in self.SYNTHETIC_FIELDS: if k in data: data.pop(k, None) for k, v in TaskwTask.FIELDS.items(): if k in data and v.read_only: data.pop(k, None) for k, v in data.items(): if not v: data.pop(k) bundle.obj = Task( store.client.task_add(**data), store=store, ) store.log_message( "New task created: %s.", bundle.obj.get_json(), ) return bundle
def is_authenticating(self, user, credentials, request): ''' Checks authentication credentials for validity and prepares them for authentication. @returns `True` if somebody tries to authenticate, `False` otherwise. ''' if not set(credentials.keys()).issuperset(['one_time_salt', 'password_hash', 'salt', ]): return False try: credentials['salt'] = crypto.from_string(credentials['salt']) except (ValueError, TypeError, ): raise exceptions.BadRequest('Incorrect salt value.') try: credentials['one_time_salt'] = crypto.from_string(credentials['one_time_salt']) except (ValueError, TypeError, ): raise exceptions.BadRequest('Incorrect one_time_salt value.') try: credentials['password_hash'] = crypto.from_string(credentials['password_hash']) except (ValueError, TypeError, ): raise exceptions.BadRequest('Incorrect password_hash value.') return True
def full_hydrate(self, bundle): if not bundle.request.user.is_authenticated(): self.unauthorized_result(bundle=bundle) bundle = super(User, self).full_hydrate(bundle) bundle.obj.profile.data = bundle.data['data'] fields = set(bundle.data.keys()) if fields.intersection(self.PASSWORD_CHANGING_FIELDS): if fields.issuperset(self.PASSWORD_CHANGING_FIELDS): try: password_hash = crypto.from_string(bundle.data['new_password_hash']) except (ValueError, TypeError, ): raise exceptions.BadRequest('Incorrect new_password_hash value.') try: salt = crypto.from_string(bundle.data['new_salt']) except (ValueError, TypeError, ): raise exceptions.BadRequest('Incorrect new_salt value.') bundle.obj.password = crypto.make_password(password_hash, salt) else: raise exceptions.BadRequest('Both new_password_hash and new_salt fields should be presented.') bundle.data = {} # To prevent update data e.g. `password_hash` population. return bundle
def obj_update(self, bundle, store, **kwargs): with git_checkpoint(store, "Updating Task"): if bundle.data['uuid'] != kwargs['pk']: raise exceptions.BadRequest( "Changing the UUID of an existing task is not possible." ) elif not bundle.data['description']: raise exceptions.BadRequest( "You must specify a description for each task." ) bundle.data.pop('id', None) serialized = Task.from_serialized(bundle.data).get_safe_json() serialized['uuid'] = kwargs['pk'] store.client.task_update(serialized) store.log_message( "Task %s updated: %s.", kwargs['pk'], serialized ) bundle.obj = Task(store.client.get_task(uuid=kwargs['pk'])[1]) return bundle
def get_offset(self): offset = self.offset if 'offset' in self.request_data: offset = self.request_data['offset'] try: offset = bson.ObjectId(offset) except (TypeError, errors.InvalidId): try: offset = int(offset) except ValueError: raise exceptions.BadRequest( "Invalid offset '%s' provided. Please provide an ObjectId or an integer." % offset) if isinstance(offset, int) and offset < 0: raise exceptions.BadRequest( "Invalid integer offset '%s' provided. Please provide a non-negative integer." % offset) return offset
def obj_create(self, bundle, store, **kwargs): with git_checkpoint(store, "Creating Task"): if not bundle.data['description']: raise exceptions.BadRequest( "You must specify a description for each task." ) safe_json = Task.from_serialized(bundle.data).get_safe_json() bundle.obj = Task( store.client.task_add(**safe_json) ) store.log_message( "New task created: %s.", safe_json ) return bundle
def obj_update(self, bundle, store, **kwargs): with git_checkpoint(store, "Updating Task", sync=True): if bundle.data['uuid'] != kwargs['pk']: raise exceptions.BadRequest( "Changing the UUID of an existing task is not possible.") elif not bundle.data['description']: raise exceptions.BadRequest( "You must specify a description for each task.") original = store.client.get_task(uuid=kwargs['pk'])[1] if not original: raise exceptions.NotFound() bundle.obj = self.get_empty_task(bundle.request) bundle = self.full_hydrate(bundle) data = bundle.obj.get_json() for k in json.loads(bundle.request.body).keys(): v = data.get(k) if ((k in original.FIELDS and original.FIELDS[k].read_only) or k in self.SYNTHETIC_FIELDS): continue original[k] = v changes = original.get_changes(keep=True) store.client.task_update(original) store.log_message( "Task %s updated: %s.", kwargs['pk'], changes, ) bundle.obj = Task( store.client.get_task(uuid=kwargs['pk'])[1], store=store, ) return bundle
def get_limit(self): limit = getattr(settings, 'API_LIMIT_PER_PAGE', 20) if 'limit' in self.request_data: limit = self.request_data['limit'] elif self.limit is not None: limit = self.limit try: limit = int(limit) except ValueError: raise exceptions.BadRequest( "Invalid limit '%s' provided. Please provide an integer." % limit) return limit
def resource_from_data(self, fk_resource, data, request=None, related_obj=None, related_name=None): data = dict_strip_unicode_keys(data) type_map = self.to_class._meta.polymorphic object_type = data.get('resource_type', None) if object_type not in type_map: raise tastypie_exceptions.BadRequest("Invalid object type.") resource = type_map[object_type]() fk_bundle = resource.build_bundle( data=data, request=request ) if related_obj: fk_bundle.related_obj = related_obj fk_bundle.related_name = related_name return resource.full_hydrate(fk_bundle)
def get_slice(self, limit, offset): if isinstance(offset, int): if limit < 0: raise exceptions.BadRequest( "Invalid limit '%s' provided. Please provide a non-negative integer." % limit) return super(Paginator, self).get_slice(limit, offset) # TODO: Very very inefficient, optimize! if limit < 0: iterator = reversed(self.objects) limit = -limit else: iterator = self.objects.__iter__() if limit == 0: limit = None iterator = itertools.dropwhile(lambda obj: obj.pk != offset, iterator) iterator = itertools.islice(iterator, limit) return iterator
def build_filters(self, *args, **kwargs): filters = super(User, self).build_filters(*args, **kwargs) if not filters: raise exceptions.BadRequest('Specify user\'s email.') return filters
def build_filters(self, filters=None): if not filters or 'contains' not in filters or filters['contains'] in ' ': # Checks for empty "contains" filter and space-only filter simultaneously. raise exceptions.BadRequest('Specify some string for "contains" filter.') return filters
def obj_delete_list(self, bundle, store, **kwargs): raise exceptions.BadRequest()