def dbGeneralisedGetTickets(db, user, query): """A generic ticket-reading query from DB, specialized in many ways.""" return (Ticket(**ticDoc) for ticDoc in dbRetrieveRecordsByKey( db, 'tickets', query, dbTablesDesc=dbSchema, ))
def dbToggleBoxRolePermissionBit(db, thisBox, roleClass, roleId, bit, user, skipCommit=False): """ Toggle (t<-->f) a bit from an existing permission set (a role) for a box. """ roleKey = (roleClass, roleId) if thisBox.box_id == '' and roleKey == ('system', 'admin'): raise OstracionError('Cannot edit root box permissions for admin') elif thisBox.box_id == '' and roleKey == ('system', 'anonymous'): raise OstracionError('Cannot edit root box permissions for anonymous') else: if userIsAdmin(db, user): foundRecords = list( dbRetrieveRecordsByKey( db, 'box_role_permissions', { 'box_id': thisBox.box_id, 'role_class': roleClass, 'role_id': roleId, }, dbTablesDesc=dbSchema, )) if len(foundRecords) > 0: foundBRP = BoxRolePermission(**foundRecords[0]) lBit = bit.lower() newBRPDict = recursivelyMergeDictionaries( {lBit: 1 if not foundBRP.booleanBit(lBit) else 0}, defaultMap={ k: v for k, v in foundBRP.asDict().items() if k in {'box_id', 'role_class', 'role_id'} }, ) try: dbUpdateRecordOnTable( db, 'box_role_permissions', newBRPDict, dbTablesDesc=dbSchema, allowPartial=True, ) if not skipCommit: db.commit() except Exception as e: db.rollback() raise e else: raise OstracionError('Box role permission does not exist') else: raise OstracionError('Insufficient permissions')
def dbGetBoxRolePermissions(db, boxId, asDict=False): """ Get all permission sets (i.e. each is <--> a role) for a given box.""" for brPermission in dbRetrieveRecordsByKey( db, 'box_role_permissions', {'box_id': boxId}, dbTablesDesc=dbSchema, ): if asDict: yield brPermission else: yield BoxRolePermission(**brPermission)
def getLinksFromBox(db, box): """ Perform a 'ls' call and return all links found in a given box. """ return ( Link(**linkDict) for linkDict in dbRetrieveRecordsByKey( db, 'links', {'box_id': box.box_id}, dbTablesDesc=dbSchema, ) )
def getFilesFromBox(db, box): """ Perform a 'ls' call and return all files found in a given box. """ return ( File(**fileDict) for fileDict in dbRetrieveRecordsByKey( db, 'files', {'box_id': box.box_id}, dbTablesDesc=dbSchema, ) )
def isLinkNameUnderParentBox(db, parentBox, newName, excludedIds=[]): """ Check if the proposed name is already a contained link. User-agnostic: only gives a yes/no answer to the question: can I use this as box/file/... name? (hence it needs to know the complete list of contained items). """ exIds = {p[1] for p in excludedIds if p[0] == 'link'} return newName in ( link['name'] for link in dbRetrieveRecordsByKey( db, 'links', {'box_id': parentBox.box_id}, dbTablesDesc=dbSchema, ) if link['link_id'] not in exIds )
def dbGetUsersByRole(db, roleClass, roleId, user): """ Get all users with a given roleId attached. In particular, a list of "UserRole" instances is returned, whose userid is to be inspected. """ if userIsAdmin(db, user): return (UserRole(**u) for u in dbRetrieveRecordsByKey( db, 'user_roles', { 'role_id': roleId, 'role_class': roleClass }, dbTablesDesc=dbSchema, )) else: raise OstracionError('Insufficient permissions')
def dbDeleteBoxRolePermission(db, boxId, roleClass, roleId, user, skipCommit=False): """Remove a permission set (i.e. for a role) from a box.""" if boxId == '': raise OstracionError('Cannot delete root box permissions') else: if userIsAdmin(db, user): recordExists = len( list( dbRetrieveRecordsByKey( db, 'box_role_permissions', { 'box_id': boxId, 'role_class': roleClass, 'role_id': roleId, }, dbTablesDesc=dbSchema, ))) != 0 if recordExists: try: dbDeleteRecordsByKey( db, 'box_role_permissions', { 'box_id': boxId, 'role_class': roleClass, 'role_id': roleId, }, dbTablesDesc=dbSchema, ) if not skipCommit: db.commit() except Exception as e: db.rollback() raise e else: raise OstracionError('Box role permission does not exist') else: raise OstracionError('Insufficient permissions')
def dbGetUserRoles(db, user, asDict=False): """ Retrieve roles associated to a user. Here we implement the automatic attribution of anonymous role to unauthenticated visitors. """ anonymousRole = dbRetrieveRecordByKey( db, 'roles', { 'role_id': 'anonymous', 'role_class': 'system' }, dbTablesDesc=dbSchema, ) # if user.is_authenticated: for userRole in (ur for urBlock in (dbRetrieveRecordsByKey( db, 'user_roles', {'username': user.username}, dbTablesDesc=dbSchema, ), (anonymousRole, )) for ur in urBlock): # role = dbRetrieveRecordByKey( db, 'roles', { 'role_class': userRole['role_class'], 'role_id': userRole['role_id'], }, dbTablesDesc=dbSchema, ) # if asDict: yield role else: yield Role(**role) else: if asDict: yield anonymousRole else: yield anonymousRole(**role)
def getBoxesFromParent(db, parentBox, user, accountDeletionInProgress=False): """ Return, as in Yield, all boxes in a given box: if boxes are not accessible, None's are returned instead (which is important for some callers as it tells them the parentBox has indeed sub-boxes, albeit invisible to user). """ for boxDict in dbRetrieveRecordsByKey( db, 'boxes', {'parent_id': parentBox.box_id}, dbTablesDesc=dbSchema, ): # newPermissionLayer = list( dbGetBoxRolePermissions(db, boxDict['box_id']) ) if accountDeletionInProgress or userHasPermission( db, user, parentBox.permissions, 'r', ): thisBox = Box(**boxDict) thisBox.updatePermissionData( fromBox=parentBox, lastPermissionLayer=newPermissionLayer, ) if accountDeletionInProgress or userHasPermission( db, user, thisBox.permissions, 'r', ): yield thisBox else: yield None else: # the mere existence of not-visible-at-all boxes # must be reported, e.g. for the deletebox chain of calls yield None
def sqliteLikeSubstringSearch( db, searchTerm, searchBoxes, searchFiles, searchLinks): """ Perform a file/box search using the sqlite "like" operator. Limited, but fast. No other options available in this avenue. See e.g. https://www.sqlitetutorial.net/sqlite-like/ for escaping "like" statements. Returns a map { 'files': [ { 'item': File object, 'score': number }, ... ], 'boxes': [ { 'item': Box object, 'score': number } ], } """ escapedSearchTerm = escapeForSqlite(searchTerm) # if searchFiles: foundFiles = [ { 'item': File(**fileDict), 'score': 1.0, } for fileDict in dbRetrieveRecordsByKey( db, 'files', {}, whereClauses=[ ( 'name LIKE ? ESCAPE \'\\\'', '%' + escapedSearchTerm + '%', ), ], dbTablesDesc=dbSchema, ) ] else: foundFiles = [] if searchBoxes: foundBoxes = [ { 'item': Box(**boxDict), 'score': 1.0, } for boxDict in dbRetrieveRecordsByKey( db, 'boxes', {}, whereClauses=[ ( 'box_name LIKE ? ESCAPE \'\\\'', '%' + escapedSearchTerm + '%', ), ], dbTablesDesc=dbSchema, ) if boxDict['box_id'] != '' ] else: foundBoxes = [] # return { 'files': foundFiles, 'boxes': foundBoxes, }