Exemplo n.º 1
0
async def remove_directory(
    directory_id: int,
    current_user: schemas.User = Depends(get_current_user),
    db: crud.Session = Depends(get_db)):
    """Removes the directory. Note that the directory MUST BE EMPTY, User has to be at least maintainer."""
    required_level = models.AccessTypeEnum.maintainer
    if get_access_level(db, user_id=current_user.id,
                        directory_id=directory_id) < required_level:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="You do not have authorization to remove this directory",
            headers={"WWW-Authenticate": "Bearer"},
        )

    # directory_db apparently exists if get_access_level got us this far
    directory_db: models.MachineDirectory = crud.directory_get(
        db, directory_id)
    # but it should not have machines inside
    if len(directory_db.machines) > 0 or len(directory_db.children) > 0:
        raise HTTPException(
            status_code=status.HTTP_406_NOT_ACCEPTABLE,
            detail="The directory is not empty!",
            headers={"WWW-Authenticate": "Bearer"},
        )

    crud.directory_remove(db, directory_db.id)
Exemplo n.º 2
0
async def add_machine(machine: schemas.MachineBase,
                      request: Request,
                      current_user: schemas.User = Depends(get_current_user),
                      db: crud.Session = Depends(get_db)):
    """
    Adds a machine with certain name, description and then returns a whole machine object with generated values.
    Only an administrator or an maintainer of certain directory can do that. A machine has to be in some directory
    """

    required_level = models.AccessTypeEnum.admin if not machine.directory_id else models.AccessTypeEnum.maintainer
    if get_access_level(db,
                        user_id=current_user.id,
                        directory_id=machine.directory_id) < required_level:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=
            "You do not have any authorization for creating a machine here",
            headers={"WWW-Authenticate": "Bearer"},
        )

    if not machine.directory_id or not crud.directory_get(
            db, machine.directory_id):
        raise HTTPException(
            status_code=status.HTTP_406_NOT_ACCEPTABLE,
            detail=
            "The specified directory does not exist: A machine must be in a directory",
        )

    machine_create = schemas.MachineAfterCreate(**dict(machine))
    # generate random token for downloading the install script
    one_time_installer_token = crypto.generate_provable_token(True)
    machine_create.one_time_installer_token = one_time_installer_token
    # now generate random token for sending stats
    token: str = crypto.generate_provable_token(False)

    machine_full: schemas.Machine = crud.machine_create(
        db, machine_create, token)

    # lastly add the url for convenience
    machine_full.one_time_installer_url = (
        ("http://" if settings.TEST_MODE else "https://") +
        str(request.url.hostname) + ":" + str(request.url.port) + "/" +
        one_time_installer_token)

    return machine_full
Exemplo n.º 3
0
def get_access_level(db: crud.Session,
                     user_id: int,
                     machine_id: int = None,
                     directory_id: int = None):
    """Helper function that returns the highest current access level of a user to particular machine or directory"""
    user: models.User = crud.user_get(db, user_id)
    if user.is_admin:
        return models.AccessTypeEnum.admin

    if bool(machine_id) == bool(
            directory_id):  # XOR - only one of them might be specified
        return models.AccessTypeEnum.none

    highest_access = models.AccessTypeEnum.none

    machine: models.Machine = crud.machine_get(db, machine_id)
    directory_db: models.MachineDirectory = crud.directory_get(
        db, directory_id)
    if (bool(machine_id) and not machine) or (bool(directory_id)
                                              and not directory_db):
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="The machine or directory nas not been found",
        )

    # First get all the accesses from the groups in which the user is
    user_accesses: [models.Access] = []

    g: models.UserGroup
    if user.groups:
        for g in user.groups:
            user_accesses.extend(g.accesses)

    # Now crawl from the machine up and find the highest access
    pdir: models.MachineDirectory = machine.directory if machine_id else directory_db
    a: models.Access
    while pdir:
        for a in pdir.accesses:
            if a in user_accesses and a.type > highest_access:
                highest_access = a.type
        pdir = pdir.parent

    return highest_access
Exemplo n.º 4
0
async def edit_machine_directory(
    directory_id: int,
    name: str,
    current_user: schemas.User = Depends(get_current_user),
    db: crud.Session = Depends(get_db)):
    """Edit the name of a directory. The user has to be at least maintainer."""
    required_level = models.AccessTypeEnum.maintainer
    level = get_access_level(db,
                             user_id=current_user.id,
                             directory_id=directory_id)
    if level < required_level:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="You do not have authorization to add edit this directory",
            headers={"WWW-Authenticate": "Bearer"},
        )

    dir_db: models.MachineDirectory = crud.directory_get(db, directory_id)

    dir_db.name = name
    db.commit()
Exemplo n.º 5
0
async def move_machine_directory(
    directory_id: int,
    parent_id: int = None,
    current_user: schemas.User = Depends(get_current_user),
    db: crud.Session = Depends(get_db)):
    """Moves the directory (including it's contents, of course) to another directory. User has to be at least maintainer
    for both directories. Note that this can cause movement in between the user groups. At least the machines can not
    be lost forever"""
    if not current_user.is_admin and parent_id is None:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=
            "You do not have authorization to move the directory to the root",
            headers={"WWW-Authenticate": "Bearer"},
        )

    required_level = models.AccessTypeEnum.maintainer
    level_moving: models.AccessTypeEnum = get_access_level(
        db, current_user.id, directory_id=directory_id)
    level_parent: models.AccessTypeEnum = models.AccessTypeEnum.none
    if parent_id:
        level_parent = get_access_level(db,
                                        current_user.id,
                                        directory_id=parent_id)
    # the upper resolves for us if either directory is not to be found

    if not current_user.is_admin and (level_moving < required_level
                                      or level_parent < required_level):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="You do not have authorization for on of the directories",
            headers={"WWW-Authenticate": "Bearer"},
        )

    directory_db: models.MachineDirectory = crud.directory_get(
        db, directory_id)
    directory_db.parent_id = parent_id
    db.commit()
Exemplo n.º 6
0
async def update_access(
    group_id: int,
    directory_id: int,
    level: models.AccessTypeEnum,
    db: crud.Session = Depends(get_db),
    current_user: schemas.User = Depends(check_current_user_admin)):
    """Updates the access of a particular user group to a particular directory. Note that multiple accesses for one
    user group on one tree path are not allowed!"""
    if not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="You do not have authorization to do this operation",
            headers={"WWW-Authenticate": "Bearer"},
        )

    if level > models.AccessTypeEnum.maintainer:
        raise HTTPException(
            status_code=status.HTTP_406_NOT_ACCEPTABLE,
            detail=
            "You can not use create any higher access than maintainer. Consider a different approach."
        )

    group_db: models.UserGroup = crud.user_group_get(db, group_id)
    directory_db: models.MachineDirectory = crud.directory_get(
        db, directory_id)

    if not group_db:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
                            detail="The user group has not been found")

    if not directory_db:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
                            detail="The directory has not been found")

    # Now there are some restrictions: At all times one group can only have one path of access to a directory.
    # We first need all the directories IDs from the accessess
    a: models.Access
    adirids = []
    for a in group_db.accesses:
        adirids.append(a.machine_directory_id)

    if directory_id in adirids:
        # let's just update that, shall we?
        access_db: models.Access = crud.access_get(
            db, machine_directory_id=directory_id, user_group_id=group_id)
        if level == 0:
            crud.access_delete(db, access_db.id)
        else:
            access_db.type = level
            db.commit()
        return

    else:
        # First see if the directory we are looking for is not a descendant of one of the dirs already in accessess
        # This is not allowed at all!
        d: models.MachineDirectory = directory_db
        while d.parent:
            if d.parent_id in adirids:
                raise HTTPException(
                    status_code=status.HTTP_406_NOT_ACCEPTABLE,
                    detail=
                    "There already is an implicit access for this group and directory from the directory {}. If you "
                    "need to change the explicit access for this directory and group, please consider different "
                    "directory and group management instead ".format(
                        d.parent.name))
            d = d.parent

        # Ok so it is not a descendant of existing access if we got here
        # Now in case that the old access is some descendant of new one, we will just remove them
        overriden = False
        accessess_to_delete = []
        ad: models.MachineDirectory
        for a in group_db.accesses:
            ad = a.directory
            while ad.parent_id:
                if ad.parent_id is directory_id:
                    overriden = True
                    accessess_to_delete.append(a)
                ad = ad.parent
        for a in accessess_to_delete:
            crud.access_delete(db, a.id)

        # Now we can finally add the access
        if level > 0:
            newac = schemas.Access(type=level,
                                   user_group_id=group_id,
                                   machine_directory_id=directory_id)
            crud.access_add(db, newac)

        if overriden:
            return {"detail": "Original child accessess has been removed!"}