Example #1
0
def updateBoxThumbnail(
        db, box, tId, tMT, user, fileStorageDirectory,
        accountDeletionInProgress=False, skipCommit=False):
    """ Update the thumbnail info for a box.
        Return a list of zero or one full paths for deletion."""
    prevId = box.icon_file_id
    if prevId != '':
        delQueue = [
            fileIdToPath(prevId, fileStorageDirectory=fileStorageDirectory)
        ]
    else:
        delQueue = []
    #
    box.icon_file_id = tId if tId is not None else ''
    box.icon_mime_type = tMT if tMT is not None else ''
    box.icon_file_id_username = (user.username
                                 if not accountDeletionInProgress
                                 else '')
    dbUpdateRecordOnTable(
        db,
        'boxes',
        box.asDict(),
        dbTablesDesc=dbSchema,
    )
    #
    if not skipCommit:
        db.commit()
    return delQueue
Example #2
0
def updateUserThumbnail(
        db, targetUser, tId, tMT, user,
        fileStorageDirectory, skipCommit=False):
    """ Update the thumbnail info for a user.
        Return a list of zero or one full paths for deletion."""
    prevId = targetUser.icon_file_id
    if prevId != '':
        delQueue = [
            fileIdToPath(prevId, fileStorageDirectory=fileStorageDirectory)
        ]
    else:
        delQueue = []
    #
    targetUser.icon_file_id = tId if tId is not None else ''
    targetUser.icon_mime_type = tMT if tMT is not None else ''
    targetUser.icon_file_id_username = user.username
    dbUpdateRecordOnTable(
        db,
        'users',
        targetUser.asDict(),
        dbTablesDesc=dbSchema,
    )
    #
    if not skipCommit:
        db.commit()
    return delQueue
Example #3
0
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')
Example #4
0
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')
Example #5
0
def secondsToWaitBeforeLogin(db,
                             ipAddress,
                             doWrite,
                             loginProtectionSeconds,
                             hashSalt,
                             skipCommit=False):
    """ Check at once if the record exists
        and if the login is attemptable.
        Moreover update/insert the attempted-login entry in all cases
        and finally (optionally) commit.
    """
    #
    atLogin = AttemptedLogin(
        sender_hash=hashOfIpAddress(ipAddress, hashSalt=hashSalt),
        datetime=datetime.datetime.now(),
    )
    #
    prevLoginDict = dbRetrieveRecordByKey(
        db,
        'attempted_logins',
        {'sender_hash': atLogin.sender_hash},
        dbTablesDesc=dbSchema,
    )
    if prevLoginDict is not None:
        prevLogin = AttemptedLogin(**prevLoginDict)
    else:
        prevLogin = None
    #
    if (prevLogin is None
            or (datetime.datetime.now() - prevLogin.datetime).seconds >=
            loginProtectionSeconds):
        secondsToWait = 0
    else:
        secondsToWait = loginProtectionSeconds - (datetime.datetime.now() -
                                                  prevLogin.datetime).seconds
    #
    if doWrite and secondsToWait <= 0:
        if prevLogin is None:
            dbAddRecordToTable(
                db,
                'attempted_logins',
                atLogin.asDict(),
                dbTablesDesc=dbSchema,
            )
        else:
            dbUpdateRecordOnTable(
                db,
                'attempted_logins',
                atLogin.asDict(),
                dbTablesDesc=dbSchema,
            )
        if not skipCommit:
            db.commit()
    #
    return secondsToWait
Example #6
0
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')
Example #7
0
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')
Example #8
0
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')
Example #9
0
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')
Example #10
0
def updateSettingThumbnail(db,
                           richSetting,
                           tId,
                           tMT,
                           user,
                           fileStorageDirectory,
                           skipCommit=False):
    """ Update the image in a setting of type Image. This returns
        the (actual) filesystem deletion queue after taking care of
        the DB part.
        The new thumbnail ID is passed to this function ('' to reset).
        richSetting['setting'] is the DB object, at top-level we
        have enrichment info (such as the default/value resolved etc)
    """
    prevId = richSetting['setting'].value
    if prevId != '':
        delQueue = [
            fileIdToPath(prevId, fileStorageDirectory=fileStorageDirectory)
        ]
    else:
        delQueue = []
    #
    newSettingDict = recursivelyMergeDictionaries(
        {
            'value': tId if tId is not None else '',
            'icon_mime_type': tMT if tMT is not None else '',
        },
        defaultMap={
            k: v
            for k, v in richSetting['setting'].asDict().items()
            if k in {'value', 'icon_mime_type', 'group_id', 'id'}
        },
    )
    dbUpdateRecordOnTable(
        db,
        'settings',
        newSettingDict,
        dbTablesDesc=dbSchema,
        allowPartial=True,
    )
    #
    if not skipCommit:
        db.commit()
    return delQueue
Example #11
0
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')
Example #12
0
                 db,
                 tName,
                 model.asDict(),
                 dbTablesDesc=dbSchema,
             )
             print('done ', end='')
         else:
             # careful override and update back
             mergedDict = recursivelyMergeDictionaries(
                 {'value': itemDictFound['value']},
                 defaultMap=model.asDict(),
             )
             print('updating... ', end='')
             dbUpdateRecordOnTable(
                 db,
                 tName,
                 mergedDict,
                 dbTablesDesc=dbSchema,
             )
             print('done ', end='')
         print('#')
     print('        * done.')
 elif tName == 'links':
     # we may have to add a field
     columns = dbQueryColumns(db, tName)
     if 'title' not in columns:
         # must add 'title' and upgrade existing records
         print('        * Adding "title" column')
         db.execute('ALTER TABLE links ADD COLUMN title TEXT;')
         db.execute(
             'ALTER TABLE links ADD COLUMN dvector_title TEXT;')
         print('        * Upgrading entries ... ', end='')
Example #13
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')
Example #14
0
def moveBox(db, box, srcBox, dstBox, user, skipCommit=False):
    """ Move 'box' from being contained in
        'srcBox' to being contained in 'dstBox'
        (with all involved permission checks).
    """
    if box.box_id == '':
        # nobody can touch root
        raise OstracionError('Cannot act on this object')
    else:
        if box.parent_id != srcBox.box_id:
            # consistency in request
            raise RuntimeError(
                'Parent mismatch between box to move and source box'
            )
        else:
            if box.parent_id == dstBox.box_id:
                raise OstracionError(
                    'Source and destination box are the same'
                )
            else:
                if not canDeleteBox(db, box, srcBox, user):
                    # must be able to remove from source
                    raise OstracionError(
                        'Insufficient permissions to move box away'
                    )
                else:
                    if not all(
                            userHasPermission(
                                db, user, dstBox.permissions, prm
                            )
                            for prm in {'w', 'c'}):
                        # must be able to upload and create to dest
                        raise OstracionError(
                            'Insufficient permissions to move boxes '
                            'to the destination box'
                        )
                    else:
                        # name clash check for destination
                        if isNameUnderParentBox(db, dstBox, box.box_name):
                            raise OstracionError(
                                'An object with that name '
                                'exists already'
                            )
                        else:
                            # check against box incest
                            if isAncestorBoxOf(db, box, dstBox):
                                raise OstracionError(
                                    'Cannot move box to a sub-box of itself'
                                )
                            else:
                                # perform the move
                                newBox = recursivelyMergeDictionaries(
                                    {'parent_id': dstBox.box_id},
                                    defaultMap=box.asDict(),
                                )
                                dbUpdateRecordOnTable(
                                    db,
                                    'boxes',
                                    newBox,
                                    dbTablesDesc=dbSchema,
                                )
                                #
                                if not skipCommit:
                                    db.commit()
                                return []