def dbDeleteTicket(db, ticketId, user, mode, skipCommit=False): """ Remove a ticket from DB.""" ticketDict = dbRetrieveRecordByKey( db, 'tickets', {'ticket_id': ticketId}, dbTablesDesc=dbSchema, ) if (ticketDict is not None and ticketTargetTypeToModeNameMap[ticketDict['target_type']] == mode): ticket = Ticket(**ticketDict) if userIsAdmin(db, user) or user.username == ticket.username: # dbDeleteRecordsByKey( db, 'tickets', {'ticket_id': ticketId}, dbTablesDesc=dbSchema, ) if not skipCommit: db.commit() else: raise OstracionError('Insufficient permissions') else: raise OstracionWarning('Ticket unavailable')
def dbMakeUserInvitationTicket(db, ticketName, validityHours, userName, userFullName, userEmail, ticketMessage, user, urlRoot, settings): """ Generate a ticket to be used to create a user (with/out username pre-specified. This is an admin-only operation. """ if isTicketIssuablePerSettings(validityHours, 1, settings): ''' only admins can do this by design ''' if userIsAdmin(db, user): ticketId, securityCode = randomTicketNumbers(user) issueDate = datetime.datetime.now() metadata = { k: v for k, v in { 'username': userName, 'fullname': userFullName, 'email': userEmail, 'message': ticketMessage, }.items() if v is not None } expirationDate = None if validityHours is None else ( issueDate + datetime.timedelta(hours=validityHours)) newTicket = Ticket( ticket_id=ticketId, name=ticketName, security_code=securityCode, username=user.username, issue_date=issueDate, expiration_date=expirationDate, multiplicity=1, target_type='user', metadata=json.dumps(metadata), last_redeemed=None, times_redeemed=0, ) # dbAddRecordToTable( db, 'tickets', newTicket.asDict(), dbTablesDesc=dbSchema, ) db.commit() return makeTicketMagicLink(newTicket, urlRoot) else: raise OstracionError('Insufficient permissions') else: raise OstracionError( 'Ticket parameters not allowed under the current settings')
def selectAvailableInfoItems(db, user, gg): """ Return a page descriptor adapted to the available "info" pages. """ return filterPageDescriptor( infoPageDescriptor, subTasksAccessibility={ 'root': { 'admin_guide': userIsAdmin(db, user), }, }, )
def dbGetAllUsers(db, user, accountDeletionInProgress=False): """Get a listing of all existing users (except the '' system user).""" if accountDeletionInProgress or userIsAdmin(db, user): return ( User(**u) for u in dbRetrieveAllRecords( db, 'users', dbTablesDesc=dbSchema, ) if u['username'] != '' ) else: raise OstracionError('Insufficient permissions')
def userThumbnailView(dummyId, username): """Route for access to thumbnail image files based on user name.""" user = g.user db = dbGetDatabase() fileStorageDirectory = g.settings['system']['system_directories'][ 'fs_directory']['value'] if user.username == username or userIsAdmin(db, user): targetUser = (user if user.username == username else dbGetUser( db, username)) if targetUser.icon_file_id != '': filePhysicalPath, filePhysicalName = fileIdToSplitPath( targetUser.icon_file_id, fileStorageDirectory=fileStorageDirectory, ) return send_from_directory( filePhysicalPath, filePhysicalName, mimetype=targetUser.icon_mime_type, ) else: return redirect(makeSettingImageUrl(g, 'user_images', 'user_icon')) else: return abort(400, 'User has no permission to access this resource.')
def dbUpdateStandardSettingDict(db, enrichedSetting, newFormValue, user, skipCommit=False): """ Update a non-image setting with a new value (taking care of deforming before the actual writing to DB). """ if userIsAdmin(db, user): deformedValue = _deformSettingValueByType( enrichedSetting['setting'].type, newFormValue, ) newSettingDict = recursivelyMergeDictionaries( { 'value': deformedValue, }, defaultMap={ k: v for k, v in enrichedSetting['setting'].asDict().items() if k in {'value', 'icon_mime_type', 'group_id', 'id'} }) # if (enrichedSetting['setting'].type == 'string' and enrichedSetting['metadata'].get('is_text_image', False)): # we handle the special case of deleting outdated # image-text that may have been produced # # this largerSettingDict is used only to determine the nextValue largerNextSettingDict = recursivelyMergeDictionaries( { 'value': deformedValue, }, defaultMap={ k: v for k, v in enrichedSetting['setting'].asDict().items() if k in {'value', 'type', 'default_value'} }) # prevValue = enrichedSetting['value'] nextValue = _getValueFromSetting(Setting(**largerNextSettingDict)) # if there is a picture-with-text to be superseded, delete it prevPath, prevTitle, prevTag = determineManagedTextImagePath( prevValue, prefix='%s/%s' % ( enrichedSetting['setting'].group_id, enrichedSetting['setting'].id, ), ) nextPath, nextTitle, nextTag = determineManagedTextImagePath( nextValue, prefix='%s/%s' % ( enrichedSetting['setting'].group_id, enrichedSetting['setting'].id, ), ) if prevTag != nextTag: prevFileName = os.path.join( prevPath, prevTitle, ) if os.path.isfile(prevFileName): # delete the old, unused file os.remove(prevFileName) # dbUpdateRecordOnTable(db, 'settings', newSettingDict, dbTablesDesc=dbSchema, allowPartial=True) if not skipCommit: db.commit() else: raise OstracionError('Insufficient permissions')
def storeFileAsThumbnail(db, fileToSave, mode, thumbnailFormat, targetItem, parentBox, user, tempFileDirectory, fileStorageDirectory): """ Handle setting/unsetting of thumbnail for various items (box,file,user,setting,user-as-admin). If a file to save is provided: store the file on the temp dir and if it is a valid thumbnail deal with its preparation and setting on the item, including possibly deletion of the previous thumbnail if necessary. if None is passed: simply delete any previous thumbnail if present Return True iff the (un/)setting is successful """ # permission checks if mode == 'b': if not userHasPermission(db, user, targetItem.permissions, 'w'): raise OstracionError('User has no icon permission on this item') elif mode == 'f': if not userHasPermission(db, user, parentBox.permissions, 'w'): raise OstracionError('User has no icon permission on this item') elif mode == 'l': if not userHasPermission(db, user, parentBox.permissions, 'w'): raise OstracionError('User has no icon permission on this item') elif mode == 'u': if user.username != targetItem.username: raise OstracionError('Insufficient permissions') elif mode == 'au': if not userIsAdmin(db, user): raise OstracionError('Insufficient permissions') elif mode == 's': if not userIsAdmin(db, user): raise OstracionError('Insufficient permissions') # if fileToSave is not None: tempFileName = temporaryFileName(tempFileDirectory=tempFileDirectory) fileToSave.save(tempFileName) fileProperties = determineFileProperties(tempFileName) else: tempFileName = None # failures = False if tempFileName is None: thumbnailId = None thbMimeType = None else: if isImageMimeType(fileProperties['file_mime_type']): # make thumbnail and get the new ID thumbnailId, thbMimeType = makeTempFileIntoThumbnail( tempFileName, thumbnailFormat=thumbnailFormat, fileStorageDirectory=fileStorageDirectory, ) else: failures = True if not failures: # un/set the icon ID if mode == 'f': fsDeleteQueue = updateFileThumbnail( db, targetItem, thumbnailId, thbMimeType, user, fileStorageDirectory=fileStorageDirectory) elif mode == 'l': fsDeleteQueue = updateLinkThumbnail( db, targetItem, thumbnailId, thbMimeType, user, fileStorageDirectory=fileStorageDirectory) elif mode == 'b': fsDeleteQueue = updateBoxThumbnail( db, targetItem, thumbnailId, thbMimeType, user, fileStorageDirectory=fileStorageDirectory) elif mode in {'u', 'au'}: fsDeleteQueue = updateUserThumbnail( db, targetItem, thumbnailId, thbMimeType, user, fileStorageDirectory=fileStorageDirectory) elif mode == 's': fsDeleteQueue = updateSettingThumbnail( db, targetItem, thumbnailId, thbMimeType, user, fileStorageDirectory=fileStorageDirectory) else: raise NotImplementedError('Unhandled storeFileAsThumbnail mode') flushFsDeleteQueue(fsDeleteQueue) # return not failures
def createUserUponTicket(db, user, issuer, richTicket, urlRoot): """User-creation-ticket route.""" ticketsByformerAdminsAreProtected = g.settings['behaviour'][ 'behaviour_tickets']['protect_nonadmin_user_password_tickets']['value'] appLongName = g.settings['behaviour']['behaviour_appearance'][ 'application_long_name']['value'] if not ticketsByformerAdminsAreProtected or userIsAdmin(db, issuer): form = generateNewUserForm(g.settings) if form.validate_on_submit(): userDict = { 'username': form.username.data, 'fullname': form.fullname.data, 'email': form.email.data, 'password': form.password.data, } if ('username' in richTicket['metadata'] and richTicket['metadata']['username'] != userDict['username']): raise RuntimeError( 'Detected attempt to escape username set by ticket issuer') else: # the usename must not exist (relevant if left free in ticket) if isUsername(db, userDict['username'], user): if 'username' in richTicket['metadata']: request._onErrorUrl = url_for('lsView') else: request._onErrorUrl = url_for( 'redeemTicketView', mode='u', ticketId=ticketId, securityCode=securityCode, ) raise OstracionError('Username "%s" exists already' % userDict['username']) else: # we proceed with the user creation proper newUser = User( icon_file_id='', icon_file_id_username=userDict['username'], banned=0, terms_accepted='0', terms_accepted_version='', **userDict, ) try: dbPunchRichTicket(db, richTicket, skipCommit=True) dbCreateUser(db, newUser, user) # flashMessage( 'Info', 'Success', 'User created. You can now log in to %s' % (appLongName), ) return redirect(url_for('loginView')) except Exception as e: db.rollback() raise e else: form.username.data = applyDefault( form.username.data, richTicket['metadata'].get('username', ''), ) form.fullname.data = applyDefault( form.fullname.data, richTicket['metadata'].get('fullname', ''), ) form.email.data = applyDefault( form.email.data, richTicket['metadata'].get('email', ''), ) return render_template( 'newuser.html', form=form, user=user, pageTitle='Create user', pageSubtitle='Create your user account on %s%s' % ( appLongName, ('' if richTicket['metadata'].get('message') is None else '. Message on ticket: "%s"' % (richTicket['metadata']['message'])), ), iconUrl=makeSettingImageUrl(g, 'user_images', 'user_icon'), lockUsernameField='username' in richTicket['metadata'], ) else: raise OstracionError('Ticket not acessible or expired') return redirect(url_for('lsView'))
def changePasswordUponTicket(db, user, issuer, richTicket, urlRoot): """Change-password-ticket route.""" ticketsByformerAdminsAreProtected = g.settings['behaviour'][ 'behaviour_tickets']['protect_nonadmin_user_password_tickets']['value'] applicationLongName = g.settings['behaviour']['behaviour_appearance'][ 'application_long_name']['value'] if not ticketsByformerAdminsAreProtected or userIsAdmin(db, issuer): form = generateTicketChangePasswordForm(g.settings) if form.validate_on_submit(): changeeUser = dbGetUser(db, richTicket['metadata']['username']) if form.username.data == changeeUser.username: # newPassword = form.newpassword.data minPasswordLength = g.settings['behaviour'][ 'behaviour_security']['password_min_length']['value'] if len(form.newpassword.data) < minPasswordLength: print('richTicket ', richTicket) flashMessage( 'Info', 'Please retry', 'New password too short (min. %i characters)' % (minPasswordLength, ), ) return redirect( url_for( 'redeemTicketView', mode='p', ticketId=richTicket['ticket'].ticket_id, securityCode=richTicket['ticket'].security_code, )) else: newUser = User( **({(k if k != 'passwordhash' else 'password'): ( v if k != 'passwordhash' else form.newpassword.data ) for k, v in changeeUser.asDict().items()})) try: dbPunchRichTicket(db, richTicket, skipCommit=True) dbUpdateUser(db, newUser, user, skipCommit=True) db.commit() # flash a message flashMessage( 'Success', 'Success', 'Password changed. You can now log in to %s' % (applicationLongName, ), ) # go to login return redirect(url_for('loginView')) except Exception as e: db.rollback() raise e else: raise OstracionError('Wrong username provided') else: pageSubtitle = ('Complete the process by entering your ' 'new password twice%s') % ( '' if richTicket['metadata'].get('message') is None else '. Message on ticket: "%s"' % (richTicket['metadata'].get('message'), )) return render_template( 'userchangepassword.html', user=user, form=form, showOldPasswordField=False, mode='ticket', breadCrumbs=None, pageTitle='Change password', pageSubtitle=pageSubtitle, iconUrl=makeSettingImageUrl(g, 'admin_images', 'change_password_ticket'), backToUrl=url_for('lsView'), ) else: raise OstracionError('Ticket not acessible or expired')
def lsView(lsPathString=''): """LS-of-a-box route, additionally with 'tasks' if viewing root.""" user = g.user lsPath = splitPathString(lsPathString) db = dbGetDatabase() thisBox = getBoxFromPath(db, lsPath, user) boxPath = lsPath[1:] # showBoxPermissionToAll = g.settings['behaviour']['behaviour_permissions'][ 'show_permission']['value'] # if thisBox is not None: request._onErrorUrl = url_for('lsView') if thisBox.box_id == '': tasks = prepareRootTasks(db, g, user) else: tasks = [] boxes = [ { 'box': box, 'path': boxPath + [box.box_name], 'info': prepareBoxInfo(db, box), 'actions': prepareBoxActions( db, box, boxPath + [box.box_name], thisBox, user ), } for box in sorted( ( b for b in getBoxesFromParent(db, thisBox, user) if b is not None ), key=lambda b: (b.box_name.lower(), b.box_name), ) if box.box_id != '' ] files = [ { 'file': file, 'path': boxPath + [file.name], 'nice_size': formatBytesSize(file.size), 'info': prepareFileInfo(db, file), 'actions': prepareFileActions( db, file, boxPath + [file.name], thisBox, user ), } for file in sorted( getFilesFromBox(db, thisBox), key=lambda f: (f.name.lower(), f.name), ) ] links = [ { 'link': link, 'path': boxPath + [link.name], 'info': prepareLinkInfo(db, link), 'actions': prepareLinkActions( db, link, boxPath + [link.name], thisBox, user ), } for link in sorted( getLinksFromBox(db, thisBox), key=lambda l: (l.name.lower(), l.name), ) ] # pathBCrumbs = makeBreadCrumbs(lsPath, g) boxNiceName = transformIfNotEmpty(thisBox.box_name) if thisBox.box_id == '': boxTitle, boxDescription = describeRootBoxCaptions(g) else: boxTitle = describeBoxTitle(thisBox) boxDescription = thisBox.description # boxActions = prepareBoxHeaderActions( db, thisBox, boxPath, user, g.settings, discardedActions=( set() if len(files) > 0 else {'gallery_view', 'issue_gallery_ticket'} ), ) showAdminToolsLink = userIsAdmin(db, user) if showBoxPermissionToAll or userIsAdmin(db, user): thisBoxPermissionAlgebra = calculateBoxPermissionAlgebra( thisBox.permissionHistory, thisBox.permissions, ) # roleKeyToRoleMap = { r.roleKey(): r for r in dbGetAllRoles(db, user) if r.can_box != 0 } structuredPermissionInfo = reformatBoxPermissionAlgebraIntoLists( thisBoxPermissionAlgebra, roleKeyToRoleMap, ) # permissionInfo = { 'powers': structuredPermissionInfo, 'assignments': { 'edit_url': ( url_for( 'adminLsPermissionsView', lsPathString='/'.join(boxPath), ) if showAdminToolsLink else None ), 'native': [ { 'role_class': brp.role_class, 'role_id': brp.role_id, 'r': brp.r, 'w': brp.w, 'c': brp.c, 'role': roleKeyToRoleMap[( brp.role_class, brp.role_id, )], } for brp in sorted(thisBox.listPermissions('native')) ], 'inherited': [ { 'role_class': brp.role_class, 'role_id': brp.role_id, 'r': brp.r, 'w': brp.w, 'c': brp.c, 'role': roleKeyToRoleMap[( brp.role_class, brp.role_id, )], } for brp in sorted(thisBox.listPermissions('inherited')) ], }, } else: permissionInfo = None # if len(boxes) + len(files) + len(links) > 0: foundCounts = [ (len(boxes), 'box', 'boxes'), (len(files), 'file', 'files'), (len(links), 'link', 'links'), ] foundParts = pickSingularPluralSentences( foundCounts, keepZeroes=False, ) boxChildrenCounter = colloquialJoinClauses(foundParts) else: boxChildrenCounter = 'no contents' # return render_template( 'ls.html', user=user, thisBox=thisBox, boxTitle=boxTitle, boxNiceName=boxNiceName, boxDescription=boxDescription, pageTitle=boxNiceName, boxChildrenCounter=boxChildrenCounter, boxActions=boxActions, boxPath=boxPath, permissionInfo=permissionInfo, breadCrumbs=pathBCrumbs, tasks=tasks, boxes=boxes, files=files, links=links, ) else: request._onErrorUrl = url_for( 'lsView', lsPathString='/'.join(lsPath[1:-1]), ) raise OstracionWarning( 'Cannot access the specified box "%s"' % lsPath[-1] )
def dbDeleteUser(db, username, user, fileStorageDirectory): """ Delete a user altogether. Return a fsDeletionQueue for deletions.""" if username != '': if not userIsAdmin(db, dbGetUser(db, username)): try: if username == user.username or userIsAdmin(db, user): fsDeleteQueue = [] # 1. cleanup of file system rootBox = getRootBox(db) fsDeleteQueue += _traverseForAccountDeletion( db, rootBox, username, user, path=[''], fileStorageDirectory=fileStorageDirectory, ) # 2. deleting user-related data around dbDeleteRecordsByKey( db, 'user_roles', {'username': username}, dbTablesDesc=dbSchema, ) deleteeUser = dbGetUser(db, username) if deleteeUser.icon_file_id != '': fsDeleteQueue.append(fileIdToPath( deleteeUser.icon_file_id, fileStorageDirectory=fileStorageDirectory, )) dbDeleteRecordsByKey( db, 'tickets', {'username': username}, dbTablesDesc=dbSchema, ) for u in dbGetAllUsers(db, user, accountDeletionInProgress=True): if u.username != username: if u.icon_file_id_username == username: if u.icon_file_id != '': fsDeleteQueue.append(fileIdToPath( u.icon_file_id, fileStorageDirectory, )) dbUpdateUser( db, User(**recursivelyMergeDictionaries( { 'icon_file_id': '', 'icon_file_id_username': '', }, defaultMap=u.asDict(), )), user, skipCommit=True, ) # 3. delete user-specific role association from boxes dbDeleteRecordsByKey( db, 'box_role_permissions', {'role_class': 'user', 'role_id': username}, dbTablesDesc=dbSchema, ) # 4. delete user-specific role dbDeleteRecordsByKey( db, 'roles', {'role_class': 'user', 'role_id': username}, dbTablesDesc=dbSchema ) # 5. finally, delete the user dbDeleteRecordsByKey( db, 'users', {'username': username}, dbTablesDesc=dbSchema ) db.commit() return fsDeleteQueue else: raise OstracionError('Insufficient permissions') except Exception as e: db.rollback() raise e else: raise OstracionError('Cannot delete an admin') else: raise OstracionError('Cannot alter system user')
def setIconView(mode, itemPathString=''): """ Route to set/replace the thumbnail of various items.""" if (mode == 'au' and not g.settings['behaviour']['behaviour_admin_powers'] ['admin_is_god']['value']): request._onErrorUrl = url_for('adminHomeUsersView') raise OstracionError('This feature is turned off in the configuration') else: user = g.user form = UploadIconForm() db = dbGetDatabase() tempFileDirectory = g.settings['system']['system_directories'][ 'temp_directory']['value'] fileStorageDirectory = g.settings['system']['system_directories'][ 'fs_directory']['value'] if mode == 'b': boxPath = splitPathString(itemPathString) request._onErrorUrl = url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), ) parentBox = None thisItem = getBoxFromPath(db, boxPath, user) itemName = thisItem.getName() pageFeatures = { 'breadCrumbs': makeBreadCrumbs( splitPathString(itemPathString), g, appendedItems=[{ 'kind': 'link', 'target': None, 'name': 'Icon', }], ), } elif mode == 'f': fullPath = splitPathString(itemPathString) boxPath, fileName = fullPath[:-1], fullPath[-1] request._onErrorUrl = url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), ) parentBox = getBoxFromPath(db, boxPath, user) thisItem = getFileFromParent(db, parentBox, fileName, user) itemName = thisItem.getName() pageFeatures = { 'breadCrumbs': makeBreadCrumbs( splitPathString(itemPathString)[:-1], g, appendedItems=[{ 'kind': 'file', 'target': thisItem, }, { 'kind': 'link', 'target': None, 'name': 'Icon', }], ), } elif mode == 'l': fullPath = splitPathString(itemPathString) boxPath, linkName = fullPath[:-1], fullPath[-1] request._onErrorUrl = url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), ) parentBox = getBoxFromPath(db, boxPath, user) thisItem = getLinkFromParent(db, parentBox, linkName, user) itemName = thisItem.getName() pageFeatures = { 'breadCrumbs': makeBreadCrumbs( splitPathString(itemPathString)[:-1], g, appendedItems=[{ 'kind': 'external_link', 'target': thisItem, }, { 'kind': 'link', 'target': None, 'name': 'Icon', }], ), } elif mode == 'u': pageFeatures = prepareTaskPageFeatures( userProfilePageDescriptor, ['root', 'icon'], g, overrides={ 'pageTitle': None, 'pageSubtitle': None, 'iconUrl': None, }, ) thisItem = user itemName = thisItem.getName() parentBox = None elif mode == 'au': pageFeatures = prepareTaskPageFeatures( adminPageDescriptor, ['root', 'users'], g, appendedItems=[{ 'kind': 'link', 'link': False, 'target': None, 'name': 'Icon', }], overrides={ 'pageTitle': None, 'pageSubtitle': None, 'iconUrl': None, }, ) if userIsAdmin(db, user): thisItem = dbGetUser(db, itemPathString) itemName = thisItem.getName() parentBox = None else: raise OstracionError('Insufficient permissions') elif mode == 's': pageFeatures = prepareTaskPageFeatures( adminPageDescriptor, ['root', 'settings', 'images'], g, appendedItems=[{ 'kind': 'link', 'link': False, 'target': None, 'name': 'Set image', }], overrides={ 'pageTitle': None, 'pageSubtitle': None, 'iconUrl': None, }, ) if userIsAdmin(db, user): settingGroupId, settingId = itemPathString.split('/') thisItem = g.settings['image'][settingGroupId][settingId] itemName = thisItem['setting'].getName() parentBox = None else: raise OstracionError('Insufficient permissions') else: raise RuntimeError('Unknown mode encountered') # if form.validate_on_submit(): # storageSuccess = storeFileAsThumbnail( db, fileToSave=form.file.data, mode=mode, thumbnailFormat=determineThumbnailFormatByModeAndTarget( db, mode, thisItem, ), targetItem=thisItem, parentBox=parentBox, user=user, tempFileDirectory=tempFileDirectory, fileStorageDirectory=fileStorageDirectory, ) if not storageSuccess: raise OstracionError('Could not set the icon') # if mode in {'f', 'b', 'l'}: return redirect( url_for( 'lsView', lsPathString='/'.join(boxPath[1:-1] if mode == 'b' else boxPath[1:]), )) elif mode == 'u': return redirect(url_for('userProfileView', )) elif mode == 'au': return redirect(url_for('adminHomeUsersView', )) elif mode == 's': return redirect(url_for('adminHomeSettingsImagesView', )) else: raise RuntimeError('Unknown mode encountered') else: # titleMap = { 'f': 'Set File Icon', 'l': 'Set Link Icon', 'b': 'Set Box Icon', 'u': 'Set User Icon', 'au': 'Set User Icon (as admin)', 's': 'Set Application Image', } modeNameMap = { 'f': 'for file', 'l': 'for link', 'b': 'for box', 'u': 'for user', 'au': '(as admin) for user', 's': 'for setting', } finalPageFeatures = recursivelyMergeDictionaries( { 'pageTitle': titleMap[mode], 'pageSubtitle': 'Upload an image file %s "%s"' % ( modeNameMap[mode], itemName, ), }, defaultMap=pageFeatures, ) if mode == 'u': finalPageFeatures['iconUrl'] = url_for( 'userThumbnailView', dummyId='%s_' % thisItem.icon_file_id, username=thisItem.username, ) elif mode == 'au': finalPageFeatures['iconUrl'] = url_for( 'userThumbnailView', dummyId='%s_' % thisItem.icon_file_id, username=thisItem.username, ) elif mode == 's': finalPageFeatures['iconUrl'] = makeSettingImageUrl( g, settingGroupId, settingId, ) elif mode == 'b': finalPageFeatures['iconUrl'] = url_for( 'boxThumbnailView', dummyId=thisItem.icon_file_id + '_', boxPathString='/'.join(boxPath[1:]), ) elif mode == 'f': finalPageFeatures['iconUrl'] = url_for( 'fileThumbnailView', dummyId=thisItem.icon_file_id + '_', fsPathString='/'.join(boxPath[1:] + [thisItem.name]), ) elif mode == 'l': finalPageFeatures['iconUrl'] = url_for( 'linkThumbnailView', dummyId=thisItem.icon_file_id + '_', fsPathString='/'.join(boxPath[1:] + [thisItem.name]), ) # return render_template( 'uploadicon.html', form=form, user=user, mode=mode, itemPathString=itemPathString, **finalPageFeatures, )
def unsetIconView(mode, itemPathString=''): """Route for explicit removal of thumbnail, if any, to various items.""" if (mode == 'au' and not g.settings['behaviour']['behaviour_admin_powers'] ['admin_is_god']['value']): request._onErrorUrl = url_for('adminHomeUsersView') raise OstracionError('This feature is turned off in the configuration') else: user = g.user form = UploadIconForm() db = dbGetDatabase() # tempFileDirectory = g.settings['system']['system_directories'][ 'temp_directory']['value'] fileStorageDirectory = g.settings['system']['system_directories'][ 'fs_directory']['value'] # if mode == 'b': modeName = 'box' boxPath = splitPathString(itemPathString) thisItem = getBoxFromPath(db, boxPath, user) parentBox = None elif mode == 'f': modeName = 'file' fullPath = splitPathString(itemPathString) boxPath, fileName = fullPath[:-1], fullPath[-1] parentBox = getBoxFromPath(db, boxPath, user) thisItem = getFileFromParent(db, parentBox, fileName, user) elif mode == 'l': modeName = 'link' fullPath = splitPathString(itemPathString) boxPath, linkName = fullPath[:-1], fullPath[-1] parentBox = getBoxFromPath(db, boxPath, user) thisItem = getLinkFromParent(db, parentBox, linkName, user) elif mode == 'u': modeName = 'user' parentBox = None thisItem = user elif mode == 'au': modeName = 'adminuser' if userIsAdmin(db, user): thisItem = dbGetUser(db, itemPathString) parentBox = None else: raise OstracionError('Insufficient permissions') elif mode == 's': modeName = 'settingIcon' if userIsAdmin(db, user): settingGroupId, settingId = itemPathString.split('/') thisItem = g.settings['image'][settingGroupId][settingId] parentBox = None else: raise OstracionError('Insufficient permissions') else: raise RuntimeError('Unknown mode encountered') # storageSuccess = storeFileAsThumbnail( db, fileToSave=None, mode=mode, thumbnailFormat=determineThumbnailFormatByModeAndTarget( db, mode, thisItem, ), targetItem=thisItem, parentBox=parentBox, user=user, tempFileDirectory=tempFileDirectory, fileStorageDirectory=fileStorageDirectory, ) if not storageSuccess: raise OstracionError('Could not unset the icon') # if mode in {'f', 'b', 'l'}: return redirect( url_for( 'lsView', lsPathString='/'.join(boxPath[1:-1] if mode == 'b' else boxPath[1:]), )) elif mode == 'u': return redirect(url_for('userProfileView', )) elif mode == 'au': return redirect(url_for('adminHomeUsersView', )) elif mode == 's': return redirect(url_for('adminHomeSettingsImagesView', )) else: raise RuntimeError('Unknown mode encountered')
def before_request(): """ Preparation of globally-accessible info for all views, handling of special post-install situations and of banned users and logged-in-only setups. """ db = dbGetDatabase() g.user = current_user g.settings = dbLoadAllSettings(db, g.user) g.applicationLogoUrl = makeSettingImageUrl( g, 'ostracion_images', 'navbar_logo', ) # g.canPerformSearch = isUserWithinPermissionCircle( db, g.user, g.settings['behaviour']['search']['search_access']['value'], ) g.quickFindForm = QuickFindForm() g.canShowTreeView = isUserWithinPermissionCircle( db, g.user, g.settings['behaviour']['search']['tree_view_access']['value'], ) # task lists - must happen after the above (which set access flags) g.availableApps = selectAvailableApps(db, g.user, g) g.availableInfoItems = selectAvailableInfoItems(db, g.user, g) g.availableTools = selectAvailableTools(db, g.user, g) # if g.user.is_authenticated: g.user.setRoles(list(dbGetUserRoles(db, g.user))) if g.user.banned: flashMessage( 'Warning', 'Warning', ('Your user is momentarily banned. ' 'Please continue as anonymous'), ) logout_user() # handling of first-time post-install forced steps dirsSetUp = g.settings['managed']['post_install_finalisations'][ 'directories_set_up']['value'] if (not dirsSetUp and request.endpoint not in endpointsWithoutAppInitRerouting): if g.user.is_authenticated and userIsAdmin(db, g.user): flashMessage( 'Warning', 'Action required', ('Please review carefully the following directory settings ' 'to make the application function. Changing them later, ' 'when material is uploaded, is a disruptive operation.'), ) return redirect( url_for('adminHomeSettingsGenericView', settingType='system_settings')) else: if g.user.is_authenticated: logout_user() flashMessage( 'Warning', 'Action required', ('To finalise installation/make the application function ' 'properly, an administrator should log in and ' 'complete the setup'), ) return redirect(url_for('loginView')) else: # we care about reviewing the settings only if the dirs are OK if g.user.is_authenticated and userIsAdmin(db, g.user): if request.endpoint not in endpointsWithoutAppInitRerouting: settingsReviewed = g.settings['managed'][ 'post_install_finalisations']['settings_reviewed']['value'] if not settingsReviewed: flashMessage( 'Warning', 'Action required', ('Please carefully review the following application ' 'behaviour settings before opening the service ' 'to users (anyway, these settings can be ' 'changed at any time).'), ) return redirect( url_for('adminHomeSettingsGenericView', settingType='behaviour')) # we take care of terms-and-conditions acceptance here if request.endpoint not in endpointsWithoutTermAcceptanceBlocking: usersMustAbideByTOS = g.settings['terms']['terms']['terms_must_agree'][ 'value'] anonymousMustAbideByTOS = g.settings['terms']['terms'][ 'terms_must_agree_anonymous']['value'] currentTermVersion = g.settings['terms']['terms']['terms_version'][ 'value'] # if g.user.is_authenticated: mustAbideByTOS = usersMustAbideByTOS typeOfUsers = 'Users' storedTermsVersion = g.user.terms_accepted_version storedTermsAcceptance = safeInt( g.user.terms_accepted, default=None, ) else: mustAbideByTOS = anonymousMustAbideByTOS typeOfUsers = 'Visitors' storedTermsVersion = request.cookies.get('termsAcceptedVersion') storedTermsAcceptance = safeInt( request.cookies.get('termsAccepted'), default=None, ) # if storedTermsVersion == currentTermVersion: thisVersionAcceptance = storedTermsAcceptance else: thisVersionAcceptance = None # if thisVersionAcceptance is None: canContinueTermwise = not mustAbideByTOS elif thisVersionAcceptance == 0: # explicit not-acceptance canContinueTermwise = False else: # positive updated acceptance canContinueTermwise = True # if not canContinueTermwise: quotedTravelToPath = urllib.parse.quote_plus(request.full_path) flashMessage( 'Info', 'Action required', ('%s must review the Terms and Conditions' ' before accessing the site.') % typeOfUsers, ) return redirect( url_for( 'termsView', showAgreementButtons='y', travelTo=quotedTravelToPath, )) # here the ordinary flow is resumed if g.settings['behaviour']['behaviour_permissions'][ 'logged_in_users_only']['value']: if (not g.user.is_authenticated and request.endpoint not in endpointsWithoutInviteOnlyBlocking): return redirect(url_for('loginView'))