def _check_network_ownership(network_id, user_id): try: netowner = DBSession.query(NetworkOwner).filter( NetworkOwner.network_id == network_id, NetworkOwner.user_id == user_id).one() if netowner.edit == 'N': raise PermissionError("Permission denied." " User %s cannot edit network %s" % (user_id, network_id)) except NoResultFound: raise PermissionError("Permission denied." " User %s is not an owner of network %s" % (user_id, network_id))
def _check_network_owner(network, user_id): for owner in network.owners: if owner.user_id == int(user_id): return owner raise PermissionError('User %s is not the owner of network %s' % (user_id, network.network_id))
def _check_can_edit_scenario(scenario_id, user_id): scenario_i = _get_scenario(scenario_id, False, False) scenario_i.network.check_write_permission(user_id) if scenario_i.locked == 'Y': raise PermissionError('Cannot update scenario %s as it is locked.' % (scenario_id))
def clone_dataset(dataset_id, **kwargs): """ Get a single dataset, by ID """ user_id = int(kwargs.get('user_id')) if dataset_id is None: return None dataset = DBSession.query(Dataset).filter( Dataset.dataset_id == dataset_id).options( joinedload_all('metadata')).first() if dataset is None: raise HydraError("Dataset %s does not exist." % (dataset_id)) if dataset is not None and dataset.created_by != user_id: owner = DBSession.query(DatasetOwner).filter( DatasetOwner.dataset_id == Dataset.dataset_id, DatasetOwner.user_id == user_id).first() if owner is None: raise PermissionError( "User %s is not an owner of dataset %s and therefore cannot clone it." % (user_id, dataset_id)) DBSession.expunge(dataset) make_transient(dataset) dataset.data_name = dataset.data_name + "(Clone)" dataset.dataset_id = None dataset.cr_date = None #Try to avoid duplicate metadata entries if the entry has been cloned previously for m in dataset.metadata: if m.metadata_name in ("clone_of", "cloned_by"): del (m) cloned_meta = Metadata() cloned_meta.metadata_name = "clone_of" cloned_meta.metadata_val = str(dataset_id) dataset.metadata.append(cloned_meta) cloned_meta = Metadata() cloned_meta.metadata_name = "cloned_by" cloned_meta.metadata_val = str(user_id) dataset.metadata.append(cloned_meta) dataset.set_hash() DBSession.add(dataset) DBSession.flush() cloned_dataset = DBSession.query(Dataset).filter( Dataset.dataset_id == dataset.dataset_id).first() return cloned_dataset
def check_perm(user_id, permission_code): """ Checks whether a user has permission to perform an action. The permission_code parameter should be a permission contained in tPerm. If the user does not have permission to perfom an action, a permission error is thrown. """ try: perm = DBSession.query(Perm).filter(Perm.perm_code==permission_code).one() except NoResultFound: raise PermissionError("No permission %s"%(permission_code)) try: res = DBSession.query(User).join(RoleUser, RoleUser.user_id==User.user_id).\ join(Perm, Perm.perm_id==perm.perm_id).\ join(RolePerm, RolePerm.perm_id==Perm.perm_id).filter(User.user_id==user_id).one() except NoResultFound: raise PermissionError("Permission denied. User %s does not have permission %s"% (user_id, permission_code))
def unlock_scenario(scenario_id, **kwargs): #user_id = kwargs.get('user_id') #check_perm(user_id, 'edit_network') scenario_i = _get_scenario(scenario_id, False, False) owner = _check_network_owner(scenario_i.network, kwargs['user_id']) if owner.edit == 'Y': scenario_i.locked = 'N' else: raise PermissionError('User %s cannot unlock scenario %s' % (kwargs['user_id'], scenario_id)) DBSession.flush() return 'OK'
def update_scenario(scenario, update_data=True, update_groups=True, **kwargs): """ Update a single scenario as all resources already exist, there is no need to worry about negative IDS """ user_id = kwargs.get('user_id') scen = _get_scenario(scenario.id) _check_network_ownership(scenario.network_id, user_id) if scen.locked == 'Y': raise PermissionError('Scenario is locked. Unlock before editing.') scen.scenario_name = scenario.name scen.scenario_description = scenario.description scen.layout = scenario.get_layout() scen.start_time = str(timestamp_to_ordinal( scenario.start_time)) if scenario.start_time else None scen.end_time = str(timestamp_to_ordinal( scenario.end_time)) if scenario.end_time else None scen.time_step = scenario.time_step if scenario.resourcescenarios == None: scenario.resourcescenarios = [] if scenario.resourcegroupitems == None: scenario.resourcegroupitems = [] if update_data is True: datasets = [rs.value for rs in scenario.resourcescenarios] updated_datasets = data._bulk_insert_data(datasets, user_id, kwargs.get('app_name')) for i, r_scen in enumerate(scenario.resourcescenarios): _update_resourcescenario(scen, r_scen, dataset=updated_datasets[i], user_id=user_id, source=kwargs.get('app_name')) if update_groups is True: #Get all the exiting resource group items for this scenario. #THen process all the items sent to this handler. #Any in the DB that are not passed in here are removed. for group_item in scenario.resourcegroupitems: group_item_i = _add_resourcegroupitem(group_item, scenario.id) if group_item.id is None or group_item.id < 0: scen.resourcegroupitems.append(group_item_i) DBSession.flush() return scen
def get_scenario(scenario_id, include_data=True, include_items=True, **kwargs): """ Get the specified scenario """ user_id = kwargs.get('user_id') scen = _get_scenario(scenario_id, include_data, include_items) owner = _check_network_owner(scen.network, user_id) if owner.view == 'N': raise PermissionError("Permission denied." " User %s cannot view scenario %s" % (user_id, scenario_id)) return scen
def assign_value(rs, data_type, val, units, name, dimension, metadata={}, data_hash=None, user_id=None, source=None): """ Insert or update a piece of data in a scenario. If the dataset is being shared by other resource scenarios, a new dataset is inserted. If the dataset is ONLY being used by the resource scenario in question, the dataset is updated to avoid unnecessary duplication. """ log.debug("Assigning value %s to rs %s in scenario %s", name, rs.resource_attr_id, rs.scenario_id) if rs.scenario.locked == 'Y': raise PermissionError("Cannot assign value. Scenario %s is locked" % (rs.scenario_id)) #Check if this RS is the only RS in the DB connected to this dataset. #If no results is found, the RS isn't in the DB yet, so the condition is false. update_dataset = False # Default behaviour is to create a new dataset. if rs.dataset is not None: #Has this dataset changed? if rs.dataset.data_hash == data_hash: log.debug("Dataset has not changed. Returning.") return connected_rs = DBSession.query(ResourceScenario).filter( ResourceScenario.dataset_id == rs.dataset.dataset_id).all() #If there's no RS found, then the incoming rs is new, so the dataset can be altered #without fear of affecting something else. if len(connected_rs) == 0: #If it's 1, the RS exists in the DB, but it's the only one using this dataset or #The RS isn't in the DB yet and the datset is being used by 1 other RS. update_dataset = True if len(connected_rs) == 1: if connected_rs[0].scenario_id == rs.scenario_id and connected_rs[ 0].resource_attr_id == rs.resource_attr_id: update_dataset = True else: update_dataset = False if update_dataset is True: log.info("Updating dataset '%s'", name) dataset = data.update_dataset(rs.dataset.dataset_id, name, data_type, val, units, dimension, metadata, **dict(user_id=user_id)) rs.dataset = dataset rs.dataset_id = dataset.dataset_id else: log.info("Creating new dataset %s in scenario %s", name, rs.scenario_id) dataset = data.add_dataset(data_type, val, units, dimension, metadata=metadata, name=name, **dict(user_id=user_id)) rs.dataset = dataset rs.source = source DBSession.flush()