def test_remove_collaborator_from_operation(self): pytest.skip("get_session_id has None result") sio = self._connect() operation = self._new_operation('new_operation', "example decription") sm = SocketsManager(self.cm, self.fm) sm.join_collaborator_to_operation(self.anotheruser.id, operation.id) perms = Permission(self.anotheruser.id, operation.id, "collaborator") assert perms is not None sm.remove_collaborator_from_operation(self.anotheruser.id, operation.id) sio.sleep(1) perms = Permission(self.anotheruser.id, operation.id, "collaborator") assert perms is None
def add_user_to_operation(path=None, access_level='admin', emailid=None): """ on db level we add all users to the operation TEMPLATE for user handling""" if None in (path, emailid): return False app.config['SQLALCHEMY_DATABASE_URI'] = mscolab_settings.SQLALCHEMY_DB_URI app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) with app.app_context(): operation = Operation.query.filter_by(path=path).first() if operation: user = User.query.filter_by(emailid=emailid).first() if user: new_permissions = [ Permission(user.id, operation.id, access_level) ] db.session.add_all(new_permissions) try: db.session.commit() return True except IntegrityError as err: db.session.rollback() logging.debug(f"Error writing to db: {err}") db.session.close() return False
def create_project(self, path, description, user, content=None): """ path: path to the project description: description of the project """ # set codes on these later if path.find("/") != -1 or path.find("\\") != -1 or (" " in path): logging.debug("malicious request: %s", user) return False proj_available = Project.query.filter_by(path=path).first() if proj_available: return False project = Project(path, description) db.session.add(project) db.session.flush() project_id = project.id # this is the only insertion with "creator" access_level perm = Permission(user.id, project_id, "creator") db.session.add(perm) db.session.commit() data = fs.open_fs(self.data_dir) data.makedir(project.path) project_file = data.open(fs.path.combine(project.path, 'main.ftml'), 'w') if content is not None: project_file.write(content) else: project_file.write(mscolab_settings.STUB_CODE) project_path = fs.path.combine(self.data_dir, project.path) r = git.Repo.init(project_path) r.git.clear_cache() r.index.add(['main.ftml']) r.index.commit("initial commit") return True
def test_file_save(self): url = url_join(MSCOLAB_URL_TEST, 'token') r = requests.post(url, data={'email': 'a', 'password': '******'}) response1 = json.loads(r.text) r = requests.post(url, data={'email': 'b', 'password': '******'}) response2 = json.loads(r.text) def handle_chat_message(sno, message): self.file_message_counter[sno - 1] += 1 sio1 = socketio.Client() sio2 = socketio.Client() sio1.on('file-changed', handler=partial(handle_chat_message, 1)) sio2.on('file-changed', handler=partial(handle_chat_message, 2)) sio1.connect(MSCOLAB_URL_TEST) sio2.connect(MSCOLAB_URL_TEST) with self.app.app_context(): p_id = get_recent_pid(self.fm, self.user) user2 = User.query.filter_by(id=9).first() perm = Permission(u_id=9, p_id=p_id, access_level="admin") db.session.add(perm) db.session.commit() sio1.emit('start', response1) sio2.emit('start', response2) time.sleep(2) sio1.emit( 'file-save', { "p_id": p_id, "token": response1['token'], "content": "file save content 1" }) time.sleep(2) # second file change sio1.emit( 'file-save', { "p_id": p_id, "token": response1['token'], "content": "file save content 2" }) time.sleep(2) # check if there were events triggered related to file-save assert self.file_message_counter[0] == 2 assert self.file_message_counter[1] == 2 # check if content is saved in file assert self.fm.get_file(p_id, user2) == "file save content 2" # check if change is saved properly changes = self.fm.get_all_changes(p_id, self.user) assert len(changes) == 2 change = Change.query.order_by(Change.created_at.desc()).first() change_content = self.fm.get_change_content(change.id) assert change_content == "file save content 2" perm = Permission.query.filter_by(u_id=9, p_id=p_id).first() db.session.delete(perm) db.session.commit() # to disconnect sockets later self.sockets.append(sio1) self.sockets.append(sio2)
def test_join_collaborator_to_operation(self): self._connect() operation = self._new_operation('new_operation', "example decription") sm = SocketsManager(self.cm, self.fm) sm.join_collaborator_to_operation(self.anotheruser.id, operation.id) perms = Permission(self.anotheruser.id, operation.id, "collaborator") assert perms.op_id == operation.id assert perms.u_id == self.anotheruser.id assert perms.access_level == "collaborator"
def import_permissions(self, import_p_id, current_p_id, u_id): if not self.is_admin(u_id, current_p_id): return False, None perm = Permission.query.filter_by(u_id=u_id, p_id=import_p_id).first() if not perm: return False, None existing_perms = Permission.query \ .filter(Permission.p_id == current_p_id) \ .filter((Permission.u_id != u_id) & (Permission.access_level != 'creator')) \ .all() current_project_creator = Permission.query.filter_by( p_id=current_p_id, access_level="creator").first() import_perms = Permission.query\ .filter(Permission.p_id == import_p_id)\ .filter((Permission.u_id != u_id) & (Permission.u_id != current_project_creator.u_id))\ .all() # We Delete all the existing permissions existing_users = [] for perm in existing_perms: existing_users.append(perm.u_id) db.session.delete(perm) db.session.flush() # Then add the permissions of the imported project new_users = [] for perm in import_perms: access_level = perm.access_level if perm.access_level == "creator": access_level = "admin" new_users.append(perm.u_id) db.session.add(Permission(perm.u_id, current_p_id, access_level)) # Set Difference of lists new_users - existing users add_users = [u_id for u_id in new_users if u_id not in existing_users] # Intersection of lists existing_users and new_users modify_users = [u_id for u_id in existing_users if u_id in new_users] # Set Difference of lists existing users - new_users delete_users = [u_id for u_id in new_users if u_id in existing_users] try: db.session.commit() return True, { "add_users": add_users, "modify_users": modify_users, "delete_users": delete_users } except IntegrityError: db.session.rollback() return False, None
def test_join_creator_to_operatiom(self): sio = self._connect() operation = self._new_operation('new_operation', "example decription") assert self.fm.get_file(int(operation.id), self.user) is False json_config = {"token": self.token, "op_id": operation.id} sio.emit('add-user-to-operation', json_config) perms = Permission(self.user.id, operation.id, "creator") assert perms.op_id == operation.id assert perms.u_id == self.user.id assert perms.access_level == "creator"
def add_bulk_permission(self, p_id, user, new_u_ids, access_level): if not self.is_admin(user.id, p_id): return False new_permissions = [] for u_id in new_u_ids: new_permissions.append(Permission(u_id, p_id, access_level)) db.session.add_all(new_permissions) try: db.session.commit() return True except IntegrityError: db.session.rollback() return False
def test_undo(self): url = url_join(self.url, 'token') r = requests.post(url, data={'email': 'a', 'password': '******'}) response1 = json.loads(r.text) r = requests.post(url, data={'email': 'b', 'password': '******'}) response2 = json.loads(r.text) def handle_chat_message(sno, message): self.file_message_counter[sno - 1] += 1 sio1 = socketio.Client() self.sockets.append(sio1) sio2 = socketio.Client() self.sockets.append(sio2) sio1.on('file-changed', handler=partial(handle_chat_message, 1)) sio2.on('file-changed', handler=partial(handle_chat_message, 2)) sio1.connect(self.url) sio2.connect(self.url) with self.app.app_context(): p_id = get_recent_pid(self.fm, self.user) User.query.filter_by(id=9).first() perm = Permission(u_id=9, p_id=p_id, access_level="admin") db.session.add(perm) db.session.commit() sio1.emit('start', response1) sio2.emit('start', response2) QtTest.QTest.qWait(100) sio1.emit( 'file-save', { "p_id": p_id, "token": response1['token'], "content": "file save content 1" }) QtTest.QTest.qWait(100) # second file change sio1.emit( 'file-save', { "p_id": p_id, "token": response1['token'], "content": "file save content 2" }) QtTest.QTest.qWait(100) with self.app.app_context(): p_id = get_recent_pid(self.fm, self.user) changes = Change.query.filter_by(p_id=p_id).all() assert self.fm.undo(changes[0].id, self.user) is True assert len(self.fm.get_all_changes(p_id, self.user)) == 3 assert self.fm.get_file(p_id, self.user) == "file save content 1"
def add_all_users_default_operation(path='TEMPLATE', description="Operation to keep all users", access_level='admin'): """ on db level we add all users to the operation TEMPLATE for user handling""" app.config['SQLALCHEMY_DATABASE_URI'] = mscolab_settings.SQLALCHEMY_DB_URI app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) with app.app_context(): operation_available = Operation.query.filter_by(path=path).first() if not operation_available: operation = Operation(path, description) db.session.add(operation) db.session.commit() with fs.open_fs(mscolab_settings.MSCOLAB_DATA_DIR) as file_dir: if not file_dir.exists(path): file_dir.makedir(path) file_dir.writetext(f'{path}/main.ftml', mscolab_settings.STUB_CODE) # initiate git r = git.Repo.init( fs.path.join(mscolab_settings.DATA_DIR, 'filedata', path)) r.git.clear_cache() r.index.add(['main.ftml']) r.index.commit("initial commit") operation = Operation.query.filter_by(path=path).first() op_id = operation.id user_list = User.query \ .join(Permission, (User.id == Permission.u_id) & (Permission.op_id == op_id), isouter=True) \ .add_columns(User.id, User.username) \ .filter(Permission.u_id.is_(None)) new_u_ids = [user.id for user in user_list] new_permissions = [] for u_id in new_u_ids: if Permission.query.filter_by(u_id=u_id, op_id=op_id).first() is None: new_permissions.append( Permission(u_id, operation.id, access_level)) db.session.add_all(new_permissions) try: db.session.commit() return True except IntegrityError as err: db.session.rollback() logging.debug(f"Error writing to db: {err}") db.session.close()
def add_bulk_permission(self, op_id, user, new_u_ids, access_level): if not self.is_admin(user.id, op_id) and not self.is_creator( user.id, op_id): return False new_permissions = [] for u_id in new_u_ids: if Permission.query.filter_by(u_id=u_id, op_id=op_id).first() is None: new_permissions.append(Permission(u_id, op_id, access_level)) db.session.add_all(new_permissions) try: db.session.commit() return True except IntegrityError: db.session.rollback() return False
def import_permissions(self, import_op_id, current_op_id, u_id): if not self.is_creator(u_id, current_op_id) and not self.is_admin( u_id, current_op_id): return False, None, "Not the creator or admin of this operation" perm = Permission.query.filter_by(u_id=u_id, op_id=import_op_id).first() if perm is None: return False, None, "Not a member of this operation" existing_perms = Permission.query \ .filter(Permission.op_id == current_op_id) \ .filter((Permission.u_id != u_id) & (Permission.access_level != 'creator')) \ .all() existing_users = set([perm.u_id for perm in existing_perms]) current_operation_creator = Permission.query.filter_by( op_id=current_op_id, access_level="creator").first() import_perms = Permission.query\ .filter(Permission.op_id == import_op_id)\ .filter((Permission.u_id != u_id) & (Permission.u_id != current_operation_creator.u_id))\ .all() import_users = set([perm.u_id for perm in import_perms]) is_perm = [] for perm in existing_perms: is_perm.append((perm.u_id, perm.access_level)) new_perm = [] for perm in import_perms: access_level = perm.access_level # we keep creator to the one created the operation, and substitute the imported to admin if perm.access_level == "creator": access_level = "admin" new_perm.append((perm.u_id, access_level)) if sorted(new_perm) == sorted(is_perm): return False, None, "Permissions are already given" # We Delete all permissions of existing users which not in new permission delete_users = [] for perm in existing_perms: if (perm.u_id, perm.access_level) not in new_perm: db.session.delete(perm) delete_users.append(perm.u_id) db.session.flush() # Then add the permissions of the imported operation based on new_perm new_users = [] for u_id, access_level in new_perm: if not (u_id, access_level) in is_perm: new_users.append(u_id) if Permission.query.filter_by( u_id=u_id, op_id=current_op_id).first() is None: db.session.add( Permission(u_id, current_op_id, access_level)) # prepare events based on action done delete_users = list(existing_users.difference(import_users)) add_users = list(import_users.difference(existing_users)) modify_users = [] _intersect_users = import_users.intersection(existing_users) _new_perm = dict(new_perm) _is_perm = dict(is_perm) for m_uid in _intersect_users: if _new_perm[m_uid] != _is_perm[m_uid]: modify_users.append(m_uid) try: db.session.commit() return True, { "add_users": add_users, "modify_users": modify_users, "delete_users": delete_users }, "success" except IntegrityError: db.session.rollback() return False, None, "Some error occurred! Could not import permissions. Please try again."
def seed_data(): app.config['SQLALCHEMY_DATABASE_URI'] = mscolab_settings.SQLALCHEMY_DB_URI app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) with app.app_context(): # create users users = [{ 'username': '******', 'id': 8, 'password': '******', 'emailid': 'a' }, { 'username': '******', 'id': 9, 'password': '******', 'emailid': 'b' }, { 'username': '******', 'id': 10, 'password': '******', 'emailid': 'c' }, { 'username': '******', 'id': 11, 'password': '******', 'emailid': 'd' }, { 'username': '******', 'id': 12, 'password': '******', 'emailid': 'test1' }, { 'username': '******', 'id': 13, 'password': '******', 'emailid': 'test2' }, { 'username': '******', 'id': 14, 'password': '******', 'emailid': 'test3' }, { 'username': '******', 'id': 15, 'password': '******', 'emailid': 'test4' }, { 'username': '******', 'id': 16, 'password': '******', 'emailid': 'mscolab_user' }, { 'username': '******', 'id': 17, 'password': '******', 'emailid': 'merge_waypoints_user' }] for user in users: db_user = User(user['emailid'], user['username'], user['password']) db_user.id = user['id'] db.session.add(db_user) # create operations operations = [{ 'id': 1, 'path': 'one', 'description': 'a, b', 'category': 'default' }, { 'id': 2, 'path': 'two', 'description': 'b, c', 'category': 'default' }, { 'id': 3, 'path': 'three', 'description': 'a, c', 'category': 'default' }, { 'id': 4, 'path': 'four', 'description': 'd', 'category': 'default' }, { 'id': 5, 'path': 'Admin_Test', 'description': 'Operation for testing admin window', 'category': 'default' }, { 'id': 6, 'path': 'test_mscolab', 'description': 'Operation for testing mscolab main window', 'category': 'default' }] for operation in operations: db_operation = Operation(operation['path'], operation['description'], operation['category']) db_operation.id = operation['id'] db.session.add(db_operation) # create permissions permissions = [{ 'u_id': 8, 'op_id': 1, 'access_level': "creator" }, { 'u_id': 9, 'op_id': 1, 'access_level': "collaborator" }, { 'u_id': 9, 'op_id': 2, 'access_level': "creator" }, { 'u_id': 10, 'op_id': 2, 'access_level': "collaborator" }, { 'u_id': 10, 'op_id': 3, 'access_level': "creator" }, { 'u_id': 8, 'op_id': 3, 'access_level': "collaborator" }, { 'u_id': 10, 'op_id': 1, 'access_level': "viewer" }, { 'u_id': 11, 'op_id': 4, 'access_level': 'creator' }, { 'u_id': 8, 'op_id': 4, 'access_level': 'admin' }, { 'u_id': 13, 'op_id': 3, 'access_level': 'viewer' }, { 'u_id': 12, 'op_id': 5, 'access_level': 'creator' }, { 'u_id': 12, 'op_id': 3, 'access_level': 'collaborator' }, { 'u_id': 15, 'op_id': 5, 'access_level': 'viewer' }, { 'u_id': 14, 'op_id': 3, 'access_level': 'collaborator' }, { 'u_id': 15, 'op_id': 3, 'access_level': 'collaborator' }, { 'u_id': 16, 'op_id': 6, 'access_level': 'creator' }, { 'u_id': 17, 'op_id': 6, 'access_level': 'admin' }] for perm in permissions: db_perm = Permission(perm['u_id'], perm['op_id'], perm['access_level']) db.session.add(db_perm) db.session.commit() db.session.close() with fs.open_fs(mscolab_settings.MSCOLAB_DATA_DIR) as file_dir: file_paths = [ 'one', 'two', 'three', 'four', 'Admin_Test', 'test_mscolab' ] for file_path in file_paths: file_dir.makedir(file_path) file_dir.writetext(f'{file_path}/main.ftml', mscolab_settings.STUB_CODE) # initiate git r = git.Repo.init( fs.path.join(mscolab_settings.DATA_DIR, 'filedata', file_path)) r.git.clear_cache() r.index.add(['main.ftml']) r.index.commit("initial commit")