def fsMetadataView(fsPathString=''): """Edit-file-metadata view, a web-form.""" user = g.user db = dbGetDatabase() form = FileDataForm() lsPath = splitPathString(fsPathString) boxPath, prevFileName = lsPath[:-1], lsPath[-1] parentBox = getBoxFromPath(db, boxPath, user) request._onErrorUrl = url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), ) file = getFileFromParent(db, parentBox, prevFileName, user) if form.validate_on_submit(): newFile = File(**recursivelyMergeDictionaries( { 'name': form.filename.data, 'description': form.filedescription.data, 'metadata_username': user.username, }, defaultMap=file.asDict(), )) updateFile(db, boxPath, prevFileName, newFile, user) return redirect(url_for('lsView', lsPathString='/'.join(boxPath[1:]))) else: form.filename.data = applyDefault(form.filename.data, file.name) form.filedescription.data = applyDefault(form.filedescription.data, file.description) # pageFeatures = { 'breadCrumbs': makeBreadCrumbs( boxPath, g, appendedItems=[{ 'kind': 'file', 'target': file, }, { 'kind': 'link', 'target': None, 'name': 'Metadata', }], ), 'pageTitle': 'Edit file metadata (%s)' % file.name, 'pageSubtitle': 'Name is mandatory', 'iconUrl': url_for( 'fileThumbnailView', dummyId=file.icon_file_id + '_', fsPathString='/'.join(lsPath[1:]), ), } return render_template( 'filedataedit.html', form=form, user=user, **pageFeatures, )
def calendarMakerSettingsView(): """Calendar settings form view.""" user = g.user db = dbGetDatabase() request._onErrorUrl = url_for('calendarMakerIndexView', ) # currentCalendar = cookiesToCurrentCalendar(request.cookies) cProps = currentCalendar.get('properties', {}) currentYear = datetime.datetime.now().year form = CalendarMakerPropertyForm() # if form.validate_on_submit(): month0 = safeInt(form.month0.data, 1) year0 = form.year0.data month1 = safeInt(form.month1.data, 12) year1 = form.year1.data language = form.language.data startingweekday = safeInt(form.startingweekday.data, 6) response = redirect(url_for('calendarMakerIndexView')) dResponse = dressResponseWithCurrentCalendar( response, recursivelyMergeDictionaries( { 'properties': { 'month0': month0, 'year0': year0, 'month1': month1, 'year1': year1, 'language': language, 'startingweekday': startingweekday, }, }, defaultMap=currentCalendar, ), ) return dResponse else: form.month0.data = str(applyDefault(cProps.get('month0'), 1)) form.year0.data = applyDefault(cProps.get('year0'), currentYear) form.month1.data = str(applyDefault(cProps.get('month1'), 12)) form.year1.data = applyDefault(cProps.get('year1'), currentYear) form.language.data = applyDefault(cProps.get('language'), 'en') form.startingweekday.data = applyDefault( cProps.get('startingweekday'), 6, ) # pageFeatures = prepareTaskPageFeatures( appsPageDescriptor, ['root', 'calendar_maker', 'settings'], g, ) # return render_template( 'apps/calendarmaker/settings.html', user=user, bgcolor=g.settings['color']['app_colors']['calendar_maker_color'] ['value'], form=form, **pageFeatures, )
def fsMakeTicketView(fsPathString=''): """Create-file-ticket (file-read) view.""" user = g.user lsPath = splitPathString(fsPathString) boxPath, fileName = lsPath[:-1], lsPath[-1] db = dbGetDatabase() parentBox = getBoxFromPath(db, boxPath, user) request._onErrorUrl = url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), ) if parentBox is not None: file = getFileFromParent(db, parentBox, fileName, user) if file is not None: pathBCrumbs = makeBreadCrumbs( boxPath, g, appendedItems=[ { 'kind': 'file', 'target': file, }, { 'name': '(create ticket)', 'kind': 'link', 'target': url_for( 'fsMakeTicketView', fsPathString=fsPathString, ), 'link': False, }, ], ) # if this succeeded, user has read permission on 'file' form = generateFsTicketForm( fileModePresent=True, settings=g.settings, ) if form.validate_on_submit(): magicLink = dbMakeFileTicket( db=db, ticketName=form.name.data, validityHours=transformIfNotEmpty( form.validityhours.data, int, ), multiplicity=transformIfNotEmpty( form.multiplicity.data, int, ), ticketMessage=transformIfNotEmpty( form.ticketmessage.data, ), file=file, fileMode=form.filemode.data, lsPath=lsPath, user=user, urlRoot=request.url_root, settings=g.settings, ) flashMessage( 'Success', 'Done', ('File ticket generated. Give the recipient ' 'the following magic link:'), pillText=magicLink, ) return redirect( url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), )) else: form.name.data = applyDefault(form.name.data, file.name) form.ticketmessage.data = applyDefault( form.ticketmessage.data, 'Please access this file', ) form.filemode.data = applyDefault( form.filemode.data, 'direct', additionalNulls=['None'], ) maxValidityHours = g.settings['behaviour'][ 'behaviour_tickets']['max_ticket_validityhours']['value'] form.validityhours.data = applyDefault( form.validityhours.data, (str(maxValidityHours) if maxValidityHours is not None else ''), ) maxMultiplicity = g.settings['behaviour']['behaviour_tickets'][ 'max_ticket_multiplicity']['value'] form.multiplicity.data = applyDefault( form.multiplicity.data, (str(maxMultiplicity) if maxMultiplicity is not None else ''), ) return render_template( 'fsticket.html', pageTitle='Create public file ticket', pageSubtitle=('Recipient(s) of the ticket will be able ' 'to access "%s" without an account.') % (fsPathString, ), baseMultiplicityCaption=('Number of granted accesses (bo' 'th views and downloads count)'), user=user, form=form, iconUrl=makeSettingImageUrl( g, 'app_images', 'file_ticket', ), showFileMode=True, breadCrumbs=pathBCrumbs, ) else: return abort(404) else: return abort(404)
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 makeTicketBoxGalleryView(boxPathString=''): """Make-gallery-ticket-of-box route.""" user = g.user db = dbGetDatabase() boxPath = splitPathString(boxPathString) box = getBoxFromPath(db, boxPath, user) request._onErrorUrl = url_for('lsView', lsPathString='/'.join(boxPath[1:])) # pathBCrumbs = makeBreadCrumbs( boxPath, g, appendedItems=[ { 'name': '(create gallery ticket)', 'kind': 'link', 'target': url_for( 'makeTicketBoxGalleryView', boxPathString=boxPathString, ), 'link': False, }, ], ) form = generateFsTicketForm( fileModePresent=False, settings=g.settings, ) if form.validate_on_submit(): magicLink = dbMakeGalleryTicket( db=db, ticketName=form.name.data, validityHours=transformIfNotEmpty( form.validityhours.data, int ), multiplicity=transformIfNotEmpty( form.multiplicity.data, int ), ticketMessage=transformIfNotEmpty( form.ticketmessage.data ), box=box, boxPath=boxPath, user=user, urlRoot=request.url_root, settings=g.settings, ) flashMessage( 'Success', 'Done', ('Gallery ticket generated. Give the recipient ' 'the following magic link:'), pillText=magicLink, ) return redirect(url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), )) else: defaultName = 'Gallery-View-%s' % describeBoxName(box) form.name.data = applyDefault(form.name.data, defaultName) form.ticketmessage.data = applyDefault( form.ticketmessage.data, 'Please, look at this gallery', ) maxValidityHours = g.settings['behaviour']['behaviour_tickets'][ 'max_ticket_validityhours']['value'] form.validityhours.data = applyDefault( form.validityhours.data, str(maxValidityHours) if maxValidityHours is not None else '', ) maxMultiplicity = g.settings['behaviour']['behaviour_tickets'][ 'max_ticket_multiplicity']['value'] form.multiplicity.data = applyDefault( form.multiplicity.data, str(maxMultiplicity) if maxMultiplicity is not None else '', ) return render_template( 'fsticket.html', pageTitle='Create public gallery-view ticket', pageSubtitle=('Recipient(s) of the ticket will be able to view ' 'files (and not contained boxes) in "%s", without ' 'an account, as a gallery. If setting a number of ' 'accesses, keep in mind that every single-file view' ' counts toward the total accesses.') % ( describeBoxTitle(box) ), baseMultiplicityCaption='Number of granted accesses', user=user, form=form, iconUrl=makeSettingImageUrl(g, 'app_images', 'gallery_ticket'), showFileMode=False, breadCrumbs=pathBCrumbs, )
def makeTicketBoxUploadView(boxPathString=''): """Make-upload-ticket (to a box) route.""" user = g.user db = dbGetDatabase() boxPath = splitPathString(boxPathString) box = getBoxFromPath(db, boxPath, user) request._onErrorUrl = url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), ) # if userHasPermission(db, user, box.permissions, 'w'): # pathBCrumbs = makeBreadCrumbs( boxPath, g, appendedItems=[ { 'name': '(create upload ticket)', 'kind': 'link', 'target': url_for( 'makeTicketBoxUploadView', boxPathString=boxPathString, ), 'link': False, }, ], ) form = generateFsTicketForm( fileModePresent=False, settings=g.settings, ) if form.validate_on_submit(): magicLink = dbMakeUploadTicket( db=db, ticketName=form.name.data, validityHours=transformIfNotEmpty( form.validityhours.data, int, ), multiplicity=transformIfNotEmpty( form.multiplicity.data, int, ), ticketMessage=transformIfNotEmpty( form.ticketmessage.data, ), box=box, boxPath=boxPath, user=user, urlRoot=request.url_root, settings=g.settings, ) flashMessage( 'Success', 'Done', ('Upload ticket generated. Give the recipient ' 'the following magic link:'), pillText=magicLink, ) return redirect(url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), )) else: defaultName = 'Upload-To-%s' % ( describeBoxName(box) ) form.name.data = applyDefault(form.name.data, defaultName) form.ticketmessage.data = applyDefault( form.ticketmessage.data, 'Please, upload files to this box', ) maxValidityHours = g.settings['behaviour']['behaviour_tickets'][ 'max_ticket_validityhours']['value'] form.validityhours.data = applyDefault( form.validityhours.data, str(maxValidityHours) if maxValidityHours is not None else '', ) maxMultiplicity = g.settings['behaviour']['behaviour_tickets'][ 'max_ticket_multiplicity']['value'] form.multiplicity.data = applyDefault( form.multiplicity.data, str(maxMultiplicity) if maxMultiplicity is not None else '', ) return render_template( 'fsticket.html', pageTitle='Create public upload ticket', pageSubtitle=('Recipient(s) of the ticket will be able to ' 'upload to "%s", without an account, on ' 'your behalf.') % ( describeBoxTitle(box) ), baseMultiplicityCaption='Number of granted file uploads', user=user, form=form, iconUrl=makeSettingImageUrl(g, 'app_images', 'upload_ticket'), showFileMode=False, breadCrumbs=pathBCrumbs, ) # else: raise OstracionError('Insufficient permissions')
def metadataBoxView(boxPathString=''): """edit-metadata-of-box route.""" user = g.user db = dbGetDatabase() boxPath = splitPathString(boxPathString) box = getBoxFromPath(db, boxPath, user) parentBox = getBoxFromPath(db, boxPath[:-1], user) request._onErrorUrl = url_for( 'lsView', lsPathString='/'.join(boxPath[1:-1]), ) # form = makeMakeBoxForm('Save')() if parentBox is None: # target box was root raise OstracionError('Cannot act on this object') else: if box is not None: # if form.validate_on_submit(): newBox = Box( **recursivelyMergeDictionaries( { 'box_name': form.boxname.data, 'title': form.boxtitle.data, 'description': form.boxdescription.data, 'metadata_username': user.username, }, defaultMap=box.asDict(), ) ) updateBox(db, boxPath, newBox, user) return redirect(url_for( 'lsView', lsPathString='/'.join(boxPath[1:-1]), )) else: form.boxname.data = applyDefault( form.boxname.data, box.box_name, ) form.boxdescription.data = applyDefault( form.boxdescription.data, box.description, ) form.boxtitle.data = applyDefault( form.boxtitle.data, box.title, ) pathBCrumbs = makeBreadCrumbs( boxPath, g, appendedItems=[{ 'kind': 'link', 'target': None, 'name': 'Metadata', }], ) return render_template( 'makebox.html', form=form, user=user, breadCrumbs=pathBCrumbs, pageTitle='Edit box metadata', pageSubtitle='Name and title are mandatory', iconUrl=url_for( 'boxThumbnailView', dummyId=box.icon_file_id + '_', boxPathString='/'.join(boxPath[1:]), ), ) # else: raise OstracionWarning('Box not accessible') return redirect(url_for( 'lsView', lsPathString='/'.join(boxPath[1:-1]), ))
def fsLinkMetadataView(fsPathString=''): """Edit-link-metadata view, a web-form.""" user = g.user db = dbGetDatabase() form = EditLinkForm() lsPath = splitPathString(fsPathString) boxPath, prevLinkName = lsPath[:-1], lsPath[-1] parentBox = getBoxFromPath(db, boxPath, user) request._onErrorUrl = url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), ) link = getLinkFromParent(db, parentBox, prevLinkName, user) if form.validate_on_submit(): newLink = Link(**recursivelyMergeDictionaries( { 'name': form.linkname.data, 'description': form.linkdescription.data, 'title': form.linktitle.data, 'target': form.linktarget.data, 'metadata_username': user.username, 'metadata_dict': { 'open_in_new_window': form.openinnewwindow.data, }, }, defaultMap={ k: v for k, v in link.asDict().items() if k not in { 'metadata', 'dvector_description', 'dvector_name', 'dvector_title' } }, )) updateLink(db, boxPath, prevLinkName, newLink, user) return redirect(url_for('lsView', lsPathString='/'.join(boxPath[1:]))) else: form.linkname.data = applyDefault(form.linkname.data, link.name) form.linkdescription.data = applyDefault(form.linkdescription.data, link.description) form.linktitle.data = applyDefault(form.linktitle.data, link.title) form.linktarget.data = applyDefault(form.linktarget.data, link.target) form.openinnewwindow.data = link.getMetadata( 'open_in_new_window', True, ) # pageFeatures = { 'breadCrumbs': makeBreadCrumbs( boxPath, g, appendedItems=[{ 'kind': 'external_link', 'target': link, }, { 'kind': 'link', 'target': None, 'name': 'Metadata', }], ), 'pageTitle': 'Edit link metadata (%s)' % link.name, 'pageSubtitle': 'Name and target are mandatory', 'iconUrl': url_for( 'linkThumbnailView', dummyId=link.icon_file_id + '_', fsPathString='/'.join(lsPath[1:]), ), } return render_template( 'editlink.html', form=form, user=user, **pageFeatures, )
def findView(): """Complete (i.e. in-page) box- and file-find route.""" user = g.user db = dbGetDatabase() form = FindForm() # if not g.canPerformSearch: raise OstracionError('Insufficient permissions') # if form.validate_on_submit(): # search parameter collection searchMode = form.searchMode.data searchBoxes = form.searchTypeBoxes.data searchFiles = form.searchTypeFiles.data searchLinks = form.searchTypeLinks.data searchInDescription = form.searchFieldDescription.data searchTerm = form.text.data options = { 'mode': searchMode, 'searchBoxes': searchBoxes, 'searchFiles': searchFiles, 'searchLinks': searchLinks, 'useDescription': searchInDescription, } # initTime = time.time() findResults = fsFind( db, searchTerm, user, options=options, ) resultsDescription = describeFindResults(findResults) elapsed = time.time() - initTime # pageFeatures = prepareTaskPageFeatures( toolsPageDescriptor, ['root', 'search'], g, overrides={ 'pageTitle': 'Search results', 'pageSubtitle': 'Search term: "%s"' % searchTerm, }, ) return render_template( 'findform.html', user=user, form=form, findResults=findResults, resultsDescription=resultsDescription, elapsed=elapsed, searchTerm=searchTerm, **pageFeatures, ) else: # form.searchMode.data = applyDefault( form.searchMode.data, 'sim_ci', additionalNulls=['None'], ) print(form.searchTypeBoxes.data) form.searchTypeBoxes.data = applyDefault( form.searchTypeBoxes.data, True, ) form.searchTypeFiles.data = applyDefault( form.searchTypeFiles.data, True, ) form.searchTypeLinks.data = applyDefault( form.searchTypeLinks.data, True, ) print(form.searchTypeBoxes.data) pageFeatures = prepareTaskPageFeatures( toolsPageDescriptor, ['root', 'search'], g, ) return render_template( 'findform.html', user=user, form=form, results=None, **pageFeatures, )
def editTextFileView(fsPathString=''): """Edit-text-file route.""" user = g.user db = dbGetDatabase() lsPath = splitPathString(fsPathString) boxPath, fileName = lsPath[:-1], lsPath[-1] request._onErrorUrl = url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), ) fileStorageDirectory = g.settings['system']['system_directories'][ 'fs_directory']['value'] parentBox = getBoxFromPath(db, boxPath, user) file = getFileFromParent(db, parentBox, fileName, user) if file is None: raise OstracionError('File not found.') else: fileActions = prepareFileActions( db, file, boxPath[1:] + [file.name], parentBox, user, discardedActions={'text_edit'}, ) fileInfo = prepareFileInfo(db, file) form = EditTextFileForm() form.textformat.choices = [ (mId, mDesc['title']) for mId, mDesc in sorted( textFileViewingModes.items(), key=lambda kv: kv[1]['index'], ) ] ## if form.validate_on_submit(): newcontents = form.filecontents.data filePath = fileIdToPath( file.file_id, fileStorageDirectory=fileStorageDirectory, ) with open(filePath, 'w') as openFile: openFile.write('%s' % newcontents) # file properties fileProperties = determineFileProperties(filePath) newFile = File(**file.asDict()) newFile.mime_type = fileProperties['file_mime_type'] newFile.type = fileProperties['file_type'] newFile.size = fileProperties['file_size'] newFile.textual_mode = form.textformat.data newFile.editor_username = user.username updateFile(db, boxPath, file.name, newFile, user) # flashMessage('Info', 'Info', 'File "%s" saved.' % file.name) return redirect( url_for( 'lsView', lsPathString='/'.join(boxPath[1:]), ) ) else: form.filecontents.data = applyDefault( form.filecontents.data, open( fileIdToPath( file.file_id, fileStorageDirectory=fileStorageDirectory, ) ).read(), ) form.textformat.data = applyDefault( form.textformat.data, file.textual_mode, additionalNulls=['None'], ) pathBCrumbs = makeBreadCrumbs( boxPath, g, appendedItems=[ { 'kind': 'file', 'target': file, }, { 'kind': 'link', 'target': None, 'name': 'Edit text', } ], ) return render_template( 'edittextfile.html', user=user, form=form, fileActions=fileActions, fileInfo=fileInfo, pageTitle='"%s" file edit' % file.name, pageSubtitle='Click "Save" to commit the changes', breadCrumbs=pathBCrumbs, )
def loginView(): """Login view.""" user = g.user db = dbGetDatabase() g._onErrorUrl = url_for('loginView') if user is not None and user.is_authenticated: return redirect(url_for('indexView')) form = LoginForm() loginProtectionSeconds = int(g.settings['behaviour']['behaviour_security'] ['login_protection_seconds']['value']) if form.validate_on_submit(): # loginWaitSeconds = secondsToWaitBeforeLogin( db, request.remote_addr, doWrite=True, loginProtectionSeconds=loginProtectionSeconds, hashSalt=g.settings['behaviour']['behaviour_security'] ['ip_addr_hashing_salt']['value'], ) if loginWaitSeconds <= 0: # qUser = dbGetUser(db, form.username.data) if qUser and qUser.checkPassword(form.password.data): # newUser = User(**qUser.asDict()) newUser.last_login = datetime.datetime.now() dbUpdateUser(db, newUser, qUser) # login_user(qUser) # flashMessage( 'Success', 'Login successful', 'welcome, %s!' % (qUser.fullname, ), ) # return redirect(url_for('indexView')) else: g._onErrorUrl = url_for( 'loginView', username=form.username.data, ) raise OstracionError('invalid username or password') else: raise OstracionWarning( ('Automated repeated login protection. ' 'Please wait %i seconds ...') % int(loginWaitSeconds)) else: requestParams = request.args form.username.data = applyDefault( form.username.data, requestParams.get('username', ''), ) appShortName = g.settings['behaviour']['behaviour_appearance'][ 'application_short_name']['value'] iconUrl = makeSettingImageUrl(g, 'user_images', 'login') return render_template( 'login.html', form=form, user=user, pageTitle=loginTitle(g), pageSubtitle=loginSubtitle(g), iconUrl=iconUrl, )