Beispiel #1
0
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')
Beispiel #2
0
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')
Beispiel #3
0
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),
            },
        },
    )
Beispiel #4
0
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')
Beispiel #5
0
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.')
Beispiel #6
0
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')
Beispiel #7
0
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
Beispiel #8
0
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'))
Beispiel #9
0
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')
Beispiel #10
0
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]
        )
Beispiel #11
0
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')
Beispiel #12
0
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,
            )
Beispiel #13
0
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')
Beispiel #14
0
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'))