def delete_job(public_id: int, request_user: UserModel): try: try: job_instance = exportd_manager.get_job(public_id) log_params = { 'job_id': job_instance.get_public_id(), 'state': True, 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'event': LogAction.DELETE.name, 'message': '', } log_manager.insert_log(action=LogAction.DELETE, log_type=ExportdJobLog.__name__, **log_params) except (ExportdJobManagerGetError, LogManagerInsertError) as err: LOGGER.error(err) return abort(404) ack = exportd_manager.delete_job(public_id=public_id, request_user=request_user) except ExportdJobManagerDeleteError: return abort(400) except CMDBError: return abort(500) resp = make_response(ack) return resp
def update_user(public_id: int, data: dict): """ HTTP `PUT`/`PATCH` route for update a single user resource. Args: public_id (int): Public ID of the updatable user. data (UserModel.SCHEMA): New user data to update. Raises: ManagerGetError: When the user with the `public_id` was not found. ManagerUpdateError: When something went wrong during the update. Returns: UpdateSingleResponse: With update result of the new updated user. """ user_manager: UserManager = UserManager( database_manager=current_app.database_manager) try: user = UserModel.from_data(data=data) user_manager.update(public_id=PublicID(public_id), user=user) api_response = UpdateSingleResponse(result=UserModel.to_dict(user), url=request.url, model=UserModel.MODEL) except ManagerGetError as err: return abort(404, err.message) except ManagerUpdateError as err: return abort(400, err.message) return api_response.make_response()
def worker(job: ExportdJob, request_user: UserModel): from flask import make_response as make_res from cmdb.exportd.exporter_base import ExportdManagerBase from cmdb.event_management.event import Event try: event = Event( "cmdb.exportd.run_manual", { "id": job.get_public_id(), "user_id": request_user.get_public_id(), "event": 'manuel' }) content = ExportdManagerBase(job, object_manager, log_manager, event).execute( request_user.public_id, request_user.get_display_name(), False) response = make_res(content.data, content.status) response.headers['Content-Type'] = '%s; charset=%s' % ( content.mimetype, content.charset) return response except Exception as err: LOGGER.error(err) return abort(404)
def delete_object(public_id: int, request_user: UserModel): try: current_object_instance = object_manager.get_object(public_id) current_type_instance = object_manager.get_type( 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() except ObjectManagerGetError as err: LOGGER.error(err) return abort(404) except RenderError as err: LOGGER.error(err) return abort(500) try: ack = object_manager.delete_object( public_id=public_id, user=request_user, permission=AccessControlPermission.DELETE) except ObjectManagerGetError as err: return abort(400, err.message) except AccessDeniedError as err: return abort(403, err.message) except ObjectDeleteError: return abort(400) except CMDBError: return abort(500) try: # generate log log_data = { 'object_id': public_id, 'version': current_object_render_result.object_information['version'], 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'comment': 'Object was deleted', 'render_state': json.dumps(current_object_render_result, default=default).encode('UTF-8') } log_manager.insert(action=LogAction.DELETE, log_type=CmdbObjectLog.__name__, **log_data) except (CMDBError, LogManagerInsertError) as err: LOGGER.error(err) resp = make_response(ack) return resp
def change_user_password(public_id: int): """ HTTP `PATCH` route for updating a single user password. Args: public_id (int): Public ID of the user. Raises: ManagerGetError: When the user with the `public_id` was not found. ManagerUpdateError: When something went wrong during the updated. Returns: UpdateSingleResponse: User with new password """ user_manager: UserManager = UserManager( database_manager=current_app.database_manager) security_manager: SecurityManager = SecurityManager( database_manager=current_app.database_manager) try: user = user_manager.get(public_id=public_id) password = security_manager.generate_hmac(request.json.get('password')) user.password = password user_manager.update(public_id=PublicID(public_id), user=user) api_response = UpdateSingleResponse(result=UserModel.to_dict(user), url=request.url, model=UserModel.MODEL) except ManagerGetError as err: return abort(404, err.message) except ManagerUpdateError as err: return abort(400, err.message) return api_response.make_response()
def delete_user(public_id: int): """ HTTP `DELETE` route for delete a single user resource. Args: public_id (int): Public ID of the user. Raises: ManagerGetError: When the user with the `public_id` was not found. ManagerDeleteError: When something went wrong during the deletion. Returns: DeleteSingleResponse: Delete result with the deleted user as data. """ user_manager: UserManager = UserManager( database_manager=current_app.database_manager) try: deleted_group = user_manager.delete(public_id=PublicID(public_id)) api_response = DeleteSingleResponse( raw=UserModel.to_dict(deleted_group), model=UserModel.MODEL) except ManagerGetError as err: return abort(404, err.message) except ManagerDeleteError as err: return abort(404, err.message) return api_response.make_response()
def insert_user(data: dict): """ HTTP `POST` route for insert a single user resource. Args: data (UserModel.SCHEMA): Insert data of a new user. Raises: ManagerGetError: If the inserted user could not be found after inserting. ManagerInsertError: If something went wrong during insertion. Returns: InsertSingleResponse: Insert response with the new user and its public_id. """ user_manager: UserManager = UserManager( database_manager=current_app.database_manager) security_manager: SecurityManager = SecurityManager( database_manager=current_app.database_manager) try: data['password'] = security_manager.generate_hmac(data['password']) result_id: PublicID = user_manager.insert(data) user = user_manager.get(public_id=result_id) except ManagerGetError as err: return abort(404, err.message) except ManagerInsertError as err: return abort(400, err.message) api_response = InsertSingleResponse(result_id=result_id, raw=UserModel.to_dict(user), url=request.url, model=UserModel.MODEL) return api_response.make_response(prefix='users')
def delete_object(self, public_id: int, user: UserModel, permission: AccessControlPermission = None): type_id = self.get_object(public_id=public_id).type_id type_ = self._type_manager.get(type_id) if not type_.active: raise AccessDeniedError( f'Objects cannot be removed because type `{type_.name}` is deactivated.' ) verify_access(type_, user, permission) try: if self._event_queue: event = Event( "cmdb.core.object.deleted", { "id": public_id, "type_id": self.get_object(public_id).get_type_id(), "user_id": user.get_public_id(), "event": 'delete' }) self._event_queue.put(event) ack = self._delete(CmdbObject.COLLECTION, public_id) return ack except (CMDBError, Exception): raise ObjectDeleteError(msg=public_id)
def update_file(request_user: UserModel): """ This method updates a file to the specified section in the document. Any existing value that matches the file name and metadata is taken into account. Furthermore, it is checked whether the current file name already exists in the directory. If this is the case, 'copy_(index)_' is appended as prefix. The method is executed recursively. Exception, if the parameter 'attachment' is passed with the value '{reference':true}', the name is not checked. Note: Create a unique media file element: - Folders in the same directory are unique. - The folder name can exist in different directories Create sub-folders: - Selected folder is considered as parent folder This also applies to files Changes: Is stored under 'request.json' Raises: MediaFileManagerUpdateError: If something went wrong during update. Args: Args: request_user (User): the instance of the started user (last modifier) Returns: MediaFile as JSON """ try: add_data_dump = json.dumps(request.json) new_file_data = json.loads(add_data_dump, object_hook=json_util.object_hook) reference_attachment = json.loads(request.args.get('attachment')) data = media_file_manager.get_file( metadata={'public_id': new_file_data['public_id']}) data['public_id'] = new_file_data['public_id'] data['filename'] = new_file_data['filename'] data['metadata'] = new_file_data['metadata'] data['metadata']['author_id'] = new_file_data['metadata'][ 'author_id'] = request_user.get_public_id() # Check if file / folder exist in folder if not reference_attachment['reference']: checker = { 'filename': new_file_data['filename'], 'metadata.parent': new_file_data['metadata']['parent'] } copied_name = create_attachment_name(new_file_data['filename'], 0, checker, media_file_manager) data['filename'] = copied_name media_file_manager.updata_file(data) except MediaFileManagerUpdateError: return abort(500) resp = make_response(data) return resp
def update_object(self, data: (dict, CmdbObject), user: UserModel = None, permission: AccessControlPermission = None) -> str: if isinstance(data, dict): update_object = CmdbObject(**data) elif isinstance(data, CmdbObject): update_object = data else: raise ObjectManagerUpdateError( 'Wrong CmdbObject init format - expecting CmdbObject or dict') update_object.last_edit_time = datetime.utcnow() if user: update_object.editor_id = user.public_id type_ = self._type_manager.get(update_object.type_id) verify_access(type_, user, permission) ack = self._update(collection=CmdbObject.COLLECTION, public_id=update_object.get_public_id(), data=update_object.__dict__) # create cmdb.core.object.updated event if self._event_queue and user: event = Event( "cmdb.core.object.updated", { "id": update_object.get_public_id(), "type_id": update_object.get_type_id(), "user_id": user.get_public_id() }) self._event_queue.put(event) return ack.acknowledged
def get_user(public_id: int): """ HTTP `GET`/`HEAD` route for a single user resource. Args: public_id (int): Public ID user. Raises: ManagerGetError: When the selected user does not exists. Notes: Calling the route over HTTP HEAD method will result in an empty body. Returns: GetSingleResponse: Which includes the json data of a UserModel. """ user_manager: UserManager = UserManager( database_manager=current_app.database_manager) try: user: UserModel = user_manager.get(public_id) except ManagerGetError as err: return abort(404, err.message) api_response = GetSingleResponse(UserModel.to_dict(user), url=request.url, model=UserModel.MODEL, body=request.method == 'HEAD') return api_response.make_response()
def to_dict(cls, instance: 'LoginResponse') -> dict: return { 'user': UserModel.to_dict(instance.user), 'token': instance.token.decode('UTF-8'), 'token_issued_at': instance.token_issued_at, 'token_expire': instance.token_expire }
def none_access_user(none_access_group: UserGroupModel): registration_time = datetime.now() return UserModel(public_id=2, user_name='none-access-user', active=True, group_id=none_access_group.public_id, registration_time=registration_time)
def update_template(self, data: (dict, DocapiTemplate), request_user: UserModel) -> str: """ Update new DocapiTemplat Object Args: data: init data request_user: current user, to detect who triggered event Returns: Public ID of the DocapiTemplate in database """ if isinstance(data, dict): update_object = DocapiTemplate(**data) elif isinstance(data, DocapiTemplate): update_object = data else: raise DocapiTemplateManagerUpdateError( f'Could not update template with ID: {data.get_public_id()}') update_object.last_execute_date = datetime.utcnow() ack = self._update(collection=DocapiTemplate.COLLECTION, public_id=update_object.get_public_id(), data=update_object.to_database()) if self._event_queue: event = Event( "cmdb.docapi.updated", { "id": update_object.get_public_id(), "active": update_object.get_active(), "user_id": request_user.get_public_id() }) self._event_queue.put(event) return ack.acknowledged
def update_job(self, data: (dict, ExportdJob), request_user: UserModel, event_start=True) -> str: """ Update new ExportdJob Object Args: data: init data request_user: current user, to detect who triggered event event_start: Controls whether an event should be started Returns: Public ID of the ExportdJob in database """ if isinstance(data, dict): update_object = ExportdJob(**data) elif isinstance(data, ExportdJob): update_object = data else: raise ExportdJobManagerUpdateError(f'Could not update job with ID: {data.get_public_id()}') update_object.last_execute_date = datetime.utcnow() ack = self._update( collection=ExportdJob.COLLECTION, public_id=update_object.get_public_id(), data=update_object.to_database() ) if self._event_queue and event_start: event = Event("cmdb.exportd.updated", {"id": update_object.get_public_id(), "active": update_object.scheduling["event"]["active"] and update_object.get_active(), "user_id": request_user.get_public_id()}) self._event_queue.put(event) return ack.acknowledged
def full_access_user(full_access_group: UserGroupModel): registration_time = datetime.now() return UserModel(public_id=1, user_name='full-access-user', active=True, group_id=full_access_group.public_id, registration_time=registration_time)
def run_job_manual(self, public_id: int, request_user: UserModel) -> bool: if self._event_queue: event = Event("cmdb.exportd.run_manual", {"id": public_id, "user_id": request_user.get_public_id(), "event": 'manuel'}) self._event_queue.put(event) return True
def delete_many_objects(self, filter_query: dict, public_ids, user: UserModel): ack = self._delete_many(CmdbObject.COLLECTION, filter_query) if self._event_queue: event = Event("cmdb.core.objects.deleted", {"ids": public_ids, "user_id": user.get_public_id(), "event": 'delete'}) self._event_queue.put(event) return ack
def delete_job(self, public_id: int, request_user: UserModel) -> bool: try: ack = self._delete(collection=ExportdJob.COLLECTION, public_id=public_id) if self._event_queue: event = Event("cmdb.exportd.deleted", {"id": public_id, "active": False, "user_id": request_user.get_public_id()}) self._event_queue.put(event) return ack except Exception: raise ExportdJobManagerDeleteError(f'Could not delete job with ID: {public_id}')
def add_job(request_user: UserModel): from bson import json_util add_data_dump = json.dumps(request.json) try: new_job_data = json.loads(add_data_dump, object_hook=json_util.object_hook) new_job_data['public_id'] = exportd_manager.get_new_id( ExportdJob.COLLECTION) new_job_data['last_execute_date'] = datetime.utcnow() new_job_data['author_id'] = request_user.get_public_id() new_job_data['author_name'] = request_user.get_display_name() new_job_data['state'] = ExecuteState.SUCCESSFUL.name except TypeError as e: LOGGER.warning(e) abort(400) try: job_instance = ExportdJob(**new_job_data) except CMDBError as e: LOGGER.debug(e) return abort(400) try: ack = exportd_manager.insert_job(job_instance) except ExportdJobManagerInsertError: return abort(500) # Generate new insert log try: log_params = { 'job_id': job_instance.get_public_id(), 'state': True, 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'event': LogAction.CREATE.name, 'message': '', } log_manager.insert_log(action=LogAction.CREATE, log_type=ExportdJobLog.__name__, **log_params) except LogManagerInsertError as err: LOGGER.error(err) resp = make_response(ack) return resp
def delete_template(self, public_id: int, request_user: UserModel) -> bool: try: ack = self._delete(collection=DocapiTemplate.COLLECTION, public_id=public_id) if self._event_queue: event = Event("cmdb.docapi.deleted", {"id": public_id, "active": False, "user_id": request_user.get_public_id()}) self._event_queue.put(event) return ack except Exception: raise DocapiTemplateManagerDeleteError(f'Could not delete template with ID: {public_id}')
def _decorate(*args, **kwargs): if auth: if not auth_is_valid(): return abort(401) if auth and right: if not user_has_right(right): if excepted: with current_app.app_context(): user_manager = UserManager( current_app.database_manager) token = parse_authorization_header( request.headers['Authorization']) try: decrypted_token = TokenValidator( current_app.database_manager).decode_token( token) except ValidationError as err: return abort(401) try: user_id = decrypted_token['DATAGERRY'][ 'value']['user']['public_id'] user_dict: dict = UserModel.to_dict( user_manager.get(user_id)) if excepted: for exe_key, exe_value in excepted.items(): try: route_parameter = kwargs[exe_value] except KeyError: return abort( 403, f'User has not the required right {right}' ) if exe_key not in user_dict.keys(): return abort( 403, f'User has not the required right {right}' ) if user_dict[ exe_key] == route_parameter: return f(*args, **kwargs) except ManagerGetError: return abort(404) return abort( 403, f'User has not the required right {right}') return f(*args, **kwargs)
def update_job(request_user: UserModel): from bson import json_util add_data_dump = json.dumps(request.json) new_job_data = None try: new_job_data = json.loads(add_data_dump, object_hook=json_util.object_hook) except TypeError as e: LOGGER.warning(e) abort(400) try: state = new_job_data["state"] update_job_instance = ExportdJob(**new_job_data) except CMDBError: return abort(400) try: exportd_manager.update_job(update_job_instance, request_user, False) except ExportdJobManagerUpdateError: return abort(500) # Generate new insert log if state not in ExecuteState.RUNNING.name: try: log_params = { 'job_id': update_job_instance.get_public_id(), 'state': True, 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'event': LogAction.EDIT.name, 'message': '', } log_manager.insert_log(action=LogAction.EDIT, log_type=ExportdJobLog.__name__, **log_params) except LogManagerInsertError as err: LOGGER.error(err) resp = make_response(update_job_instance) return resp
def delete_object(self, public_id: int, user: UserModel, permission: AccessControlPermission = None): type_id = self.get_object(public_id=public_id).type_id type_ = self._type_manager.get(type_id) verify_access(type_, user, permission) try: if self._event_queue: event = Event( "cmdb.core.object.deleted", { "id": public_id, "type_id": self.get_object(public_id).get_type_id(), "user_id": user.get_public_id() }) self._event_queue.put(event) ack = self._delete(CmdbObject.COLLECTION, public_id) return ack except (CMDBError, Exception): raise ObjectDeleteError(msg=public_id)
def get_users(params: CollectionParameters): """ HTTP `GET`/`HEAD` route for getting a iterable collection of resources. Args: params (CollectionParameters): Passed parameters over the http query string Returns: GetMultiResponse: Which includes a IterationResult of the UserModel. Notes: Calling the route over HTTP HEAD method will result in an empty body. Raises: ManagerIterationError: If the collection could not be iterated. ManagerGetError: If the collection/resources could not be found. """ user_manager: UserManager = UserManager( database_manager=current_app.database_manager) try: iteration_result: IterationResult[UserModel] = user_manager.iterate( filter=params.filter, limit=params.limit, skip=params.skip, sort=params.sort, order=params.order) users = [UserModel.to_dict(user) for user in iteration_result.results] api_response = GetMultiResponse(users, total=iteration_result.total, params=params, url=request.url, model=UserModel.MODEL, body=request.method == 'HEAD') except ManagerIterationError as err: return abort(400, err.message) except ManagerGetError as err: return abort(404, err.message) return api_response.make_response()
def add_template(request_user: UserModel): from bson import json_util add_data_dump = json.dumps(request.json) try: new_tpl_data = json.loads(add_data_dump, object_hook=json_util.object_hook) new_tpl_data['public_id'] = docapi_tpl_manager.get_new_id() new_tpl_data['author_id'] = request_user.get_public_id() except TypeError as err: LOGGER.warning(err) abort(400) try: template_instance = DocapiTemplate(**new_tpl_data) except CMDBError as err: LOGGER.debug(err) return abort(400) try: ack = docapi_tpl_manager.insert_template(template_instance) except DocapiTemplateManagerInsertError: return abort(500) resp = make_response(ack) return resp
def update_object(self, data: (dict, CmdbObject), user: UserModel = None, permission: AccessControlPermission = None) -> str: if isinstance(data, dict): update_object = CmdbObject(**data) elif isinstance(data, CmdbObject): update_object = data else: raise ObjectManagerUpdateError( 'Wrong CmdbObject init format - expecting CmdbObject or dict') update_object.last_edit_time = datetime.now(timezone.utc) if user: update_object.editor_id = user.public_id type_ = self._type_manager.get(update_object.type_id) if not type_.active: raise AccessDeniedError( f'Objects cannot be updated because type `{type_.name}` is deactivated.' ) verify_access(type_, user, permission) ack = self._update(collection=CmdbObject.COLLECTION, public_id=update_object.get_public_id(), data=update_object.__dict__) if self._event_queue and user: event = Event( "cmdb.core.object.updated", { "id": update_object.get_public_id(), "type_id": update_object.get_type_id(), "user_id": user.get_public_id(), 'event': 'update' }) self._event_queue.put(event) return ack.acknowledged
def preset_database(database_manager, database_name): from cmdb.database.errors.database_errors import DatabaseNotExists from cmdb.security.key.generator import KeyGenerator from cmdb.security.security import SecurityManager from cmdb.user_management.managers.group_manager import GroupManager from cmdb.user_management.managers.user_manager import UserManager try: database_manager.drop_database(database_name) except DatabaseNotExists: pass from cmdb.user_management import __FIXED_GROUPS__ from datetime import datetime kg = KeyGenerator(database_manager=database_manager) kg.generate_rsa_keypair() kg.generate_symmetric_aes_key() group_manager = GroupManager(database_manager=database_manager) user_manager = UserManager(database_manager=database_manager) security_manager = SecurityManager(database_manager=database_manager) for group in __FIXED_GROUPS__: group_manager.insert(group) admin_name = 'admin' admin_pass = '******' from cmdb.user_management import UserModel admin_user = UserModel( public_id=1, user_name=admin_name, active=True, group_id=__FIXED_GROUPS__[0].public_id, registration_time=datetime.now(), password=security_manager.generate_hmac(admin_pass), ) user_manager.insert(admin_user)
def update_object_state(public_id: int, request_user: UserModel): if isinstance(request.json, bool): state = request.json else: return abort(400) try: founded_object = object_manager.get_object(public_id=public_id) except ObjectManagerGetError as err: LOGGER.error(err) return abort(404) if founded_object.active == state: return make_response(False, 204) try: founded_object.active = state update_ack = object_manager.update_object( founded_object, user=request_user, permission=AccessControlPermission.READ) except AccessDeniedError as err: return abort(403, err.message) except ObjectManagerUpdateError as err: LOGGER.error(err) return abort(500) # get current object state try: current_type_instance = object_manager.get_type( 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) return make_response(update_ack)
def delete_many_objects(public_ids, request_user: UserModel): try: ids = [] operator_in = {'$in': []} filter_public_ids = {'public_id': {}} for v in public_ids.split(","): try: ids.append(int(v)) except (ValueError, TypeError): return abort(400) operator_in.update({'$in': ids}) filter_public_ids.update({'public_id': operator_in}) ack = [] objects = object_manager.get_objects_by(**filter_public_ids) for current_object_instance in objects: try: current_type_instance = object_manager.get_type( 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() except ObjectManagerGetError as err: LOGGER.error(err) return abort(404) except RenderError as err: LOGGER.error(err) return abort(500) try: ack.append( object_manager.delete_object( public_id=current_object_instance.get_public_id(), user=request_user, permission=AccessControlPermission.DELETE)) except ObjectDeleteError: return abort(400) except AccessDeniedError as err: return abort(403, err.message) except CMDBError: return abort(500) try: # generate log log_data = { 'object_id': current_object_instance.get_public_id(), 'version': current_object_render_result.object_information['version'], 'user_id': request_user.get_public_id(), 'user_name': request_user.get_display_name(), 'comment': 'Object was deleted', 'render_state': json.dumps(current_object_render_result, default=default).encode('UTF-8') } log_manager.insert(action=LogAction.DELETE, log_type=CmdbObjectLog.__name__, **log_data) except (CMDBError, LogManagerInsertError) as err: LOGGER.error(err) resp = make_response({'successfully': ack}) return resp except ObjectDeleteError as e: return jsonify(message='Delete Error', error=e.message) except CMDBError: return abort(500)