def end_session(session_id): """ End a session """ datastore.query('delete from sessions ' 'where session_id = ?', (session_id, ))
def get_rcis_for_user(user_id, logged_in_user): """ Fetch the rcis for which the user `user_id` is a collaborator. """ throw_if_not_valid_uuid(user_id) # You can only lookup rcis for a user if # 1 - That user is you OR # 2 - You have permissions to MODERATE_RCIS if (user_can(Permission.MODERATE_RCIS, logged_in_user)): pass else: if user_id != logged_in_user['user_id']: raise Unauthorized('You do not have sufficient permissions ' 'to lookup rcis for someone else.') user = get_user_record(user_id) rci_ids = [ x['rci_id'] for x in datastore.query( 'select rci_id ' 'from rci_collabs ' 'where user_id = ?', (user_id, )) ] rcis = [] for rci_id in rci_ids: rcis.append(get_rci_by_id(rci_id, full=True)) return rcis
def get_rci_collaborators(rci_id): """ List the collaborators for an rci """ return datastore.query('select * ' 'from rci_collabs ' 'where rci_id = ?', (rci_id, ))
def search_rcis(search_string, logged_in_user): """ Performs a full-text-search for rcis using the rci_index table """ # Only those with the MODERATE_RCIS permission can do this if not user_can(Permission.MODERATE_RCIS, logged_in_user): raise Unauthorized('You do not have sufficient permissions ' 'to perform an rci search') # If they did not have a search term, return an empty list if search_string is None or search_string.strip() == "": return [] # Quote the search string. See https://sqlite.org/fts5.html # Not doing this would treat the hyphen character `-` as a column modifier search_string = '"{}"'.format(search_string) search_results = datastore.query( 'select * ' 'from rci_index ' 'where rci_index = ?', (search_string, )) rcis = [] for result in search_results: rcis.append(get_rci_by_id(rci_id=result['rci_id'], full=True)) return rcis
def create_rci(user_id, building_name, room_name, logged_in_user): """ Creates a new rci record for a room. The user who created it is added to the list of collaborators on this rci Multiple rcis can exist for the same room """ # You can only create rcis for someone else if you have # permissions to MODERATE_RCS or you are creating an # rci for youself. if (user_can(Permission.MODERATE_RCIS, logged_in_user)): pass else: if user_id != logged_in_user['user_id']: raise Unauthorized('You do not have permissions ' 'to create an rci for someone else.') new_rci_id = str(uuid.uuid4()) rci_insert_args = { 'rci_id': new_rci_id, 'room_name': room_name, 'building_name': building_name, 'created_at': datetime.utcnow(), 'created_by': logged_in_user['user_id'] } rci_collab_insert_args = {'rci_id': new_rci_id, 'user_id': user_id} # Create the rci document datastore.query( 'insert into rcis ' '(rci_id, building_name, room_name, created_at, created_by) ' 'values ' '(:rci_id,:building_name,:room_name,:created_at,:created_by)', rci_insert_args) # Add the user as an a collaborator for the rci datastore.query( 'insert into rci_collabs(rci_id, user_id) ' 'values(:rci_id, :user_id);', rci_collab_insert_args) # Fetch the newly created rci return get_rci_by_id(new_rci_id, full=True)
def lock_rci(rci_id, logged_in_user): """ Freeze an rci, preventing it from being modified """ # We will fail with a clear error here if the rci doesn't exist rci = get_rci_record(rci_id) # You can only lock an rci if # you have permission to MODERATE_RCIS if not user_can(Permission.MODERATE_RCIS, logged_in_user): raise Unauthorized('You do not have sufficient permissions ' 'to lock this rci') # Go ahead and lock it up datastore.query('update rcis ' 'set is_locked = 1 ' 'where rci_id = ?', (rci_id, ))
def unlock_rci(rci_id, logged_in_user): """ Un-Freeze an rci, making it editable again """ # We will fail with a clear error here if the rci doesn't exist rci = get_rci_record(rci_id) # You can only unlock an rci if # you have permission to MODERATE_RCIS if not user_can(Permission.MODERATE_RCIS, logged_in_user): raise Unauthorized('You do not have sufficient permissions ' 'to unlock this rci') # Go ahead and unlock it up datastore.query('update rcis ' 'set is_locked = 0 ' 'where rci_id = ?', (rci_id, ))
def get_default_room_areas(): """ Return the list of default room areas """ return datastore.query( 'select * ' 'from room_areas' )
def get_rci_by_id(rci_id, full=False): """ Fetch an rci """ throw_if_not_valid_uuid(rci_id) rci = get_rci_record(rci_id) if not full: return rci rci_collaborators = datastore.query( 'select u.* ' 'from rci_collabs as rc ' 'inner join users as u ' 'using(user_id) ' 'where rc.rci_id = ?', (rci_id, )) damages = datastore.query( 'select ' 'd.*, ' 'coalesce(u.firstname, \'DELETED\') as firstname, ' 'coalesce(u.lastname, \'USER\') as lastname ' 'from damages as d ' 'left join users as u ' 'on d.created_by = u.user_id ' 'where rci_id =? ', (rci_id, )) damages_by_item = {} for damage in damages: damages_by_item.setdefault(damage['item'], []).append(damage) full_rci_doc = { 'rci_id': rci_id, 'collaborators': rci_collaborators, 'damages': damages_by_item, 'room_name': rci['room_name'], 'building_name': rci['building_name'], 'created_at': rci['created_at'], 'created_by': rci['created_by'], 'is_locked': True if rci['is_locked'] == 1 else False } return full_rci_doc
def get_damage_record(damage_id): damage = datastore.query('select * ' 'from damages ' 'where damage_id = ?', (damage_id, ), one=True) if damage is None: raise RecordNotFound('No such damage {}'.format(damage_id)) else: return damage
def get_rci_record(rci_id): rci = datastore.query('select * from rcis ' 'where rci_id = ? ' 'limit 1', (rci_id, ), one=True) if rci is None: raise RecordNotFound('No such rci {}'.format(rci_id)) else: return rci
def create_damage(logged_in_user, rci_id, item, text, image_url): """ Record a damage on the rci """ rci = common.get_rci_record(rci_id) # Cannot record a damage if the rci is locked if rci['is_locked']: raise Unauthorized('Rci {} is locked'.format(rci_id)) # Check that the user is one of the following # (a) a collaborator on the rci OR # (b) has Permission.MODERATE_DAMAGES if (user_can(Permission.MODERATE_DAMAGES, logged_in_user)): pass else: rci_collaborators = [ x['user_id'] for x in common.get_rci_collaborators(rci_id) ] if logged_in_user['user_id'] not in rci_collaborators: raise Unauthorized('You cannot record damage on this rci.' 'Please ask to be added to the list of ' 'collaborators') damage_insert_args = { 'damage_id': str(uuid.uuid4()), 'rci_id': rci_id, 'item': item, 'text': text, 'image_url': image_url, 'created_by': logged_in_user['user_id'], 'created_at': datetime.utcnow() } datastore.query( 'insert into ' 'damages(damage_id, rci_id, item, text, image_url, created_by, created_at) ' 'values(:damage_id,:rci_id,:item,:text,:image_url,:created_by,:created_at) ', damage_insert_args) return common.get_damage_record(damage_insert_args['damage_id'])
def get_user_record(user_id): user = datastore.query( 'select * from users ' 'where user_id = ? ' 'limit 1', (user_id, ), one=True) if user is None: raise RecordNotFound('No such user {}'.format(user_id)) else: return user
def validate(username, password): user = datastore.query( 'select * ' 'from users ' 'where username = ? ' 'limit 1;', (username, ), one=True) if user is None: return False return is_valid_login(user, username, password)
def start_session(username): """ Start a session for a given user """ user = datastore.query( 'select * ' 'from users ' 'where username = ? ' 'limit 1;', (username, ), one=True) if user is None: raise BadRequest("The user {} doesn't exist!".format(username)) s = create_session_obj(user['user_id'], 120) datastore.query( 'insert into ' 'sessions (session_id, user_id, created_at, expires_at) ' 'values (:session_id, :user_id, :created_at, :expires_at)', s) return s['session_id']
def get_building_manifest(): """ Return a summary of the building layout. """ result = datastore.query('select * from rooms'); manifest = {} for room in result: building_name = room['building_name'] manifest.setdefault(building_name, []).append(room) return manifest
def get_session_user(session_id): """ Fetch the user that is associated with a session """ # Notice that we also load the user's roles user = datastore.query( 'select u.* ' 'from sessions as s ' 'inner join users as u ' 'using(user_id) ' 'where s.session_id = ? ' 'limit 1; ', (session_id, ), one=True) return user
def user_can(permissions, user): """ Check a user's permissions against the permissions she seeks Throw if the user object does not have a permission attribute """ user_permissions = datastore.query( 'select * ' 'from roles ' 'where role = ? ', (user['role'], ), one=True) if user_permissions is None: raise ValueError('user does not have permissions attribute') return user_permissions['permissions'] & permissions == permissions
def get_user_permissions(user_id): """ Get the user's permissions """ result = datastore.query( 'select r.permissions ' 'from users as u ' 'inner join roles as r ' 'using(role) ' 'where u.user_id = ?', (user_id, ), one=True) if result is None: return result else: return result['permissions']
def get_rcis_for_buildings(buildings, logged_in_user): """ Fetch the rcis for the specified buildings """ # Only users that have the MODERATE_RCIS permission can do this if not user_can(Permission.MODERATE_RCIS, logged_in_user): raise Unauthorized('You do not have sufficient permissions ' 'to lookup rcis for a building.') rci_ids = [ x['rci_id'] for x in datastore.query( 'select rci_id ' 'from rcis ' 'where building_name in ({})'.format(', '.join( '?' for i in buildings)), buildings) ] rcis = [] for rci_id in rci_ids: rcis.append(get_rci_by_id(rci_id, full=True)) return rcis
def get_users(): """ Fetches all users """ return datastore.query('select * ' 'from users ')