def dbPunchRichTicket(db, richTicket, numPunches=1, skipCommit=False): """ Punch a ticket, i.e. mark it as been used once more. We assume the ticket has been read during this database session, i.e. it reflects current DB data. """ if richTicket['redeemable']: # newTicketDict = recursivelyMergeDictionaries( { 'times_redeemed': (richTicket['ticket'].times_redeemed + numPunches), 'last_redeemed': datetime.datetime.now(), }, defaultMap=richTicket['ticket'].asDict(), ) dbUpdateRecordOnTable( db, 'tickets', newTicketDict, dbTablesDesc=dbSchema, ) # if not skipCommit: db.commit() else: if richTicket['exhausted']: raise OstracionError('Ticket is exhausted') else: raise OstracionError('Cannot punch a non-redeemable ticket')
def dbRevokeRoleFromUser(db, role, targetUser, user): """Revoke a role from a user, i.e. ungrant it.""" if userIsAdmin(db, user): grantedRoleKeys = {r.roleKey() for r in targetUser.roles} if role.roleKey() not in grantedRoleKeys: raise OstracionError('Role is not granted to user') else: # delicate checks: cannot remove 'admin' from self if (user.username == targetUser.username and role.roleKey() == ('system', 'admin')): raise OstracionError('Cannot revoke "admin" role from self') else: dbDeleteRecordsByKey( db, 'user_roles', { 'username': targetUser.username, 'role_class': role.role_class, 'role_id': role.role_id, }, dbTablesDesc=dbSchema, ) db.commit() else: raise OstracionError('Insufficient permissions')
def dbDeleteRole(db, roleClass, roleId, user): """ Delete a role from DB.""" if userIsAdmin(db, user): role = dbGetRole(db, roleClass, roleId, user) if role.can_delete == 0: raise OstracionError('Role cannot be deleted') else: dbDeleteRecordsByKey( db, 'box_role_permissions', { 'role_class': role.role_class, 'role_id': role.role_id }, dbTablesDesc=dbSchema, ) dbDeleteRecordsByKey( db, 'roles', { 'role_class': role.role_class, 'role_id': role.role_id }, dbTablesDesc=dbSchema, ) db.commit() else: raise OstracionError('Insufficient permissions')
def dbGrantRoleToUser(db, role, targetUser, user): """Assign a role to a user, i.e. grant it.""" if userIsAdmin(db, user): grantedRoleKeys = {r.roleKey() for r in targetUser.roles} if role.can_user == 0: raise OstracionError('Role cannot be granted to users') elif role.roleKey() in grantedRoleKeys: raise OstracionError('Role is already granted to user') else: # newUserRole = UserRole( username=targetUser.username, role_class=role.role_class, role_id=role.role_id, ) dbAddRecordToTable( db, 'user_roles', newUserRole.asDict(), dbTablesDesc=dbSchema, ) # db.commit() else: raise OstracionError('Insufficient permissions')
def duplicateImageForCalendar(src, dst): """ Given a source file (e.g. a standard Ostracion physical filepath) and a destination filepath to create (with extension, amenable to LaTeX), generate the latter and return its path. May be a simple symlink or a new, capped-res file, to optimize calendar pdf for file size. """ args = [ 'convert', src, '-resize', '%ix>' % maxCalendarImageResolutionWidth, dst, ] imgDuplicationOutput = subprocess.run( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) if imgDuplicationOutput.returncode == 0: if os.path.isfile(dst): return dst else: raise OstracionError('Could not resize input image') return None else: raise OstracionError('Could not resize input image') return None
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 makeCalendarPdf(properties, imageTexPaths, coverImageTexPath, workingDirectory, pdfTitle): """ Generate the pdf of a calendar given its properties. Uses 'pdflatex' under the hood. Input properties: a dictionary with all required properties imageTexPaths: an array of physical-files-to-use coverImageTexPath: a single path to the cover physical-image-file workingDirectory: where to generate all files (incl. final pdf) pdfTitle: pdf-name, without extension Output pdfTitleOrNone, [tempFileToDelete_1, ...] pdfTitleOrNone is None upon failures. It is care of the caller to arrange deletion of temporary files. """ # generating calendarStructure = makeCalendarStructure(properties, imageTexPaths, coverImageTexPath) outputTexFile = '%s.tex' % pdfTitle outputPdfFile = '%s.pdf' % pdfTitle outputTexPath = os.path.join(workingDirectory, outputTexFile) outputPdfPath = os.path.join(workingDirectory, outputPdfFile) makeCalendarTexfile(calendarStructure, outputTexPath) # compiling, checking+returning the resulting file pdfMakingOutput = subprocess.run( [ 'timeout', '%is' % pdfGenerationTimeoutSeconds, 'pdflatex', '-halt-on-error', outputTexFile, ], cwd=workingDirectory, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) if pdfMakingOutput.returncode == 0: if os.path.isfile(outputPdfPath): finalPdfPath = outputPdfPath else: raise OstracionError('Could not retrieve generated calendar') finalPdfPath = None else: raise OstracionError('Calendar generation command failed') finalPdfPath = None temporaryFiles = [ os.path.join(workingDirectory, '%s.%s' % (pdfTitle, extension)) for extension in ['tex', 'log', 'aux'] ] return finalPdfPath, temporaryFiles
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 updateBox( db, path, newBox, user, accountDeletionInProgress=False, skipCommit=False): """ Update the fields of a box on DB.""" # # we check box_id is unchanged for updating prevBox = getBoxFromPath( db, path, user, accountDeletionInProgress=accountDeletionInProgress, ) parentBox = getBoxFromPath( db, path[:-1], user, accountDeletionInProgress=accountDeletionInProgress, ) if newBox.box_id != prevBox.box_id: raise RuntimeError('Box ID mismatch') else: if ( not accountDeletionInProgress and not userHasPermission(db, user, prevBox.permissions, 'w')): raise OstracionError('User is not allowed to edit box') else: if not isNameUnderParentBox( db, parentBox, newBox.box_name, excludedIds=[('box', newBox.box_id)]): newBoxItem = Box(**{ k: v for k, v in newBox.asDict().items() if k not in { 'dvector_box_name', 'dvector_title', 'dvector_description', } }) dbUpdateRecordOnTable( db, 'boxes', newBoxItem.asDict(), dbTablesDesc=dbSchema, ) if not skipCommit: db.commit() else: raise OstracionError('Name already exists')
def updateLink( db, boxPath, prevLinkName, newLink, user, accountDeletionInProgress=False, skipCommit=False): """ Update the fields of a link object on DB.""" # # we check link_id is unchanged parentBox = getBoxFromPath( db, boxPath, user, accountDeletionInProgress=accountDeletionInProgress, ) prevLink = getLinkFromParent( db, parentBox, prevLinkName, user, accountDeletionInProgress=accountDeletionInProgress, ) if newLink.link_id != prevLink.link_id: raise RuntimeError('Link ID mismatch') else: if (not accountDeletionInProgress and not userHasPermission(db, user, parentBox.permissions, 'w')): raise OstracionError('User is not allowed to edit link') else: if not isNameUnderParentBox( db, parentBox, newLink.name, excludedIds=[('link', prevLink.link_id)]): newLinkItem = Link(**{ k: v for k, v in newLink.asDict().items() if k not in { 'dvector_name', 'dvector_description', 'dvector_title', } }) dbUpdateRecordOnTable( db, 'links', newLinkItem.asDict(), dbTablesDesc=dbSchema, ) if not skipCommit: db.commit() else: raise OstracionError('Name already exists')
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 deleteLink( db, parentBox, link, user, fileStorageDirectory, skipCommit=False, accountDeletionInProgress=False): """ Delete a link (either because permissions allow it or the caller is working as part of an account deletion, in which case the caller is responsible for lifting permission checks). Returns the filesystem delete queue. """ if (accountDeletionInProgress or userHasPermission(db, user, parentBox.permissions, 'w')): # fsDeleteQueue = ( [ fileIdToPath( link.icon_file_id, fileStorageDirectory=fileStorageDirectory, ) ] if link.icon_file_id != '' else [] ) dbDeleteRecordsByKey( db, 'links', {'link_id': link.link_id}, dbTablesDesc=dbSchema, ) if not skipCommit: db.commit() return fsDeleteQueue else: raise OstracionError('User has no write permission')
def calendarMakerBrowseBoxView(mode): """ Three-way view to manage image-selection browsing box: handles reset initiate box selection (through preparePickBoxPageView) complete box selection """ user = g.user db = dbGetDatabase() request._onErrorUrl = url_for('calendarMakerImagesView', ) if mode == 'start': rootBox = getRootBox(db) return preparePickBoxPageView( db=db, user=user, callbackUrl=url_for('calendarMakerBrowseBoxView', mode='end'), startBox=rootBox, message='Choose box to browse images from', ) elif mode == 'end': chosenBoxObjPathBlob = request.args.get('chosenBoxObjPath') chosenBoxObjPath = urllib.parse.unquote_plus(chosenBoxObjPathBlob) response = redirect(url_for('calendarMakerImagesView')) response.set_cookie('apps_calendarmaker_browsebox', chosenBoxObjPath) return response elif mode == 'clear': response = redirect(url_for('calendarMakerImagesView')) response.set_cookie('apps_calendarmaker_browsebox', '', expires=0) return response else: raise OstracionError('Malformed request')
def _recursiveBoxDeletion( db, box, parentBox, user, fileStorageDirectory, accountDeletionInProgress=False): """ Take care of deleting a box, invoking itself on children boxes and erasing contained files, joining the results (the delete queue) accumulated in the sub-deletions. Used internaly by deleteBox. """ if box.box_id == '': raise OstracionError('Box cannot be deleted') else: if (accountDeletionInProgress or ( userHasPermission(db, user, box.permissions, 'w') and userHasPermission(db, user, parentBox.permissions, 'c') )): fsDeleteQueue = ([fileIdToPath( box.icon_file_id, fileStorageDirectory=fileStorageDirectory, )]) if box.icon_file_id != '' else [] allChildren = list(getBoxesFromParent(db, box, user)) if any(c is None for c in allChildren): raise OstracionError('User is not allowed to delete box') # for c in allChildren: if c is not None: fsDeleteQueue += _recursiveBoxDeletion( db, c, box, user, fileStorageDirectory=fileStorageDirectory, accountDeletionInProgress=accountDeletionInProgress) allChildFiles = getFilesFromBox(db, box) for f in allChildFiles: fsDeleteQueue += deleteFile( db, box, f, user, fileStorageDirectory=fileStorageDirectory, skipCommit=True, accountDeletionInProgress=accountDeletionInProgress) # actual deletion dbDeleteRecordsByKey( db, 'box_role_permissions', {'box_id': box.box_id}, dbTablesDesc=dbSchema) dbDeleteRecordsByKey( db, 'boxes', {'box_id': box.box_id}, dbTablesDesc=dbSchema) return fsDeleteQueue else: raise OstracionError('User is not allowed to delete box')
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 dbCreateRole(db, newRole, user): """Create a new role in DB.""" if userIsAdmin(db, user): if dbGetRole(db, newRole.role_class, newRole.role_id, user) is None: if newRole.can_delete == 0: raise OstracionError('Manual roles must be deletable') else: dbAddRecordToTable( db, 'roles', newRole.asDict(), dbTablesDesc=dbSchema, ) db.commit() else: raise OstracionWarning('Role "%s/%s" exists already' % newRole.roleKey()) else: raise OstracionError('Insufficient permissions')
def dbInsertBoxRolePermission(db, newBoxRolePermission, user, skipCommit=False): """Add a new permission-set (i.e. tied to a role) to a box.""" if newBoxRolePermission.box_id == '': raise OstracionError('Cannot add a permission to root box') else: # system/admin cannot be added/removed if newBoxRolePermission.roleKey() == ('system', 'admin'): raise OstracionError('Cannot add permissions for admin role') else: role = dbGetRole( db, newBoxRolePermission.role_class, newBoxRolePermission.role_id, user, ) if role is not None: # the role must have can_box attribute if role.can_box == 0: raise OstracionError( 'Cannot add permissions for this role') else: if userIsAdmin(db, user): try: dbAddRecordToTable( db, 'box_role_permissions', newBoxRolePermission.asDict(), dbTablesDesc=dbSchema, ) if not skipCommit: db.commit() except Exception as e: db.rollback() raise e else: raise OstracionError('Insufficient permissions') else: raise OstracionError('Could not find role')
def moveFile( db, file, srcBox, dstBox, user, fileStorageDirectory, skipCommit=False): """ Move a file between boxes: also check for w permission on both boxes, check that no box in dstBox yields a name clash.""" if file.box_id != srcBox.box_id: raise OstracionError('Parent mismatch between file and source box') elif srcBox.box_id == dstBox.box_id: raise OstracionError('Source and destination are the same') else: if all([ userHasPermission(db, user, srcBox.permissions, 'w'), userHasPermission(db, user, dstBox.permissions, 'w'), ]): # fileName = file.name if isNameUnderParentBox(db, dstBox, fileName): raise OstracionError( 'Destination box contains an item with same name' ) else: # now can the actual MV be performed newFile = recursivelyMergeDictionaries( {'box_id': dstBox.box_id}, defaultMap=file.asDict(), ) dbUpdateRecordOnTable( db, 'files', newFile, dbTablesDesc=dbSchema, ) # if not skipCommit: db.commit() # messages = [] return messages else: raise OstracionError('User has no write permission')
def makeBoxInParent(db, parentBox, newBox, user, skipCommit=False): """ Create a box, with name newBox, in parentBox on behalf of 'user'. Does all permission/name availability checks. """ # first we check user has permission to create boxes here if not userHasPermission(db, user, parentBox.permissions, 'c'): raise OstracionError('User is not allowed to create boxes') else: # then we check there are no children with same name in the parent if not isNameUnderParentBox(db, parentBox, newBox.box_name): # now we create dbAddRecordToTable( db, 'boxes', newBox.asDict(), dbTablesDesc=dbSchema, ) if not skipCommit: db.commit() else: raise OstracionError('Name already exists')
def dbUpdateUser(db, newUser, user, skipCommit=False): """Update some columns of a user row.""" if newUser.username != '': dbUpdateRecordOnTable( db, 'users', newUser.asDict(), dbTablesDesc=dbSchema, ) if not skipCommit: db.commit() else: raise OstracionError('Cannot alter system user')
def deleteBoxView(boxPathString=''): """RMBOX route.""" user = g.user db = dbGetDatabase() fileStorageDirectory = g.settings['system']['system_directories'][ 'fs_directory']['value'] boxPath = splitPathString(boxPathString) box = getBoxFromPath(db, boxPath, user) parentBox = getBoxFromPath(db, boxPath[:-1], user) request._onErrorUrl = url_for( 'lsView', lsPathString='/'.join(boxPath[1:-1]), ) # canDelete = canDeleteBox(db, box, parentBox, user) # if canDelete: if parentBox is None: # deletee box was root raise OstracionError('Cannot act on this object') else: if box is not None: fsDeleteQueue = deleteBox( db, box, parentBox, user, fileStorageDirectory=fileStorageDirectory, ) flushFsDeleteQueue(fsDeleteQueue) else: raise OstracionError('Box not accessible') else: raise OstracionError('Cannot delete this box') return redirect(url_for( 'lsView', lsPathString='/'.join(boxPath[1:-1]), ))
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 makeFileInParent(db, parentBox, newFile): """ Create a file object in a box.""" if newFile.box_id != parentBox.box_id: raise RuntimeError('wrong parent box id in makeFileInParent') else: if not isBoxNameUnderParentBox(db, parentBox, newFile.name): dbAddRecordToTable( db, 'files', newFile.asDict(), dbTablesDesc=dbSchema, ) db.commit() else: raise OstracionError('Name already exists')
def makeLinkInParent( db, user, parentBox, date, linkName, linkTitle, linkDescription, linkTarget, linkOptions={}): """ Create a new external link object in the specified box. Return a dummy value (True upon success, but it is the errors that are raised.) """ if userHasPermission(db, user, parentBox.permissions, 'w'): if not isNameUnderParentBox(db, parentBox, linkName): userName = user.username newLink = Link( box_id=parentBox.box_id, name=linkName, title=linkTitle, description=linkDescription, icon_file_id='', date=date, creator_username=userName, icon_file_id_username=userName, icon_mime_type='', metadata_username=userName, target=linkTarget, metadata_dict=linkOptions, ) dbAddRecordToTable( db, 'links', newLink.asDict(), dbTablesDesc=dbSchema, ) db.commit() else: raise OstracionError('Name already exists') else: raise OstracionError('User has no write permission')
def dbPunchTicket(db, mode, ticketId, securityCode, urlRoot, protectBannedUserTickets): """Retrieve/enrich a ticket and punch it with dbPunchRichTicket.""" richTicket = dbGetEnrichAndCheckTicket( db, mode, ticketId, securityCode, urlRoot, ) issuer = (dbGetUser(db, richTicket['ticket'].username) if richTicket is not None else None) if (issuer is not None and (not protectBannedUserTickets or issuer.banned == 0)): dbPunchRichTicket(db, richTicket) else: raise OstracionError('Not allowed to punch ticket')
def dbUpdateRole(db, newRole, user): """Update role metadata on DB.""" if userIsAdmin(db, user): dbUpdateRecordOnTable( db, 'roles', { k: v for k, v in newRole.asDict().items() if k in {'description', 'role_class', 'role_id'} }, dbTablesDesc=dbSchema, allowPartial=True, ) db.commit() else: raise OstracionError('Insufficient permissions')
def dbMakeGalleryTicket(db, ticketName, validityHours, multiplicity, ticketMessage, box, boxPath, user, urlRoot, settings): """ Generate a gallery-view ticket on a box (with the specified ticket settings). """ if isTicketIssuablePerSettings(validityHours, multiplicity, settings): ticketId, securityCode = randomTicketNumbers(user) issueDate = datetime.datetime.now() metadata = { k: v for k, v in { 'box_id': box.box_id, 'box_path': boxPath, 'box_name': box.box_name, 'box_title': box.title, '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=multiplicity, target_type='gallery', 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( 'Ticket parameters not allowed under the current settings')
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 calendarMakerDestBoxView(mode): """ Three-way view to manage pdf destination box: handles reset initiate box selection (through preparePickBoxPageView) complete box selection """ user = g.user db = dbGetDatabase() request._onErrorUrl = url_for('calendarMakerIndexView', ) rootBox = getRootBox(db) if mode == 'start': def writableRichBoxPicker(rBox): return userHasPermission(db, user, rBox['box'].permissions, 'w') return preparePickBoxPageView( db=db, user=user, callbackUrl=url_for('calendarMakerDestBoxView', mode='end'), startBox=rootBox, predicate=writableRichBoxPicker, message='Choose the box where the calendar will be created', ) elif mode == 'end': chosenBoxObjPathBlob = request.args.get('chosenBoxObjPath') chosenBoxObjPath = urllib.parse.unquote_plus(chosenBoxObjPathBlob) response = redirect(url_for('calendarMakerIndexView')) response.set_cookie('apps_calendarmaker_destbox', chosenBoxObjPath) return response elif mode == 'clear': response = redirect(url_for('calendarMakerIndexView')) response.set_cookie('apps_calendarmaker_destbox', '', expires=0) return response else: raise OstracionError('Malformed request')
def calendarMakerGenerateCalendar(): """ Calendar actual generation view. Handles everything: building temporary image files driving the engine functions to make the pdf inserting the pdf in the box removing temporary files """ user = g.user db = dbGetDatabase() request._onErrorUrl = url_for('calendarMakerIndexView', ) # destBoxString = request.cookies.get('apps_calendarmaker_destbox') currentCalendar = cookiesToCurrentCalendar(request.cookies) coverImagePathString = currentCalendar.get('cover_image_path_string') calendarImagePaths = currentCalendar.get('image_path_strings', []) cProps = currentCalendar.get('properties', {}) # if destBoxString is None: destBox = None else: destBoxPath = splitPathString(destBoxString) destBox = getBoxFromPath(db, destBoxPath, user) if coverImagePathString is None: coverImageFileObject = None else: coverImageFileObject = pathToFileStructure( db, user, coverImagePathString, ) # calendarImages = [ pathToFileStructure(db, user, imgPath) for imgPath in calendarImagePaths ] numRequiredImages = countMonths( cProps.get('year0'), cProps.get('month0'), cProps.get('year1'), cProps.get('month1'), ) if (destBox is None or coverImageFileObject is None or any([ci is None for ci in calendarImages]) or numRequiredImages is None or numRequiredImages > len(calendarImages)): raise OstracionError('Cannot generate calendar') else: fileStorageDirectory = g.settings['system']['system_directories'][ 'fs_directory']['value'] # proceed with generation tempFileDirectory = g.settings['system']['system_directories'][ 'temp_directory']['value'] mkDirP(tempFileDirectory) texImageCoverPath = duplicateImageForCalendar( fileIdToPath( coverImageFileObject['file'].file_id, fileStorageDirectory=fileStorageDirectory, ), os.path.join( tempFileDirectory, '%s.%s' % ( uuid4().hex, admittedImageMimeTypeToExtension[ coverImageFileObject['file'].mime_type], )), ) texImagePaths = [ duplicateImageForCalendar( fileIdToPath( imageFile['file'].file_id, fileStorageDirectory=fileStorageDirectory, ), os.path.join( tempFileDirectory, '%s.%s' % ( uuid4().hex, admittedImageMimeTypeToExtension[ imageFile['file'].mime_type], )), ) for imageFile in calendarImages ] # fsDeletionQueue = [texImageCoverPath] + texImagePaths createdPdfTitle = uuid4().hex createdFile, creationToDelete = makeCalendarPdf( cProps, texImagePaths, texImageCoverPath, tempFileDirectory, createdPdfTitle, ) # if createdFile is not None: # name and description calDescription = 'Calendar %i/%i - %i/%i' % ( cProps['month0'], cProps['year0'], cProps['month1'], cProps['year1'], ) calFileName = findFirstAvailableObjectNameInBox( db, destBox, 'calendar_', '.pdf', ) # place the pdf in the box placeFSFileInBox( db, user, fileStorageDirectory, destBox, createdFile, calFileName, calDescription, ) # flushing the delete queue flushFsDeleteQueue(fsDeletionQueue + creationToDelete + [createdFile]) # messaging the user successMessage = ('Calendar generated. Please find the file ' '"%s" in the destination box.') % calFileName flashMessage('Success', 'Info', successMessage) # redirecting user to box return redirect(url_for('lsView', lsPathString=destBoxString)) else: # flushing the delete queue flushFsDeleteQueue( fsDeletionQueue + creationToDelete + [createdFile], ) # messaging the user flashMessage('Error', 'Error', 'Could not generate the calendar') return redirect(url_for('calendarMakerIndexView'))