def update_property(self, request, response, obj, property): """Update the property via a POST to the specific property, Typically this means we're putting up a BLOB""" if not hasattr(obj, property): raise BadRequest("%s has no attribute %s" % (obj.__class__.__name__, property)) val = request.POST.get(property) if hasattr(val, "file"): val = val.file.read() setattr(obj, property, val) if hasattr(obj, "_indexed_%s" % property) and val: setattr(obj, "_indexed_%s" % property, index_string(val.upper)) self.log.debug("Indexed: %s" % property) obj.modified_by = request.user obj.modified_at = datetime.utcnow() obj.put() self.log.info("Updated %s<%s>.%s" % (obj.__class__.__name__, obj.id, property)) # 204 is the proper status code but it does not allow the onload event # to fire in the browser, which expects a 200. Without the onload event # we cannot determine when an upload is complete. #response.set_status(204) return response
def update(self, obj, props, user, request): """ Update our object :param obj: Object to update :type obj: self.db_class :param props: A hash of properties to update :type props: hash :param user: The user making these changes :type user: User :param request: The request object :type request: botoweb.request.Request """ # Be sure they can acutally update this object if not request.user or not request.user.has_auth('PUT', obj.__class__.__name__): raise Forbidden("You may not update %ss!" % obj.__class__.__name__) self.log.debug("===========================") self.log.info("Update %s" % obj.__class__.__name__) for prop_name in props: # Make sure it's not a hidden prop and that # this user is allowed to write to it if not prop_name.startswith("_") and user.has_auth('PUT', obj.__class__.__name__, prop_name): prop_val = props[prop_name] self.log.debug("%s = %s" % (prop_name, prop_val)) if isinstance(obj, DynamoModel): # DynamoDB Objects get set as dict-values # Check to make sure the value isn't empty if prop_val: # Check to make sure it's a valid property if obj.find_property(prop_name): obj[prop_name] = prop_val else: self.log.error('Ignoring invalid property %s for object %s' % (prop_name, obj.__class__.__name__)) else: # If it's not there, we delete it del obj[prop_name] else: try: setattr(obj, prop_name, prop_val) except Exception, e: if prop_val != "": # If it was a nothing request, we ignore it self.log.exception(e) raise BadRequest("Bad value for %s: %s" % (prop_name, e)) if hasattr(obj, "_indexed_%s" % prop_name) and prop_val: setattr(obj, "_indexed_%s" % prop_name, index_string(prop_val)) self.log.debug("Indexed: %s" % prop_name)
def create(self, obj, user, request): """Create an object in the DB :param obj: an object with all the properties to create :type obj: botoweb.xmlize.ProxyObject OR dict :param user: The user doing the creation :type user: User """ now = datetime.utcnow() if isinstance(obj, dict): model_class = obj.get('__type__') prop_dict = obj else: model_class = obj.__model_class__ prop_dict = obj.__dict__ id = prop_dict.get("__id__") if model_class: newobj = model_class(id) else: newobj = self.db_class(id) # Make sure the user is auth'd to "POST" (aka. create) this type of object if not request.user or not request.user.has_auth('POST', newobj.__class__.__name__): raise Forbidden("You may not create new %ss!" % newobj.__class__.__name__) if not isinstance(newobj, self.db_class): raise BadRequest("Object you passed in isn't of a type this handler understands!") for prop in prop_dict: # Only allow them to set public properties, # and verify that they're allowed to set each one # Anything else they try to send is ignored if not prop.startswith("_") and (user.has_auth('PUT', newobj.__class__.__name__, prop) or user.has_auth('POST', newobj.__class__.__name__, prop)): prop_value = prop_dict[prop] if isinstance(newobj, DynamoModel): # DynamoDB Objects get set as dict-values # Check to make sure the value isn't empty if prop_value: # Check to make sure it's a valid property if newobj._properties.has_key(prop): newobj[prop] = prop_value else: self.log.error('Ignoring invalid property %s for object %s' % (prop, newobj.__class__.__name__)) else: # SimpleDB objects get set as attributes try: setattr(newobj, prop, prop_value) except Exception, e: raise BadRequest("Invalid value for %s" % prop) # Set an index, if it exists if hasattr(newobj, "_indexed_%s" % prop) and prop_value: setattr(newobj, "_indexed_%s" % prop, index_string(prop_value))
def update(self, obj, props, user, request): """ Update our object :param obj: Object to update :type obj: self.db_class :param props: A hash of properties to update :type props: hash :param user: The user making these changes :type user: User :param request: The request object :type request: botoweb.request.Request """ # Be sure they can acutally update this object if not request.user or not request.user.has_auth( 'PUT', obj.__class__.__name__): raise Forbidden("You may not update %ss!" % obj.__class__.__name__) self.log.debug("===========================") self.log.info("Update %s" % obj.__class__.__name__) for prop_name in props: # Make sure it's not a hidden prop and that # this user is allowed to write to it if not prop_name.startswith("_") and user.has_auth( 'PUT', obj.__class__.__name__, prop_name): prop_val = props[prop_name] self.log.debug("%s = %s" % (prop_name, prop_val)) try: setattr(obj, prop_name, prop_val) except Exception, e: if prop_val != "": # If it was a nothing request, we ignore it self.log.exception(e) raise BadRequest("Bad value for %s: %s" % (prop_name, e)) if hasattr(obj, "_indexed_%s" % prop_name) and prop_val: setattr(obj, "_indexed_%s" % prop_name, index_string(prop_val)) self.log.debug("Indexed: %s" % prop_name)
def update(self, obj, props, user, request): """ Update our object :param obj: Object to update :type obj: self.db_class :param props: A hash of properties to update :type props: hash :param user: The user making these changes :type user: User :param request: The request object :type request: botoweb.request.Request """ # Be sure they can acutally update this object if not request.user or not request.user.has_auth('PUT', obj.__class__.__name__): raise Forbidden("You may not update %ss!" % obj.__class__.__name__) self.log.debug("===========================") self.log.info("Update %s" % obj.__class__.__name__) for prop_name in props: # Make sure it's not a hidden prop and that # this user is allowed to write to it if not prop_name.startswith("_") and user.has_auth('PUT', obj.__class__.__name__, prop_name): prop_val = props[prop_name] self.log.debug("%s = %s" % (prop_name, prop_val)) try: setattr(obj, prop_name, prop_val) except Exception, e: if prop_val != "": # If it was a nothing request, we ignore it self.log.exception(e) raise BadRequest("Bad value for %s: %s" % (prop_name, e)) if hasattr(obj, "_indexed_%s" % prop_name) and prop_val: setattr(obj, "_indexed_%s" % prop_name, index_string(prop_val)) self.log.debug("Indexed: %s" % prop_name)
def build_query(self, params, query, user=None, show_deleted=False): """Build the query based on the parameters specified here, You must pass in the base query object to start with """ query_str = params.get("query", None) sort_by = params.get("sort_by", None) next_token = params.get("next_token", None) simple_query = params.get('q', None) properties = [p.name for p in query.model_class.properties(hidden=False)] if query_str: if query_str.startswith("["): try: filters = json.loads(query_str) except: raise BadRequest("Bad query string") for filter in filters: param_names = filter[0] prop_value = filter[2] if not isinstance(param_names, list): param_names = [param_names] for pnum, param_name in enumerate(param_names): # Handle the "auto indexing" # to make SDB searching case-insensitive if hasattr(self.db_class, "_indexed_%s" % param_name): param_name = "_indexed_%s" % param_name # Make sure the uppercased version is # also in the prop_value array # we have to add this to the accepted values, # not just replace, since they may have # multiple param_names in the list, and # not all of them may be indexed if isinstance(prop_value, list): for pv in prop_value: pv = index_string(pv) if not pv in prop_value: prop_value.append(pv) else: prop_value = [prop_value, index_string(prop_value)] param_names[pnum] = param_name # Allows a ['prop_name', 'sort', 'desc|asc'] if filter[1] == "sort": if filter[2] == "desc": param_names[0] = "-%s" % param_names[0] query.sort_by = param_names[0] # Allows a ['', 'limit', '1'] elif filter[1] == "limit": query.limit = int(filter[2]) # Allows a ['', 'offset', '25'] elif filter[1] == "offset": query.offset = int(filter[2]) else: param_filters = [] for param_name in param_names: param_filters.append("%s %s" % (param_name, filter[1])) query.filter(param_filters, prop_value) else: pass elif simple_query: if hasattr(self.db_class, '_indexed_name'): query.filter('_indexed_name like', '%%%s%%' % index_string(simple_query)) else: query.filter('name like', '%%%s%%' % simple_query) else: for filter in set(params.keys()): if filter in ["sort_by", "next_token"]: continue filter_value = params[filter] filter_args = filter.split(".") if len(filter_args) > 1: filter_cmp = filter_args[1] else: filter_cmp = "=" filter = filter_args[0] if len(filter_value) == 1: filter_value = filter_value[0] if filter_value: query.filter("%s %s " % (filter, filter_cmp), filter_value) if sort_by: query.order(sort_by) if next_token: query.next_token = urllib.unquote(next_token.strip()).replace(" ", "+") if not show_deleted and "deleted" in properties: query.filter("deleted =", [False, None]) # Allow deleted to be either not set or set to false return query