Example #1
0
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')
Example #2
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 #3
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')
Example #4
0
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')
Example #5
0
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')
Example #6
0
def dbCreateUser(db, newUser, user):
    """Create a new user row."""
    dbAddRecordToTable(
        db,
        'users',
        newUser.asDict(),
        dbTablesDesc=dbSchema,
    )
    # we read the config flag about new users having or not the 'ticketer' role
    # new_users_are_ticketer
    addTicketerRole = dbGetSetting(
        db,
        'behaviour',
        'behaviour_tickets',
        'new_users_are_ticketer',
        user
    )['value']
    if addTicketerRole:
        dbAddRecordToTable(
            db,
            'user_roles',
            UserRole(
                username=newUser.username,
                role_class='system',
                role_id='ticketer',
            ).asDict(),
            dbTablesDesc=dbSchema,
        )
    # user-tied role handling
    dbAddRecordToTable(
        db,
        'roles',
        Role(
            role_id=newUser.username,
            description='%s user-role' % newUser.username,
            role_class='user',
            can_box=1,
            can_user=0,
            can_delete=0,
        ).asDict(),
        dbTablesDesc=dbSchema,
    )
    dbAddRecordToTable(
        db,
        'user_roles',
        UserRole(
            username=newUser.username,
            role_class='user',
            role_id=newUser.username,
        ).asDict(),
        dbTablesDesc=dbSchema,
    )
    #
    db.commit()
Example #7
0
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')
Example #8
0
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')
Example #9
0
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')
Example #10
0
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')
Example #11
0
def fixRoleTablesAddingRoleClass(db):
    """ Deal with the schema changes
        to bring 'roles' from
            primary key = role_id
        to
            primary_key = (role_class, role_id)
        by acting on all involved tables
        while preserving the contents thereof.

        Returns whether it did something or not as a bool
    """
    rolesTableExists = dbTableExists(db, 'roles')
    roleColumns = dbQueryColumns(db, 'roles') if rolesTableExists else {}
    mustAct = all([
        rolesTableExists,
        'role_class' not in roleColumns,
        'system' in roleColumns,
    ])
    if not mustAct:
        return False
    else:
        print(' * Applying patch to roles')
        # get ready to dance
        targetSchema = {
            tempTableName(tName): tDesc
            for tName, tDesc in dbSchema.items()
            if tName in legacySchema
        }
        targetTableCreationOrder = {
            tempTableName(k): v
            for k, v in tableCreationOrder.items()
        }
        # create the transitional tables (new schema)
        for ntName, ntContents in sorted(
                targetSchema.items(),
                key=lambda tnc: targetTableCreationOrder[tnc[0]]):
            print('     * creating "%s" ' % ntName, end='')
            dbCreateTable(
                db,
                ntName,
                {k: v for k, v in ntContents.items() if k != 'foreign_keys'},
            )
            print('done.')
        # copy items table by table
        print('     * populating ...')
        for srcTName, srcSchema in sorted(
                legacySchema.items(),
                key=lambda tnc: tableCreationOrder[tnc[0]]):
            print('         - "%s" ...' % srcTName)
            # read all items from this srcTName and
            # copy it - with changes - onto tempTableName(srcTName)
            dstTName = tempTableName(srcTName)
            dstSchema = targetSchema[dstTName]
            for inRecordIndex, inRecord in enumerate(dbRetrieveAllRecords(
                db,
                srcTName,
                dbTablesDesc=legacySchema,
            )):
                print('             record[%i] ... ' % inRecordIndex, end='')
                outRecord = convertRoleRelatedRecord(db, legacySchema,
                                                     srcTName, inRecord)
                dbAddRecordToTable(
                    db,
                    dstTName,
                    outRecord,
                    dbTablesDesc=targetSchema,
                )
                print('inserted.')
            print('         - done "%s"' % srcTName)
        print('     * done populating.')
        # we drop the original tables and recreate them with the new schema
        print('     * dropping legacy tables ...')
        for srcTName, srcSchema in sorted(
                legacySchema.items(),
                key=lambda tnc: tableCreationOrder[tnc[0]],
                reverse=True):
            print('         - "%s" ... ' % srcTName, end='')
            dbDeleteTable(db, srcTName)
            print('dropped.')
        print('     * done dropping legacy tables.')
        # we recreate the tables with the new schema
        print('     * re-creating tables ...')
        for srcTName, _ in sorted(
                legacySchema.items(),
                key=lambda tnc: tableCreationOrder[tnc[0]]):
            print('         - "%s" ... ' % srcTName, end='')
            dbCreateTable(
                db,
                srcTName,
                dbSchema[srcTName],
            )
            print('re-created.')
        print('     * done re-creating tables.')
        # we populate the recreated tables with the temporary tables' contents
        print('     * repopulating tables ...')
        for srcTName, srcSchema in sorted(
                legacySchema.items(),
                key=lambda tnc: tableCreationOrder[tnc[0]]):
            print('         - "%s" ... ' % srcTName)
            for recordIndex, record in enumerate(dbRetrieveAllRecords(
                db,
                tempTableName(srcTName),
                dbTablesDesc=targetSchema,
            )):
                print('             record [%i] ... ' % recordIndex, end='')
                dbAddRecordToTable(
                    db,
                    srcTName,
                    record,
                    dbTablesDesc=dbSchema,
                )
                print('inserted.')
            print('         - done "%s"' % srcTName)
        print('     * done repopulating tables.')
        # we drop the temporary tables
        print('     * dropping temporary tables ...')
        for srcTName, srcSchema in sorted(
                legacySchema.items(),
                key=lambda tnc: tableCreationOrder[tnc[0]],
                reverse=True):
            print('         - "%s" ... ' % srcTName, end='')
            deleteeTName = tempTableName(srcTName)
            dbDeleteTable(db, deleteeTName)
            print('dropped.')
        print('     * done dropping temporary tables.')
        #
        return True
Example #12
0
     dbCreateTable(db, tName, tContents)
     print(' done', end='')
 else:
     print('already_there', end='')
 print('.')
 # record insertion
 if not tableFound:
     tcontents = initialDbValues.get(tName)
     if tcontents is not None:
         # ordinary new-table filling
         print('        * Populating')
         for item in tcontents['values']:
             model = tcontents['model'](**item)
             dbAddRecordToTable(
                 db,
                 tName,
                 model.asDict(),
                 dbTablesDesc=dbSchema,
             )
             print('            - %s' % model)
         print('        * done.')
 else:
     # special handling of some tables
     if tName == 'settings':
         # here we add new settings and refresh some fields of the
         # existing ones (namely all but 'value')
         tcontents = initialDbValues.get(tName)
         print('        * Refreshing')
         for item in tcontents['values']:
             model = tcontents['model'](**item)
             print('            - %s : ' % model, end='')
             itemDictFound = dbRetrieveRecordByKey(