def worker(self, type): try: from datetime import datetime manager = ObjectManager( database_manager=self.database_manager ) # TODO: Replace when object api is updated object_list = self.object_manager.get_objects_by_type( type.public_id) matches = type.matches for obj in object_list: for field in obj.fields: if [x for x in matches if x['name'] == field['name']]: # name = field['name'] value = field['value'] if value: if isinstance(value, datetime): field['value'] = value else: field['value'] = datetime.strptime( value, '%Y-%m-%dT%H:%M:%S.%fZ') manager.update(public_id=obj.public_id, data=obj, user=None, permission=None) except (ObjectManagerGetError, ObjectManagerUpdateError, CMDBError) as err: LOGGER.error(err.message)
def from_database(self, database_manager, user: UserModel, permission: AccessControlPermission): """Get all objects from the collection""" manager = ObjectManager(database_manager=database_manager) dep_object_manager = CmdbObjectManager( database_manager=database_manager) try: _params = self.export_config.parameters _result: List[CmdbObject] = manager.iterate( filter=_params.filter, sort=_params.sort, order=_params.order, limit=0, skip=0, user=user, permission=permission).results self.data = RenderList( object_list=_result, request_user=user, database_manager=database_manager, object_manager=dep_object_manager, ref_render=True).render_result_list(raw=False) except CMDBError as e: return abort(400, e)
def get_objects(params: CollectionParameters, request_user: UserModel): manager = ObjectManager(database_manager=current_app.database_manager) view = params.optional.get('view', 'native') if _fetch_only_active_objs(): if isinstance(params.filter, dict): filter_ = params.filter params.filter = [{'$match': filter_}] params.filter.append({'$match': {'active': {"$eq": True}}}) elif isinstance(params.filter, list): params.filter.append({'$match': {'active': {"$eq": True}}}) try: iteration_result: IterationResult[CmdbObject] = manager.iterate( filter=params.filter, limit=params.limit, skip=params.skip, sort=params.sort, order=params.order, user=request_user, permission=AccessControlPermission.READ) if view == 'native': object_list: List[dict] = [ object_.__dict__ for object_ in iteration_result.results ] api_response = GetMultiResponse(object_list, total=iteration_result.total, params=params, url=request.url, model=CmdbObject.MODEL, body=request.method == 'HEAD') elif view == 'render': rendered_list = RenderList( object_list=iteration_result.results, request_user=request_user, database_manager=current_app.database_manager, object_manager=object_manager, ref_render=True).render_result_list(raw=True) api_response = GetMultiResponse(rendered_list, total=iteration_result.total, params=params, url=request.url, model=Model('RenderResult'), body=request.method == 'HEAD') else: return abort(401, 'No possible view parameter') except ManagerIterationError as err: return abort(400, err.message) except ManagerGetError as err: return abort(404, err.message) return api_response.make_response()
def get_corresponding_object_logs(public_id: int, request_user: UserModel): try: selected_log = log_manager.get(public_id=public_id) ObjectManager(database_manager=database_manager).get( selected_log.object_id, user=request_user, permission=AccessControlPermission.READ) query = { 'log_type': CmdbObjectLog.__name__, 'object_id': selected_log.object_id, 'action': LogAction.EDIT.value, '$nor': [{ 'public_id': public_id }] } logs = log_manager.iterate(filter=query, limit=0, skip=0, order=1, sort='public_id') corresponding_logs = [CmdbObjectLog.to_json(_) for _ in logs.results] except ManagerGetError as err: return abort(404, err.message) except AccessDeniedError as err: return abort(403, err.message) except ManagerIterationError as err: return abort(400, err.message) if len(corresponding_logs) < 1: return make_response(corresponding_logs, 204) return make_response(corresponding_logs)
def get_logs_by_object(object_id: int, params: CollectionParameters, request_user: UserModel): manager = CmdbLogManager(database_manager=database_manager) try: ObjectManager(database_manager=database_manager).get( object_id, user=request_user, permission=AccessControlPermission.READ) body = request.method == 'HEAD' iteration_result = manager.iterate(public_id=object_id, filter=params.filter, limit=params.limit, skip=params.skip, sort=params.sort, order=params.order) logs = [CmdbObjectLog.to_json(_) for _ in iteration_result.results] api_response = GetMultiResponse(logs, total=iteration_result.total, params=params, url=request.url, model=CmdbMetaLog.MODEL, body=body) except ManagerGetError as err: return abort(404, err.message) except AccessDeniedError as err: return abort(403, err.message) except ManagerIterationError as err: return abort(400, err.message) return api_response.make_response()
def get_log(public_id: int, request_user: UserModel): manager = CmdbLogManager(database_manager=database_manager) try: selected_log: CmdbObjectLog = manager.get(public_id=public_id) ObjectManager(database_manager=database_manager).get( selected_log.object_id, user=request_user, permission=AccessControlPermission.READ) except ManagerGetError as err: return abort(404, err.message) except AccessDeniedError as err: return abort(403, err.message) return make_response(selected_log)
def get_unstructured_objects(public_id: int, request_user: UserModel): """ HTTP `GET`/`HEAD` route for a multi resources which are not formatted according the type structure. Args: public_id (int): Public ID of the type. Raises: ManagerGetError: When the selected type does not exists or the objects could not be loaded. Returns: GetListResponse: Which includes the json data of multiple objects. """ manager = ObjectManager(database_manager=current_app.database_manager) try: type_instance: TypeModel = type_manager.get(public_id=public_id) objects: List[CmdbObject] = manager.iterate({ 'type_id': public_id }, limit=0, skip=0, sort='public_id', order=1, user=request_user).results except ManagerGetError as err: return abort(400, err.message) type_fields = sorted([field.get('name') for field in type_instance.fields]) unstructured: List[dict] = [] for object_ in objects: object_fields = [field.get('name') for field in object_.fields] if sorted(object_fields) != type_fields: unstructured.append(object_.__dict__) api_response = GetListResponse(unstructured, url=request.url, model=CmdbObject.MODEL, body=request.method == 'HEAD') return api_response.make_response()
def update_unstructured_objects(public_id: int, request_user: UserModel): """ HTTP `PUT`/`PATCH` route for a multi resources which will be formatted based on the TypeModel Args: public_id (int): Public ID of the type. Raises: ManagerGetError: When the type with the `public_id` was not found. ManagerUpdateError: When something went wrong during the update. Returns: UpdateMultiResponse: Which includes the json data of multiple updated objects. """ manager = ObjectManager(database_manager=current_app.database_manager) try: update_type_instance = type_manager.get(public_id) type_fields = update_type_instance.fields objects_by_type = manager.iterate({ 'type_id': public_id }, limit=0, skip=0, sort='public_id', order=1, user=request_user).results for obj in objects_by_type: incorrect = [] correct = [] obj_fields = obj.get_all_fields() for t_field in type_fields: name = t_field["name"] for field in obj_fields: if name == field["name"]: correct.append(field["name"]) else: incorrect.append(field["name"]) removed_type_fields = [ item for item in incorrect if not item in correct ] for field in removed_type_fields: manager.update_many( query={'public_id': obj.public_id}, update={'$pull': { 'fields': { "name": field } }}) objects_by_type = manager.iterate({ 'type_id': public_id }, limit=0, skip=0, sort='public_id', order=1, user=request_user).results for obj in objects_by_type: for t_field in type_fields: name = t_field["name"] value = None if [ item for item in obj.get_all_fields() if item["name"] == name ]: continue if "value" in t_field: value = t_field["value"] manager.update_many(query={'public_id': obj.public_id}, update={ '$addToSet': { 'fields': { "name": name, "value": value } } }) except ManagerUpdateError as err: return abort(400, err.message) api_response = UpdateMultiResponse([], url=request.url, model=CmdbObject.MODEL) return api_response.make_response()
def update_object_state(public_id: int, request_user: UserModel): if isinstance(request.json, bool): state = request.json else: return abort(400) try: manager = ObjectManager(database_manager=current_app.database_manager, event_queue=current_app.event_queue) founded_object = manager.get(public_id=public_id, user=request_user, permission=AccessControlPermission.READ) except ObjectManagerGetError as err: LOGGER.error(err) return abort(404, err.message) if founded_object.active == state: return make_response(False, 204) try: founded_object.active = state manager.update(public_id, founded_object, user=request_user, permission=AccessControlPermission.UPDATE) except AccessDeniedError as err: return abort(403, err.message) except ObjectManagerUpdateError as err: LOGGER.error(err) return abort(500, err.message) # get current object state try: current_type_instance = type_manager.get(founded_object.get_type_id()) current_object_render_result = CmdbRender( object_instance=founded_object, object_manager=object_manager, type_instance=current_type_instance, render_user=request_user).result() except ObjectManagerGetError as err: LOGGER.error(err) return abort(404) except RenderError as err: LOGGER.error(err) return abort(500) try: # generate log change = {'old': not state, 'new': state} log_data = { 'object_id': public_id, 'version': founded_object.version, 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'render_state': json.dumps(current_object_render_result, default=default).encode('UTF-8'), 'comment': 'Active status has changed', 'changes': change, } log_manager.insert(action=LogAction.ACTIVE_CHANGE, log_type=CmdbObjectLog.__name__, **log_data) except (CMDBError, LogManagerInsertError) as err: LOGGER.error(err) api_response = UpdateSingleResponse(result=founded_object.__dict__, url=request.url, model=CmdbObject.MODEL) return api_response.make_response()
def update_object(public_id: int, data: dict, request_user: UserModel): object_ids = request.args.getlist('objectIDs') if len(object_ids) > 0: object_ids = list(map(int, object_ids)) else: object_ids = [public_id] manager = ObjectManager(database_manager=current_app.database_manager, event_queue=current_app.event_queue) results: [dict] = [] failed = [] for obj_id in object_ids: # deep copy active_state = request.get_json().get('active', None) new_data = copy.deepcopy(data) try: current_object_instance = manager.get( obj_id, user=request_user, permission=AccessControlPermission.READ) current_type_instance = type_manager.get( current_object_instance.get_type_id()) current_object_render_result = CmdbRender( object_instance=current_object_instance, object_manager=object_manager, type_instance=current_type_instance, render_user=request_user).result() update_comment = '' try: # check for comment new_data['public_id'] = obj_id new_data[ 'creation_time'] = current_object_instance.creation_time new_data['author_id'] = current_object_instance.author_id new_data[ 'active'] = active_state if active_state else current_object_instance.active if 'version' not in data: new_data['version'] = current_object_instance.version old_fields = list( map( lambda x: {k: v for k, v in x.items() if k in ['name', 'value']}, current_object_render_result.fields)) new_fields = data['fields'] for item in new_fields: for old in old_fields: if item['name'] == old['name']: old['value'] = item['value'] new_data['fields'] = old_fields update_comment = data['comment'] del new_data['comment'] except (KeyError, IndexError, ValueError): update_comment = '' except TypeError as err: LOGGER.error( f'Error: {str(err.args)} Object: {json.dumps(new_data, default=default)}' ) failed.append( ResponseFailedMessage(error_message=str(err.args), status=400, public_id=obj_id, obj=new_data).to_dict()) continue # update edit time new_data['last_edit_time'] = datetime.now(timezone.utc) new_data['editor_id'] = request_user.public_id update_object_instance = CmdbObject( **json.loads(json.dumps(new_data, default=json_util.default), object_hook=object_hook)) # calc version changes = current_object_instance / update_object_instance if len(changes['new']) == 1: new_data['version'] = update_object_instance.update_version( update_object_instance.VERSIONING_PATCH) elif len(changes['new']) == len(update_object_instance.fields): new_data['version'] = update_object_instance.update_version( update_object_instance.VERSIONING_MAJOR) elif len( changes['new']) > (len(update_object_instance.fields) / 2): new_data['version'] = update_object_instance.update_version( update_object_instance.VERSIONING_MINOR) else: new_data['version'] = update_object_instance.update_version( update_object_instance.VERSIONING_PATCH) manager.update(obj_id, new_data, request_user, AccessControlPermission.UPDATE) results.append(new_data) # Generate log entry try: log_data = { 'object_id': obj_id, 'version': update_object_instance.get_version(), 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'comment': update_comment, 'changes': changes, 'render_state': json.dumps(update_object_instance, default=default).encode('UTF-8') } log_manager.insert(action=LogAction.EDIT, log_type=CmdbObjectLog.__name__, **log_data) except (CMDBError, LogManagerInsertError) as err: LOGGER.error(err) except AccessDeniedError as err: LOGGER.error(err) return abort(403) except ObjectManagerGetError as err: LOGGER.error(err) failed.append( ResponseFailedMessage(error_message=err.message, status=400, public_id=obj_id, obj=new_data).to_dict()) continue except (ManagerGetError, ObjectManagerUpdateError) as err: LOGGER.error(err) failed.append( ResponseFailedMessage(error_message=err.message, status=404, public_id=obj_id, obj=new_data).to_dict()) continue except (CMDBError, RenderError) as e: LOGGER.warning(e) failed.append( ResponseFailedMessage(error_message=str(e.__repr__), status=500, public_id=obj_id, obj=new_data).to_dict()) continue api_response = UpdateMultiResponse(results=results, failed=failed, url=request.url, model=CmdbObject.MODEL) return api_response.make_response()