def update(self, request, *args, **kwargs): """ HTTP PUT item entry """ if self.conf.enable_perm_update_check: if not request.user.has_perm('%s.change_%s' % (self.app, self.model.lower())): return LuResponse(status=403, code=4003, message="Not Allow For `update` action!") if self.conf.enable_join_multiple_key_value_pair: data = self.get_body_data(request) # Join multiple key with delimiter for key in data: value = data.getlist(key) if len(value) > 1: data[ key] = self.conf.join_multiple_key_value_pair_delimiter.join( value) request = self.set_body_data(request, data) return super(LuModelViewSet, self).update(request, *args, **kwargs)
def handle_exception(self, exc): try: response = super(viewsets.ModelViewSet, self).handle_exception(exc) except ObjectDoesNotExist, err: msg = traceback.format_exc() if settings.DEBUG else str(err) lu_logger.warn(msg) response = LuResponse(status=400, code=status.LU_4004_NOT_FOUND, message=msg)
def retrieve(self, request, *args, **kwargs): """ HTTP GET item entry """ if self.conf.enable_perm_get_check: return LuResponse(status=403, code=4003, message='Not Allow For `get` action!') return super(LuModelViewSet, self).retrieve(request, *args, **kwargs)
def destroy(self, request, *args, **kwargs): """ HTTP DELETE item entry """ if self.conf.enable_perm_delete_check: if not request.user.has_perm('%s.delete_%s' % (self.app, self.model.lower())): return LuResponse(status=403, code=4003, message="Not Allow For `delete` action!") return super(LuModelViewSet, self).destroy(request, *args, **kwargs)
def partial_update(self, request, *args, **kwargs): """ HTTP PATCH item entry """ if self.conf.enable_perm_update_check: if not request.user.has_perm('%s.change_%s' % (self.app, self.model.lower())): return LuResponse(status=403, code=4003, message="Not Allow For `update` action!") return super(LuModelViewSet, self).partial_update(request, *args, **kwargs)
def dispatch(self, request, *args, **kwargs): """ Override dispatch """ # Attach the conf to request request.conf = self.conf try: response = super(LuModelViewSet, self).dispatch(request, *args, **kwargs) except Exception, err: log.error(ErrorLogObject(request, err)) response = LuResponse(code=status.LU_5000_SERVER_ERROR, message=str(err))
class LuExceptionHandler(object): """ Exception handler """ # Post exception handler def handle_exception(self, exc): try: response = super(viewsets.ModelViewSet, self).handle_exception(exc) except ObjectDoesNotExist, err: msg = traceback.format_exc() if settings.DEBUG else str(err) lu_logger.warn(msg) response = LuResponse(status=400, code=status.LU_4004_NOT_FOUND, message=msg) except (FieldError, ValidationError), err: msg = traceback.format_exc() if settings.DEBUG else str(err) lu_logger.warn(msg) response = LuResponse(status=400, code=status.LU_4007_INVALID_PARAM, message=msg)
msg = traceback.format_exc() if settings.DEBUG else str(err) lu_logger.warn(msg) response = LuResponse(status=400, code=status.LU_4004_NOT_FOUND, message=msg) except (FieldError, ValidationError), err: msg = traceback.format_exc() if settings.DEBUG else str(err) lu_logger.warn(msg) response = LuResponse(status=400, code=status.LU_4007_INVALID_PARAM, message=msg) except ImproperlyConfigured, err: msg = traceback.format_exc() if settings.DEBUG else str(err) lu_logger.warn(msg) response = LuResponse(status=500, code=status.LU_5001_SERVER_ERROR_CONFIGURED, message=msg) except (ValueError, IntegrityError), err: msg = traceback.format_exc() if settings.DEBUG else str(err) lu_logger.warn(msg) response = LuResponse(status=400, code=status.LU_4009_PARAM_TYPE_ERROR, message=msg) except AssertionError, err: msg = traceback.format_exc() if settings.DEBUG else str(err) lu_logger.error(msg) response = LuResponse(status=500, code=status.LU_5000_SERVER_ERROR, message=msg) except LuSQLNotAllowError, err: msg = traceback.format_exc() if settings.DEBUG else str(err)
def history(self, request, *args, **kwargs): """ Get Object history """ model = self.serializer_class.Meta.model admin_manager = admin.site._registry[model] object_id = kwargs.get('pk') # Check the response format _format = 'json' if request.query_params.get('format') == 'html': _format = 'html' # Check for the limit and offset limit = int( request.query_params.get(settings.LIMIT_FIELD, settings.DEFAULT_LIMIT)) offset = int(request.query_params.get(settings.OFFSET_FIELD, 0)) # Get the object obj = get_object_or_404(admin_manager.model.objects.using( self.conf.db).all(), pk=object_id) queryset = admin_manager.revision_manager.get_for_object(obj) # Get the versions versions = [] if request.query_params.get( 'version_id1') and request.query_params.get('version_id2'): version_id1 = request.query_params.get('version_id1') version_id2 = request.query_params.get('version_id2') if version_id1 > version_id2: # Compare always the newest one (#2) with the older one (#1) version_id1, version_id2 = version_id2, version_id1 version1 = get_object_or_404(queryset, pk=version_id1) version2 = get_object_or_404(queryset, pk=version_id2) versions.append(version2) versions.append(version1) else: # Get all version for the object if limit == int(settings.UNLIMIT): versions = admin_manager.revision_manager.get_for_object_reference( model, object_id).order_by('-pk') else: versions = admin_manager.revision_manager.get_for_object_reference( model, object_id).order_by('-pk')[offset:offset + limit + 1] # Response data data = [] if len(versions) == 0: return LuResponse(data=data) # For the first versions, show the original data if len(versions) == 1: data.append({ 'updated_by': versions[0].revision.user.username, 'updated_at': versions[0].revision.date_created, 'comment': versions[0].revision.comment, 'diff': json.loads(versions[0].serialized_data)[0]['fields'] }) return LuResponse(data=data) # Compare the diff for i, version in enumerate(versions): version2 = version version1 = versions[i + 1] compare_data, has_unfollowed_fields = admin_manager.compare( obj, version1, version2) version_diff = { 'updated_by': version2.revision.user.username, 'updated_at': version2.revision.date_created, 'comment': version2.revision.comment, 'diff': [] } if _format == 'html': # For the data in html part for item in compare_data: version_diff['diff'].append({ 'field': item['field'].name, 'diff': item['diff'] }) else: # For the data in json part version1_data = json.loads( version1.serialized_data)[0]['fields'] version2_data = json.loads( version2.serialized_data)[0]['fields'] version_diff['diff'] = diff(version1_data, version2_data, syntax='explicit', dump=True) # Append the version original data version_diff['before'] = {} version_diff['after'] = {} for action, item in json.loads(version_diff['diff']).items(): for key, value in item.items(): version_diff['before'][key] = version1_data[key] version_diff['after'][key] = version2_data[key] data.append(version_diff) if i == len(versions) - 2: break return LuResponse(data=data)
def create(self, request, *args, **kwargs): """ HTTP POST item entry """ if self.conf.enable_perm_create_check: if not request.user.has_perm('%s.add_%s' % (self.app, self.model.lower())): return LuResponse(status=403, code=4003, message="Not Allow For `create` action!") # Check if do SQL injection first sql = request.data.get(settings.SQL_TEXT, '') search_condition = request.data.get(settings.SQL_SEARCH_CONDITION, '') if sql or search_condition: sql_param = request.data.get(settings.SQL_PARAM, []) sql_param = [ item for item in sql_param.split(self.conf.sql_param_delimiter) ] if sql_param else sql_param # For the list item sql_param = map( lambda x: request.data.getlist(x) if x.endswith('[]') else request.data.get(x, x), sql_param) # Convert json data if need, this would workable for type like mysql json field sql_param = map( lambda x: json.dumps(x) if isinstance(x, dict) or isinstance(x, list) else x, sql_param) allow_sql = self.conf.sql_injection_allow map_sql = self.conf.sql_injection_map conf_sql = copy.deepcopy(LuConf.sql_injection_conf) conf_sql.update(copy.deepcopy(self.conf.sql_injection_conf)) # Process limit and offset limit = int( request.data.get(settings.LIMIT_FIELD, settings.DEFAULT_LIMIT)) offset = int(request.data.get(settings.OFFSET_FIELD, 0)) # Process response field response_field = request.data.get(settings.RESPONSE_FIELD, None) # Process for the runtime configuration for key, conf in conf_sql.items(): try: if conf.mode == LuSQLConf.MODE_RUNTIME: conf.value = eval(conf.value) except Exception, err: lu_logger.warn(str(err)) # Use the default sql if no sql specify sql = sql if sql else 'get_%s' % self.model.lower() data = LuSQL(self.queryset._db, sql, sql_param, allow_sql, map_sql, search_condition, conf_sql, limit, offset, response_field, request).execute() count = data.pop(-1) if data else None _pagination = { 'count': count, 'previous': pagination.get_previous_link(request, limit, offset, count), 'next': pagination.get_next_link(request, limit, offset, count) } return LuResponse(data=data, pagination=_pagination)
# Works for SQL: SELECT item1, count(item1) FROM table1 WHERE (Condition) GROUP BY item1 ORDER BY count(item1) full_search_type_list = request.query_params.get( settings.SEARCH_TYPE, self.SEARCH_TYPE.contain).split(settings.SEARCH_TYPE_DELIMITER) if set(full_search_type_list) & set([ self.SEARCH_TYPE.count, self.SEARCH_TYPE.max, self.SEARCH_TYPE.min, self.SEARCH_TYPE.avg ]): # Put aggregate search type in the last, as we may group by multiple fields if full_search_type_list[-1] not in [ self.SEARCH_TYPE.count, self.SEARCH_TYPE.max, self.SEARCH_TYPE.min, self.SEARCH_TYPE.avg ]: return LuResponse( code=status.LU_4007_INVALID_PARAM, message= 'Please put aggregate func type in the last of `lu_search_type`!' ) search_field = request.query_params.get(settings.SEARCH_KEY) if not search_field: return LuResponse( code=status.LU_4010_PARAM_NEEDED, message= 'Please specify param `lu_search_field` for the search field!' ) group_field = request.query_params.get(settings.GROUP_PARAM) if not group_field: return LuResponse(